transferToATA.test.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import { generateKeyPairSigner } from '@solana/kit';
  2. import test from 'ava';
  3. import {
  4. Mint,
  5. TOKEN_PROGRAM_ADDRESS,
  6. Token,
  7. fetchMint,
  8. fetchToken,
  9. findAssociatedTokenPda,
  10. getTransferToATAInstructionPlan,
  11. getTransferToATAInstructionPlanAsync,
  12. } from '../src';
  13. import {
  14. createDefaultSolanaClient,
  15. createDefaultTransactionPlanner,
  16. createMint,
  17. createTokenPdaWithAmount,
  18. createTokenWithAmount,
  19. generateKeyPairSignerWithSol,
  20. } from './_setup';
  21. test('it transfers tokens from one account to a new ATA', async (t) => {
  22. // Given a mint account, one token account with 100 tokens, and a second owner.
  23. const client = createDefaultSolanaClient();
  24. const [payer, mintAuthority, ownerA, ownerB] = await Promise.all([
  25. generateKeyPairSignerWithSol(client),
  26. generateKeyPairSigner(),
  27. generateKeyPairSigner(),
  28. generateKeyPairSigner(),
  29. ]);
  30. const decimals = 2;
  31. const mint = await createMint(client, payer, mintAuthority.address, decimals);
  32. const tokenA = await createTokenWithAmount(
  33. client,
  34. payer,
  35. mintAuthority,
  36. mint,
  37. ownerA.address,
  38. 100n
  39. );
  40. const [tokenB] = await findAssociatedTokenPda({
  41. owner: ownerB.address,
  42. mint,
  43. tokenProgram: TOKEN_PROGRAM_ADDRESS,
  44. });
  45. // When owner A transfers 50 tokens to owner B.
  46. const instructionPlan = getTransferToATAInstructionPlan({
  47. payer,
  48. mint,
  49. source: tokenA,
  50. authority: ownerA,
  51. destination: tokenB,
  52. recipient: ownerB.address,
  53. amount: 50n,
  54. decimals,
  55. });
  56. const transactionPlanner = createDefaultTransactionPlanner(client, payer);
  57. const transactionPlan = await transactionPlanner(instructionPlan);
  58. await client.sendTransactionPlan(transactionPlan);
  59. // Then we expect the mint and token accounts to have the following updated data.
  60. const [{ data: mintData }, { data: tokenDataA }, { data: tokenDataB }] =
  61. await Promise.all([
  62. fetchMint(client.rpc, mint),
  63. fetchToken(client.rpc, tokenA),
  64. fetchToken(client.rpc, tokenB),
  65. ]);
  66. t.like(mintData, <Mint>{ supply: 100n });
  67. t.like(tokenDataA, <Token>{ amount: 50n });
  68. t.like(tokenDataB, <Token>{ amount: 50n });
  69. });
  70. test('derives a new ATA and transfers tokens to it', async (t) => {
  71. // Given a mint account, one token account with 100 tokens, and a second owner.
  72. const client = createDefaultSolanaClient();
  73. const [payer, mintAuthority, ownerA, ownerB] = await Promise.all([
  74. generateKeyPairSignerWithSol(client),
  75. generateKeyPairSigner(),
  76. generateKeyPairSigner(),
  77. generateKeyPairSigner(),
  78. ]);
  79. const decimals = 2;
  80. const mint = await createMint(client, payer, mintAuthority.address, decimals);
  81. const tokenA = await createTokenWithAmount(
  82. client,
  83. payer,
  84. mintAuthority,
  85. mint,
  86. ownerA.address,
  87. 100n
  88. );
  89. // When owner A transfers 50 tokens to owner B.
  90. const instructionPlan = await getTransferToATAInstructionPlanAsync({
  91. payer,
  92. mint,
  93. source: tokenA,
  94. authority: ownerA,
  95. recipient: ownerB.address,
  96. amount: 50n,
  97. decimals,
  98. });
  99. const transactionPlanner = createDefaultTransactionPlanner(client, payer);
  100. const transactionPlan = await transactionPlanner(instructionPlan);
  101. await client.sendTransactionPlan(transactionPlan);
  102. // Then we expect the mint and token accounts to have the following updated data.
  103. const [tokenB] = await findAssociatedTokenPda({
  104. owner: ownerB.address,
  105. mint,
  106. tokenProgram: TOKEN_PROGRAM_ADDRESS,
  107. });
  108. const [{ data: mintData }, { data: tokenDataA }, { data: tokenDataB }] =
  109. await Promise.all([
  110. fetchMint(client.rpc, mint),
  111. fetchToken(client.rpc, tokenA),
  112. fetchToken(client.rpc, tokenB),
  113. ]);
  114. t.like(mintData, <Mint>{ supply: 100n });
  115. t.like(tokenDataA, <Token>{ amount: 50n });
  116. t.like(tokenDataB, <Token>{ amount: 50n });
  117. });
  118. test('it transfers tokens from one account to an existing ATA', async (t) => {
  119. // Given a mint account and two token accounts.
  120. // One with 90 tokens and the other with 10 tokens.
  121. const client = createDefaultSolanaClient();
  122. const [payer, mintAuthority, ownerA, ownerB] = await Promise.all([
  123. generateKeyPairSignerWithSol(client),
  124. generateKeyPairSigner(),
  125. generateKeyPairSigner(),
  126. generateKeyPairSigner(),
  127. ]);
  128. const decimals = 2;
  129. const mint = await createMint(client, payer, mintAuthority.address, decimals);
  130. const [tokenA, tokenB] = await Promise.all([
  131. createTokenWithAmount(
  132. client,
  133. payer,
  134. mintAuthority,
  135. mint,
  136. ownerA.address,
  137. 90n
  138. ),
  139. createTokenPdaWithAmount(
  140. client,
  141. payer,
  142. mintAuthority,
  143. mint,
  144. ownerB.address,
  145. 10n,
  146. decimals
  147. ),
  148. ]);
  149. // When owner A transfers 50 tokens to owner B.
  150. const instructionPlan = getTransferToATAInstructionPlan({
  151. payer,
  152. mint,
  153. source: tokenA,
  154. authority: ownerA,
  155. destination: tokenB,
  156. recipient: ownerB.address,
  157. amount: 50n,
  158. decimals,
  159. });
  160. const transactionPlanner = createDefaultTransactionPlanner(client, payer);
  161. const transactionPlan = await transactionPlanner(instructionPlan);
  162. await client.sendTransactionPlan(transactionPlan);
  163. // Then we expect the mint and token accounts to have the following updated data.
  164. const [{ data: mintData }, { data: tokenDataA }, { data: tokenDataB }] =
  165. await Promise.all([
  166. fetchMint(client.rpc, mint),
  167. fetchToken(client.rpc, tokenA),
  168. fetchToken(client.rpc, tokenB),
  169. ]);
  170. t.like(mintData, <Mint>{ supply: 100n });
  171. t.like(tokenDataA, <Token>{ amount: 40n });
  172. t.like(tokenDataB, <Token>{ amount: 60n });
  173. });