test.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. import {
  2. PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID
  3. } from '@metaplex-foundation/mpl-token-metadata';
  4. import {
  5. Connection,
  6. Keypair,
  7. PublicKey,
  8. SystemProgram,
  9. SYSVAR_RENT_PUBKEY,
  10. TransactionInstruction,
  11. Transaction,
  12. sendAndConfirmTransaction,
  13. } from '@solana/web3.js';
  14. import {
  15. ASSOCIATED_TOKEN_PROGRAM_ID,
  16. getAssociatedTokenAddress,
  17. TOKEN_PROGRAM_ID,
  18. } from '@solana/spl-token';
  19. import { Buffer } from "buffer";
  20. import {
  21. CreateTokenArgs,
  22. MintNftArgs,
  23. MintSplArgs,
  24. TransferTokensArgs,
  25. MyInstruction,
  26. } from './instructions';
  27. import { BN } from 'bn.js';
  28. function createKeypairFromFile(path: string): Keypair {
  29. return Keypair.fromSecretKey(
  30. Buffer.from(JSON.parse(require('fs').readFileSync(path, "utf-8")))
  31. )
  32. };
  33. describe("Transferring Tokens", async () => {
  34. // const connection = new Connection(`http://localhost:8899`, 'confirmed');
  35. const connection = new Connection(`https://api.devnet.solana.com/`, 'confirmed');
  36. const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
  37. const program = createKeypairFromFile('./program/target/deploy/program-keypair.json');
  38. const tokenMintKeypair: Keypair = Keypair.generate();
  39. const nftMintKeypair: Keypair = Keypair.generate();
  40. const recipientWallet = Keypair.generate();
  41. it("Create an SPL Token!", async () => {
  42. const metadataAddress = (PublicKey.findProgramAddressSync(
  43. [
  44. Buffer.from("metadata"),
  45. TOKEN_METADATA_PROGRAM_ID.toBuffer(),
  46. tokenMintKeypair.publicKey.toBuffer(),
  47. ],
  48. TOKEN_METADATA_PROGRAM_ID
  49. ))[0];
  50. const instructionData = new CreateTokenArgs({
  51. instruction: MyInstruction.Create,
  52. token_title: "Solana Gold",
  53. token_symbol: "GOLDSOL",
  54. token_uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/spl-token.json",
  55. decimals: 9,
  56. });
  57. let ix = new TransactionInstruction({
  58. keys: [
  59. { pubkey: tokenMintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
  60. { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
  61. { pubkey: metadataAddress, isSigner: false, isWritable: true }, // Metadata account
  62. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Payer
  63. { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
  64. { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
  65. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  66. { pubkey: TOKEN_METADATA_PROGRAM_ID, isSigner: false, isWritable: false }, // Token metadata program
  67. ],
  68. programId: program.publicKey,
  69. data: instructionData.toBuffer(),
  70. });
  71. const sx = await sendAndConfirmTransaction(
  72. connection,
  73. new Transaction().add(ix),
  74. [payer, tokenMintKeypair]
  75. );
  76. console.log("Success!");
  77. console.log(` Mint Address: ${tokenMintKeypair.publicKey}`);
  78. console.log(` Tx Signature: ${sx}`);
  79. });
  80. it("Create an NFT!", async () => {
  81. const metadataAddress = (PublicKey.findProgramAddressSync(
  82. [
  83. Buffer.from("metadata"),
  84. TOKEN_METADATA_PROGRAM_ID.toBuffer(),
  85. nftMintKeypair.publicKey.toBuffer(),
  86. ],
  87. TOKEN_METADATA_PROGRAM_ID
  88. ))[0];
  89. const instructionData = new CreateTokenArgs({
  90. instruction: MyInstruction.Create,
  91. token_title: "Homer NFT",
  92. token_symbol: "HOMR",
  93. token_uri: "https://raw.githubusercontent.com/solana-developers/program-examples/new-examples/tokens/tokens/.assets/nft.json",
  94. decimals: 0,
  95. });
  96. let ix = new TransactionInstruction({
  97. keys: [
  98. { pubkey: nftMintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
  99. { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
  100. { pubkey: metadataAddress, isSigner: false, isWritable: true }, // Metadata account
  101. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Payer
  102. { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
  103. { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
  104. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  105. { pubkey: TOKEN_METADATA_PROGRAM_ID, isSigner: false, isWritable: false }, // Token metadata program
  106. ],
  107. programId: program.publicKey,
  108. data: instructionData.toBuffer(),
  109. });
  110. const sx = await sendAndConfirmTransaction(
  111. connection,
  112. new Transaction().add(ix),
  113. [payer, nftMintKeypair]
  114. );
  115. console.log("Success!");
  116. console.log(` Mint Address: ${nftMintKeypair.publicKey}`);
  117. console.log(` Tx Signature: ${sx}`);
  118. });
  119. it("Mint some tokens to your wallet!", async () => {
  120. const associatedTokenAccountAddress = await getAssociatedTokenAddress(
  121. tokenMintKeypair.publicKey,
  122. payer.publicKey,
  123. );
  124. const instructionData = new MintSplArgs({
  125. instruction: MyInstruction.MintSpl,
  126. quantity: new BN(150),
  127. });
  128. let ix = new TransactionInstruction({
  129. keys: [
  130. { pubkey: tokenMintKeypair.publicKey, isSigner: false, isWritable: true }, // Mint account
  131. { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
  132. { pubkey: associatedTokenAccountAddress, isSigner: false, isWritable: true }, // ATA
  133. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Payer
  134. { pubkey: SystemProgram.programId, isSigner: false, isWritable: true }, // System program
  135. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  136. { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token metadata program
  137. ],
  138. programId: program.publicKey,
  139. data: instructionData.toBuffer(),
  140. });
  141. const sx = await sendAndConfirmTransaction(
  142. connection,
  143. new Transaction().add(ix),
  144. [payer],
  145. );
  146. console.log("Success!");
  147. console.log(` ATA Address: ${associatedTokenAccountAddress}`);
  148. console.log(` Tx Signature: ${sx}`);
  149. });
  150. it("Mint the NFT to your wallet!", async () => {
  151. const metadataAddress = (PublicKey.findProgramAddressSync(
  152. [
  153. Buffer.from("metadata"),
  154. TOKEN_METADATA_PROGRAM_ID.toBuffer(),
  155. nftMintKeypair.publicKey.toBuffer(),
  156. ],
  157. TOKEN_METADATA_PROGRAM_ID
  158. ))[0];
  159. const editionAddress = (PublicKey.findProgramAddressSync(
  160. [
  161. Buffer.from("metadata"),
  162. TOKEN_METADATA_PROGRAM_ID.toBuffer(),
  163. nftMintKeypair.publicKey.toBuffer(),
  164. Buffer.from("edition"),
  165. ],
  166. TOKEN_METADATA_PROGRAM_ID
  167. ))[0];
  168. const associatedTokenAccountAddress = await getAssociatedTokenAddress(
  169. nftMintKeypair.publicKey,
  170. payer.publicKey,
  171. );
  172. const instructionData = new MintNftArgs({
  173. instruction: MyInstruction.MintNft,
  174. });
  175. let ix = new TransactionInstruction({
  176. keys: [
  177. { pubkey: nftMintKeypair.publicKey, isSigner: false, isWritable: true }, // Mint account
  178. { pubkey: metadataAddress, isSigner: false, isWritable: true }, // Metadata account
  179. { pubkey: editionAddress, isSigner: false, isWritable: true }, // Edition account
  180. { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
  181. { pubkey: associatedTokenAccountAddress, isSigner: false, isWritable: true }, // ATA
  182. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Payer
  183. { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
  184. { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
  185. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  186. { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Associated token program
  187. { pubkey: TOKEN_METADATA_PROGRAM_ID, isSigner: false, isWritable: false }, // Token metadata program
  188. ],
  189. programId: program.publicKey,
  190. data: instructionData.toBuffer(),
  191. });
  192. const sx = await sendAndConfirmTransaction(
  193. connection,
  194. new Transaction().add(ix),
  195. [payer],
  196. );
  197. console.log("Success!");
  198. console.log(` ATA Address: ${associatedTokenAccountAddress}`);
  199. console.log(` Tx Signature: ${sx}`);
  200. });
  201. it("Prep a new test wallet for transfers", async () => {
  202. await connection.confirmTransaction(
  203. await connection.requestAirdrop(
  204. recipientWallet.publicKey,
  205. await connection.getMinimumBalanceForRentExemption(0),
  206. )
  207. );
  208. console.log(`Recipient Pubkey: ${recipientWallet.publicKey}`);
  209. });
  210. it("Transfer tokens to another wallet!", async () => {
  211. const fromAssociatedTokenAddress = await getAssociatedTokenAddress(
  212. tokenMintKeypair.publicKey,
  213. payer.publicKey
  214. );
  215. console.log(`Owner Token Address: ${fromAssociatedTokenAddress}`);
  216. const toAssociatedTokenAddress = await getAssociatedTokenAddress(
  217. tokenMintKeypair.publicKey,
  218. recipientWallet.publicKey
  219. );
  220. console.log(`Recipient Token Address: ${toAssociatedTokenAddress}`);
  221. const transferToInstructionData = new TransferTokensArgs({
  222. instruction: MyInstruction.TransferTokens,
  223. quantity: new BN(15),
  224. });
  225. let ix = new TransactionInstruction({
  226. keys: [
  227. { pubkey: tokenMintKeypair.publicKey, isSigner: false, isWritable: true }, // Mint account
  228. { pubkey: fromAssociatedTokenAddress, isSigner: false, isWritable: true }, // Owner Token account
  229. { pubkey: toAssociatedTokenAddress, isSigner: false, isWritable: true }, // Recipient Token account
  230. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Owner
  231. { pubkey: recipientWallet.publicKey, isSigner: true, isWritable: true }, // Recipient
  232. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Payer
  233. { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
  234. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  235. { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Associated token program
  236. ],
  237. programId: program.publicKey,
  238. data: transferToInstructionData.toBuffer(),
  239. });
  240. await sendAndConfirmTransaction(
  241. connection,
  242. new Transaction().add(ix),
  243. [payer, recipientWallet],
  244. { skipPreflight: true }
  245. );
  246. });
  247. it("Transfer NFT to another wallet!", async () => {
  248. const fromAssociatedTokenAddress = await getAssociatedTokenAddress(
  249. nftMintKeypair.publicKey,
  250. payer.publicKey
  251. );
  252. console.log(`Owner Token Address: ${fromAssociatedTokenAddress}`);
  253. const toAssociatedTokenAddress = await getAssociatedTokenAddress(
  254. nftMintKeypair.publicKey,
  255. recipientWallet.publicKey
  256. );
  257. console.log(`Recipient Token Address: ${toAssociatedTokenAddress}`);
  258. const transferToInstructionData = new TransferTokensArgs({
  259. instruction: MyInstruction.TransferTokens,
  260. quantity: new BN(1),
  261. });
  262. let ix = new TransactionInstruction({
  263. keys: [
  264. { pubkey: nftMintKeypair.publicKey, isSigner: false, isWritable: true }, // Mint account
  265. { pubkey: fromAssociatedTokenAddress, isSigner: false, isWritable: true }, // Owner Token account
  266. { pubkey: toAssociatedTokenAddress, isSigner: false, isWritable: true }, // Recipient Token account
  267. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Owner
  268. { pubkey: recipientWallet.publicKey, isSigner: true, isWritable: true }, // Recipient
  269. { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Payer
  270. { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
  271. { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
  272. { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // Associated token program
  273. ],
  274. programId: program.publicKey,
  275. data: transferToInstructionData.toBuffer(),
  276. });
  277. await sendAndConfirmTransaction(
  278. connection,
  279. new Transaction().add(ix),
  280. [payer, recipientWallet],
  281. { skipPreflight: true }
  282. );
  283. });
  284. });