escrow.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import * as anchor from "@project-serum/anchor";
  2. import { TOKEN_PROGRAM_ID, Token } from "@solana/spl-token";
  3. import {assert} from "chai";
  4. import {EscrowIDL} from "./types/escrow";
  5. describe("escrow", () => {
  6. const provider = anchor.Provider.env();
  7. anchor.setProvider(provider);
  8. const program = anchor.workspace.Escrow as anchor.Program<EscrowIDL>;
  9. let mintA : Token = null;
  10. let mintB : Token = null;
  11. let initializerTokenAccountA : anchor.web3.PublicKey = null;
  12. let initializerTokenAccountB : anchor.web3.PublicKey = null;
  13. let takerTokenAccountA : anchor.web3.PublicKey = null;
  14. let takerTokenAccountB : anchor.web3.PublicKey = null;
  15. let pda : anchor.web3.PublicKey = null;
  16. const takerAmount = 1000;
  17. const initializerAmount = 500;
  18. const escrowAccount = anchor.web3.Keypair.generate();
  19. const payer = anchor.web3.Keypair.generate();
  20. const mintAuthority = anchor.web3.Keypair.generate();
  21. it("Initialise escrow state", async () => {
  22. // Airdropping tokens to a payer.
  23. await provider.connection.confirmTransaction(
  24. await provider.connection.requestAirdrop(payer.publicKey, 10000000000),
  25. "confirmed"
  26. );
  27. mintA = await Token.createMint(
  28. provider.connection,
  29. payer,
  30. mintAuthority.publicKey,
  31. null,
  32. 0,
  33. TOKEN_PROGRAM_ID
  34. );
  35. mintB = await Token.createMint(
  36. provider.connection,
  37. payer,
  38. mintAuthority.publicKey,
  39. null,
  40. 0,
  41. TOKEN_PROGRAM_ID
  42. );
  43. initializerTokenAccountA = await mintA.createAccount(provider.wallet.publicKey);
  44. takerTokenAccountA = await mintA.createAccount(provider.wallet.publicKey);
  45. initializerTokenAccountB = await mintB.createAccount(provider.wallet.publicKey);
  46. takerTokenAccountB = await mintB.createAccount(provider.wallet.publicKey);
  47. await mintA.mintTo(
  48. initializerTokenAccountA,
  49. mintAuthority.publicKey,
  50. [mintAuthority],
  51. initializerAmount
  52. );
  53. await mintB.mintTo(
  54. takerTokenAccountB,
  55. mintAuthority.publicKey,
  56. [mintAuthority],
  57. takerAmount
  58. );
  59. let _initializerTokenAccountA = await mintA.getAccountInfo(initializerTokenAccountA);
  60. let _takerTokenAccountB = await mintB.getAccountInfo(takerTokenAccountB);
  61. assert.ok(_initializerTokenAccountA.amount.toNumber() == initializerAmount);
  62. assert.ok(_takerTokenAccountB.amount.toNumber() == takerAmount);
  63. });
  64. it("Initialize escrow", async () => {
  65. await program.rpc.initializeEscrow(
  66. new anchor.BN(initializerAmount),
  67. new anchor.BN(takerAmount),
  68. {
  69. accounts: {
  70. initializer: provider.wallet.publicKey,
  71. initializerDepositTokenAccount: initializerTokenAccountA,
  72. initializerReceiveTokenAccount: initializerTokenAccountB,
  73. escrowAccount: escrowAccount.publicKey,
  74. tokenProgram: TOKEN_PROGRAM_ID,
  75. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  76. },
  77. instructions: [
  78. await program.account.escrowAccount.createInstruction(escrowAccount),
  79. ],
  80. signers: [escrowAccount],
  81. }
  82. );
  83. // Get the PDA that is assigned authority to token account.
  84. const [_pda, _nonce] = await anchor.web3.PublicKey.findProgramAddress(
  85. [Buffer.from(anchor.utils.bytes.utf8.encode("escrow"))],
  86. program.programId
  87. );
  88. pda = _pda;
  89. let _initializerTokenAccountA = await mintA.getAccountInfo(initializerTokenAccountA);
  90. let _escrowAccount = await program.account.escrowAccount.fetch(
  91. escrowAccount.publicKey
  92. );
  93. // Check that the new owner is the PDA.
  94. assert.ok(_initializerTokenAccountA.owner.equals(pda));
  95. // Check that the values in the escrow account match what we expect.
  96. assert.ok(_escrowAccount.initializerKey.equals(provider.wallet.publicKey));
  97. assert.ok(_escrowAccount.initializerAmount.toNumber() == initializerAmount);
  98. assert.ok(_escrowAccount.takerAmount.toNumber() == takerAmount);
  99. assert.ok(
  100. _escrowAccount.initializerDepositTokenAccount.equals(initializerTokenAccountA)
  101. );
  102. assert.ok(
  103. _escrowAccount.initializerReceiveTokenAccount.equals(initializerTokenAccountB)
  104. );
  105. });
  106. it("Exchange escrow", async () => {
  107. await program.rpc.exchange({
  108. accounts: {
  109. taker: provider.wallet.publicKey,
  110. takerDepositTokenAccount: takerTokenAccountB,
  111. takerReceiveTokenAccount: takerTokenAccountA,
  112. pdaDepositTokenAccount: initializerTokenAccountA,
  113. initializerReceiveTokenAccount: initializerTokenAccountB,
  114. initializerMainAccount: provider.wallet.publicKey,
  115. escrowAccount: escrowAccount.publicKey,
  116. pdaAccount: pda,
  117. tokenProgram: TOKEN_PROGRAM_ID,
  118. },
  119. });
  120. let _takerTokenAccountA = await mintA.getAccountInfo(takerTokenAccountA);
  121. let _takerTokenAccountB = await mintB.getAccountInfo(takerTokenAccountB);
  122. let _initializerTokenAccountA = await mintA.getAccountInfo(initializerTokenAccountA);
  123. let _initializerTokenAccountB = await mintB.getAccountInfo(initializerTokenAccountB);
  124. // Check that the initializer gets back ownership of their token account.
  125. assert.ok(_takerTokenAccountA.owner.equals(provider.wallet.publicKey));
  126. assert.ok(_takerTokenAccountA.amount.toNumber() == initializerAmount);
  127. assert.ok(_initializerTokenAccountA.amount.toNumber() == 0);
  128. assert.ok(_initializerTokenAccountB.amount.toNumber() == takerAmount);
  129. assert.ok(_takerTokenAccountB.amount.toNumber() == 0);
  130. });
  131. let newEscrow = anchor.web3.Keypair.generate();
  132. it("Initialize escrow and cancel escrow", async () => {
  133. // Put back tokens into initializer token A account.
  134. await mintA.mintTo(
  135. initializerTokenAccountA,
  136. mintAuthority.publicKey,
  137. [mintAuthority],
  138. initializerAmount
  139. );
  140. await program.rpc.initializeEscrow(
  141. new anchor.BN(initializerAmount),
  142. new anchor.BN(takerAmount),
  143. {
  144. accounts: {
  145. initializer: provider.wallet.publicKey,
  146. initializerDepositTokenAccount: initializerTokenAccountA,
  147. initializerReceiveTokenAccount: initializerTokenAccountB,
  148. escrowAccount: newEscrow.publicKey,
  149. tokenProgram: TOKEN_PROGRAM_ID,
  150. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  151. },
  152. instructions: [await program.account.escrowAccount.createInstruction(newEscrow)],
  153. signers: [newEscrow],
  154. }
  155. );
  156. let _initializerTokenAccountA = await mintA.getAccountInfo(initializerTokenAccountA);
  157. // Check that the new owner is the PDA.
  158. assert.ok(_initializerTokenAccountA.owner.equals(pda));
  159. // Cancel the escrow.
  160. await program.rpc.cancelEscrow({
  161. accounts: {
  162. initializer: provider.wallet.publicKey,
  163. pdaDepositTokenAccount: initializerTokenAccountA,
  164. pdaAccount: pda,
  165. escrowAccount: newEscrow.publicKey,
  166. tokenProgram: TOKEN_PROGRAM_ID,
  167. },
  168. });
  169. // Check the final owner should be the provider public key.
  170. _initializerTokenAccountA = await mintA.getAccountInfo(initializerTokenAccountA);
  171. assert.ok(_initializerTokenAccountA.owner.equals(provider.wallet.publicKey));
  172. // Check all the funds are still there.
  173. assert.ok(_initializerTokenAccountA.amount.toNumber() == initializerAmount);
  174. });
  175. });