0

I have a workflow such that an ATA needs to be passed into an instruction in a contract but I would like to check to see whether or not i need to initialize it first on the client (there may be instances where one is expected but has not yet been initialized).

What RPC methods should I use to whether or not the token account has been initialized and what should the workflow look like?

I assume it has something to do with provider.getAccountInfo. If an account does not exist, what will the response look like? Would it be null or will the RPC call error out?

4 Answers 4

2

The easiest thing to do would be to use getOrCreateAssociatedTokenAccount on the client. This will get the account if it exists, and create it if required. See https://solana-labs.github.io/solana-program-library/token/js/modules.html#getOrCreateAssociatedTokenAccount

If you need to do something else if it doesn't exist, you can take a look at the source code of that function to see how it works: https://github.dev/solana-labs/solana-program-library/blob/80f8890dd35cc51f5836868a71f08721635a6b5f/token/js/src/actions/getOrCreateAssociatedTokenAccount.ts#L46

The main structure is this:

let account: Account;
try {
  account = await getAccount(connection, associatedToken, commitment, programId);
} catch (error: unknown) {
  // TokenAccountNotFoundError can be possible if the associated address has already received some lamports,
  // becoming a system account. Assuming program derived addressing is safe, this is the only case for the
  // TokenInvalidAccountOwnerError in this code path.
  if (error instanceof TokenAccountNotFoundError || error instanceof TokenInvalidAccountOwnerError) {
    // your logic if the account doesn't exist yet
  }    
2

From the solana cookbook example, using the ts package "@solana/spl-token": "^0.2.0"

import { getAccount } from "@solana/spl-token";
...
let tokenAccount = await getAccount(connection, tokenAccountPubkey);

Presumably you can wrap this in a try catch. I'm not sure what error this returns if it can't load the token account data but please feel free to update this answer once you find out!

0

You can use getOrCreateAssociatedTokenAccount from @solana/spl-token module.

import {getOrCreateAssociatedTokenAccount} from '@solana/spl-token';

// get or create an account associated with the mint
const tokenAccount = await getOrCreateAssociatedTokenAccount(connection, payer, mint, payer.publicKey);
console.log(`Token account created: ${tokenAccount.address.toBase58()}`);
0

This will give you the TransactionInstruction if the ATA doesn't exist:

export async function getOrCreateTokenAccountInstruction(mint: PublicKey, user: PublicKey, connection: Connection, payer: PublicKey|null = null): Promise<TransactionInstruction | null> {
    const userTokenAccountAddress = await getAssociatedTokenAddress(mint, user, false);
    const userTokenAccount = await connection.getParsedAccountInfo(userTokenAccountAddress);
    if (userTokenAccount.value === null) {
        return createAssociatedTokenAccountInstruction(payer ? payer : user, userTokenAccountAddress, user, mint);
    } else {
        return null;
    }
}

When you pass it to the Transaction run a filter incase it returned null:

[tokenInstructions, instructions].filter((i) => i)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.