import { describe, test } from 'node:test'; import { AccountLayout } from '@solana/spl-token'; import { Transaction } from '@solana/web3.js'; import { assert } from 'chai'; import { start } from 'solana-bankrun'; import { OfferAccount } from './account'; import { buildMakeOffer, buildTakeOffer } from './instruction'; import { createValues, mintingTokens } from './utils'; describe('Escrow!', async () => { const values = createValues(); const context = await start([{ name: 'escrow_native_program', programId: values.programId }], []); const client = context.banksClient; const payer = context.payer; console.log(`Program Address : ${values.programId}`); console.log(`Payer Address : ${payer.publicKey}`); test('mint tokens to maker and taker', async () => { // mint token a to maker account await mintingTokens({ context, holder: values.maker, mintKeypair: values.mintAKeypair, }); // mint Token B to Taker account await mintingTokens({ context, holder: values.taker, mintKeypair: values.mintBKeypair, }); }); test('Make Offer', async () => { const ix = buildMakeOffer({ id: values.id, maker: values.maker.publicKey, maker_token_a: values.makerAccountA, offer: values.offer, token_a_offered_amount: values.amountA, token_b_wanted_amount: values.amountB, vault: values.vault, mint_a: values.mintAKeypair.publicKey, mint_b: values.mintBKeypair.publicKey, payer: payer.publicKey, programId: values.programId, }); const blockhash = context.lastBlockhash; const tx = new Transaction(); tx.recentBlockhash = blockhash; tx.add(ix).sign(payer, values.maker); await client.processTransaction(tx); const offerInfo = await client.getAccount(values.offer); const offer = OfferAccount.fromBuffer(offerInfo.data).toData(); const vaultInfo = await client.getAccount(values.vault); const vaultTokenAccount = AccountLayout.decode(vaultInfo.data); assert(offer.id.toString() === values.id.toString(), 'wrong id'); assert(offer.maker.toBase58() === values.maker.publicKey.toBase58(), 'maker key does not match'); assert(offer.token_mint_a.toBase58() === values.mintAKeypair.publicKey.toBase58(), 'wrong mint A'); assert(offer.token_mint_b.toBase58() === values.mintBKeypair.publicKey.toBase58(), 'wrong mint B'); assert(offer.token_b_wanted_amount.toString() === values.amountB.toString(), 'unexpected amount B'); assert(vaultTokenAccount.amount.toString() === values.amountA.toString(), 'unexpected amount A'); }); test('Take Offer', async () => { const ix = buildTakeOffer({ maker: values.maker.publicKey, offer: values.offer, vault: values.vault, mint_a: values.mintAKeypair.publicKey, mint_b: values.mintBKeypair.publicKey, maker_token_b: values.makerAccountB, taker: values.taker.publicKey, taker_token_a: values.takerAccountA, taker_token_b: values.takerAccountB, payer: payer.publicKey, programId: values.programId, }); const blockhash = context.lastBlockhash; const tx = new Transaction(); tx.recentBlockhash = blockhash; tx.add(ix).sign(payer, values.taker); await client.processTransaction(tx); const offerInfo = await client.getAccount(values.offer); assert(offerInfo === null, 'offer account not closed'); const vaultInfo = await client.getAccount(values.vault); assert(vaultInfo === null, 'vault account not closed'); const makerTokenBInfo = await client.getAccount(values.makerAccountB); const makerTokenAccountB = AccountLayout.decode(makerTokenBInfo.data); const takerTokenAInfo = await client.getAccount(values.takerAccountA); const takerTokenAccountA = AccountLayout.decode(takerTokenAInfo.data); assert(takerTokenAccountA.amount.toString() === values.amountA.toString(), 'unexpected amount a'); assert(makerTokenAccountB.amount.toString() === values.amountB.toString(), 'unexpected amount b'); }); });