{"id":19593497,"url":"https://github.com/magicblock-labs/solana.unity-core","last_synced_at":"2025-05-09T00:06:13.193Z","repository":{"id":38334780,"uuid":"471773476","full_name":"magicblock-labs/Solana.Unity-Core","owner":"magicblock-labs","description":"Solana's Unity SDK and integration library.","archived":false,"fork":false,"pushed_at":"2025-04-26T10:47:32.000Z","size":4035,"stargazers_count":50,"open_issues_count":9,"forks_count":17,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-09T00:06:00.313Z","etag":null,"topics":["rpc","solana","solana-client","unity","unity3d"],"latest_commit_sha":null,"homepage":"https://solana.unity-sdk.gg","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/magicblock-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.rst","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-03-19T17:59:24.000Z","updated_at":"2025-03-19T13:16:34.000Z","dependencies_parsed_at":"2023-02-16T01:01:13.040Z","dependency_job_id":"28aae855-c359-47df-b18f-0d3a367124f6","html_url":"https://github.com/magicblock-labs/Solana.Unity-Core","commit_stats":null,"previous_names":[],"tags_count":55,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicblock-labs%2FSolana.Unity-Core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicblock-labs%2FSolana.Unity-Core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicblock-labs%2FSolana.Unity-Core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magicblock-labs%2FSolana.Unity-Core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magicblock-labs","download_url":"https://codeload.github.com/magicblock-labs/Solana.Unity-Core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253166518,"owners_count":21864476,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rpc","solana","solana-client","unity","unity3d"],"created_at":"2024-11-11T08:39:54.045Z","updated_at":"2025-05-09T00:06:13.126Z","avatar_url":"https://github.com/magicblock-labs.png","language":"C#","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg height=\"170x\" src=\"https://solana.unity-sdk.gg/logo.png\" /\u003e\n\n  \u003ch1\u003eSolana.Unity Core\u003c/h1\u003e\n\n  \u003cp\u003e\n    \u003cstrong\u003eSolana.Unity integration Framework\u003c/strong\u003e\n  \u003c/p\u003e\n\n  \u003cp\u003e\n    \u003ca href=\"https://github.com/garbles-labs/Solana.Unity-Core/actions/workflows/dotnet.yml\"\u003e\n        \u003cimg src=\"https://github.com/garbles-labs/Solana.Unity-Core/actions/workflows/dotnet.yml/badge.svg\"\n            alt=\"Build\" \u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/garbles-labs/Solana.Unity-Core/actions/workflows/publish.yml\"\u003e\n       \u003cimg src=\"https://github.com/garbles-dev/Solana.Unity/actions/workflows/publish.yml/badge.svg\" \n            alt=\"Release\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://coveralls.io/github/garbles-labs/Solana.Unity-Core?branch=master\"\u003e\n        \u003cimg src=\"https://coveralls.io/repos/github/garbles-labs/Solana.Unity-Core/badge.svg?branch=master\" \n            alt=\"Coverage Status\" \u003e\u003c/a\u003e\n    \u003ca href=\"\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/license/garbles-labs/Solana.Unity-Core?style=flat-square\"\n            alt=\"Code License\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://twitter.com/intent/follow?screen_name=garblesfun\"\u003e\n        \u003cimg src=\"https://img.shields.io/twitter/follow/garblesfun?style=flat-square\u0026logo=twitter\"\n            alt=\"Follow on Twitter\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://discord.gg/MBkdC3gxcv\"\u003e\n       \u003cimg alt=\"Discord\" src=\"https://img.shields.io/discord/943797222162726962?style=flat-square\"\n            alt=\"Join the discussion!\"\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n# Introduction\n\nSolana.Unity is a ported version of [Solnet](https://blockmountain.io/Solnet/), compatible with .net standard 2.0. It can be used with [Unity](https://unity.com/).\n\nIf you are looking for the installable version via Unity Package Manager with examples, see here: https://github.com/magicblock-labs/Solana.Unity-SDK. \n\nSeveral changes have been made to make it compatible with Unity, incompatible libraries have been replaced and external dependencies have been reduced. The API and documentation remain unchanged. The original tests are run on every commit.\n    \n## Solnet\n\nSolnet is Solana's .NET SDK to integrate with the .NET ecosystem. Wherever you are developing for the Web or Desktop, we are here to help. Learn more about the provided samples, documentation, integrating the SDK into your app, and more [here](https://blockmountain.io/Solnet/).\n\n\u003c/p\u003e\n\n\u003c/div\u003e\n\n\n## Features\n- Full JSON RPC API coverage\n- Full Streaming JSON RPC API coverage\n- Wallet and accounts (sollet and solana-keygen compatible)\n- Keystore (sollet and solana-keygen compatible)\n- Transaction decoding from base64 and wire format and encoding back into wire format\n- Message decoding from base64 and wire format and encoding back into wire format\n- Instruction decompilation\n- TokenWallet object to send SPL tokens and JIT provisioning of [Associated Token Accounts](https://spl.solana.com/associated-token-account)\n- Programs\n    - Native Programs\n      - System Program\n      - Stake Program\n    - Solana Program Library (SPL)\n      - Memo Program\n      - Token Program\n      - Token Swap Program\n      - Associated Token Account Program\n      - Name Service Program\n      - Shared Memory Program\n\nFor the sake of maintainability and sometimes due to the size and complexity of some other programs, this repository will only contain Solana's Native Programs and Programs which are part of the SPL,\nfor a list of other commonly needed programs see below:\n\n- [Serum](https://github.com/bmresearch/Solnet.Serum/)\n- [Mango](https://github.com/bmresearch/Solnet.Mango/)\n- [Pyth](https://github.com/bmresearch/Solnet.Pyth/)\n- [Metaplex](https://github.com/bmresearch/Solnet.Metaplex/)\n\n## Requirements\n- net standard 2.0\n\n## Dependencies\n- Chaos.NaCl.Standard\n- Portable.BouncyCastle\n\n## Examples\n\nThe [Solana.Unity.Examples](https://github.com/magicblock-labs/Solana.Unity-Core/tree/master/src/Solana.Unity.Examples/) project contains some code examples,\nessentially we're trying very hard to make it intuitive and easy to use the library.\nWhen trying to run these examples they might lead to errors in cases where they create new accounts, in these cases, the response from the RPC\ncontains an and the transaction simulation logs which state that `account address is ... already in use`,\nall you need to do is increment the value that is used to derive that account from the seed being used, i.e `wallet.GetAccount(value+1)`.\n\n### Wallets\n\nThe [Solana.Unity.Wallet](https://github.com/magicblock-labs/Solana.Unity-Core/tree/master/src/Solana.Unity.Wallet/) project implements wallet and key generation features, these were made compatible\nwith both the keys generated using `solana-keygen` and the keys generated using the popular browser wallet [sollet.io](https://www.sollet.io).\n\n#### Initializing a wallet compatible with sollet\n\n```c#\n// To initialize a wallet and have access to the same keys generated in sollet (the default)\nvar sollet = new Wallet(\"mnemonic words ...\", WordList.English);\n\n// Retrieve accounts by derivation path index\nvar account = sollet.GetAccount(10);\n``` \n\n#### Initializing a wallet compatible with solana-keygen\n\n```c#\n// To initialize a wallet and have access to the same keys generated in solana-keygen\nvar wallet = new Wallet(\"mnemonic words ...\", WordList.English, \"passphrase\", SeedMode.Bip39);\n\n// Retrieve the account\nvar account = wallet.Account; // the solana-keygen mechanism does not allow account retrieval by derivation path index\n```\n\n### Generating new wallets\n\n```c#\n// Generate a new mnemonic\nvar newMnemonic = new Mnemonic(WordList.English, WordCount.Twelve);\n\nvar wallet = new Wallet(newMnemonic);\n```\n\n\n### KeyStore\n\nThe [Solana.Unity.KeyStore](https://github.com/bmresearch/Solnet/tree/master/src/Solana.Unity.KeyStore/) project implements functionality to be able to securely store keys, seeds,\nmnemonics, and whatever you so desire. It contains an implementation of the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition)\nas well as a `SolanaKeyStoreService` which can be used to read keys generated by `solana-keygen`.\n\n#### Secret KeyStore Service\n\n```c#\n// Initialize the KeyStore\nvar secretKeyStoreService = new SecretKeyStoreService();\n\n// Encrypt a private key, seed or mnemonic associated with a certain address\nvar jsonString = secretKeyStoreService.EncryptAndGenerateDefaultKeyStoreAsJson(password, data, address);\n\n// Or decrypt a web3 secret storage encrypted json data\nbyte[] data = null;\ntry { \n    data = KeyStore.DecryptKeyStoreFromJson(password, jsonString);\n} catch (Exception) {\n    Console.WriteLine(\"Invalid password!\");\n}\n```\n\n#### Solana KeyStore Service\n\n```c#\n// Initialize the KeyStore\nvar secretKeyStoreService = new SolanaKeyStoreService();\n\n// Restore a wallet from the json file generated by solana-keygen,\n// with the same passphrase used when generating the keys\nvar wallet = secretKeyStoreService.RestoreKeystore(filePath, passphrase);\n```\n\n### RPC and Streaming RPC\n\nThe [Solana.Unity.Rpc](https://github.com/bmresearch/Solnet/tree/master/src/Solana.Unity.Rpc/) project contains a full-fidelity implementation of the [Solana JSON RPC](https://docs.solana.com/developing/clients/jsonrpc-api), this implementation is compatible\nwith both the [methods expected to be removed in v1.8](https://docs.solana.com/developing/clients/jsonrpc-api#json-rpc-api-deprecated-methods) and the methods which were added on v1.7 to replace them.\n\n#### ClientFactory pattern\n\nThe client factory allows you to pass a `Logger` which implements the `Microsoft.Extensions.Logging.ILogger` interface.\n\n```c#\nvar rpcClient = ClientFactory.GetClient(Cluster.MainNet, logger);\nvar streamingRpcClient = ClientFactory.GetStreamingClient(Cluster.MainNet, logger);\n```\n\n#### Using the RPC\n\n```c#\n// Get a certain account's info\nvar accountInfo = rpcClient.GetAccountInfo(\"5omQJtDUHA3gMFdHEQg1zZSvcBUVzey5WaKWYRmqF1Vj\");\n\n// Or get the token accounts owned by a certain account\nvar tokenAccounts = rpcClient.GetTokenAccountsByOwner(\"5omQJtDUHA3gMFdHEQg1zZSvcBUVzey5WaKWYRmqF1Vj\");\n\n// Or even filter the token accounts by the token's mint\nvar wrappedSolAccounts = rpcClient.GetTokenAccountsByOwner(\"5omQJtDUHA3gMFdHEQg1zZSvcBUVzey5WaKWYRmqF1Vj\", \"So11111111111111111111111111111111111111112\");\n\n// The following address represents Serum's address and it can be used for a number of things\nvar serumAddress = \"9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin\";\n\n// You can query the accounts owned by a certain program, and filter based on their account data!\nvar programAccounts = rpcClient.GetProgramAccounts(serumAddress);\nvar filters = new List\u003cMemCmp\u003e(){ new MemCmp{ Offset = 45, Bytes = OwnerAddress } };\n\nvar filteredProgramAccounts = rpcClient.GetProgramAccounts(serumAddress, memCmpList: filters);\n```\n\n#### Using the Streaming RPC\n\n```c#\n// After having sent a transaction\nvar txSig = rpcClient.SendTransaction(tx);\n\n// You can subscribe to that transaction's signature to be finalized\nvar subscription = streaminRpcClient.SubscribeSignature(txSig.Result, (subscriptionState, response) =\u003e {\n    // do something\n}, Commitment.Finalized);\n```\n\n### Sending a transaction\n\n```c#\n// Initialize the rpc client and a wallet\nvar rpcClient = ClientFactory.GetClient(Cluster.MainNet);\nvar wallet = new Wallet();\n// Get the source account\nvar fromAccount = wallet.GetAccount(0);\n// Get the destination account\nvar toAccount = wallet.GetAccount(1);\n// Get a recent block hash to include in the transaction\nvar blockHash = rpcClient.GetRecentBlockHash();\n\n// Initialize a transaction builder and chain as many instructions as you want before building the message\nvar tx = new TransactionBuilder().\n        SetRecentBlockHash(blockHash.Result.Value.Blockhash).\n        SetFeePayer(fromAccount).\n        AddInstruction(MemoProgram.NewMemo(fromAccount, \"Hello from Sol.Net :)\")).\n        AddInstruction(SystemProgram.Transfer(fromAccount, toAccount.GetPublicKey, 100000)).\n        Build(fromAccount);\n\nvar firstSig = rpcClient.SendTransaction(tx);\n```\n\n### Create, Initialize and Mint\n\n```c#\nvar wallet = new Wallet.Wallet(MnemonicWords);\n\nvar blockHash = rpcClient.GetRecentBlockHash();\nvar minBalanceForExemptionAcc = rpcClient.GetMinimumBalanceForRentExemption(TokenProgram.TokenAccountDataSize).Result;\n\nvar minBalanceForExemptionMint =rpcClient.GetMinimumBalanceForRentExemption(TokenProgram.MintAccountDataSize).Result;\n\nvar mintAccount = wallet.GetAccount(21);\nvar ownerAccount = wallet.GetAccount(10);\nvar initialAccount = wallet.GetAccount(22);\n\nvar tx = new TransactionBuilder().\n    SetRecentBlockHash(blockHash.Result.Value.Blockhash).\n    SetFeePayer(ownerAccount).\n    AddInstruction(SystemProgram.CreateAccount(\n        ownerAccount,\n        mintAccount,\n        minBalanceForExemptionMint,\n        TokenProgram.MintAccountDataSize,\n        TokenProgram.ProgramIdKey)).\n    AddInstruction(TokenProgram.InitializeMint(\n        mintAccount.PublicKey,\n        2,\n        ownerAccount.PublicKey,\n        ownerAccount.PublicKey)).\n    AddInstruction(SystemProgram.CreateAccount(\n        ownerAccount,\n        initialAccount,\n        minBalanceForExemptionAcc,\n        TokenProgram.TokenAccountDataSize,\n        TokenProgram.ProgramIdKey)).\n    AddInstruction(TokenProgram.InitializeAccount(\n        initialAccount.PublicKey,\n        mintAccount.PublicKey,\n        ownerAccount.PublicKey)).\n    AddInstruction(TokenProgram.MintTo(\n        mintAccount.PublicKey,\n        initialAccount.PublicKey,\n        25000,\n        ownerAccount)).\n    AddInstruction(MemoProgram.NewMemo(initialAccount, \"Hello from Sol.Net\")).\n    Build(new List\u003cAccount\u003e{ ownerAccount, mintAccount, initialAccount });\n```\n\n### Transfer a Token to a new Token Account\n\n```c#\n// Initialize the rpc client and a wallet\nvar rpcClient = ClientFactory.GetClient(Cluster.MainNet);\nvar wallet = new Wallet();\n\nvar blockHash = rpcClient.GetRecentBlockHash();\nvar minBalanceForExemptionAcc =\n    rpcClient.GetMinimumBalanceForRentExemption(TokenProgram.TokenAccountDataSize).Result;\n\nvar mintAccount = wallet.GetAccount(21);\nvar ownerAccount = wallet.GetAccount(10);\nvar initialAccount = wallet.GetAccount(22);\nvar newAccount = wallet.GetAccount(23);\n\nvar tx = new TransactionBuilder().\n    SetRecentBlockHash(blockHash.Result.Value.Blockhash).\n    SetFeePayer(ownerAccount).\n    AddInstruction(SystemProgram.CreateAccount(\n        ownerAccount,\n        newAccount,\n        minBalanceForExemptionAcc,\n        TokenProgram.TokenAccountDataSize,\n        TokenProgram.ProgramIdKey)).\n    AddInstruction(TokenProgram.InitializeAccount(\n        newAccount.PublicKey,\n        mintAccount.PublicKey,\n        ownerAccount.PublicKey)).\n    AddInstruction(TokenProgram.Transfer(\n        initialAccount.PublicKey,\n        newAccount.PublicKey,\n        25000,\n        ownerAccount)).\n    AddInstruction(MemoProgram.NewMemo(initialAccount, \"Hello from Sol.Net\")).\n    Build(new List\u003cAccount\u003e{ ownerAccount, newAccount });\n```\n\n### Transaction and Message decoding\n\n```c#\n// Given a message or transaction encoded as base64 or a byte array, you can decode it into their structures\nvar tx = Transaction.Deserialize(txData);\nvar msg = Message.Deserialize(msgData)\n\n// This allows you to sign messages crafted by other components using Solnet\nvar signedTx = Transaction.Populate(msg, new List\u003cbyte[]\u003e { account.Sign(msgData) });\n```\n\n### Programs\n\nThe [Solana.Unity.Programs](https://github.com/bmresearch/Solnet/tree/master/src/Solana.Unity.Programs/) project contains our implementation of several Native and SPL programs,\nfor brevity, they are not exemplified in depth here, but you should check out [Solana.Unity.Examples](https://github.com/bmresearch/Solnet/tree/master/src/Solana.Unity.Examples/) which contains numerous examples,\nsuch as how to do multi signature operations.\n\n### Hello Solana World\n\n```c#\nvar memoInstruction = MemoProgram.NewMemo(wallet.Account, \"Hello Solana World, using Solnet :)\");\n\nvar recentHash = rpcClient.GetRecentBlockHash();\n\nvar tx = new TransactionBuilder().\n    SetFeePayer(wallet.Account).\n    AddInstruction(memoInstruction).\n    SetRecentBlockHash(recentHash.Result.Value.Blockhash).\n    Build(wallet.Account);\n```\n\n### Creating and sending tokens to an Associated Token Account\n\n```c#\nvar recentHash = rpcClient.GetRecentBlockHash();\n\n// By taking someone's address, derive the associated token account for their address and a corresponding mint\n// NOTE: You should check if that person already has an associated token account for that mint!\nPublicKey associatedTokenAccountOwner = new (\"65EoWs57dkMEWbK4TJkPDM76rnbumq7r3fiZJnxggj2G\");\nPublicKey associatedTokenAccount =\n    AssociatedTokenAccountProgram.DeriveAssociatedTokenAccount(associatedTokenAccountOwner, mintAccount);\n\nbyte[] txBytes = new TransactionBuilder().\n    SetRecentBlockHash(recentHash.Result.Value.Blockhash).\n    SetFeePayer(ownerAccount).\n    AddInstruction(AssociatedTokenAccountProgram.CreateAssociatedTokenAccount(\n        ownerAccount,\n        associatedTokenAccountOwner,\n        mintAccount)).\n    AddInstruction(TokenProgram.Transfer(\n        initialAccount,\n        associatedTokenAccount,\n        25000,\n        ownerAccount)).// the ownerAccount was set as the mint authority\n    AddInstruction(MemoProgram.NewMemo(ownerAccount, \"Hello from Sol.Net\")).\n    Build(new List\u003cAccount\u003e {ownerAccount});\n\nstring signature = rpcClient.SendTransaction(txBytes)\n```\n\n### Instruction decoding\n\n```c#\n// For more advanced usage, this package also has an instruction decoder\n// You can deserialize a transaction's message similar to how you would using web3.js\nvar msg = Message.Deserialize(msgBase64);\n\n// And you can decode all of the instructions in that message into a friendly structure\n// which holds the program name, the instruction name, and parameters relevant to the instruction itself\nvar decodedInstructions = InstructionDecoder.DecodeInstructions(msg);\n```\n\n### Display token balances of a wallet\n\n```c#\n// load Solana token list and get RPC client\nvar tokens = TokenInfoResolver.Load();\nvar client = ClientFactory.GetClient(Cluster.MainNet);\n\n// load snapshot of wallet and sub-accounts\nTokenWallet tokenWallet = TokenWallet.Load(client, tokens, ownerAccount);\nvar balances = tokenWallet.Balances();\n\n// show individual token accounts\nvar maxsym = balances.Max(x =\u003e x.Symbol.Length);\nvar maxname = balances.Max(x =\u003e x.TokenName.Length);\nConsole.WriteLine(\"Individual Accounts...\");\nforeach (var account in tokenWallet.TokenAccounts())\n{\n    Console.WriteLine($\"{account.Symbol.PadRight(maxsym)} {account.BalanceDecimal,14} {account.TokenName.PadRight(maxname)} {account.PublicKey} {(account.IsAssociatedTokenAccount ? \"[ATA]\" : \"\")}\");\n}\nConsole.WriteLine();\n```\n\n### Sending an SPL token\n\n```c#\nvar client = ClientFactory.GetClient(Cluster.MainNet, logger);\nvar tokens = New TokenInfoResolver();\nvar wallet = TokenWallet.Load(client, tokens, feePayer);\n\n// find source of funds\nvar source = wallet.TokenAccounts.ForToken(WellKnownTokens.Serum).WithAtLeast(12.75D).FirstOrDefault();\n\n// single-line SPL send - sends 12.75 SRM to target wallet ATA \n// if required, ATA will be created funded by feePayer\nvar sig = wallet.Send(source, 12.75D, target, feePayer);\n```\n\n## Support\n\nConsider supporting us for maintaining the integration with Unity:\n\n* Sol Address: **59JofSV1DiU2rrhFRghvFY2j8Pmhq4cgbEp6dSTJMiHx**\n\nConsider supporting the solnet developers:\n\n* Sol Address: **oaksGKfwkFZwCniyCF35ZVxHDPexQ3keXNTiLa7RCSp**\n\n## Contribution\n\nWe encourage everyone to contribute, submit issues, PRs, discuss. Every kind of help is welcome.\n\n## Solana.Unity Maintainers\n\n* **Gabriele** - [GabrielePicco](https://github.com/GabrielePicco)\n\n## Solnet Maintainers\n\n* **Hugo** - [murlokito](https://github.com/murlokito)\n* **Tiago** - [tiago](https://github.com/tiago18c)\n\nSee also the list of [contributors](https://github.com/bmresearch/Solnet/contributors) who participated in this project.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](https://github.com/bmresearch/Solnet/blob/master/LICENSE) file for details\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagicblock-labs%2Fsolana.unity-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagicblock-labs%2Fsolana.unity-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagicblock-labs%2Fsolana.unity-core/lists"}