Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems to Mint an NFT from Unity #7

Closed
BlackDemonZyT opened this issue May 11, 2023 · 7 comments
Closed

Problems to Mint an NFT from Unity #7

BlackDemonZyT opened this issue May 11, 2023 · 7 comments

Comments

@BlackDemonZyT
Copy link

BlackDemonZyT commented May 11, 2023

Hello, i have the following problem when trying to Mint an NFT from Unity:
See the picture: https://i.imgur.com/oaLuf18.png

The users login in their wallets with:

        walletCurrent = new SolanaWalletAdapterWebGL(options, RpcCluster.MainNet, "https://api.metaplex.solana.com/", null, true);
        accountCurrent = await walletCurrent.Login();

I call the method with the following:

    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;
        }

The console debugs the following:

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.
@Woody4618
Copy link
Owner

Woody4618 commented May 11, 2023

Hey, yeah sorry i didnt get to upgrade it to the new unity sdk version. You already found out you dont need to change the private key in fromAccount anymore and that metadatav2 doesnt exist anymore. 👍
Maybe check the meta data if its correct or try metadata v3. Also check if your name and symbol are not too long. You could also check if puffmetadata is still needed.

@BlackDemonZyT
Copy link
Author

Hi! How can i specify to use metadatav3 in my code? I do not understand 😅

@BlackDemonZyT
Copy link
Author

Hello, do you have Whatsapp, telegram or Discord in order to comunicate quickly? My project is pretty big and i need urgent help.

@Woody4618
Copy link
Owner

Woody4618 commented May 13, 2023

Hey did you check the name and symbol length? There is a max limit on name length.

In general its probably better to ask in the magic block sdk repo now, since i dont have much time to maintain the solplay sdk and its behind in the sdk version.

This code here I just tested and it works using magic block unity sdk version 0.1.0:
Its not creating a master edition. But not sure if you need it. Depends on what you plan to do.

