walletCurrent = new SolanaWalletAdapterWebGL(options, RpcCluster.MainNet, "https://api.metaplex.solana.com/", null, true);
accountCurrent = await walletCurrent.Login();
public async void OnClickMint()
{
var signature = await ServiceFactory.Resolve<NftMintingService>().MintNftWithMetaData(
"https://cryptodogs.fun/nfts/jsons/cryptoDogsFreeMintGolden.json",
"CryptoDogs Free Mint | Golden", "CDFMG");
}
And this is the code for NftMintingService.cs which i touched the initial parts of it so i could integrate it with the wallet login from MagicBlock SDK:
public async Task<string> MintNftWithMetaData(string metaDataUri, string name, string symbol, Action<bool> mintDone = null)
{
//var walletHolderService = ServiceFactory.Resolve<WalletHolderService>();
var wallet = ConnectWallet.walletCurrent;
var rpcClient = ConnectWallet.walletCurrent.ActiveRpcClient;
Account mintAccount = new Account();
Account tokenAccount = new Account();
var fromAccount = ConnectWallet.walletCurrent.Account;
Debug.Log("KEYBITES");
Debug.Log(ConnectWallet.walletCurrent.Account.PrivateKey.KeyBytes.Length);
// To be able to sign the transaction while using the transaction builder we need to have a private key set in the signing account.
// TODO: I will try to make this nicer later.
//fromAccount = new Account(ConnectWallet.walletCurrent.Account.PrivateKey.KeyBytes,
//ConnectWallet.walletCurrent.Account.PublicKey.KeyBytes);
RequestResult<ResponseValue<ulong>> balance =
await rpcClient.GetBalanceAsync(wallet.Account.PublicKey, Commitment.Confirmed);
// TODO: Check if there is enough sol in the wallet to mint.
if (balance.Result != null && balance.Result.Value < SolanaUtils.SolToLamports / 10)
{
LoggingService.Log("Sol balance is low. Minting may fail", true);
}
Debug.Log($"Balance: {balance.Result.Value} ");
Debug.Log($"Mint key : {mintAccount.PublicKey} ");
var blockHash = await rpcClient.GetRecentBlockHashAsync();
var rentMint = await rpcClient.GetMinimumBalanceForRentExemptionAsync(
TokenProgram.MintAccountDataSize,
Commitment.Confirmed
);
var rentToken = await rpcClient.GetMinimumBalanceForRentExemptionAsync(
TokenProgram.TokenAccountDataSize,
Commitment.Confirmed
);
Debug.Log($"Token key : {tokenAccount.PublicKey} ");
//2. create a mint and a token
var createMintAccount = SystemProgram.CreateAccount(
fromAccount,
mintAccount,
rentMint.Result,
TokenProgram.MintAccountDataSize,
TokenProgram.ProgramIdKey
);
var initializeMint = TokenProgram.InitializeMint(
mintAccount.PublicKey,
0,
fromAccount.PublicKey,
fromAccount.PublicKey
);
var createTokenAccount = SystemProgram.CreateAccount(
fromAccount,
tokenAccount,
rentToken.Result,
TokenProgram.TokenAccountDataSize,
TokenProgram.ProgramIdKey
);
var initializeMintAccount = TokenProgram.InitializeAccount(
tokenAccount.PublicKey,
mintAccount.PublicKey,
fromAccount.PublicKey
);
var mintTo = TokenProgram.MintTo(
mintAccount.PublicKey,
tokenAccount,
1,
fromAccount.PublicKey
);
// If you freeze the account the users will not be able to transfer the NFTs anywhere or burn them
/*var freezeAccount = TokenProgram.FreezeAccount(
tokenAccount,
mintAccount,
fromAccount,
TokenProgram.ProgramIdKey
);*/
// PDA Metadata
PublicKey metadataAddressPDA;
byte nonce;
PublicKey.TryFindProgramAddress(
new List<byte[]>()
{
Encoding.UTF8.GetBytes("metadata"),
MetadataProgram.ProgramIdKey,
mintAccount.PublicKey
},
MetadataProgram.ProgramIdKey,
out metadataAddressPDA,
out nonce
);
Console.WriteLine($"PDA METADATA: {metadataAddressPDA}");
// PDA master edition (Makes sure there can only be one minted)
PublicKey masterEditionAddress;
PublicKey.TryFindProgramAddress(
new List<byte[]>()
{
Encoding.UTF8.GetBytes("metadata"),
MetadataProgram.ProgramIdKey,
mintAccount.PublicKey,
Encoding.UTF8.GetBytes("edition")
},
MetadataProgram.ProgramIdKey,
out masterEditionAddress,
out nonce
);
Console.WriteLine($"PDA MASTER: {masterEditionAddress}");
// Craetors
var creator1 = new Creator(fromAccount.PublicKey, 100);
// Meta Data
var data = new MetadataV1()
{
name = name,
symbol = symbol,
uri = metaDataUri,
creators = new List<Creator>() { creator1 },
sellerFeeBasisPoints = 77,
};
var signers = new List<Account> { fromAccount, mintAccount, tokenAccount };
var transactionBuilder = new TransactionBuilder()
.SetRecentBlockHash(blockHash.Result.Value.Blockhash)
.SetFeePayer(fromAccount)
.AddInstruction(createMintAccount)
.AddInstruction(initializeMint)
.AddInstruction(createTokenAccount)
.AddInstruction(initializeMintAccount)
.AddInstruction(mintTo)
//.AddInstruction(freezeAccount)
.AddInstruction(
MetadataProgram.CreateMetadataAccount(
metadataAddressPDA, // PDA
mintAccount,
fromAccount.PublicKey,
fromAccount.PublicKey,
fromAccount.PublicKey, // update Authority
data, // DATA
true,
true // ISMUTABLE
)
)
.AddInstruction(
MetadataProgram.SignMetada(
metadataAddressPDA,
creator1.key
)
)
.AddInstruction(
MetadataProgram.PuffMetada(
metadataAddressPDA
)
)
.AddInstruction(
MetadataProgram.CreateMasterEdition(
1,
masterEditionAddress,
mintAccount,
fromAccount.PublicKey,
fromAccount.PublicKey,
fromAccount.PublicKey,
metadataAddressPDA
)
);
byte[] transaction = transactionBuilder.Build(signers);
Transaction deserializedTransaction = Transaction.Deserialize(transaction);
Transaction signedTransaction =
await ConnectWallet.walletCurrent.SignTransaction(deserializedTransaction);
var transactionSignature =
await ConnectWallet.walletCurrent.ActiveRpcClient.SendTransactionAsync(
Convert.ToBase64String(signedTransaction.Serialize()), false, Commitment.Finalized);
if (!transactionSignature.WasSuccessful)
{
mintDone?.Invoke(false);
LoggingService
.Log("Mint was not successfull: " + transactionSignature.Reason, true);
}
else
{
ServiceFactory.Resolve<TransactionService>().CheckSignatureStatus(transactionSignature.Result,
success =>
{
mintDone?.Invoke(success);
LoggingService.Log("Mint Successfull! Woop woop!", true);
MessageRouter.RaiseMessage(new NftMintFinishedMessage());
}, null, TransactionService.TransactionResult.finalized);
}
Debug.Log(transactionSignature.Reason);
return transactionSignature.Result;
}
42 sendTransaction Sending request: {"method":"sendTransaction","params":["A7kZz5+BnfYE8QG4qkCDwQZnvT8WPrhl2X0G4VoKiPESp7JxMrq7DGSWX5gorknQ/uE8/8LJBKwBCsaFlLA2fgj9oQF8VUbSLVROgZCm4nqW3Bh1Sw+odYn9dKhkMJCZeykjnUJMvTvSt8KtnUd3Q8/dSnRhDmEJejHhEeyfjA8AdGjfkV21PPmrvg0f2W6oJwRmSZEuP6oI0pa8eqV/gt90fA+SOqCfCgn9KFyIScPleNOJ9PUCdDX9qyhbxadACgMABAnNeWp9Sce4IRgzH852q2WEug4CN1lqzRu1ZNK3TzBCCk9t1UZx6Wu3gglWGHaTF3G0dGxv1NpQ+rX7aVBSnuUVquCd3qTkHveqcZDRNvYeDvSToGIqjkNpE5E+3C5gn8lT9/wS4T4vGy5EAz5ARESO9fdO5B6UInCxy6Owj0kkepEhBGyZo17nKNZ/2XXwJJX1XwhLjLhoAGBHoNpi78oPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGp9UXGSxcUSGMyUw9SvF/WNruCJuh/UTj29mKAAAAAAbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpC3BlsePRfEU4nVJ/awTDzVi4bHMaoP21SbbRvAP4KUZkfYIEZCt5u4H2ZsfuO3HVvdvVgXQIZarOhVpwwugv+gkFAgABNAAAAABgTRYAAAAAAFIAAAAAAAAABt324ddloZPZy+FGzut5rBy0he1fWzeROoz1hX7/AKkHAgEGQwAAzXlqfUnHuCEYMx/OdqtlhLoOAjdZas0btWTSt08wQgoBzXlqfUnHuCEYMx/OdqtlhLoOAjdZas0btWTSt08wQgoFAgACNAAAAADwHR8AAAAAAKUAAAAAAAAABt324ddloZPZy+FGzut5rBy0he1fWzeROoz1hX7/AKkHBAIBAAYBAQcDAQIACQcBAAAAAAAAAAgHBAEAAAAFBpgBAB0AAABDcnlwdG9Eb2dzIEZyZWUgTWludCB8IEdvbGRlbgUAAABDREZNRz8AAABodHRwczovL2NyeXB0b2RvZ3MuZnVuL25mdHMvanNvbnMvY3J5cHRvRG9nc0ZyZWVNaW50R29sZGVuLmpzb25NAAEBAAAAzXlqfUnHuCEYMx/OdqtlhLoOAjdZas0btWTSt08wQgoAZAEIAgQAAQcIAQQBDggJAwEAAAAEBwUGCgoBAQAAAAAAAAA=",{"encoding":"base64"}],"jsonrpc":"2.0","id":42}
mywebsite.framework.js:2937 Found NO interfaces on host .
mywebsite.framework.js:2937 Player connection [] Multi
```-casting "" to [225.0.0.222:54997]...
mywebsite.loader.js:77 42 sendTransaction Result: {"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: Error processing Instruction 5: Failed to serialize or deserialize account data: Unknown","data":{"accounts":null,"err":{"InstructionError":[5,{"BorshIoError":"Unknown"}]},"logs":["Program 11111111111111111111111111111111 invoke [1]","Program 11111111111111111111111111111111 success","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]","Program log: Instruction: InitializeMint","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2967 of 1400000 compute units","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success","Program 11111111111111111111111111111111 invoke [1]","Program 11111111111111111111111111111111 success","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]","Program log: Instruction: InitializeAccount","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4523 of 1397033 compute units","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]","Program log: Instruction: MintTo","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4535 of 1392510 compute units","Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success","Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s invoke [1]","Program log: Error: BorshIoError","Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s consumed 4273 of 1387975 compute units","Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s failed: Failed to serialize or deserialize account data: Unknown"],"unitsConsumed":12025}},"id":42}
mywebsite.loader.js:77
mywebsite.loader.js:77 42 sendTransaction Caught exception: Unexpected token when deserializing object: StartArray. Path 'error.data.logs', line 1, position 262.
mywebsite.framework.js:2937 Mint was not successfull: Unable to parse json.
mywebsite.framework.js:2937 Unable to parse json.