Streamlined Player Onboarding with Eidolon
In this section we’ll look at how we can use the WebGLWallet
class to interact with browser based wallets like MetaMask
, TrustWallet
and more. We’ll instantiate a new wallet and connect our player to a specified network.
Step 1: Instantiate a Wallet
To create a new wallet instance, follow these steps:
using UnityEngine;using System.Numerics;using Nethereum.Web3;
public class WalletExample : MonoBehaviour{ // Reference to your wallet provider WebGLWallet wallet;
// Reference to our smart contract SmartContract contract;
public void Awake() { // Instantiate a new wallet using the Wallet class wallet = new WebGLWallet();
// Instantiate a new smart contract and pass our wallet to the constructor contract = new SmartContract("contractAddress", "ContractABI", wallet) }}
In the example above, we instantiate a new wallet and smart contract instance by providing the contract address and ABI of the smart contract we want to interact with. We then pass the wallet in the smart contract constructor to let Eidolon know we want to sign transactions with that wallet.
Step 2: Connect to a Network
Now, let’s connect the player to an example network, in this case, the SKALE Chaos Test Network. We will set the required network-specific information.
private void ConnectToNetwork(){ string chainId = "1351057110"; // SKALE Calypso Test Network
// Connect to the SKALE Network and retrieve the connected account address string account = wallet.Connect(chainId);}
In this step, we set up the connection to the SKALE Calypso Test Network by providing the chain ID.
Step 3: Send a Test Transaction
Let’s send a test transaction to a smart contract using the wallet and smart contract instance. We use Named arguments to pass only the method name and arguments. You can however adjust the gas, gasPrice, value and nonce if required.
private void SendTransactionToSmartContract(){ string methodName = "transfer"; // Replace with the desired method name object[] arguments = new object[] { "0xAddressTo", 100 }; // Example parameters
// Send a transaction to a smart contract method contract.SendTransaction(methodName, parameters: arguments);}
Here, we send a test transaction by calling a method on a smart contract with the provided parameters.
Step 5: Read Data from Smart Contract
To read data from a smart contract, use the Call
method asynchronously. In this example, we read the balance of an address.
private async void ReadDataFromSmartContract(){string methodName = "balanceOf"; // Replace with the desired method nameobject[] parameters = new object[] { "0xAddress" }; // Example parameters
BigInteger result = await contract.Call<BigInteger>(methodName, parameters);}
In this step, we asynchronously read data from the smart contract and handle the result when the task is completed.
Conclusion
By following these steps, you can successfully use the Wallet
class to create a new wallet, connect a player to any EVM network, and interact with smart contracts in your Unity project. This allows you to integrate blockchain functionality into your game seamlessly.
In this section, we’ll explore two distinct methods for player onboarding using the Eidolon SDK. Whether you prefer a traditional interactive login approach or a seamless invisible login experience, Eidolon makes it easy to integrate Ethereum blockchain features into your game.
Interactive Login
Overview
The Interactive Login method allows players to sign up and log in using a familiar username and password system. Players can manage their accounts and store information securely. This approach provides flexibility for players to choose their credentials.
Code Example
using TMPro;using UnityEngine;
public class InteractiveLogin : MonoBehaviour{ // Input fields public TMP_InputField usernameInput; public TMP_InputField passwordInput;
// Status Text public TextMeshProUGUI statusText;
// RPC Provider public JsonRpcProvider provider;
// Account variables private string username; private string password;
private void Awake() { // Instantiate a new RPC Provider using the default project RPC provider = new JsonRpcProvider(); }
// Variables = Inputfield.value private void Update() { username = usernameInput.text; password = passwordInput.text; }
// Used to sign-up a new player to your game. public void SignUp() { // Clear the input fields (optional) usernameInput.text = ""; passwordInput.text = "";
// We can call the BackgroundSigner class to create a new account for us based on the users input. bool signUpSuccess = Signer.Create(username, password);
// If the account is created successfully if (signUpSuccess) { // Success logic goes here Debug.Log("Account created successfully!"); statusText.text = "Account created successfully!"; } // Otherwise else { // Failed logic goes here Debug.Log("Username already exists. Please choose a different username."); statusText.text = "Username already exists. Please choose a different username."; } }
// Used to login an existing player based on their account details set at Sign-up public async void Login() { // The signer key used sign transactions in your game string signer = Signer.Load(username, password);
// If the user logs in successfully if (signer != null) { // Success logic goes here Debug.Log("Logged in Successfully!");
// You can create a new wallet intance using the logged in signer. Please see the smart contract example to see where a wallet is used. EmbeddedWallet wallet = new EmbeddedWallet(signer);
// You can assign the public address for the wallet using the below string account = wallet.GetAddress();
// The connected wallet can be retrieved with PlayerPrefs.GetString("Account") statusText.text = "Logged in Successfully! Connected Address: " + account;
// Add any other logic required here. ie checking gas / sending gas. var currentGasBalance = await Provider.GetBalance(account);
// Example showcasing how we would fetch the gas for this signer. Debug.Log("Signer Gas Balance: " + currentGasBalance); } // Otherwise else { // Failed logic goes here // The BackgroundSigner class will log errors for failed login attempts. Feel free to add more here. statusText.text = "Failed to login - Wallet doesn't exist! Please Sign-up first!"; } }}
Explanation
- The
InteractiveLogin
script provides a user-friendly interface for player account creation and login. - Players can enter their desired username and password in the input fields.
- The
SignUp
method creates a new account based on the provided credentials and handles success or failure accordingly. - The
Login
method loads the signer key for transaction signing upon successful login and sets it as the signer for transactions. - Gas balance checking and other necessary logic can be added to the
Login
method as required.
Invisible Login
Overview
The Invisible Login method generates a wallet ID and secret, securely stores it within the device keystore, and enables seamless background login flows without player input. This method is ideal for creating a frictionless player experience.
Code Example
using TMPro;using UnityEngine;
public class InvisibleLogin : MonoBehaviour{ // Variables public TextMeshProUGUI statusText; private string ID; public JsonRpcProvider provider;
private void Awake() { // Instantiate a new RPC Provider using the default project RPC provider = new JsonRpcProvider(); }
// We can create a new invisible signer by calling the Signer.Create() method. public void CreateAccount() { // We can use anything to identify the signer -IP/MAC Address, GUID - In this example we use a unique, persistent device ID. ID = SystemInfo.deviceUniqueIdentifier;
// Generate a new secret to secure the signer. We can pass a length to our PasswordGenerator class. string secret = PasswordGenerator.GenerateRandomPassword(32);
// Create the signer bool accountCreated = Signer.Create(ID, secret);
// If the signer has been created... if (accountCreated) { statusText.text = "Account created successfully with ID: " + ID;
// Add any other logic required here. ie checking gas / sending gas.
// In our example we'll just login Invoke(nameof(LoadAccount), 4f); } // Otherwise if the ID already exists, we can login. else { LoadAccount(); } }
public async void LoadAccount() { // Load our private key using the Signer.Load() method. string signer = Signer.Load(ID, WindowsKeystore.GetStringFromKeystore(ID));
// If the signer value isn't empty.. if (signer != null) { // You can create a new wallet intance using the logged in signer. Please see the smart contract example to see where a wallet is used. EmbeddedWallet wallet = new EmbeddedWallet(signer);
// You can assign the public address for the wallet using the below string account = wallet.GetAddress();
// Sanity check to ensure we're connected. statusText.text = "Account: " + account + " logged in successfully!";
// Add any other logic required here. ie checking gas / sending gas. var currentGasBalance = await Provider.GetBalance(account);
// Example showcasing how we would fetch the gas for this signer. Debug.Log("Signer Gas Balance: " + currentGasBalance);
// You can go even further and add a conditional statement so that if the signer has < X amount of gas // You can send it gas using an API or your preferred method for gas distribution. } // Otherwise if the key is empty.. else { // There is error handling in the core library, but the developer can add extra here for debugging. statusText.text = "Couldn't log in"; } }}
Explanation
- The
InvisibleLogin
script allows developers to create and manage Ethereum accounts on behalf of players, enabling seamless background login flows. - In the
CreateAccount
method, a unique identifier (e.g., device ID) is used to identify the signer, and a secure secret is generated for the signer. - The
LoadAccount
method loads the private key using theSigner.Load
method based on the identifier. - Gas balance checking and other necessary logic can be added to the
LoadAccount
method as needed.
These examples showcase how Eidolon empowers developers to implement player onboarding mechanisms seamlessly, whether through traditional interactive login or frictionless invisible login experiences.