escrow.ts 7.1 KB

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