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

Combine Immutable Owner extension and Non-transferable extension together fail. #215

Open
andrewzhang97 opened this issue May 21, 2024 · 0 comments

Comments

@andrewzhang97
Copy link

andrewzhang97 commented May 21, 2024

Following guides, https://solana.com/developers/guides/token-extensions/non-transferable#build-instructions and https://solana.com/developers/guides/token-extensions/immutable-owner#conclusion

They can work separately well. However, if I put them together, immutable-owner always show Error processing Instruction 2: invalid account data for instruction.
My code is based on guide.

import * as anchor from "@coral-xyz/anchor";
import {Program, web3} from "@coral-xyz/anchor";
import { ZkmeSol } from "../target/types/zkme_sol";
import {it} from "mocha";
import {Connection, Keypair, sendAndConfirmTransaction, SystemProgram, Transaction} from "@solana/web3.js";
import {
    AuthorityType,
    createInitializeAccountInstruction,
    createInitializeImmutableOwnerInstruction,
    createInitializeMintInstruction,
    createInitializeNonTransferableMintInstruction,
    createMint,
    ExtensionType,
    getAccountLen, getMintLen, setAuthority,
    TOKEN_2022_PROGRAM_ID
} from "@solana/spl-token";
import {min} from "bn.js";

//anchor test
describe("zkme_sol", () => {
    // Configure the client to use the local cluster.
    anchor.setProvider(anchor.AnchorProvider.env());

    const program = anchor.workspace.ZkmeSol as Program<ZkmeSol>;
    const zkmeSeed = anchor.utils.bytes.utf8.encode("zkme_conf");

    let adminPubKey;

    before( async () => {
        [adminPubKey] = await anchor.web3.PublicKey.findProgramAddress(
            [zkmeSeed, anchor.AnchorProvider.env().wallet.publicKey.toBytes()],
            program.programId
        );
    });
    it( "Is createAdmin", async () => {
        const payer = web3.Keypair.generate();

// Connection to devnet cluster
        const connection = new Connection('http://127.0.0.1:8899', 'confirmed');

// Transaction signature returned from sent transaction
        let transactionSignature: string;

        const airdropSignature = await connection.requestAirdrop(
            payer.publicKey,
            web3.LAMPORTS_PER_SOL, // 1 SOL
        );
        await connection.confirmTransaction(airdropSignature);
        const balanceA = await connection.getBalance(payer.publicKey)
        console.log("airdropSignature success", balanceA);


        // Authority that can mint new tokens
        const mintAuthority = payer.publicKey;
// Decimals for Mint Account
        const decimals = 2;



        

        const mintLen = getMintLen([ExtensionType.NonTransferable]);
// Minimum lamports required for Mint Account
        let lamports = await connection.getMinimumBalanceForRentExemption(mintLen);

        const mintKeypair = Keypair.generate();
// Address for Mint Account
        const mint = mintKeypair.publicKey;

        const createAccountInstructionA = SystemProgram.createAccount({
            fromPubkey: payer.publicKey, // Account that will transfer lamports to created account
            newAccountPubkey: mint, // Address of the account to create
            space: mintLen, // Amount of bytes to allocate to the created account
            lamports, // Amount of lamports transferred to created account
            programId: TOKEN_2022_PROGRAM_ID, // Program assigned as owner of created account
        });
        console.log("createAccountInstruction",createAccountInstructionA)

// Instruction to initialize the NonTransferable Extension
        const initializeNonTransferableMintInstructionA =
            createInitializeNonTransferableMintInstruction(
                mint, // Mint Account address
                TOKEN_2022_PROGRAM_ID, // Token Extension Program ID
            );
        console.log("initializeNonTransferableMintInstruction",initializeNonTransferableMintInstructionA)

        // Instruction to initialize Mint Account data
        const initializeMintInstructionA = createInitializeMintInstruction(
            mint, // Mint Account Address
            decimals, // Decimals of Mint
            anchor.AnchorProvider.env().publicKey, // Designated Mint Authority
            null, // Optional Freeze Authority
            TOKEN_2022_PROGRAM_ID, // Token Extension Program ID
        );
        console.log("initializeMintInstruction",initializeMintInstructionA)
        // Add instructions to new transaction
        const transactionA = new Transaction().add(
            createAccountInstructionA,
            initializeNonTransferableMintInstructionA,
            initializeMintInstructionA,
        );
        console.log("mint:",mint)

// Send transaction
        transactionSignature = await sendAndConfirmTransaction(
            connection,
            transactionA,
            [payer, mintKeypair], // Signers
        );

        console.log(
            "transactionSignature",transactionSignature
        )








        // Random keypair to use as owner of Token Account
        const tokenAccountKeypair = Keypair.generate();
// Address for Token Account
        const tokenAccount = tokenAccountKeypair.publicKey;

        // Size of Token Account with extension
        const accountLen = getAccountLen([ExtensionType.ImmutableOwner]);
// Minimum lamports required for Token Account
         lamports = await connection.getMinimumBalanceForRentExemption(accountLen);


        // Instruction to invoke System Program to create new account
        const createAccountInstruction = SystemProgram.createAccount({
            fromPubkey: payer.publicKey, // Account that will transfer lamports to created account
            newAccountPubkey: tokenAccount, // Address of the account to create
            space: accountLen, // Amount of bytes to allocate to the created account
            lamports, // Amount of lamports transferred to created account
            programId: TOKEN_2022_PROGRAM_ID, // Program assigned as owner of created account
        });

        // Instruction to initialize the ImmutableOwner Extension
        const initializeImmutableOwnerInstruction =
            createInitializeImmutableOwnerInstruction(
                tokenAccount, // Token Account address
                TOKEN_2022_PROGRAM_ID, // Token Extension Program ID
            );

        // Instruction to initialize Token Account data
        const initializeAccountInstruction = createInitializeAccountInstruction(
            tokenAccount, // Token Account Address
            mint, // Mint Account
            payer.publicKey, // Token Account Owner
            TOKEN_2022_PROGRAM_ID, // Token Extension Program ID
        );
        console.log("mint:",mint)

        // Add instructions to new transaction
        const transaction = new Transaction().add(
            createAccountInstruction,
           // initializeImmutableOwnerInstruction,
            initializeAccountInstruction,
        );

// Send transaction
        transactionSignature = await sendAndConfirmTransaction(
            connection,
            transaction,
            [payer, tokenAccountKeypair], // Signers
        );

        console.log(
            "\nCreate Token Account:",
            `https://solana.fm/tx/${transactionSignature}?cluster=devnet-solana`,
        );




        


    })





    });

Proposed Solution

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

1 participant