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 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.