forked from solana-developers/pirate-bootcamp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path3.createTokenWithMetadata.ts
192 lines (164 loc) · 5.76 KB
/
3.createTokenWithMetadata.ts
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/**
* Demonstrates how to create a SPL token and store it's metadata on chain (using the Metaplex MetaData program)
*/
// import custom helpers for demos
import { payer, testWallet, connection } from "@/lib/vars";
import {
buildTransaction,
explorerURL,
extractSignatureFromFailedTransaction,
printConsoleSeparator,
savePublicKeyToFile,
} from "@/lib/helpers";
import { Keypair, PublicKey, SystemProgram, clusterApiUrl } from "@solana/web3.js";
import {
MINT_SIZE,
TOKEN_PROGRAM_ID,
createAccount,
createInitializeMint2Instruction,
createMint,
mintTo,
} from "@solana/spl-token";
import {
PROGRAM_ID as METADATA_PROGRAM_ID,
createCreateMetadataAccountV3Instruction,
} from "@metaplex-foundation/mpl-token-metadata";
(async () => {
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
console.log("Payer address:", payer.publicKey.toBase58());
console.log("Test wallet address:", testWallet.publicKey.toBase58());
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// generate a new keypair to be used for our mint
const mintKeypair = Keypair.generate();
console.log("Mint address:", mintKeypair.publicKey.toBase58());
// define the assorted token config settings
const tokenConfig = {
// define how many decimals we want our tokens to have
decimals: 2,
//
name: "Seven Seas Gold",
//
symbol: "GOLD",
//
uri: "https://thisisnot.arealurl/info.json",
};
// image url: https://bafybeihkc3tu4ugc5camayoqw7tl2lahtzgm2kpiwps3itvfsv7zcmceji.ipfs.nftstorage.link/
/**
* Build the 2 instructions required to create the token mint:
* - standard "create account" to allocate space on chain
* - initialize the token mint
*/
// create instruction for the token mint account
const createMintAccountInstruction = SystemProgram.createAccount({
fromPubkey: payer.publicKey,
newAccountPubkey: mintKeypair.publicKey,
// the `space` required for a token mint is accessible in the `@solana/spl-token` sdk
space: MINT_SIZE,
// store enough lamports needed for our `space` to be rent exempt
lamports: await connection.getMinimumBalanceForRentExemption(MINT_SIZE),
// tokens are owned by the "token program"
programId: TOKEN_PROGRAM_ID,
});
// Initialize that account as a Mint
const initializeMintInstruction = createInitializeMint2Instruction(
mintKeypair.publicKey,
tokenConfig.decimals,
payer.publicKey,
payer.publicKey,
);
/**
* Alternatively, you could also use the helper function from the
* `@solana/spl-token` sdk to create and initialize the token's mint
* ---
* NOTE: this method is normally efficient since the payer would need to
* sign and pay for multiple transactions to perform all the actions. It
* would also require more "round trips" to the blockchain as well.
* But this option is available, should it fit your use case :)
* */
/*
console.log("Creating a token mint...");
const mint = await createMint(
connection,
payer,
// mint authority
payer.publicKey,
// freeze authority
payer.publicKey,
// decimals - use any number you desire
tokenConfig.decimals,
// manually define our token mint address
mintKeypair,
);
console.log("Token's mint address:", mint.toBase58());
*/
/**
* Build the instruction to store the token's metadata on chain
* - derive the pda for the metadata account
* - create the instruction with the actual metadata in it
*/
// derive the pda address for the Metadata account
const metadataAccount = PublicKey.findProgramAddressSync(
[Buffer.from("metadata"), METADATA_PROGRAM_ID.toBuffer(), mintKeypair.publicKey.toBuffer()],
METADATA_PROGRAM_ID,
)[0];
console.log("Metadata address:", metadataAccount.toBase58());
// Create the Metadata account for the Mint
const createMetadataInstruction = createCreateMetadataAccountV3Instruction(
{
metadata: metadataAccount,
mint: mintKeypair.publicKey,
mintAuthority: payer.publicKey,
payer: payer.publicKey,
updateAuthority: payer.publicKey,
},
{
createMetadataAccountArgsV3: {
data: {
creators: null,
name: tokenConfig.name,
symbol: tokenConfig.symbol,
uri: tokenConfig.uri,
sellerFeeBasisPoints: 0,
collection: null,
uses: null,
},
// `collectionDetails` - for non-nft type tokens, normally set to `null` to not have a value set
collectionDetails: null,
// should the metadata be updatable?
isMutable: true,
},
},
);
/**
* Build the transaction to send to the blockchain
*/
const tx = await buildTransaction({
connection,
payer: payer.publicKey,
signers: [payer, mintKeypair],
instructions: [
createMintAccountInstruction,
initializeMintInstruction,
createMetadataInstruction,
],
});
printConsoleSeparator();
try {
// actually send the transaction
const sig = await connection.sendTransaction(tx);
// print the explorer url
console.log("Transaction completed.");
console.log(explorerURL({ txSignature: sig }));
// locally save our addresses for the demo
savePublicKeyToFile("tokenMint", mintKeypair.publicKey);
} catch (err) {
console.error("Failed to send transaction:");
console.log(tx);
// attempt to extract the signature from the failed transaction
const failedSig = await extractSignatureFromFailedTransaction(connection, err);
if (failedSig) console.log("Failed signature:", explorerURL({ txSignature: failedSig }));
throw err;
}
})();