Examples
What is Contained in this Document
In this document you will find Integration examples for popular Unity wallets such as Metamask and Metafab.
MetaMask Integration
If you want to use MetaMask with String, you will need to know:
- How to set up MetaMask in your project
- How to Initialize MetaMask and connect to the players wallet
- How to request a transaction signature from the player using MetaMask
Please refer to the official MetaMask Unity documentation for further detail on how to use it. We will succinctly go over the areas of MetaMask Unity implementation which overlap with using String in Unity. This document presumes that the reader has already familiarized themselves with the Integration Steps section of this documentation.
Prerequisites
You will need to install the MetaMask Unity SDK in your project. You will also need the MetaMaskUnity object and the MetaMaskTransportBroadcaster with the QR Code listener in your scene - as shown in their example.
using Cysharp.Threading.Tasks;
using StringSDK;
using MetaMask.Unity;
using MetaMask.Models;
using System.Text;
This example uses StringSDK, MetaMask, a C# Promises package and System Text for Base64 Decryption.
Initialization
Your initialization might look something like this:
public class GameLogicBehavior : MonoBehavior
{
// Not required, but used for brevity
private MetaMask.MetaMaskWallet wallet;
// We will use this later to execute the blockchain actions
private TransactionRequest lastQuote;
// We will use this later to store the execution response
private TransactionResponse txResponse;
// We will use this to keep track of the String internal ID for the player
private string stringPlayerID;
async UniTaskVoid Start()
{
// Initialize the String SDK with your API key
StringXYZ.ApiKey = "YOUR_API_KEY_HERE";
// Initialize MetaMask, display QR code and subscribe to events
MetaMaskUnity.Instance.Initialize();
wallet = MetaMaskUnity.Instance.Wallet;
wallet.Connect();
wallet.WalletConnected += OnWalletConnected;
wallet.WalletAuthorized += OnWalletAuthorized;
}
// ...
}
Notice how the Start() method initializes MetaMaskUnity, gets a handle to its wallet, initializes a connection to the wallet, then subscribes to some events that the wallet emits.
Logging the Player In
Your login code might look something like this:
public async void LoginPlayerToString()
{
// Request String login payload for the player to sign
var payloadToSign = await StringXYZ.RequestLogin(wallet.SelectedAddress);
// To display the payload in human readable form in MetaMask, we need to decode it
var base64decode = Encoding.UTF8.GetString(Convert.FromBase64String(payloadToSign.nonce));
// Construct a signature request for MetaMask using our login payload
var parameters = new string[] { wallet.SelectedAddress, base64decode };
var request = new MetaMaskEthereumRequest
{
Method = "personal_sign",
Parameters = parameters
};
// Request the signature and store the string of the JSON response
var jsonResponse = await wallet.Request(request);
var signature = jsonResponse.GetString();
// Construct the String login request using the signature
var login = new LoginRequest(
nonce: payloadToSign.nonce,
signature: signature
);
// Log the player in - if they do not have an account one will be created automatically
var auth = await StringXYZ.Login(login);
// Store the String player ID for future use
stringPlayerID = auth.user.id;
// Set the users name and email with String. See VerifyUser()
if (auth.user.status == "unverified")
{
VerifyUser();
}
}
Please note the use of wallet.SelectedAddress which denotes the players public key, as well as the construction of the "personal_sign" MetaMaskEthereumRequest along with its execution and response. It's a good idea to store the String Player ID (auth.user.id) for future reference.
That's it
That's it! Accessing the public key (address) of the player and signing a message are all that's required of any wallet service to interact with String.
Metafab Integration
If you want to use Metafab with String, you will need to know:
- How to set up Metafab in your project
- How to Initialize Metafab and connect to the players wallet
- How to sign a transaction on behalf of the player using Metafab
Please refer to the official Metafab Unity documentation for further detail on how to use it. We will succinctly go over the areas of Metafab Unity implementation which overlap with using String in Unity. This document presumes that the reader has already familiarized themselves with the Integration Steps section of this documentation.
Prerequisites
You will need to install the Metafab Unity SDK in your project. You will also need the Cysharp Threading package installed in your project, which String Unity also uses.
using Cysharp.Threading.Tasks;
using StringSDK;
using MetafabSDK;
using System.Text;
This example uses StringSDK, MetaFab, a C# Promises package and System Text for Base64 Decryption.
Initialization
Your initialization might look something like this:
public class GameLogicBehavior : MonoBehavior
{
// These Metafab vars will be passed into our String package
private string playerWallet;
private string playerWalletID;
// We will use this later to execute the blockchain actions
private TransactionRequest lastQuote;
// We will use this later to store the execution response
private TransactionResponse txResponse;
// We will use this internal ID to submit the players information to String
private string stringPlayerID;
async UniTaskVoid Start()
{
// Authenticate the Game with Metafab
var response = await Metafab.GamesApi.AuthGame(Config.Email, Config.Password, default);
// Metafab needs us to copy some of the response data
Config.PublishedKey = response.publishedKey;
Metafab.PublishedKey = Config.PublishedKey;
Metafab.SecretKey = response.secretKey;
Metafab.Password = Config.Password;
// Log player into game with their credentials
var auth = await Metafab.PlayersApi.AuthPlayer("sample-player", "password", 0);
// Store the information we need about the player to be passed into our String package
playerWallet = auth.wallet.address;
playerWalletID = auth.wallet.id;
// Metafab uses this header in order to create cryptographic signatures on behalf of the player
Metafab.WalletDecryptKey = auth.walletDecryptKey;
}
// ...
}
Please note the use of auth.wallet.address which contains the public key of the players Metafab wallet, as well as its internal Metafab ID auth.wallet.id which will be used later in conjunction with auth.walletDecryptKey to sign a transaction on their behalf.
Logging the Player In
Your login code might look something like this:
public async void LoginPlayerToString()
{
// Request String login payload for the player to sign
var payloadToSign = await StringXYZ.RequestLogin(playerWallet);
// To display the payload in human readable form in MetaMask, we need to decode it
var base64decode = Encoding.UTF8.GetString(Convert.FromBase64String(payloadToSign.nonce));
// Construct a signature request for MetaFab using our login payload
var request = new CreateWalletSignatureRequest(base64decode);
// Request the signature and store the string of the JSON response
var res = await Metafab.WalletsApi.CreateWalletSignature(playerWalletID, request);
var signature = res.signature;
// Construct the String login request using the signature
var login = new LoginRequest(
nonce: payloadToSign.nonce,
signature: signature
);
// Log the player in - if they do not have an account one will be created automatically
var auth = await StringXYZ.Login(login);
// Store the String player ID for future use
stringPlayerID = auth.user.id;
// Set the users name and email with String. See VerifyUser()
if (auth.user.status == "unverified")
{
VerifyUser();
}
}
The Wallet Signature Request is created by passing in the decoded String login payload nonce. Then the signature is created on behalf of the user by calling Metafab.WalletsApi.CreateWalletSignature().
That's it!
That's it. Accessing the public key (address) of the players Metafab wallet and signing the login payload are all that are required to use Metafab with String.
Transaction Request Examples
The TransactionRequest is an object which you will construct according to your specific needs, and the desired operation on the blockchain you wish to execute. We will provide a couple examples to demonstrate what they might look like. Check out the Appendices section of this Implementation Guide for an in-depth explanation of each parameter in the TransactionRequest.
Mint an NFT on Fuji Testnet using mintTo(address)
TransactionRequest transactionRequest = new TransactionRequest(
userAddress: walletAddr,
assetName: "String Avalanche NFT",
chainId: 43113,
contractAddress: "0xea1ffe2cf6630a20e1ba397e95358daf362c8781",
contractFunction: "mintTo(address)",
contractReturn: "uint256",
contractParameters: new string[] { walletAddr },
txValue: "0.08 eth",
gasLimit: "800000");
Here, we are specifying the Chain ID of the Fuji Testnet (aka Avalanche Testnet). The contract is located at 0xea1ffe2cf6630a20e1ba397e95358daf362c8781, and its mint function mintTo(address)
takes in a single address
parameter and it returns a uint256
. It costs 0.08 AVAX (the native network token) to mint. We set the gas limit high just to be safe. We will likely not be anywhere near this limit in terms of the actual gas cost charged.
Mint an NFT on Ethereum Mainnet using mintTo(address[])
TransactionRequest transactionRequest = new TransactionRequest(
userAddress: walletAddr,
assetName: "String Ethereum NFT",
chainID: 1,
contractAddress: "0xB2153Ef7d90bb03637855E2f96e83e30EA73f940",
contractFunction: "mintTo(address[])",
contractReturn: "uint256[]",
contractParameters: new string[] {$"[{walletAddr},{walletAddr},{walletAddr}]"},
txValue: "0.24 eth",
gasLimit: "800000"
);
Notice how this smart contract takes in an array of addresses as its first and only parameter for the mintTo
method. In order to specify this, we construct a string representing an array as the first (and only) index of the contractParameters
string array. We also multiplied the txValue because each token costs 0.08 eth to mint.
Updated over 1 year ago