Home

Awesome

<div style="text-align:center"> <p>

Unity-Solana Wallet

The First Open-Source Unity-Solana Wallet with NFT support

The Unity-Solana Wallet is an essential bridge connecting game developers and the Solana blockchain. With Solana’s quick and low-cost transactions, games can start using blockchain technology like never before - in real-time. Thousands of developers will bring millions of players into the Solana ecosystem. This will, in turn, make the Solana projects benefit from an increased number of participants, and cross-protocol interoperability in games will take us beyond the current understanding of DeFi.

Unity-Solana Wallet uses Solnet's implementation .NET SDK, but we had to modify the library to make it Unity compatible with .NET Standard 2.0 and .NET 4.x. Solnet is Solana's .NET SDK to integrate with the .NET ecosystem. Solnet.

</p> </div>

Features

Dependencies

External packages

Roadmap

Installation

  1. Clone this repository outside of the main Unity project
  2. Go to Package Manager in your project
  3. Click on the plus in the top left corner and select "Add package from disk"
  4. Select package.json file from a cloned dir
  5. Once the package is installed, in the Package Manager inspector you will have Samples. Click on Import

Step-by-step instructions

  1. If you have an older version of Unity that doesn't have imported Newtonsoft.Json just import it.
  2. After importing the wallet Unity will throw unity-plastic error. Just restart Unity.
  3. Create a new scene.
  4. Import WalletController prefab into your scene.
  5. Set Client Source (Mainnet/Testnet/Devnet/Custom uri) and Storage Method (Json/Simple txt) on SimpleWallet script in WalletController prefab.
  6. If you use custom URI be careful to use WS/WSS instead of HTTP/HTTPS because WebSocket does not work with HTTP / HTTPS.
  7. To save mnemonics in JSON format, select the JSON storage method, and if you want to save it as a regular string, select Simple Txt.
  8. If you want to use mnemonics saved in JSON format, you must deserialize it first. You have an example in ReGenerateAccountScreen.cs in the ResolveMnemonicsByType method.
  9. Create new Canvas
  10. Import WalletHolder prefab into the Canvas or if you want your design just import wallet prefab and customize the scene like we did with WalletHolder.

Functionalities description

Login Screen

Create Wallet Screen

Regenerate Wallet Screen

Wallet Screen

Recieve Screen

Transfer Screen

Introduction to WalletBaseComponent.cs

Create account

public async void CreateAccount(Account account, string toPublicKey = "", long ammount = 1000)

Start connection

public SolanaRpcClient StartConnection(EClientUrlSource clientUrlSource, string customUrl = "")
StartConnection(clientSource);

Generate wallet with mnemonics

 public Wallet GenerateWalletWithMenmonic(string mnemonics)
SimpleWallet.instance.GenerateWalletWithMenmonic(_simpleWallet.LoadPlayerPrefs(_simpleWallet.MnemonicsKey));

Login check with mnemonics and password

 public bool LoginCheckMnemonicAndPassword(string password)
private void LoginChecker()
{
    if (_simpleWallet.LoginCheckMnemonicAndPassword(_passwordInputField.text))
    {
        SimpleWallet.instance.GenerateWalletWithMenmonic(_simpleWallet.LoadPlayerPrefs(_simpleWallet.MnemonicsKey));
        MainThreadDispatcher.Instance().Enqueue(() => { _simpleWallet.StartWebSocketConnection(); }); 
        manager.ShowScreen(this, "wallet_screen");
        this.gameObject.SetActive(false);
    }
    else
    {
        SwitchButtons("TryAgain");
    }
}

Get sol amount

public async Task<double> GetSolAmmount(Account account)
double sol = await SimpleWallet.instance.GetSolAmmount(SimpleWallet.instance.wallet.GetAccount(0));

Transfer sol

public async Task<RequestResult<string>> TransferSol(string toPublicKey, long ammount = 10000000)
private async void TransferSol()
{
    RequestResult<string> result = await SimpleWallet.instance.TransferSol(toPublic_txt.text, long.Parse(ammount_txt.text));
    HandleResponse(result);
}

Transfer token

public async Task<RequestResult<string>> TransferToken(string sourceTokenAccount, string toWalletAccount, Account sourceAccountOwner, string tokenMint, long ammount = 1)
private async void TransferToken()
{
    RequestResult<string> result = await SimpleWallet.instance.TransferToken(
                        transferTokenAccount.pubkey,
                        toPublic_txt.text,
                        SimpleWallet.instance.wallet.GetAccount(0),
                        transferTokenAccount.Account.Data.Parsed.Info.Mint,
                        long.Parse(ammount_txt.text));

    HandleResponse(result);
}

Request airdrop

public async Task<string> RequestAirdrop(Account account, ulong ammount = 1000000000)
airdrop_btn.onClick.AddListener(async () => {
            await SimpleWallet.instance.RequestAirdrop(SimpleWallet.instance.wallet.GetAccount(0));
        });

Get owned token accounts

public async Task<TokenAccount[]> GetOwnedTokenAccounts(Account account)
TokenAccount[] result = await SimpleWallet.instance.GetOwnedTokenAccounts(SimpleWallet.instance.wallet.GetAccount(0));

Delete wallet and clear key

public void DeleteWalletAndClearKey()

Start WebSocket connection

public void StartWebSocketConnection()

Introduction to WebsocketService.cs

Start connection

public void StartConnection(string address)
 webSocketService.StartConnection(GetWebsocketConnectionURL(clientSource));

Subscribe to wallet account events

 public void SubscribeToWalletAccountEvents(string pubKey)
 webSocketService.SubscribeToWalletAccountEvents(wallet.Account.GetPublicKey);

Unsubscribe to wallet account events

 public void UnSubscribeToWalletAccountEvents()
public void StartWebSocketConnection()
{
    if (webSocketService.Socket != null) return;

    webSocketService.StartConnection(GetWebsocketConnectionURL(clientSource));
}

On Message

private void OnMessage(object sender, MessageEventArgs e)
 WebSocketActions.WebSocketAccountSubscriptionAction += CheckSubscription;

Close connection

 public void CloseConnection()
 {
     if (_socket == null) return;

     _socket.CloseAsync();
 }

-To close WebSocket connection call CloseConnection from WebSocketService.cs

Introduction to Nft.cs

Try get nft data

public static async Task<Nft> TryGetNftData(string mint, SolanaRpcClient connection, bool tryUseLocalContent = true)
Nft.Nft nft = await Nft.Nft.TryGetNftData(item.Account.Data.Parsed.Info.Mint, SimpleWallet.instance.activeRpcClient, true);

Try load nft from local

public static Nft TryLoadNftFromLocal(string mint)
if (tryUseLocalContent)
{ 
    Nft nft = TryLoadNftFromLocal(mint);
    if (nft != null)
    {
        return nft;
    }
}

Create address

public static Solnet.Wallet.PublicKey CreateAddress(List<byte[]> seed, string programId)
try
{
     seeds[3] = new[] { (byte)nonce };
     publicKey = CreateAddress(seeds, programId);
     return publicKey;
}

Find program address

public static Solnet.Wallet.PublicKey FindProgramAddress(string mintPublicKey, string programId = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s")
Solnet.Wallet.PublicKey metaplexDataPubKey = FindProgramAddress(mint);

Get metaplex Json data

public static async Task<T> GetMetaplexJsonData<T>(string jsonUrl)

Resize

private static Texture2D Resize(Texture2D texture2D, int targetX, int targetY)
Texture2D compressedTexture = Resize(texture, 75, 75);

License

This project is licensed under the MIT License - see the LICENSE file for details