test.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import {
  2. Connection,
  3. Keypair,
  4. PublicKey,
  5. SystemProgram,
  6. SYSVAR_RENT_PUBKEY,
  7. TransactionInstruction,
  8. Transaction,
  9. sendAndConfirmTransaction,
  10. LAMPORTS_PER_SOL,
  11. } from '@solana/web3.js';
  12. import {
  13. ASSOCIATED_TOKEN_PROGRAM_ID,
  14. getAssociatedTokenAddress,
  15. TOKEN_PROGRAM_ID,
  16. } from '@solana/spl-token';
  17. import * as borsh from "borsh";
  18. import { Buffer } from "buffer";
  19. const TOKEN_METADATA_PROGRAM_ID = new PublicKey(
  20. "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
  21. );
  22. function createKeypairFromFile(path: string): Keypair {
  23. return Keypair.fromSecretKey(
  24. Buffer.from(JSON.parse(require('fs').readFileSync(path, "utf-8")))
  25. )
  26. };
  27. class Assignable {
  28. constructor(properties) {
  29. Object.keys(properties).map((key) => {
  30. return (this[key] = properties[key]);
  31. });
  32. };
  33. };
  34. class TokenMetadata extends Assignable {
  35. toBuffer() {
  36. return Buffer.from(borsh.serialize(TokenMetadataSchema, this));
  37. }
  38. };
  39. const TokenMetadataSchema = new Map([
  40. [
  41. TokenMetadata, {
  42. kind: 'struct',
  43. fields: [
  44. ['title', 'string'],
  45. ['symbol', 'string'],
  46. ['uri', 'string'],
  47. ['mint_authority_pda_bump', 'u8'],
  48. ]
  49. }
  50. ]
  51. ]);
  52. class MintTokensTo extends Assignable {
  53. toBuffer() {
  54. return Buffer.from(borsh.serialize(MintTokensToSchema, this));
  55. }
  56. };
  57. const MintTokensToSchema = new Map([
  58. [
  59. MintTokensTo, {
  60. kind: 'struct',
  61. fields: [
  62. ['amount', 'u64'],
  63. ['mint_authority_pda_bump', 'u8'],
  64. ]
  65. }
  66. ]
  67. ]);
  68. class TransferTokensTo extends Assignable {
  69. toBuffer() {
  70. return Buffer.from(borsh.serialize(TransferTokensToSchema, this));
  71. }
  72. };
  73. const TransferTokensToSchema = new Map([
  74. [
  75. TransferTokensTo, {
  76. kind: 'struct',
  77. fields: [
  78. ['amount', 'u64'],
  79. ]
  80. }
  81. ]
  82. ]);
  83. describe("mint-token", async () => {
  84. const connection = new Connection(`http://api.devnet.solana.com/`, 'confirmed');
  85. const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
  86. const program = createKeypairFromFile('./program/target/so/program-keypair.json');
  87. const mintKeypair: Keypair = Keypair.generate();
  88. console.log(`New token: ${mintKeypair.publicKey}`);
  89. it("Mint!", async () => {
  90. const [mintAuthorityPda, mintAuthorityPdaBump] = await PublicKey.findProgramAddress(
  91. [
  92. Buffer.from("mint_authority_"),
  93. mintKeypair.publicKey.toBuffer(),
  94. ],
  95. program.publicKey,
  96. );
  97. const metadataAddress = (await PublicKey.findProgramAddress(
  98. [
  99. Buffer.from("metadata"),
  100. TOKEN_METADATA_PROGRAM_ID.toBuffer(),
  101. mintKeypair.publicKey.toBuffer(),
  102. ],
  103. TOKEN_METADATA_PROGRAM_ID
  104. ))[0];
  105. const metadataInstructionData = new TokenMetadata({
  106. title: "Solana Gold",
  107. symbol: "GOLDSOL",
  108. uri: "https://raw.githubusercontent.com/solana-developers/program-examples/main/tokens/mint-2/native/tests/token_metadata.json",
  109. mint_authority_pda_bump: mintAuthorityPdaBump
  110. });
  111. let ix = new TransactionInstruction({
  112. keys: [
  113. { pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
  114. { pubkey: mintAuthorityPda, isSigner: false, isWritable: true }, // Mint authority account
  115. { pubkey: metadataAddress, isSigner: false, isWritable: true }, // Metadata account
  116. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Payer
  117. { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
  118. { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
  119. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  120. { pubkey: TOKEN_METADATA_PROGRAM_ID, isSigner: false, isWritable: false }, // Token metadata program
  121. ],
  122. programId: program.publicKey,
  123. data: metadataInstructionData.toBuffer(),
  124. });
  125. await sendAndConfirmTransaction(
  126. connection,
  127. new Transaction().add(ix),
  128. [payer, mintKeypair]
  129. );
  130. });
  131. it("Mint to a wallet!", async () => {
  132. const [mintAuthorityPda, mintAuthorityPdaBump] = await PublicKey.findProgramAddress(
  133. [
  134. Buffer.from("mint_authority_"),
  135. mintKeypair.publicKey.toBuffer(),
  136. ],
  137. program.publicKey,
  138. );
  139. const tokenAddress = await getAssociatedTokenAddress(
  140. mintKeypair.publicKey,
  141. payer.publicKey
  142. );
  143. console.log(`Token Address: ${tokenAddress}`);
  144. const mintToInstructionData = new MintTokensTo({
  145. amount: 1,
  146. mint_authority_pda_bump: mintAuthorityPdaBump,
  147. });
  148. let ix = new TransactionInstruction({
  149. keys: [
  150. { pubkey: mintKeypair.publicKey, isSigner: false, isWritable: true }, // Mint account
  151. { pubkey: mintAuthorityPda, isSigner: false, isWritable: false }, // Mint authority account
  152. { pubkey: tokenAddress, isSigner: false, isWritable: true }, // Token account
  153. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Payer
  154. { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
  155. { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
  156. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  157. { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Associated token program
  158. ],
  159. programId: program.publicKey,
  160. data: mintToInstructionData.toBuffer(),
  161. });
  162. await sendAndConfirmTransaction(
  163. connection,
  164. new Transaction().add(ix),
  165. [payer]
  166. );
  167. });
  168. it("Transfer to a wallet!", async () => {
  169. const recipientWallet = Keypair.generate();
  170. await connection.confirmTransaction(
  171. await connection.requestAirdrop(recipientWallet.publicKey, 2 * LAMPORTS_PER_SOL)
  172. );
  173. console.log(`Recipient Pubkey: ${recipientWallet.publicKey}`);
  174. const ownerTokenAddress = await getAssociatedTokenAddress(
  175. mintKeypair.publicKey,
  176. payer.publicKey
  177. );
  178. console.log(`Owner Token Address: ${ownerTokenAddress}`);
  179. const recipientTokenAddress = await getAssociatedTokenAddress(
  180. mintKeypair.publicKey,
  181. recipientWallet.publicKey
  182. );
  183. console.log(`Recipient Token Address: ${recipientTokenAddress}`);
  184. const transferToInstructionData = new TransferTokensTo({
  185. amount: 1,
  186. });
  187. let ix = new TransactionInstruction({
  188. keys: [
  189. { pubkey: mintKeypair.publicKey, isSigner: false, isWritable: true }, // Mint account
  190. { pubkey: ownerTokenAddress, isSigner: false, isWritable: true }, // Owner Token account
  191. { pubkey: recipientTokenAddress, isSigner: false, isWritable: true }, // Recipient Token account
  192. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Owner
  193. { pubkey: recipientWallet.publicKey, isSigner: true, isWritable: true }, // Recipient
  194. { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
  195. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  196. { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Associated token program
  197. ],
  198. programId: program.publicKey,
  199. data: transferToInstructionData.toBuffer(),
  200. });
  201. await sendAndConfirmTransaction(
  202. connection,
  203. new Transaction().add(ix),
  204. [payer, recipientWallet]
  205. );
  206. });
  207. });