-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcreate_mint.rs
More file actions
95 lines (85 loc) · 3.35 KB
/
create_mint.rs
File metadata and controls
95 lines (85 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use light_client::{
indexer::{AddressWithTree, Indexer},
rpc::Rpc,
};
use light_program_test::{LightProgramTest, ProgramTestConfig};
use light_token::instruction::{
derive_mint_compressed_address, find_mint_address, CreateMint, CreateMintParams,
DEFAULT_RENT_PAYMENT, DEFAULT_WRITE_TOP_UP,
};
use light_token_interface::{
instructions::extensions::{
token_metadata::TokenMetadataInstructionData, ExtensionInstructionData,
},
state::AdditionalMetadata,
};
use solana_sdk::{signature::Keypair, signer::Signer};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut rpc = LightProgramTest::new(ProgramTestConfig::new(false, None)).await?;
let payer = rpc.get_payer().insecure_clone();
let mint_seed = Keypair::new();
let decimals = 9u8;
// Get address tree to store compressed address for when mint turns inactive
// We must create a compressed address at creation to ensure the mint does not exist yet
let address_tree = rpc.get_address_tree_v2();
// Get state tree to store mint when inactive
let output_queue = rpc.get_random_state_tree_info().unwrap().queue;
// Derive mint addresses
let compression_address =
derive_mint_compressed_address(&mint_seed.pubkey(), &address_tree.tree);
let mint = find_mint_address(&mint_seed.pubkey()).0; // on-chain Mint PDA
// Fetch validity proof to proof address does not exist yet
let rpc_result = rpc
.get_validity_proof(
vec![],
vec![AddressWithTree {
address: compression_address,
tree: address_tree.tree,
}],
None,
)
.await
.unwrap()
.value;
// Build CreateMintParams with token metadata extension
let params = CreateMintParams {
decimals,
address_merkle_tree_root_index: rpc_result.addresses[0].root_index, // stores mint compressed address
mint_authority: payer.pubkey(),
proof: rpc_result.proof.0.unwrap(),
compression_address, // address for compression when mint turns inactive
mint,
bump: find_mint_address(&mint_seed.pubkey()).1,
freeze_authority: None,
extensions: Some(vec![ExtensionInstructionData::TokenMetadata(
TokenMetadataInstructionData {
update_authority: Some(payer.pubkey().to_bytes().into()),
name: b"Example Token".to_vec(),
symbol: b"EXT".to_vec(),
uri: b"https://example.com/metadata.json".to_vec(),
additional_metadata: Some(vec![AdditionalMetadata {
key: b"type".to_vec(),
value: b"example".to_vec(),
}]),
},
)]),
rent_payment: DEFAULT_RENT_PAYMENT, // 24h of rent
write_top_up: DEFAULT_WRITE_TOP_UP, // 3h of rent
};
// Build and send instruction (mint_seed must sign)
let create_mint_instruction = CreateMint::new(
params,
mint_seed.pubkey(),
payer.pubkey(),
address_tree.tree,
output_queue,
)
.instruction()?;
let sig = rpc
.create_and_send_transaction(&[create_mint_instruction], &payer.pubkey(), &[&payer, &mint_seed])
.await?;
let data = rpc.get_account(mint).await?;
println!("Mint: {} exists: {} Tx: {sig}", mint, data.is_some());
Ok(())
}