utils.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import {
  2. ASSOCIATED_TOKEN_PROGRAM_ID,
  3. MINT_SIZE,
  4. TOKEN_PROGRAM_ID,
  5. createAssociatedTokenAccountIdempotentInstruction,
  6. createInitializeMint2Instruction,
  7. createMintToInstruction,
  8. getAssociatedTokenAddressSync,
  9. } from '@solana/spl-token';
  10. import { Keypair, PublicKey, type Signer, SystemProgram, Transaction } from '@solana/web3.js';
  11. import BN from 'bn.js';
  12. import { ProgramTestContext } from 'solana-bankrun';
  13. export async function sleep(seconds: number) {
  14. new Promise((resolve) => setTimeout(resolve, seconds * 1000));
  15. }
  16. export const expectRevert = async (promise: Promise<any>) => {
  17. try {
  18. await promise;
  19. throw new Error('Expected a revert');
  20. } catch {
  21. return;
  22. }
  23. };
  24. export const mintingTokens = async ({
  25. context,
  26. holder,
  27. mintKeypair,
  28. mintedAmount = 100,
  29. decimals = 6,
  30. }: {
  31. context: ProgramTestContext;
  32. holder: Signer;
  33. mintKeypair: Keypair;
  34. mintedAmount?: number;
  35. decimals?: number;
  36. }) => {
  37. async function createMint(context: ProgramTestContext, mint: Keypair, decimals: number) {
  38. const rent = await context.banksClient.getRent();
  39. const lamports = rent.minimumBalance(BigInt(MINT_SIZE));
  40. const transaction = new Transaction().add(
  41. SystemProgram.createAccount({
  42. fromPubkey: context.payer.publicKey,
  43. newAccountPubkey: mint.publicKey,
  44. space: MINT_SIZE,
  45. lamports: new BN(lamports.toString()).toNumber(),
  46. programId: TOKEN_PROGRAM_ID,
  47. }),
  48. createInitializeMint2Instruction(mint.publicKey, decimals, context.payer.publicKey, context.payer.publicKey, TOKEN_PROGRAM_ID),
  49. );
  50. transaction.recentBlockhash = context.lastBlockhash;
  51. transaction.sign(context.payer, mint);
  52. await context.banksClient.processTransaction(transaction);
  53. }
  54. async function createAssociatedTokenAccountIfNeeded(context: ProgramTestContext, mint: PublicKey, owner: PublicKey) {
  55. const associatedToken = getAssociatedTokenAddressSync(mint, owner, true);
  56. const rent = await context.banksClient.getRent();
  57. rent.minimumBalance(BigInt(MINT_SIZE));
  58. const transaction = new Transaction().add(
  59. createAssociatedTokenAccountIdempotentInstruction(
  60. context.payer.publicKey,
  61. associatedToken,
  62. owner,
  63. mint,
  64. TOKEN_PROGRAM_ID,
  65. ASSOCIATED_TOKEN_PROGRAM_ID,
  66. ),
  67. );
  68. transaction.recentBlockhash = context.lastBlockhash;
  69. transaction.sign(context.payer);
  70. await context.banksClient.processTransaction(transaction);
  71. }
  72. async function mintTo(context: ProgramTestContext, mint: PublicKey, destination: PublicKey, amount: number | bigint) {
  73. const transaction = new Transaction().add(createMintToInstruction(mint, destination, context.payer.publicKey, amount, [], TOKEN_PROGRAM_ID));
  74. transaction.recentBlockhash = context.lastBlockhash;
  75. transaction.sign(context.payer);
  76. await context.banksClient.processTransaction(transaction);
  77. }
  78. // creator creates the mint
  79. await createMint(context, mintKeypair, decimals);
  80. // create holder token account
  81. await createAssociatedTokenAccountIfNeeded(context, mintKeypair.publicKey, holder.publicKey);
  82. // mint to holders token account
  83. await mintTo(
  84. context,
  85. mintKeypair.publicKey,
  86. getAssociatedTokenAddressSync(mintKeypair.publicKey, holder.publicKey, true),
  87. mintedAmount * 10 ** decimals,
  88. );
  89. };
  90. export interface TestValues {
  91. id: BN;
  92. amountA: BN;
  93. amountB: BN;
  94. maker: Keypair;
  95. taker: Keypair;
  96. mintAKeypair: Keypair;
  97. mintBKeypair: Keypair;
  98. offer: PublicKey;
  99. vault: PublicKey;
  100. makerAccountA: PublicKey;
  101. makerAccountB: PublicKey;
  102. takerAccountA: PublicKey;
  103. takerAccountB: PublicKey;
  104. programId: PublicKey;
  105. }
  106. type TestValuesDefaults = {
  107. [K in keyof TestValues]+?: TestValues[K];
  108. };
  109. export function createValues(defaults?: TestValuesDefaults): TestValues {
  110. const programId = PublicKey.unique();
  111. const id = defaults?.id || new BN(0);
  112. const maker = Keypair.generate();
  113. const taker = Keypair.generate();
  114. // Making sure tokens are in the right order
  115. const mintAKeypair = Keypair.generate();
  116. let mintBKeypair = Keypair.generate();
  117. while (new BN(mintBKeypair.publicKey.toBytes()).lt(new BN(mintAKeypair.publicKey.toBytes()))) {
  118. mintBKeypair = Keypair.generate();
  119. }
  120. const offer = PublicKey.findProgramAddressSync([Buffer.from('offer'), maker.publicKey.toBuffer(), Buffer.from(id.toArray('le', 8))], programId)[0];
  121. return {
  122. id,
  123. maker,
  124. taker,
  125. mintAKeypair,
  126. mintBKeypair,
  127. offer,
  128. vault: getAssociatedTokenAddressSync(mintAKeypair.publicKey, offer, true),
  129. makerAccountA: getAssociatedTokenAddressSync(mintAKeypair.publicKey, maker.publicKey, true),
  130. makerAccountB: getAssociatedTokenAddressSync(mintBKeypair.publicKey, maker.publicKey, true),
  131. takerAccountA: getAssociatedTokenAddressSync(mintAKeypair.publicKey, taker.publicKey, true),
  132. takerAccountB: getAssociatedTokenAddressSync(mintBKeypair.publicKey, taker.publicKey, true),
  133. amountA: new BN(4 * 10 ** 6),
  134. amountB: new BN(1 * 10 ** 6),
  135. programId,
  136. };
  137. }