2

I have a program lib.rs that at some point make a USDC transfer from one account to another.

It works on mainnet because I put the token_program_id that corresponds to USDC but this token_program_id does not exist anymore when I test with anchor test.

        let transfer_to_store = transfer(
            token_program_id,
            source_pubkey,
            destination_pubkey,
            authority_pubkey,
            signer_pubkeys,
            amount,
        );

Is there a way to test with the same token_program_id ?

1 Answer 1

3

There are a couple ways to load account data from mainnet (or devnet etc) into your localnet every time you run anchor test.

1. Cloning

Under the hood, anchor test uses solana-test-validator. This has an argument you can pass it called --clone whose doc string reads as follows:

    -c, --clone <ADDRESS>...
            Copy an account from the cluster referenced 
            by the --url argument the genesis 
            configuration. If the ledger already exists 
            then this parameter is silently ignored.

You can configure your Anchor.toml so that on every run of anchor test, it effectively adds these flags to its internal solana-test-validator.

2. Loading manually procured JSON data

Similar to what is described above, there is a --account argument:

 --account <ADDRESS FILENAME.JSON>...
            Load an account from the provided JSON file 
            (see `solana account --help` on how to dump 
            an account to file).
            Files are searched for relatively to CWD and 
            tests/fixtures. If the ledger already exists
            then this parameter is silently ignored.

Following the solana account --help, what you'd want to do to e.g. dump the USDC mint account from mainnet is:

$ solana -um account -o usdc_mint.json --output json EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

And there's a similar way to configure your Anchor.toml.

3. Copying Programs

You can use solana program dump to copy a program from mainnet into a local .so file. From there, it's a simple configuration to add that program to your localnet testing as well.

Edit: On the topic of modifying cloned account data

In a reply, OP effectively asks, "how do I modify cloned account data, for example changing an account's mint authority?"

This requires that you have some means to deserialize the data, modify it, and serialize it back into JSON data to be used with technique (2) above. This is not trivial, and the only way I've accomplished this is to write my own crate, which I've open sourced.

In response to your reply, I added an example showing explicitly how to clone and modify the USDC mint. Here's the relevant part below:

    let usdc = LocalnetAccount::new_from_clone::<SplMintAccount, _>(
        &pubkey!("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),
        &RpcClient::new("https://api.mainnet-beta.solana.com".to_string()),
        "usdc_mint.json".to_string(),
        Some(|mint: SplMintAccount| {
            let mut mint = mint.clone();
            mint.mint_authority = COption::Some(test_user.address.clone());
            SplMintAccount::from_spl_mint(mint)
        })
    ).unwrap();

Instead of creating entire test suites like in the example, you could write something simple that creates this LocalnetAccount object, and just calls write_to_validator_json_file on it.

You could also use this technique to just create token accounts with arbitrary USDC balances instead of modifying the mint.

Note that the T: AccountSerialize + AccountDeserialize that I am using in this example is not the Anchor SPL mint directly, but my own wrapper struct (it serializes all the same). This is because Anchor SPL types have an empty impl AccountSerialize, which by default do nothing.

2
  • Thanks for the great answer, I still have a question. So I can add a program from the mainnet with the 3 techniques you showed me. In my test, I copied the USDC mint program. I would like to give some USDC to an account to test the function in my rust program that interest with USDC. I obviously do not have the mint authority so how am I supposed to test ? Commented Dec 11, 2022 at 13:07
  • See edited answer above. I'll add an example to my repo in a bit.
    – HelmetFace
    Commented Dec 11, 2022 at 16:14

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.