public async Task<string> MintNftWithMetaData(string metaDataUri, string name, string symbol, Action<bool> mintDone = null)
        {
            var walletHolderService = ServiceFactory.Resolve<WalletHolderService>();
            var wallet = walletHolderService.BaseWallet;
            var rpcClient = walletHolderService.BaseWallet.ActiveRpcClient;

            Account mintAccount = new Account();
            Account tokenAccount = new Account();

            var fromAccount = walletHolderService.BaseWallet.Account;

            RequestResult<ResponseValue<ulong>> balance =
                await rpcClient.GetBalanceAsync(wallet.Account.PublicKey, Commitment.Confirmed);

            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, false);

            // Meta Data
            var data = new Metadata()
            {
                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
                        TokenStandard.NonFungible,
                        true,
                        true, // ISMUTABLE,
                        masterEditionKey: null,
                        1,
                        0UL,
                        MetadataVersion.V3
                    )
                )
                .AddInstruction(
                    MetadataProgram.SignMetadata(
                        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 walletHolderService.BaseWallet.SignTransaction(deserializedTransaction);

            var transactionSignature =
                await walletHolderService.BaseWallet.ActiveRpcClient.SendTransactionAsync(
                    Convert.ToBase64String(signedTransaction.Serialize()), true, 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.confirmed);
            }

            Debug.Log(transactionSignature.Reason);
            Debug.Log(transactionSignature.Result);
            return transactionSignature.Result;
        }`

@Woody4618
Copy link
Owner

Doesnt seem to work with wallet adapter though for some reason only with ingame wallet. Ill write the magic block devs.

@BlackDemonZyT
Copy link
Author

Alright, i appreciate your help, i hope it gets fixed soon, there are people waiting for me xD

@Woody4618
Copy link
Owner

Hey, its fixed in Unity SDK version 0.1.1 please update and this is the updated mint code:

public async Task<string> MintNftWithMetaData(string metaDataUri, string name, string symbol, Action<bool> mintDone = null)
        {
            var walletHolderService = ServiceFactory.Resolve<WalletHolderService>();
            var wallet = walletHolderService.BaseWallet;
            var rpcClient = walletHolderService.BaseWallet.ActiveRpcClient;

            Account mint = new Account();
            var associatedTokenAccount = AssociatedTokenAccountProgram
                .DeriveAssociatedTokenAccount(wallet.Account, mint.PublicKey);
            
            var fromAccount = walletHolderService.BaseWallet.Account;

            RequestResult<ResponseValue<ulong>> balance =
                await rpcClient.GetBalanceAsync(wallet.Account.PublicKey, Commitment.Confirmed);

            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 : {mint.PublicKey} ");

            var blockHash = await rpcClient.GetRecentBlockHashAsync();
            var rentMint = await rpcClient.GetMinimumBalanceForRentExemptionAsync(
                TokenProgram.MintAccountDataSize,
                Commitment.Confirmed
            );
            var rentToken = await rpcClient.GetMinimumBalanceForRentExemptionAsync(
                TokenProgram.TokenAccountDataSize,
                Commitment.Confirmed
            );


            //2. create a mint and a token
            var createMintAccount = SystemProgram.CreateAccount(
                fromAccount,
                mint,
                rentMint.Result,
                TokenProgram.MintAccountDataSize,
                TokenProgram.ProgramIdKey
            );
            var initializeMint = TokenProgram.InitializeMint(
                mint.PublicKey,
                0,
                fromAccount.PublicKey,
                fromAccount.PublicKey
            );
            var createTokenAccount = AssociatedTokenAccountProgram.CreateAssociatedTokenAccount(
                fromAccount,
                fromAccount,
                mint.PublicKey);

            var mintTo = TokenProgram.MintTo(
                mint.PublicKey,
                associatedTokenAccount,
                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,
                    mint.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,
                    mint.PublicKey,
                    Encoding.UTF8.GetBytes("edition"),
                },
                MetadataProgram.ProgramIdKey,
                out masterEditionAddress,
                out nonce
            );
            Console.WriteLine($"PDA MASTER: {masterEditionAddress}");

            // Craetors
            var creator1 = new Creator(fromAccount.PublicKey, 100, false);

            // Meta Data
            var data = new Metadata()
            {
                name = name,
                symbol = symbol,
                uri = metaDataUri,
                creators = new List<Creator>() {creator1},
                sellerFeeBasisPoints = 77
            };

            var signers = new List<Account> {fromAccount, mint};
            var transactionBuilder = new TransactionBuilder()
                .SetRecentBlockHash(blockHash.Result.Value.Blockhash)
                .SetFeePayer(fromAccount)
                .AddInstruction(createMintAccount)
                .AddInstruction(initializeMint)
                .AddInstruction(createTokenAccount)
                .AddInstruction(mintTo)
                //.AddInstruction(freezeAccount)
                .AddInstruction(
                    MetadataProgram.CreateMetadataAccount(
                        metadataAddressPDA, // PDA
                        mint,
                        fromAccount.PublicKey,
                        fromAccount.PublicKey,
                        fromAccount.PublicKey, // update Authority 
                        data, // DATA
                        TokenStandard.NonFungible,
                        true,
                        true, // ISMUTABLE,
                        masterEditionKey: null,
                        1,
                        0UL,
                        MetadataVersion.V3
                    )
                )
                .AddInstruction(
                    MetadataProgram.SignMetadata(
                        metadataAddressPDA,
                        creator1.key
                    )
                )
               .AddInstruction(
                    MetadataProgram.PuffMetada(
                        metadataAddressPDA
                    )
                )
                /*.AddInstruction(
                    MetadataProgram.CreateMasterEdition(
                        1,
                        masterEditionAddress,
                        mintAccount,
                        fromAccount.PublicKey,
                        fromAccount.PublicKey,
                        fromAccount.PublicKey,
                        metadataAddressPDA
                    )
                )*/;

            var tx = Transaction.Deserialize(transactionBuilder.Build(new List<Account> {fromAccount, mint}));
            var res = await walletHolderService.BaseWallet.SignAndSendTransaction(tx, true, Commitment.Confirmed);
            Debug.Log(res.Result);

            if (!res.WasSuccessful)
            {
                mintDone?.Invoke(false);
                LoggingService
                    .Log("Mint was not successfull: " + res.Reason, true);
            }
            else
            {
                ServiceFactory.Resolve<TransactionService>().CheckSignatureStatus(res.Result,
                    success =>
                    {
                        mintDone?.Invoke(success);
                        LoggingService.Log("Mint Successfull! Woop woop!", true);
                        MessageRouter.RaiseMessage(new NftMintFinishedMessage());
                    }, null, TransactionService.TransactionResult.confirmed);
            }

            return res.Result;
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants