diff --git a/docs/dApps/unity.md b/docs/dApps/unity.md deleted file mode 100644 index abdcb1529..000000000 --- a/docs/dApps/unity.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Tezos SDK for Unity -authors: John Joubert -last_update: - date: 5 June 2023 ---- - -The Tezos SDK for Unity offers a comprehensive toolkit designed to facilitate Web3 gaming development. This SDK provides game developers with the necessary tools to: - -1. **Connect to a Tezos wallet**: Enable user authentication, transaction signing, on-chain asset access, and cryptocurrency usage for in-game purchases. -2. **Access blockchain data**: Retrieve data from the Tezos blockchain, like in-game asset ownership. Manage asset storage through smart contracts or off-chain views, accessing blockchain-stored data. -3. **Invoke smart contracts**: Generate calls to Tezos smart contracts, allowing user-signed transactions for purchasing features or creating achievement-based in-game assets. -4. **Establish true ownership of in-game assets**: Enable users to own and verify in-game assets' authenticity via the Tezos blockchain, using smart contracts for data validation. - -## Get Started - -Begin by watching our [Getting Started video](https://youtu.be/0ouzNVxYI9g). - -This Getting Started guide covers the following five steps essential for using the Tezos SDK in your Unity game or app development: - -1. Installation of the Unity Editor (if not already installed) -2. Installation of the Tezos Integration SDK in the Unity Editor within a new project -3. Obtaining a Tezos-compatible wallet as an app or browser plugin (we'll use the **Temple** wallet for our [Inventory Sample Game](https://opentezos.com/gaming/unity-sdk/inventory-sample-game)) -4. Creating a wallet account for the Ghostnet test network and acquiring test currency from an appropriate faucet -5. Linking this wallet account with the new Unity project - -By following these steps, your Unity app will be connected to the Tezos Ghostnet test network via your specific wallet address. This allows you to invoke specific functionality on smart contracts you've created and deployed to GhostNet, as demonstrated in our [Inventory Sample Game](https://opentezos.com/gaming/unity-sdk/inventory-sample-game). - -Explore the [Inventory Sample Game](https://opentezos.com/gaming/unity-sdk/inventory-sample-game) project and consult our [API Documentation](https://opentezos.com/gaming/unity-sdk/api-documentation/) to learn more about the exposed methods of our SDK, both for establishing wallet connections and for calling specific smart-contract entrypoints and Tezos data-view functions. - -This SDK documentation is designed for users with some familiarity with Unity game development but may have little to no experience with Web3 or Tezos blockchain. If you're well-versed in both domains, you might want to skip "Getting Started" and proceed directly to the [API documentation](https://opentezos.com/gaming/unity-sdk/api-documentation/). Nonetheless, the [Inventory Sample Game](https://opentezos.com/gaming/unity-sdk/inventory-sample-game) can still be valuable for visualizing potential SDK applications in your own game development. - -## Installing the Unity Editor - -:::note -- Install Unity Editor version 2021.3.13 or above -- Enable iOS Build Support, even if you don't plan to build for iOS -::: - -The Tezos SDK has been developed and tested primarily in Unity 2021.3.13. If you're using an earlier version, you must install version 2021.3.13 or above. - -Newer Unity versions can coexist with older ones, allowing you to maintain older games built in previous editor versions. Manage different Unity installations through the **Installs** tab of your **Unity Hub**. This tool helps you track installations, projects, and required **modules** for publishing games or dApps to platforms like Windows, iOS, Android, WebGL, and others. - -If you're new to Unity, download the [Unity editor for free.](https://unity.com/download) The free "personal" Unity editor offers a comprehensive core feature set for creating 2D and 3D games, apps, and environments, including AR, VR, and Web3 development. - -:::warning -The current SDK version requires iOS Build Support, even if you don't plan to build for iOS. This will be fixed in a future update. In the meantime, enable iOS Build Support in the "Installs" tab of your Unity Hub. -::: - -## Installing the Tezos SDK for Unity (Latest) - -### Install from a Git URL - -You can install the UPM package directly from a Git URL. To do this: - -1. Open the [Unity Package Manager](https://docs.unity3d.com/Manual/upm-ui.html) window. -2. Click the add **+** button in the status bar. -3. Select **Add package from git URL** from the add menu. A text box and an Add button will appear. -4. Enter the `https://github.com/trilitech/tezos-unity-sdk.git` Git URL in the text box and click Add. -5. You can also install a specific package version using the URL with the specified version: - - `https://github.com/trilitech/tezos-unity-sdk.git#X.Y.Z` - - Replace `X.Y.Z` with the version you want to install. - - Check all available releases [here](https://github.com/trilitech/tezos-unity-sdk/releases). - - The latest available release version is: [![Last Release](https://img.shields.io/github/v/release/trilitech/tezos-unity-sdk)](https://github.com/trilitech/tezos-unity-sdk/releases/latest) - -For more information about supported protocols, see [Git URLs](https://docs.unity3d.com/Manual/upm-git.html). - -### Install from NPM - -1. Navigate to your project's `Packages` directory. -2. Edit the [project manifest file](https://docs.unity3d.com/Manual/upm-manifestPrj.html) `manifest.json` in a text editor. -3. Ensure `https://registry.npmjs.org/` is part of `scopedRegistries`. - - Make sure `com.trilitech` is included in `scopes`. - - Add `com.trilitech.tezos-unity-sdk` to the `dependencies`, specifying the latest version. - - - A minimal example looks like this. Replace `X.Y.Z` with [the latest released version](https://www.npmjs.com/package/com.trilitech.tezos-unity-sdk), which is currently: [![NPM Package](https://img.shields.io/npm/v/com.trilitech.tezos-unity-sdk?color=blue)](https://www.npmjs.com/package/com.trilitech.tezos-unity-sdk) - - ```json - { - "scopedRegistries": [ - { - "name": "npmjs", - "url": "https://registry.npmjs.org/", - "scopes": [ - "com.trilitech" - ] - } - ], - "dependencies": { - "com.trilitech.tezos-unity-sdk": "X.Y.Z", - ... - } - } - ``` - -4. Return to the Unity Editor and wait for it to finish importing the added package. - -## WebGL Support - -* Open Unity Editor. -* Navigate to Project -> Packages and find the Tezos Unity SDK. -* Double-click the package file WebGLSupport.unitypackage. Project->Packages->Tezos-Unity-SDK. -* The Import Unity Package dialog box displays, with all the items in the package pre-checked, ready to install. -* This action creates WebGL template folders in your Project. Each template is a subfolder within the WebGLTemplates - folder. Each template subfolder contains an index.html file along with any other resources the page needs, such as - images or stylesheets. - -## API Summary - -The [SDK's API](https://opentezos.com/gaming/unity-sdk/api-documentation/) includes seven methods, which, together with the BeaconSDK and Netezos libraries, provide comprehensive access to the Tezos Blockchain for your games: - -1. **ConnectWallet**: Handles wallet pairings using QRCode scans, deep links, or injections, depending on the platform. Supports various Tezos wallets such as Kukai, Umami, or Temple. -2. **DisconnectWallet**: Disconnects the app from the user's wallet. -3. **GetActiveWalletAddress**: Retrieves the Tezos address of the currently active wallet account. -4. **ReadBalance**: Returns the tez balance of the current user. -5. **ReadView**: Calls an off-chain view to obtain data from a smart contract and its storage. -6. **CallContract**: Enables calls to any Tezos contract by specifying the entrypoint, input parameters, and tez amount sent to the contract. -7. **RequestSignPayload**: Requests the user to digitally sign data with their wallet. - -Additional features and data retrieval options from the Netezos SDK are included in this SDK. - -## Dependencies - -The Tezos SDK utilizes modified versions of the following libraries for communication: - -1. **Airgap Beacon SDK**: Interacts with Tezos wallets through the Beacon standard for iOS, Android, and WebGL platforms. -2. **Netezos**: Interacts with Tezos wallets through the Beacon standard for Windows, Linux, and MacOS platforms. Also prepares parameters for smart contract calls and interprets complex data returned by the ReadView method. - -## Supported Platforms - -The SDK supports Windows, Linux, MacOS, iOS, Android, and WebGL platforms. - -:::note More information -For more information you can read detailed [documentation](https://opentezos.com/gaming/unity-sdk/api-documentation/) on OpenTezos. -::: diff --git a/docs/unity.md b/docs/unity.md new file mode 100644 index 000000000..239bf6203 --- /dev/null +++ b/docs/unity.md @@ -0,0 +1,42 @@ +--- +title: Tezos SDK for Unity +authors: Tim McMackin +last_update: + date: 11 January 2024 +--- + +The Tezos SDK for Unity provides tools that let you access user wallets and Tezos in games and other Unity projects. +You can use Tezos via the SDK to: + +- Use a player's Tezos account as their account for a game and their wallet as their way of logging in to the game +- Accept payments from players in tez +- Use Tezos to create game assets, store player inventories, and transfer assets between players +- Verify that users own specific game assets and allow them to sell or share them to other players +- Use Tezos smart contracts as backend logic for games + +## Installation and use + +For a walkthrough of installing and using the SDK in an existing Unity project, see [Quickstart](./unity/quickstart). + +## Tutorial scenes + +The SDK includes tutorial scenes that demonstrate how to use the SDK. +For information about setting up and using the scenes, see [Tutorial scenes](./unity/scenes). + +## SDK objects + +The SDK provides objects that you can use to interact with user wallets and with Tezos. +See [Unity SDK reference](./unity/reference). + +## Dependencies + +The Tezos SDK uses modified versions of the following libraries for communication: + +- **Airgap Beacon SDK**: Interacts with Tezos wallets through the Beacon standard for iOS, Android, and WebGL platforms. +- **Netezos**: Interacts with Tezos wallets through the Beacon standard for Windows, Linux, and MacOS platforms. Also prepares parameters for smart contract calls and interprets complex data returned by the ReadView method. + +The SDK also uses the [Newtonsoft JSON Unity Package](https://docs.unity3d.com/Packages/com.unity.nuget.newtonsoft-json@3.2/manual/index.html). + +## Supported Platforms + +The SDK supports Windows, Linux, MacOS, iOS, Android, and WebGL platforms. diff --git a/docs/unity/prefabs.md b/docs/unity/prefabs.md new file mode 100644 index 000000000..353a8058c --- /dev/null +++ b/docs/unity/prefabs.md @@ -0,0 +1,36 @@ +--- +title: Unity SDK prefabs +sidebar_label: Prefabs +authors: Tim McMackin +last_update: + date: 11 January 2024 +--- + +The Tezos SDK for Unity provides these prefabs: + +## TezosManager + +This prefab sets the metadata for the scene, such as the application name that users see in their wallet applications before connecting to the project. +It also initializes the Tezos SDK for use in the scene and creates an instance of the `TezosSDK.Tezos.Tezos` class, which provides access to the SDK objects such as the [Wallet](./reference/Wallet) and [EventManager](./reference/EventManager) objects. + +Its fields control what users see in their wallet applications before connecting to the project, as shown in this picture of the Inspector panel: + +The Inspector panel, showing information about the project + +## TezosAuthenticator + +This prefab provides code to connect to different kinds of Tezos wallets. + +If you copy this prefab into your scene and run the scene, it shows a QR code or connection buttons that Tezos wallet applications can scan to connect with the application. +Whether it shows the QR code or buttons depends on whether the project is running in standalone, mobile, or WebGL mode. +You can access these features through the prefab and change how the project manages its connection to users' wallets. + +The prefab's `LoginPanel` object includes objects that connect to wallets in different ways: + +- The `QRCode` object shows a QR code that wallet apps can scan to connect +- The `LoginButtonDeepLink` object shows a button that opens a wallet app on a mobile device or a wallet browser extension in a web browser via the Beacon SDK +- The `SocialLoginButton` object shows a button that opens a social wallet, such as Kukai + +For details about how the prefab works, see the file `TezosAuthenticator.cs`. + +For an example of the prefab in use, see the [WalletConnection tutorial scene](./scenes#walletconnection-scene). diff --git a/docs/unity/quickstart.md b/docs/unity/quickstart.md new file mode 100644 index 000000000..dea0105da --- /dev/null +++ b/docs/unity/quickstart.md @@ -0,0 +1,355 @@ +--- +title: Quickstart +authors: Tim McMackin +last_update: + date: 11 January 2024 +--- + +Follow these steps to install the Tezos SDK for Unity in an existing Unity project and start using it. + +These instructions cover: + +- Installing the SDK into an existing Unity project +- Testing that the SDK works in your project +- Connecting to a user's Tezos wallet +- Creating and managing tokens +- Prompting the user to sign messages + +## Installing the SDK + +1. In your Unity project, in the Package Manager panel, click the `+` symbol and then click **Add package from git URL**. + +1. Enter the url `https://github.com/trilitech/tezos-unity-sdk.git` and click **Add**. + + The Package Manager panel downloads and installs the SDK. + You can see its assets in the Project panel under Packages > Tezos Unity SDK. + +1. Ensure that you have a Tezos-compatible wallet configured for the Ghostnet testnet on your mobile device. +For instructions, see [Installing and funding a wallet](../developing/wallet-setup). + +1. If you want to publish the project to WebGL, follow the steps in [Enabling WebGL support](#enabling-webgl-support). + +1. To import the tutorial scenes, see [Scenes](./scenes). + +## Enabling WebGL support + +The Unity SDK provides a WebGL template that you can use to publish Unity projects to run in a web browser. +Follow these steps to set up the Tezos SDK to work with WebGL: + +1. In the Unity Editor, go to the Project panel and expand the **Packages > Tezos Unity SDK > WebGLFrontend** folder. +1. From the `WebGLFrontend/output` folder, copy the `StreamingAssets` and `WebGLTemplates` folders into the `Assets` folder of your project. + +1. Select the AirGap template to use in the WebGL build: + + 1. Click **Edit > Project Settings**. + 1. Go to the **Player** tab. + 1. On the Player tab, go to the **WebGL settings** tab. + 1. Under **Resolution and Presentation**, select the AirGap WebGL template, as shown in this picture: + + The project settings, with the Airgap WebGL template selected + +1. To enable copy and paste in the WebGL build, double-click `_WebGLCopyAndPaste.unitypackage`, which is in the `WebGLFrontend/output` folder of the SDK, to install it. + + This package automatically enables copy and paste on selectable text fields, such as the account address field in the WalletConnection tutorial scene. + +## Connecting to wallets + +Connecting to a user's wallet is a prerequisite to working with Tezos in any application. +Accessing the wallet allows your project to see the tokens in it and to prompt the user to submit transactions, but it does not give your project direct control over the wallet. +Users must still confirm all transactions in their wallet application. + +Using a wallet application in this way saves you from having to implement payment processing and security in your application. +Game developers can also use the wallet and its account as a unique account identifier and as the user's inventory. + +1. Copy the `TezosAuthenticator` and `TezosManager` prefabs to your scene. +These prefabs provide prerequisites to use Tezos in a scene and help connect to accounts. +For more information about them, see [Prefabs](./prefabs). + + The `TezosAuthenticator` prefab automatically adds features that connect to users' wallets. + If you copy these prefabs into your scene and run it, it shows a QR code or connection buttons that Tezos wallet applications can scan to connect with the application. + Whether it shows the QR code or buttons depends on whether the project is running in standalone, mobile, or WebGL mode. + +1. Add features to your project to use the connected account. +For example, the `Tutorials/Common/Scripts/WalletInfoUI.cs` file responds to the `WalletConnected` event, which runs when the user approves the connection in their wallet application. +You can use this event to get the address of the connected account, as in this code: + + ```csharp + private void Start() + { + addressText.text = NOT_CONNECTED_TEXT; + + // Subscribe to events; + TezosManager.Instance.EventManager.WalletConnected += OnWalletConnected; + TezosManager.Instance.EventManager.WalletDisconnected += OnWalletDisconnected; + } + + private void OnWalletConnected(WalletInfo walletInfo) + { + // We can get the address from the wallet + addressText.text = TezosManager.Instance.Wallet.GetWalletAddress(); + // Or from the event data + addressText.text = walletInfo.Address; + } + + private void OnWalletDisconnected(WalletInfo walletInfo) + { + addressText.text = NOT_CONNECTED_TEXT; + } + ``` + + You can use this address as a user's account ID because Tezos account addresses are unique. + +1. To respond to other events, add listeners for the events that the SDK provides. +You can see these events and their return values in the [EventManager object](./reference/EventManager). + +For an example, see the [WalletConnection tutorial scene](./scenes#wallet-connection-scene). + +## Deploying contracts + +Contracts are backend programs that run on the Tezos blockchains. +Smart contracts can do many tasks, but for gaming they have two main purposes: + +- They handle tokens, which are digital assets stored on the blockchain +- They provide backend logic that users can trust because it cannot change + +The ContractAndMinting tutorial scene shows how to deploy a contract from a Unity project. + +The SDK provides a built-in contract that you can use instead of writing your own. +This contract manages different kinds of tokens. + +To deploy the built-in contract, call the [`TokenContract.Deploy()`](./reference/TokenContract#deploy) method and pass a callback function: + +```csharp +public void DeployContract() +{ + TezosManager + .Instance + .Tezos + .TokenContract + .Deploy(OnContractDeployed); +} + +private void OnContractDeployed(string contractAddress) +{ + Debug.Log(contractAddress); +} +``` + +The project sends the deployment transaction to the connected wallet, which must approve the transaction and pay the related fees. +The SDK stores the address of the contract as [`TokenContract.address`](./reference/TokenContract). + +For an example, see the [ContractAndMinting tutorial scene](./scenes/#contractandminting-scene). + +## Creating tokens + +To create a token type, call the contract's `mint` entrypoint and pass these parameters: + +- A callback function to run when the token is created +- The metadata for the token, which includes a name and description, URIs to preview media or thumbnails, and how many decimal places the token can be broken into +- The destination account that owns the new tokens, which can be a user account, this smart contract, or any other smart contract +- The number of tokens to create + +For example, this code creates a token type with a quantity of 100: + +```csharp +// Get the address of the connected wallet +var initialOwner = TezosManager + .Instance + .Wallet + .GetWalletAddress(); + +// To preview the IPFS-hosted image: +// https://ipfs.io/ipfs/QmX4t8ikQgjvLdqTtL51v6iVun9tNE7y7Txiw4piGQVNgK +const string imageAddress = "ipfs://QmX4t8ikQgjvLdqTtL51v6iVun9tNE7y7Txiw4piGQVNgK"; + +// Prepare metadata +var tokenMetadata = new TokenMetadata +{ + Name = "My token", + Description = "Description for my token", + Symbol = "MYTOKEN", + Decimals = "0", + DisplayUri = imageAddress, + ArtifactUri = imageAddress, + ThumbnailUri = imageAddress +}; + +// Call the "mint" entrypoint of the contract +TezosManager + .Instance + .Tezos + .TokenContract + .Mint( + completedCallback: OnTokenMinted, + tokenMetadata: tokenMetadata, + destination: initialOwner, + amount: 100); + +// This callback is triggered after the contract call successfully completes and the resulting transaction is recorded on the blockchain. +private void OnTokenMinted(TokenBalance tokenBalance) +{ + Debug.Log($"Successfully minted token with Token ID {tokenBalance.TokenId}"); +} +``` + +For an example, see the [ContractAndMinting tutorial scene](./scenes/#contractandminting-scene). + +## Transferring tokens + +To transfer tokens, call the contract's `Transfer` entrypoint and pass these parameters: + +- A callback function to run when the transfer is complete +- The account to transfer the tokens to +- The ID of the token +- The amount of tokens to transfer + +This example transfers 12 tokens with the ID 5 to the account in the variable `destinationAccountAddress`. + +```csharp +public void HandleTransfer() +{ + TezosManager + .Instance + .Tezos + .TokenContract + .Transfer( + completedCallback: TransferCompleted, + destination: destinationAccountAddress, + tokenId: 5, + amount: 12); +} + +private void TransferCompleted(string txHash) +{ + Logger.LogDebug($"Transfer complete with transaction hash {txHash}"); +} +``` + +For a complete example, see the [Transfer tutorial scene](./scenes/#transfer-scene). + +## Getting token balances + +To get the tokens that the connected account owns, call the [`API.GetTokensForOwner()`](./reference/API#gettokensforowner) method in a coroutine. +This example prints information about the tokens that the account owns to the log: + +```csharp +private void Start() +{ + // Subscribe to account connection event + TezosManager.Instance.EventManager.WalletConnected += OnWalletConnected; +} + +private void OnWalletConnected(WalletInfo walletInfo) +{ + // Address of the connected wallet + var address = walletInfo.Address; + + // Prepare the coroutine to fetch the tokens + var routine = TezosManager.Instance.Tezos.API.GetTokensForOwner( + OnTokensFetched, // Callback to be called when the tokens are fetched + address, true, 10_000, new TokensForOwnerOrder.ByLastTimeAsc(0)); + + StartCoroutine(routine); +} + +private void OnTokensFetched(IEnumerable tokenBalances) +{ + var walletAddress = TezosManager.Instance.Wallet.GetWalletAddress(); + var contractAddress = TezosManager.Instance.Tezos.TokenContract.Address; + + var tokens = new List(tokenBalances); + + // Filter the tokens by the current contract address + var filteredTokens = tokens.Where(tb => tb.TokenContract.Address == contractAddress).ToList(); + + if (filteredTokens.Count > 0) + { + foreach (var tb in filteredTokens) + { + Debug.Log($"{walletAddress} has {tb.Balance} tokens on contract {tb.TokenContract.Address}"); + Debug.Log(tb.TokenMetadata); + } + } + else + { + Debug.Log($"{walletAddress} has no tokens in the active contract"); + } +} +``` + +## Uploading files to IPFS + +The InterPlanetary File System (IPFS) is a protocol and peer-to-peer network for storing and sharing data in a distributed file system. +Blockchain developers use it to store data such as token images and metadata. + +The SDK provides tools to upload to IPFS by using the [Pinata](https://pinata.cloud/) API, but you can set up IPFS upload in other ways. + +To use the SDK, create instances of the Tezos Configuration and Data Provider Configuration objects and put your Pinata JWT (not the API key or secret) in the `TezosConfigSO` object's Pinata Api Key field. + +To use the SDK, see the code in the `UploadImageButton.cs` file, which handles uploading files in the IPFSUpload scene. +It has a UI upload button that triggers this method, which uses the built-in Pinata uploader to upload the file and get the URL for it: + +```csharp +public void HandleUploadClick() +{ + if (string.IsNullOrEmpty(TezosManager.Instance.Config.PinataApiKey)) + { + Logger.LogError("Can not proceed without Pinata API key."); + return; + } + + var uploader = UploaderFactory.GetPinataUploader(TezosManager.Instance.Config.PinataApiKey); + + var uploadCoroutine = uploader.UploadFile(ipfsUrl => + { + Logger.LogDebug($"File uploaded, url is {ipfsUrl}"); + }); + + StartCoroutine(uploadCoroutine); +} +``` + +For a complete example, see the [IPFSUpload tutorial scene](./scenes#ipfsupload-scene). + +## Signing messages + +You can also use the connection to the user's wallet to prompt them to sign messages. +Signing a message proves that it came from a specific user's wallet because the wallet encrypts the message with the user's account's key. + +For example, this code prompts the user to sign the message "This message came from my account." +Then, the callback verifies that the signature is valid and that it came from the user's account: + +```csharp +string payload = "This message came from my account."; + +private void Start() +{ + // Subscribe to the wallet event + TezosManager.Instance.EventManager.PayloadSigned += OnPayloadSigned; + + TezosManager.Instance.Wallet.RequestSignPayload(SignPayloadType.micheline, payload); +} + +private void OnPayloadSigned(SignResult obj) +{ + // Result is true if the message is signed correctly + // And that it came from the currently-connected wallet + var result = TezosManager.Instance.Wallet.VerifySignedPayload(SignPayloadType.micheline, payload); + + Debug.Log($"Payload verification response: {result}"); +} +``` + +## Changing the RPC node + +As described in [The RPC protocol](../architecture/rpc), Tezos clients including the Unity SDK send transactions to RPC nodes. +By default, the SDK sends requests to a public RPC node that uses the Ghostnet test network, where you can test transactions without spending real tez. +For more information about test networks, see [Using sandboxes and testnets](../developing/testnets). + +If you need to change the RPC node that the SDK uses, such as if the default node is overloaded or if you are ready to send transactions to Mainnet, you can set the RPC node by creating an instance of the [TezosConfigSO scriptable object](./reference/TezosConfigSO) and setting the node in the **Rpc Url Format** field, as in this picture: + +Adding the Pinata API key and the data provider to the TezosConfigSO object + +Then, drag this instance of the TezosConfigSO scriptable object to the Config field of the TezosManager prefab. + +For more examples of how to work with the SDK, see [Tutorial scenes](./scenes). diff --git a/docs/unity/reference.md b/docs/unity/reference.md new file mode 100644 index 000000000..cc9d1b2de --- /dev/null +++ b/docs/unity/reference.md @@ -0,0 +1,20 @@ +--- +title: Unity SDK reference +sidebar_label: Reference +authors: Tim McMackin +last_update: + date: 11 January 2024 +--- + +The Tezos SDK for Unity provides several objects that your Unity project can use to work with Tezos. +These pages provide reference for the most important of these objects: + +- [API object](./reference/API): Provides information about the Tezos blockchain, such as what tokens accounts or contracts control +- [DAppMetadata object](./reference/DAppMetadata): Provides read-only properties that describe the project +- [DataProviderConfigSO scriptable object](./reference/DataProviderConfigSO): Sets the indexer to get information about Tezos from +- [EventManager object](./reference/EventManager): Provides events that you can add listeners to, such as when users connect their wallets +- [TezosConfigSO scriptable object](./reference/TezosConfigSO): Stores information about connecting to Tezos, including the RPC node and Pinata API key to use +- [TokenContract object](./reference/TokenContract): Provides a built-in FA2-compatible smart contract and convenience methods to work with it +- [Wallet object](./reference/Wallet): Provides methods to connect to wallets and send transactions from the connected account + +The SDK also provides Unity prefabs that are prerequisites for the SDK; see [Prefabs](./prefabs). diff --git a/docs/unity/reference/API.md b/docs/unity/reference/API.md new file mode 100644 index 000000000..4279c61e3 --- /dev/null +++ b/docs/unity/reference/API.md @@ -0,0 +1,534 @@ +--- +title: Unity SDK API object +sidebar_label: API object +authors: Tim McMackin +last_update: + date: 6 December 2023 +--- + +The Unity SDK class `TezosSDK.Tezos.API.TezosAPI`, which is available at runtime as the `TezosManager.Instance.Tezos.API` object, provides information about the Tezos blockchain, such as what tokens accounts or contracts control. + +## Properties + +None. + +## Methods + +### `GetTezosBalance()` + +```csharp +IEnumerator GetTezosBalance(Action callback, string address); +``` + +Returns the balance of the specified account address in mutez. + +Example: + +```csharp +public void RunGetTezosBalance() +{ + Debug.Log("Getting balance"); + var routine = TezosManager.Instance.Tezos.API.GetTezosBalance( + callback: HandleTezosBalance, + address: myAddress + ); + StartCoroutine(routine); +} + +private void HandleTezosBalance(ulong balanceMutez) +{ + Debug.Log(balanceMutez/1000000); +} +``` + +### `ReadView()` + +```csharp +IEnumerator ReadView( + string contractAddress, + string entrypoint, + string input, + Action callback); +``` + +Returns the response from a contract [view](../../smart-contracts/views). +Note that the `input` parameter must be a Michelson-encoded object, as in the following example, which passes an integer and string parameter to the view: + +Example: + +```csharp +public void RunReadView() +{ + var input = new MichelinePrim + { + Prim = PrimType.Pair, + Args = new List + { + new MichelineInt(2), + new MichelineString("hello") + } + }.ToJson(); + + var routine = TezosManager.Instance.Tezos.API.ReadView( + contractAddress: TezosManager.Instance.Tezos.TokenContract.Address, + entrypoint: viewName, + input: input, + callback: HandleRunReadView + ); + StartCoroutine(routine); +} + +public void HandleRunReadView(JsonElement viewResponse) +{ + Debug.Log(viewResponse); +} +``` + +### `GetTokensForOwner()` + +```csharp +IEnumerator GetTokensForOwner( + Action> callback, + string owner, + bool withMetadata, + long maxItems, + TokensForOwnerOrder orderBy); +``` + +Gets the tokens that an account owns. + +Example: + +```csharp +public void RunGetTokensForOwner() +{ + var routine = TezosManager.Instance.Tezos.API.GetTokensForOwner( + callback: HandleTokenBalances, + owner: myAddress, + withMetadata: true, + maxItems: 10, + orderBy: new TokensForOwnerOrder.ByLastTimeAsc(0) + ); + StartCoroutine(routine); +} + +private void HandleTokenBalances(IEnumerable tokenBalances) +{ + List tokens = new List(tokenBalances); + foreach (var tb in tokens) + { + Debug.Log($"{tb.Balance} tokens on contract {tb.TokenContract.Address}"); + } +} +``` + +### `GetOwnersForToken()` + +```csharp +IEnumerator GetOwnersForToken( + Action> callback, + string contractAddress, + uint tokenId, + long maxItems, + OwnersForTokenOrder orderBy); +``` + +Gets the accounts that own the specified token. + +Example: + +```csharp +public void RunGetOwnersForToken() +{ + var routine = TezosManager.Instance.Tezos.API.GetOwnersForToken( + callback: HandleTokenOwners, + contractAddress: TezosManager.Instance.Tezos.TokenContract.Address, + tokenId: 0, + maxItems: 10, + orderBy: new OwnersForTokenOrder.ByLastTimeAsc(0) + ); + StartCoroutine(routine); +} + +private void HandleTokenOwners(IEnumerable tokenBalances) +{ + List tokens = new List(tokenBalances); + foreach (var tb in tokens) + { + Debug.Log($"{tb.Balance} tokens on contract {tb.TokenContract.Address}"); + } +} +``` + +### `GetOwnersForContract()` + +```csharp +IEnumerator GetOwnersForContract( + Action> callback, + string contractAddress, + long maxItems, + OwnersForContractOrder orderBy); +``` + +Gets the accounts that own tokens on the specified contract. + +Example: + +```csharp +public void RunGetOwnersForContract() +{ + var routine = TezosManager.Instance.Tezos.API.GetOwnersForContract( + callback: HandleOwnersForContract, + contractAddress: TezosManager.Instance.Tezos.TokenContract.Address, + maxItems: 10, + orderBy: new OwnersForContractOrder.ByLastTimeAsc(0) + ); + StartCoroutine(routine); +} + +private void HandleOwnersForContract(IEnumerable tokenBalances) +{ + List tokens = new List(tokenBalances); + foreach (var tb in tokens) + { + Debug.Log($"{tb.Owner} owns {tb.Balance} tokens on contract {tb.TokenContract.Address}"); + } +} +``` + +### `IsHolderOfContract()` + +```csharp +IEnumerator IsHolderOfContract( + Action callback, + string wallet, + string contractAddress); +``` + +Returns true if the specified account owns any token in the specified contract. + +Example: + +```csharp +public void GetIsHolderOfContract() +{ + var routine = TezosManager.Instance.Tezos.API.IsHolderOfContract( + callback: HandleIsHolderOfContract, + wallet: myAddress, + contractAddress: TezosManager.Instance.Tezos.TokenContract.Address + ); + StartCoroutine(routine); +} + +private void HandleIsHolderOfContract(bool response) +{ + Debug.Log(response); +} +``` + +### `IsHolderOfToken()` + +```csharp +IEnumerator IsHolderOfToken( + Action callback, + string wallet, + string contractAddress, + uint tokenId); +``` + +Returns true if the specified account owns the specified token in the specified contract. + +Example: + +```csharp +public void GetIsHolderOfToken() +{ + var routine = TezosManager.Instance.Tezos.API.IsHolderOfToken( + callback: HandleIsHolderOfToken, + wallet: myAddress, + contractAddress: TezosManager.Instance.Tezos.TokenContract.Address, + tokenId: 0 + ); + StartCoroutine(routine); +} + +private void HandleIsHolderOfToken(bool response) +{ + Debug.Log(response); +} +``` + +### `GetTokenMetadata()` + +```csharp +IEnumerator GetTokenMetadata( + Action callback, + string contractAddress, + uint tokenId); +``` + +Gets the metadata for the specified token. + +Example: + +```csharp +public void RunGetTokenMetadata() +{ + var routine = TezosManager.Instance.Tezos.API.GetTokenMetadata( + callback: HandleGetTokenMetadata, + contractAddress: TezosManager.Instance.Tezos.TokenContract.Address, + tokenId: 0 + ); + StartCoroutine(routine); +} + +private void HandleGetTokenMetadata(JsonElement tokenMetadata) +{ + Debug.Log(tokenMetadata.GetProperty("name")); +} +``` + +### `GetContractMetadata()` + +```csharp +public IEnumerator GetContractMetadata( + Action callback, + string contractAddress); +``` + +Gets the metadata for the specified contract. +Most contracts, including the built-in FA2 contract, do not have metadata. + +Example: + +```csharp +public void RunGetContractMetadata() +{ + var routine = TezosManager.Instance.Tezos.API.GetContractMetadata( + callback: HandleGetContractMetadata, + contractAddress: TezosManager.Instance.Tezos.TokenContract.Address + ); + StartCoroutine(routine); +} + +private void HandleGetContractMetadata(JsonElement contractMetadata) +{ + Debug.Log(contractMetadata); +} +``` + +### `GetTokensForContract()` + +```csharp +IEnumerator GetTokensForContract( + Action> callback, + string contractAddress, + bool withMetadata, + long maxItems, + TokensForContractOrder orderBy); +``` + +Gets the tokens in a contract. + +Example: + +```csharp +public void RunGetTokensForContract() +{ + timesCalled = 0; + var routine = TezosManager.Instance.Tezos.API.GetTokensForContract( + callback: HandleGetTokensForContract, + contractAddress: TezosManager.Instance.Tezos.TokenContract.Address, + withMetadata: true, + maxItems: 10, + orderBy: new TokensForContractOrder.ByLastTimeAsc(0) + ); + StartCoroutine(routine); +} + +private void HandleGetTokensForContract(IEnumerable tokenList) +{ + List tokens = new List(tokenList); + foreach (var tk in tokens) + { + Debug.Log(tk.TokenId); + } +} +``` + +The callback returns a list of tokens, but not all of the fields in the `Token` objects are populated by default. +You can populate the fields you want to retrieve by editing the `GetTokensForContract` method of the `TezosSDK.Tezos.API.TezosAPI` class. + +The methods in this class retrieves information about Tezos via the [TZKT](https://tzkt.io/) block explorer. +To change the information that the `GetTokensForContract` method retrieves, update the URL to add fields. + +The default URL looks like this: + +```csharp +var url = + $"tokens?contract={contractAddress}&select=contract,tokenId as token_id" + + $"{(withMetadata ? ",metadata as token_metadata" : "")},holdersCount as holders_count,id," + + $"lastTime as last_time&{sort}&limit={maxItems}"; +``` + +To get the total supply of each token type, add the `totalSupply` field to the URL, like this: + +```csharp +var url = + $"tokens?contract={contractAddress}&select=contract,tokenId as token_id" + + $"{(withMetadata ? ",metadata as token_metadata" : "")},holdersCount as holders_count,id," + + $"totalSupply as total_supply," + + $"lastTime as last_time&{sort}&limit={maxItems}"; +``` + +Now when you run the `GetTokensForContract` method, the data passed to the callback includes the total supply of each token: + +```csharp +private void HandleGetTokensForContract(IEnumerable tokenList) +{ + List tokens = new List(tokenList); + foreach (var tk in tokens) + { + Debug.Log($"Token ID {tk.TokenId} has total supply {tk.TotalSupply} among {tk.HoldersCount} holders"); + } +} +``` + +For information about what fields you can add to this URL, see the [TZKT API reference](https://api.tzkt.io/). + +### `GetOperationStatus()` + +```csharp +IEnumerator GetOperationStatus( + Action callback, + string operationHash); +``` + +Returns true if the specified operation was successful, false if it failed, or null (or HTTP 204) if it doesn't exist. + +Example: + +```csharp +public void HandleTransfer() +{ + TezosManager + .Instance + .Tezos + .TokenContract + .Transfer( + completedCallback: TransferCompleted, + destination: address.text, + tokenId: int.Parse(id.text), + amount: int.Parse(amount.text)); +} + +private void TransferCompleted(string txHash) +{ + Debug.Log($"Transfer complete with transaction hash {txHash}"); + var routine = TezosManager.Instance.Tezos.API.GetOperationStatus( + callback: HandleGetOperationStatus, + operationHash: txHash + ); + StartCoroutine(routine); +} + +private void HandleGetOperationStatus(bool? result) +{ + Debug.Log(result); +} +``` + +### `GetLatestBlockLevel()` + +```csharp +IEnumerator GetLatestBlockLevel( + Action callback); +``` + +Returns the block level, or the number of blocks since the genesis block. + +Example: + +```csharp +public void RunGetLatestBlockLevel() +{ + var routine = TezosManager.Instance.Tezos.API.GetLatestBlockLevel( + callback: HandleGetLatestBlockLevel + ); + StartCoroutine(routine); +} + +private void HandleGetLatestBlockLevel(int blockLevel) +{ + Debug.Log(blockLevel); +} +``` + +### `GetAccountCounter()` + +```csharp +IEnumerator GetAccountCounter( + Action callback, + string address); +``` + +Returns the counter for implicit accounts, which is a unique number that you can use to ensure that transactions are not duplicated. + +Example: + +```csharp +public void RunGetAccountCounter() +{ + var routine = TezosManager.Instance.Tezos.API.GetAccountCounter( + callback: HandleGetAccountCounter, + address: myAddress + ); + StartCoroutine(routine); +} + +private void HandleGetAccountCounter(int counter) +{ + Debug.Log(counter); +} +``` + +### `GetOriginatedContractsForOwner()` + +```csharp +IEnumerator GetOriginatedContractsForOwner( + Action> callback, + string creator, + string codeHash, + long maxItems, + OriginatedContractsForOwnerOrder orderBy); +``` + +Gets the contracts that the specified account deployed (originated). +Optionally, you can pass the hash of a contract to return only contracts that match that hash. +For example, the hash of the contract in the [`TokenContract`](./TokenContract) object is in the `Resources/Contracts/FA2TokenContractCodeHash.txt` file. + +Example: + +```csharp +public void RunGetOriginatedContractsForOwner() +{ + var routine = TezosManager.Instance.Tezos.API.GetOriginatedContractsForOwner( + callback: HandleGetOriginatedContractsForOwner, + creator: myAddress, + codeHash: "", + maxItems: 10, + orderBy: new OriginatedContractsForOwnerOrder.ByLastActivityTimeAsc(0) + + ); + StartCoroutine(routine); +} + +private void HandleGetOriginatedContractsForOwner(IEnumerable contractList) +{ + List contracts = new List(contractList); + foreach (var contract in contracts) + { + Debug.Log(contract.Address); + } +} +``` diff --git a/docs/unity/reference/DAppMetadata.md b/docs/unity/reference/DAppMetadata.md new file mode 100644 index 000000000..2e9a3dc4f --- /dev/null +++ b/docs/unity/reference/DAppMetadata.md @@ -0,0 +1,22 @@ +--- +title: Unity SDK DAppMetadata object +sidebar_label: DAppMetadata object +authors: Tim McMackin +last_update: + date: 6 December 2023 +--- + +The Unity SDK class `TezosSDK.Tezos.DAppMetadata`, which is available at runtime as the `TezosManager.Instance.Tezos.DAppMetadata` object, provides read-only properties that provide access to the values that you set on the `TezosManager` prefab in the Unity Editor. + +## Properties + +These properties are read-only: + +- `Name`: The name of the project, which is shown in wallet applications when users connect to the project +- `Url`: The home page of the project +- `Icon`: The URL to a favicon for the project +- `Description`: A description of hte project + +## Methods + +None. diff --git a/docs/unity/reference/DataProviderConfigSO.md b/docs/unity/reference/DataProviderConfigSO.md new file mode 100644 index 000000000..8f179966b --- /dev/null +++ b/docs/unity/reference/DataProviderConfigSO.md @@ -0,0 +1,23 @@ +--- +title: DataProviderConfigSO scriptable object +authors: Tim McMackin +last_update: + date: 11 January 2024 +--- + +The DataProviderConfigSO scriptable object sets the indexer that the SDK uses to get information about Tezos, such as an account's token balances. +Some Tezos dApps use a custom indexer to provide specific information that they need. + +To use this object, create an instance of it, put your information in its fields, and then drag this instance to the Data Provider Config field of the [TezosConfigSO scriptable object](./TezosConfigSO) object, as in this picture: + +Adding the Pinata API key and the data provider to the TezosConfigSO object + +## Properties + +- `Script`: The attached script that implements the object +- `Network`: A variable that lets you select which network to use, such as Tezos Mainnet or the Ghostnet testnet +- `Base Url Format`: The URL of the indexer to use; this value replaces the variable `{network}` with the value of the `Network` field +- `Request Timeout Seconds`: The time in seconds to wait for a response from the indexer +- `Documentation Url`: A link to the API reference for the indexer + +For more information about indexers, see [Indexers](../../developing/information/indexers). diff --git a/docs/unity/reference/EventManager.md b/docs/unity/reference/EventManager.md new file mode 100644 index 000000000..e5e7cb125 --- /dev/null +++ b/docs/unity/reference/EventManager.md @@ -0,0 +1,86 @@ +--- +title: Unity SDK EventManager object +sidebar_label: EventManager object +authors: Tim McMackin +last_update: + date: 28 December 2023 +--- + +The Unity SDK class `TezosSDK.Beacon.WalletEventManager`, which is available at runtime as the `TezosManager.Instance.EventManager` object, provides events that you can add listeners to. + +These events are asynchronous. +For example, if your project makes multiple calls to smart contracts, the `ContractCallCompleted` event runs multiple times, not necessarily in the order that you called the contracts. + +## Example + +This code adds a listener for the `WalletConnected` and `WalletDisconnected` events: + +```csharp +private void Start() +{ + TezosManager.Instance.EventManager.WalletConnected += OnWalletConnected; + TezosManager.Instance.EventManager.WalletDisconnected += OnWalletDisconnected; +} + +private void OnWalletConnected(WalletInfo walletInfo) +{ + Debug.Log(walletInfo.Address); +} + +private void OnWalletDisconnected(WalletInfo walletInfo) +{ + Debug.Log(walletInfo.Address); + Debug.Log("Wallet disconnected."); +} +``` + +## Events + +### `public event Action WalletConnected` + +Runs when a wallet connects successfully. +Returns a `TezosSDK.Beacon.WalletInfo` object with information that includes the address of the connected account. + +### `public event Action WalletConnectionFailed` + +Runs when a connection to a wallet fails. +Returns a `TezosSDK.Beacon.ErrorInfo` object with an error message. + +### `public event Action WalletDisconnected` + +Runs when a wallet disconnects successfully. +Returns a `TezosSDK.Beacon.WalletInfo` object with information that includes the address of the connected account. + +### `public event Action ContractCallCompleted` + +Runs when a call to a smart contract is confirmed on the blockchain. +Returns a `TezosSDK.Beacon.OperationResult` object with the hash of the transaction. + +### `public event Action ContractCallFailed` + +Runs when a call to a smart contract fails. +Returns a `TezosSDK.Beacon.ErrorInfo` object with an error message. + +### `public event Action ContractCallInjected` + +Runs when a call to a smart contract is sent to Tezos but before it has been included in a block and confirmed. +Returns a `TezosSDK.Beacon.OperationResult` object with the hash of the transaction. + +### `public event Action HandshakeReceived` + +Runs when a handshake with a user's wallet application is received. +Returns a `TezosSDK.Beacon.HandshakeData` object with the data that applications need to connect to the wallet. + +### `public event Action PairingCompleted` + +Runs when the user's wallet is connected to the project but before the user has approved the connection in the wallet app. +Returns a `TezosSDK.Beacon.PairingDoneData` object with details about the pairing, such as the dApp's public key and the timestamp of pairing completion. + +### `public event Action PayloadSigned` + +Runs when the user signs a payload. +Returns a `TezosSDK.Beacon.PairingDoneData` object with the signed payload. + +### `public event void SDKInitialized` + +Runs when the SDK loads. diff --git a/docs/unity/reference/TezosConfigSO.md b/docs/unity/reference/TezosConfigSO.md new file mode 100644 index 000000000..23bfdb4fc --- /dev/null +++ b/docs/unity/reference/TezosConfigSO.md @@ -0,0 +1,23 @@ +--- +title: TezosConfigSO scriptable object +authors: Tim McMackin +last_update: + date: 11 January 2024 +--- + +The TezosConfigSO scriptable object sets the RPC node that the SDK sends Tezos transactions to. + +To use this object, create an instance of it, put your information in its fields, and then drag this instance of the TezosConfigSO scriptable object to the Config field of the TezosManager prefab. + +Adding the Pinata API key and the data provider to the TezosConfigSO object + +## Properties + +- `Script`: The attached script that implements the object +- `Network`: A variable that lets you select which network to use, such as Tezos Mainnet or the Ghostnet testnet +- `RPC Url Format`: The URL of the RPC node to use; this value replaces the variable `{network}` with the value of the `Network` field +- `Request Timeout Seconds`: The time in seconds to wait for a response from the indexer +- `Pinata Api Key`: The Pinata JWT (not the API key or secret key) to use to upload files and data to IPFS +- `Data Provider Config`: The instance of the [DataProviderConfig](./DataProviderConfigSO) scriptable object to use + +For more information about RPC nodes, see [The RPC protocol](../../architecture/rpc). diff --git a/docs/unity/reference/TokenContract.md b/docs/unity/reference/TokenContract.md new file mode 100644 index 000000000..8abb83460 --- /dev/null +++ b/docs/unity/reference/TokenContract.md @@ -0,0 +1,202 @@ +--- +title: Unity SDK TokenContract object +sidebar_label: TokenContract object +authors: Tim McMackin +last_update: + date: 6 December 2023 +--- + +The Unity SDK class `TezosSDK.Tezos.API.Models.TokenContract`, which is available at runtime as the `TezosManager.Instance.Tezos.TokenContract` object, provides a built-in FA2-compatible smart contract and convenience methods to work with it. + +For information about FA2 contracts and tokens, see [FA2 tokens](../../architecture/tokens/FA2). + +The Michelson source code of the built-in contract is in the `Resources/Contracts` folder of the SDK. + +## Properties + +These properties are populated after you deploy the contract with the `Deploy()` method: + +- `Address`: The address of the deployed contract +- `TokensCount`: The total number of token types in the contract +- `LastActivityTime`: The timestamp of the last time tokens were minted or transferred + +## Entrypoints + +The built-in contract has the entrypoints that the FA2 standard requires and a few other entrypoints for the convenience of developers. + +- `transfer`: Transfers tokens from a source account to one or more destination accounts. +Its parameters are the address of the source account and a list of destination accounts, each with the token ID and amount to transfer. +For a simpler way to transfer tokens, see the [`Transfer()`](#transfer) method. + +- `mint`: Creates a token type and one or more tokens of that type. +Its parameters are the address of the owner of the new tokens, the amount of tokens to create, and the metadata for the token type. +This entrypoint can be called only by the current administrator account. +For a simpler way to create tokens, see the [`Mint()`](#mint) method. + +- `balance_of`: Sends information about an owner's token balance to another contract. +Its parameters are a callback contract that accepts a list of token IDs and the amount that the specified account owns. +For a simpler way to get information about token ownership, see the [`API.GetTokensForOwner()`](./API#gettokensforowner) method. + +- `update_operators`: Adds or removes operators for the specified token owners and token IDs. +Its parameters are a list of commands to add or remove operators for token owners and IDs. +For information about operators, see [Operators](../../architecture/tokens/FA2#operators). + +- `set_administrator`: Changes the account that can mint tokens. +Its parameter is the address of the new administrator account. +This entrypoint can be called only by the current administrator account. + +- `set_metadata`: Creates or changes a metadata field in the specified contract's storage. +Its parameters are a key-value pair for the new or updated metadata value. +This metadata is a value in the contract's storage, which is different from the metadata returned by the [`API.GetContractMetadata()`](./API#getcontractmetadata) method. +This entrypoint can be called only by the current administrator account. + +- `set_pause`: Sets the value of the `paused` storage field. +When this field is set to true, tokens can be minted but not transferred between accounts. +This entrypoint can be called only by the current administrator account. + + +For information about entrypoints, see [entrypoints](../../smart-contracts/entrypoints). + +## Methods + +### Constructors + +```csharp +new TokenContract(); +``` + +This constructor is for internal use. +To deploy the built-in contract, use the `Deploy()` method. + +```csharp +new TokenContract(string address); +``` + +Initializes a `TokenContract` object with a copy of the built-in contract that you have deployed already. + +To deploy the built-in contract, use the [`Deploy()`](#deploy) method. + +### `Deploy()` + +```csharp +void Deploy(Action completedCallback) +``` + +Deploys (originates) a contract based on the built-in contract, including prompting the connected wallet to pay the origination fees. + +The SDK stores the address of the contract with the Unity [PlayerPrefs](https://docs.unity3d.com/ScriptReference/PlayerPrefs.html). + +Parameters: + +- `completedCallback`: A callback method to run when the contract is deployed, which receives the address of the new contract + +Example: + +```csharp +public void HandleDeploy() +{ + TezosManager.Instance.Tezos.TokenContract.Deploy(OnContractDeployed); +} + +private void OnContractDeployed(string contractAddress) +{ + Debug.Log(contractAddress); +} +``` + +### `Mint()` + +```csharp +void Mint( + Action completedCallback, + TokenMetadata tokenMetadata, + string destination, + int amount) +``` + +Calls the `Mint` entrypoint of the contract to create a token type and mint tokens. + +Parameters: + +- `completedCallback`: A callback method to run when the token is minted, which receives a `TokenBalance` object with information about the new token +- `tokenMetadata`: A `TokenMetadata` object with information about the new token +- `destination`: The account that owns the new token, which can be a user account or a smart contract account +- `amount`: The number of tokens of the new type to create + +Example: + +```csharp +var initialOwner = TezosManager + .Instance + .Wallet + .GetWalletAddress(); + +const string imageAddress = "ipfs://QmX4t8ikQgjvLdqTtL51v6iVun9tNE7y7Txiw4piGQVNgK"; + +var tokenMetadata = new TokenMetadata +{ + Name = "My token", + Description = "Description for my token", + Symbol = "MYTOKEN", + Decimals = "0", + DisplayUri = imageAddress, + ArtifactUri = imageAddress, + ThumbnailUri = imageAddress +}; + +TezosManager + .Instance + .Tezos + .TokenContract + .Mint( + completedCallback: OnTokenMinted, + tokenMetadata: tokenMetadata, + destination: initialOwner, + amount: 100); + +private void OnTokenMinted(TokenBalance tokenBalance) +{ + Debug.Log($"Successfully minted token with Token ID {tokenBalance.TokenId}"); +} +``` + +### `Transfer()` + +```csharp +void Transfer( + Action completedCallback, + string destination, + int tokenId, + int amount) +``` + +Transfers tokens from the currently connected account to the destination account. + +Parameters: + +- `completedCallback`: A callback method to run when the token is minted, which receives the hash of the transfer transaction +- `destination`: The account to send the token to, which can be a user account or a smart contract account +- `tokenId`: The ID of the token to transfer +- `amount`: The number of tokens to transfer + +Example: + +```csharp +public void HandleTransfer() +{ + TezosManager + .Instance + .Tezos + .TokenContract + .Transfer( + completedCallback: TransferCompleted, + destination: address.text, + tokenId: int.Parse(id.text), + amount: int.Parse(amount.text)); +} + +private void TransferCompleted(string txHash) +{ + Logger.LogDebug($"Transfer complete with transaction hash {txHash}"); +} +``` diff --git a/docs/unity/reference/Wallet.md b/docs/unity/reference/Wallet.md new file mode 100644 index 000000000..7a9c8c8d1 --- /dev/null +++ b/docs/unity/reference/Wallet.md @@ -0,0 +1,144 @@ +--- +title: Unity SDK Wallet object +sidebar_label: Wallet object +authors: Tim McMackin +last_update: + date: 28 December 2023 +--- + +The Unity SDK class `TezosSDK.Tezos.Wallet.WalletProvider`, which is available at runtime as `TezosManager.Instance.Wallet`, provides methods to connect to wallets and send transactions from the connected account. + +## Properties + +### `IsConnected` + +Returns true if a wallet is currently connected. + +### `HandshakeData` + +An object with a field named `PairingData` with the data that applications need to connect to the wallet. + +## Methods + +### `Connect()` + +```csharp +void Connect(WalletProviderType walletProvider, bool withRedirectToWallet) +``` + +Sends a request to a user's wallet to connect to the application. + +Parameters: + + - `walletProvider`: The type of wallet to connect to, including `WalletProviderType.beacon` for TZIP-10 wallets (most Tezos wallets) and `WalletProviderType.kukai` for Kukai wallets. + - `withRedirectToWallet`: When running on a mobile platform, whether to open the connected mobile app after connecting to a wallet. + +This method triggers the `WalletConnected` or `WalletConnectionFailed` events, depending on whether the connection was successful or not. + +When the `walletProvider` parameter is set to `WalletProviderType.beacon`, this method automatically picks the correct way to connect to wallets: + +- In WebGL applications, it uses the `TezosSDK.Beacon.BeaconConnectorWebGl` class to trigger the browser to connect to a wallet app in a browser plugin. +- In all other applications, it uses the `TezosSDK.Beacon.BeaconConnectorDotNet` class to generate a QR code to connect to a wallet app on a mobile device or use a "deep link" to connect to a wallet on the same mobile device that is running the application. + +When the `walletProvider` parameter is set to `WalletProviderType.kukai` in a WebGL application, it triggers the web browser to open the user's Kukai wallet. +This type of connection is appropriate only for WebGL applications. + + + +### `Disconnect()` + +```csharp +void Disconnect() +``` + +Disconnects from the currently connected wallet. + +This method triggers the `WalletDisconnected` event. + +### `GetWalletAddress()` + +```csharp +void GetWalletAddress() +``` + +Returns the address (public key hash) of the currently connected account, or NULL if no wallet is connected. + +### `RequestSignPayload()` + +```csharp +public void RequestSignPayload( + SignPayloadType signingType, + string payload) +``` + +Sends a request to the connected wallet to sign a payload string. + +Parameters: + + - `signingType`: The type of payload, such as raw, operation or micheline. + - `payload`: The payload to send to the wallet to sign. + + + +Signing a message proves that it came from a specific user's wallet because the wallet encrypts the message with the user's account's key. +For example, this code prompts the user to sign the message "This message came from my account." + +```csharp +string payload = "This message came from my account."; + +TezosManager.Instance.EventManager.PayloadSigned += OnPayloadSigned; +TezosManager.Instance.Wallet.RequestSignPayload(SignPayloadType.micheline, payload); +``` + +### `VerifySignedPayload()` + +```csharp +bool VerifySignedPayload(SignPayloadType signingType, string payload) +``` + +Returns true if most recent response to `RequestSignPayload` matches the specified payload and is properly signed. + +### `CallContract()` + +```csharp +void CallContract( + string contractAddress, + string entryPoint, + string input, + ulong amount = 0); +``` + +Calls the specified entrypoint of the specified contract. + +This method triggers the `ContractCallInjected` event if the call is successfully sent to Tezos. +Then it triggers `ContractCallCompleted` or `ContractCallFailed` events, depending on whether the call succeeded or failed. + + + +### `OriginateContract()` + +```csharp +void OriginateContract( + string script, + string delegateAddress); +``` + +Deploys (originates) the specified contract. + +To use this method, you must compile a contract to Michelson in a JSON file. +For an example, see the code of the built-in contract in `Resources/Contracts`. + +The optional `delegateAddress` parameter is the address of the account to delegate the contract's tez to. +For more information, see [Delegation](../../smart-contracts/delegation). + +This method triggers the `ContractCallInjected` event if the call is successfully sent to Tezos. +Then it triggers `ContractCallCompleted` or `ContractCallFailed` events, depending on whether the origination operation succeeded or failed. diff --git a/docs/unity/scenes.md b/docs/unity/scenes.md new file mode 100644 index 000000000..7a27b7864 --- /dev/null +++ b/docs/unity/scenes.md @@ -0,0 +1,270 @@ +--- +title: Unity SDK tutorial scenes +sidebar_label: Tutorial scenes +authors: Tim McMackin +last_update: + date: 11 January 2024 +--- + +The SDK includes tutorial scenes that demonstrate how to use the SDK. + +Before using any of the scenes, install a Tezos-compatible wallet on a mobile device and get some test tez tokens that you can use to pay transaction fees. +For instructions, see [Installing and funding a wallet](./developing/wallet-setup). + +## Setup instructions + +After you have installed the SDK according to the instructions in the [Quickstart](./quickstart), you can import the tutorial scenes from the Package Manager panel: + +1. In the Package Manager panel, click the Tezos Unity SDK package. + +1. In the package information, go to the **Samples** tab. + +1. Under **Tutorials**, click **Import**. + +1. In the Project panel, expand **Assets > Samples > Tezos Unity SDK > [SDK version number] > Tutorials**. + +1. Add the tutorial scenes to the build settings: + + 1. Click **File > Build Settings**. + + 1. Drag these scenes from the Project panel to the **Scenes in Build** list: + + - `Tutorials/ContractAndMinting/_ContractAndMinting` + - `Tutorials/IPFSUpload/_IPFSUpload` + - `Tutorials/TransferToken/_TransferToken` + - `Tutorials/WalletConnection/_WalletConnection` + + The Build Settings window looks like this: + + ![The Build Settings window, showing the tutorial scenes that are included in the build](/img/unity/unity-tutorial-scene-build.png) + + 1. Close the Build Settings window. + +1. Optional: To use the IPFSUpload scene, set up your Pinata key as described in [IPFSUpload scene](#ipfsupload-scene). + +1. In the Tutorials folder, double-click the **_Tutorials** scene. + +1. Click the **Play** button to start the scene. + +The Tutorials scene shows links to the other tutorial scenes. +Click a link to run a scene. +For more information about these scenes, see the sections below. + +## Tutorials scene + +This scene includes buttons that link to the other scenes. + +## Wallet Connection scene + +This scene shows how to to use the TezosAuthenticator prefab to connect to a user's wallet and get information about their account. + +The scene uses the platform type to determine how to connect to a user's wallet. +In the TezosAuthenticator `SetPlatformFlags` function, it checks what platform it is running on: + +```csharp +private void SetPlatformFlags() +{ + _isMobile = Application.platform == RuntimePlatform.IPhonePlayer || + Application.platform == RuntimePlatform.Android; + _isWebGL = Application.platform == RuntimePlatform.WebGLPlayer; +} +``` + +Then based on the platform, it shows different buttons for different connection types: + +```csharp +// Activate deepLinkButton when on mobile or WebGL, but not authenticated +deepLinkButton.SetActive(_isMobile || _isWebGL); + +// Activate socialLoginButton only when on WebGL and not authenticated +socialLoginButton.SetActive(_isWebGL); + +// Activate qrCodePanel only on standalone and not authenticated +qrCodePanel.SetActive(!_isMobile && !_isWebGL); +``` + +These buttons correspond to the ways that the SDK can connect to wallets: + +- For mobile and WebGL platforms, the scene shows a button that links directly to a wallet app, such as a browser plugin or mobile app +- For WebGL platforms, the scene shows a button that links to social wallets, such as Kukai +- For standalone platforms, the scene shows a QR code that you can scan in any Tezos-compatible wallet app + +This picture of the Wallet Connection scene in standalone mode shows the QR code automatically generated by the TezosAuthenticator prefab: + +The start of the WalletConnection scene, with no account information, showing a QR code + +This picture of the Wallet Connection scene in WebGL mode shows the deep link and social connection buttons: + +The start of the WalletConnection scene, with no account information, showing deep link and social connection buttons + +These UI elements call the [`Wallet.Connect()`](./reference/Wallet#connect) method with the `walletProvider` parameter set to `WalletProviderType.beacon` for the direct links or QR code connections and the `walletProvider` parameter set to `WalletProviderType.kukai` for the social wallet connections. + +After the user approves the connection in the wallet, the scene shows the address of the connected account and its balance, as in the following picture. +At the bottom of the scene there is a logout button that closes the connection. + +The Wallet Connection scene with a connected account + +## ContractAndMinting scene + +This scene shows how to deploy a smart contract to Tezos and create tokens with it. + +A _smart contract_ is a program stored on the blockchain. +Smart contracts can do many things, but the main thing that game developers use them for is to manage _tokens_, which are assets that are stored on Tezos. +In this case, the smart contract keeps track of tokens, their metadata, and who owns them. + +The SDK comes with a sample smart contract that allows a Unity project to create tokens. +You can customize these tokens, give them to users, and treat them like the players' in-game inventories. + +Like the Wallet Connection scene, you must first connect to a wallet. +Then the scene shows the address of the connected account and enables the "Deploy Contract" and "Mint Token" buttons. + +When you click "Deploy Contract," your connected wallet prompts you to confirm the transaction and pay the transaction fees. +Because you are connected to the test network, these are worthless testnet tokens and not real currency. +This process can take some time. + +The scene calls the [`TokenContract.Deploy()`](./reference/TokenContract#deploy) method to deploy the contract to Tezos. + +When you confirm the transaction in the wallet app, you must wait for the contract to be deployed on Tezos. +The log in the Console panel shows a message that looks like `Received operation with hash oopFjLYGTbZTEFsTh4p1YPnHR1Up1SNnvE5xk2SRaGH6PZ4ry56`, which is the address of the Tezos transaction that deployed the contract. +This process can take a few minutes. + +For example, this is what the transaction looks like in the Temple wallet: + +Approving the contract deployment transaction in the wallet app + +When the contract is deployed, the project updates to show the address of the contract, which starts with `KT1`. +The project remembers the contract if you reload the scene later. +To see information about the deployed contract, copy this address and put it into a block explorer such as [Better Call Dev](https://better-call.dev/) or [tzkt.io](https://tzkt.io/). + +The block explorer shows information about the contract, including recent transactions, its source code, and the tokens it controls and their owners. +Currently, the block explorer shows only the origination transaction, which deployed the contract: + +The newly originated contract on the block explorer + +Now you can go back to the Simulation panel in the Unity Editor and click "Mint Token." +The project gets approval in your wallet and then sends a transaction to the smart contract to create (mint) a token. +Like the deployment transaction, it can take time for the transaction to complete and be confirmed on Tezos. + +When the mint transaction is complete, the "Tokens Count" text in the scene updates to show the number of token types that have been minted with this contract. +The mint process creates a random number of tokens with this type. +Your tokens can have a quantity of 1 to make them unique or a larger quantity to represent an amount of something. + +You can also see the mint transaction on the block explorer. +Because the contract follows the FA2 standard for tokens, the block explorer also shows the tokens and information about them, as in this picture: + +The new token on the block explorer + +The tokens that this scene creates have randomly generated metadata. +To change the metadata, open the `TezosSDK/Examples/Contract/Scripts/MintToken.cs` file. +The file's `HandleMint` function creates the token by generating random numbers, creating a metadata object for the token, and using the [`TokenContract.Mint()`](./reference/TokenContract#mint) method to send the mint transaction to the contract: + +```csharp +public void HandleMint() +{ + var tokenMetadata = CreateRandomTokenMetadata(); + var destinationAddress = TezosManager.Instance.Wallet.GetWalletAddress(); + var randomAmount = new Random().Next(1, 1024); + + TezosManager.Instance.Tezos.TokenContract.Mint(OnTokenMinted, tokenMetadata, destinationAddress, randomAmount); +} +``` + +In your projects, you can set the metadata to store information about what the token represents. +For more information about creating tokens with Tezos, see [Tokens](../architecture/tokens) and the tutorials [Create an NFT](../tutorials/create-an-nft) and [Build an NFT marketplace](../../tutorials/build-an-nft-marketplace). + + +## Transfer scene + +This scene shows how to transfer tokens between accounts. + +Like the Wallet Connection scene, you must first connect to a wallet. +By default, the scene uses the contract that you deployed with the Contract scene. +It also shows the IDs of the tokens that you created with that contract, starting with 0. + +To transfer a token, make sure that the scene shows the address of the contract. +Then, fill in the fields and click the Transfer button. +The scene looks like this: + +The Transfer scene, showing information about the token to transfer + +After you approve the transaction in your wallet app, the contract transfers the token to the new owner. +You can see the token owners by looking at the contract storage in a block explorer. +For example, in [Better Call Dev](https://better-call.dev/), go to the Storage tab, expand the `ledger` object, and look at the entries. +For example, this entry shows that the account that ends in `2zD` owns 9 of the token with the ID 1: + +The block explorer's Storage tab, showing the account address and the quantity of a token it owns + +The transfer tutorial scene uses the [`TokenContract.Transfer()`](./reference/TokenContract#transfer) method to transfer the token: + +```csharp +public void HandleTransfer() +{ + TezosManager + .Instance + .Tezos + .TokenContract + .Transfer( + completedCallback: TransferCompleted, + destination: address.text, + tokenId: int.Parse(id.text), + amount: int.Parse(amount.text)); +} +``` + +This ledger of token ownership is stored in a big-map data type, which is serialized on Tezos to save space. + +## IPFSUpload scene + +This scene shows how to upload files to IPFS with the Pinata API. + +The InterPlanetary File System (IPFS) is a protocol and peer-to-peer network for storing and sharing data in a distributed file system. +Blockchain developers use it to store data such as token images and metadata. + +To use the scene, create instances of the `TezosConfigSO` and `DataProviderConfigSO` objects and connect them to the scene: + +1. Get a Pinata API key from [Pinata](https://pinata.cloud/) and copy the JWT for the key. + +1. In the Project view, right-click **Assets** and then click **Create > Tezos > Data Provider Configuration**. + +1. In the Project view, right-click **Assets** and then click **Create > Tezos > Configuration**. + +1. With the new `TezosConfigSO` object selected, go to the Inspector panel and put your Pinata JWT (not your key or secret key) in the **Pinata Api Key** field. + +1. With the `TezosConfigSO` object still selected, drag the `DataProviderConfigSO` object to the `Data Provider Config` field. + + The Inspector panel for the `TezosConfigSO` object looks like this, with your Pinata API key: + + Adding the Pinata API key and the data provider to the TezosConfigSO object + +1. Open the IPFSUpload scene. + +1. In the Hierarchy panel, select the `TezosManager` object. +The `TezosManager` object opens in the Inspector panel. + +1. From the Assets folder in the Project panel, drag the `TezosConfigSO` object with your Pinata key to the `config` field of the `TezosManager` object. + +Now you can run the scene and use your Pinata key to upload files to IPFS. + +When you run the scene, it shows a button that opens a file selection window, uploads that file to IPFS, and returns the IPFS URI that you can use to access the file later. + +The relevant code is in the `UploadImageButton.cs` script that is bound to the upload button: + +```csharp +public void HandleUploadClick() +{ + if (string.IsNullOrEmpty(TezosManager.Instance.Config.PinataApiKey)) + { + Logger.LogError("Can not proceed without Pinata API key."); + return; + } + + var uploader = UploaderFactory.GetPinataUploader(TezosManager.Instance.Config.PinataApiKey); + + var uploadCoroutine = uploader.UploadFile(ipfsUrl => + { + Logger.LogDebug($"File uploaded, url is {ipfsUrl}"); + }); + + StartCoroutine(uploadCoroutine); +} +``` diff --git a/docusaurus.config.js b/docusaurus.config.js index ab755b229..83007e25c 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -89,6 +89,7 @@ const config = { }, prism: { theme: require('prism-react-renderer/themes/github'), + additionalLanguages: ['csharp'], }, // https://github.com/flexanalytics/plugin-image-zoom // Enable click to zoom in to large images diff --git a/sidebars.js b/sidebars.js index 50001f939..808834a97 100644 --- a/sidebars.js +++ b/sidebars.js @@ -186,7 +186,6 @@ const sidebars = { 'dApps/wallets', 'dApps/sending-transactions', 'dApps/taquito', - 'dApps/unity', // 'dApps/frameworks', // TODO // Hide defi for now because the content is very outdated // 'dApps/defi', @@ -196,6 +195,36 @@ const sidebars = { 'dApps/best-practices', ], }, + { + type: 'category', + label: 'Tezos SDK for Unity', + link: { + id: 'unity', + type: 'doc', + }, + items: [ + 'unity/quickstart', + 'unity/scenes', + 'unity/prefabs', + { + type: 'category', + label: 'Reference', + link: { + id: 'unity/reference', + type: 'doc', + }, + items: [ + 'unity/reference/API', + 'unity/reference/DAppMetadata', + 'unity/reference/DataProviderConfigSO', + 'unity/reference/EventManager', + 'unity/reference/TezosConfigSO', + 'unity/reference/TokenContract', + 'unity/reference/Wallet', + ], + }, + ], + }, { type: 'category', label: 'Reference', diff --git a/static/img/unity/unity-bcd-tokens.png b/static/img/unity/unity-bcd-tokens.png new file mode 100644 index 000000000..fc64c7a0d Binary files /dev/null and b/static/img/unity/unity-bcd-tokens.png differ diff --git a/static/img/unity/unity-contract-scene-origination-temple.png b/static/img/unity/unity-contract-scene-origination-temple.png new file mode 100644 index 000000000..f713ff8e2 Binary files /dev/null and b/static/img/unity/unity-contract-scene-origination-temple.png differ diff --git a/static/img/unity/unity-contract-scene-origination.png b/static/img/unity/unity-contract-scene-origination.png new file mode 100644 index 000000000..dea076bef Binary files /dev/null and b/static/img/unity/unity-contract-scene-origination.png differ diff --git a/static/img/unity/unity-contract-scene-token.png b/static/img/unity/unity-contract-scene-token.png new file mode 100644 index 000000000..829107726 Binary files /dev/null and b/static/img/unity/unity-contract-scene-token.png differ diff --git a/static/img/unity/unity-hierarchy-panel-quickstart.png b/static/img/unity/unity-hierarchy-panel-quickstart.png new file mode 100644 index 000000000..da90e69d7 Binary files /dev/null and b/static/img/unity/unity-hierarchy-panel-quickstart.png differ diff --git a/static/img/unity/unity-inspector-tezosmanager.png b/static/img/unity/unity-inspector-tezosmanager.png new file mode 100644 index 000000000..21bf3b725 Binary files /dev/null and b/static/img/unity/unity-inspector-tezosmanager.png differ diff --git a/static/img/unity/unity-ipfs-scene-config.png b/static/img/unity/unity-ipfs-scene-config.png new file mode 100644 index 000000000..a45e49d60 Binary files /dev/null and b/static/img/unity/unity-ipfs-scene-config.png differ diff --git a/static/img/unity/unity-quickstart-bind-accountinfo.png b/static/img/unity/unity-quickstart-bind-accountinfo.png new file mode 100644 index 000000000..9b3fb894a Binary files /dev/null and b/static/img/unity/unity-quickstart-bind-accountinfo.png differ diff --git a/static/img/unity/unity-transfer-scene-address.png b/static/img/unity/unity-transfer-scene-address.png new file mode 100644 index 000000000..1ee997265 Binary files /dev/null and b/static/img/unity/unity-transfer-scene-address.png differ diff --git a/static/img/unity/unity-transfer-scene-block-explorer-token-ownership.png b/static/img/unity/unity-transfer-scene-block-explorer-token-ownership.png new file mode 100644 index 000000000..35e425c2f Binary files /dev/null and b/static/img/unity/unity-transfer-scene-block-explorer-token-ownership.png differ diff --git a/static/img/unity/unity-tutorial-scene-build.png b/static/img/unity/unity-tutorial-scene-build.png new file mode 100644 index 000000000..7f10bb907 Binary files /dev/null and b/static/img/unity/unity-tutorial-scene-build.png differ diff --git a/static/img/unity/unity-walletconnection-scene-connected.png b/static/img/unity/unity-walletconnection-scene-connected.png new file mode 100644 index 000000000..4f3168a8b Binary files /dev/null and b/static/img/unity/unity-walletconnection-scene-connected.png differ diff --git a/static/img/unity/unity-walletconnection-scene-qrcode-unconnected.png b/static/img/unity/unity-walletconnection-scene-qrcode-unconnected.png new file mode 100644 index 000000000..7ee89154b Binary files /dev/null and b/static/img/unity/unity-walletconnection-scene-qrcode-unconnected.png differ diff --git a/static/img/unity/unity-walletconnection-scene-webgl-unconnected.png b/static/img/unity/unity-walletconnection-scene-webgl-unconnected.png new file mode 100644 index 000000000..96a556a0f Binary files /dev/null and b/static/img/unity/unity-walletconnection-scene-webgl-unconnected.png differ diff --git a/static/img/unity/unity-webgl-template.png b/static/img/unity/unity-webgl-template.png new file mode 100644 index 000000000..f2224a186 Binary files /dev/null and b/static/img/unity/unity-webgl-template.png differ