Skip to main content
adds example
Source Link
HelmetFace
  • 1.8k
  • 4
  • 15

In that repo is an example ofresponse to your reply, I added an example showing explicitly how to spin up account data wholeclothclone and modify the USDC mint. Here's the relevant part below:

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

In this case, test_user.address is the Pubkey of the mint authority. Instead of creating entire test suites like in the example, you could write something simple that creates this newLocalnetAccount constructor aboveobject, you'd useand just new_from_clone, which allows one to modify the cloned data however you see fitcalls write_to_validator_json_file on it. I will add an example showing explicitly how

You could also use this technique to clone and modify thejust 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.

In that repo is an example of how to spin up account data wholecloth:

    let test_mint = LocalnetAccount::new(
        Pubkey::new_unique(),
        "mint.json".to_string(),
        spl_mint_account(&test_user.address, 0, 9),
    );

In this case, test_user.address is the Pubkey of the mint authority. Instead of the new constructor above, you'd use new_from_clone, which allows one to modify the cloned data however you see fit. I will add an example showing explicitly how to clone and modify the USDC mint.

Note that the T: AccountSerialize + AccountDeserialize that I am using is not the Anchor SPL mint, but my own wrapper struct. This is because Anchor SPL types have an empty impl AccountSerialize, which by default do nothing.

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.

Adds details about modifying mint authority.
Source Link
HelmetFace
  • 1.8k
  • 4
  • 15

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 that repo is an example of how to spin up account data wholecloth:

    let test_mint = LocalnetAccount::new(
        Pubkey::new_unique(),
        "mint.json".to_string(),
        spl_mint_account(&test_user.address, 0, 9),
    );

In this case, test_user.address is the Pubkey of the mint authority. Instead of the new constructor above, you'd use new_from_clone, which allows one to modify the cloned data however you see fit. I will add an example showing explicitly how to clone and modify the USDC mint.

Note that the T: AccountSerialize + AccountDeserialize that I am using is not the Anchor SPL mint, but my own wrapper struct. This is because Anchor SPL types have an empty impl AccountSerialize, which by default do nothing.

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 that repo is an example of how to spin up account data wholecloth:

    let test_mint = LocalnetAccount::new(
        Pubkey::new_unique(),
        "mint.json".to_string(),
        spl_mint_account(&test_user.address, 0, 9),
    );

In this case, test_user.address is the Pubkey of the mint authority. Instead of the new constructor above, you'd use new_from_clone, which allows one to modify the cloned data however you see fit. I will add an example showing explicitly how to clone and modify the USDC mint.

Note that the T: AccountSerialize + AccountDeserialize that I am using is not the Anchor SPL mint, but my own wrapper struct. This is because Anchor SPL types have an empty impl AccountSerialize, which by default do nothing.

Source Link
HelmetFace
  • 1.8k
  • 4
  • 15

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.