diff --git a/web3.js/test/transaction-payer.test.js b/web3.js/test/transaction-payer.test.js new file mode 100644 index 0000000000..dc1569a90b --- /dev/null +++ b/web3.js/test/transaction-payer.test.js @@ -0,0 +1,159 @@ +// @flow +import {Account, Connection, SystemProgram} from '../src'; +import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch'; +import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash'; +import {url} from './url'; +import {sleep} from '../src/util/sleep'; + +if (!mockRpcEnabled) { + // The default of 5 seconds is too slow for live testing sometimes + jest.setTimeout(30000); +} + +test('transaction-payer', async () => { + const accountPayer = new Account(); + const accountFrom = new Account(); + const accountTo = new Account(); + const connection = new Connection(url); + + mockRpc.push([ + url, + { + method: 'requestAirdrop', + params: [accountPayer.publicKey.toBase58(), 100], + }, + { + error: null, + result: + '0WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', + }, + ]); + await connection.requestAirdrop(accountPayer.publicKey, 100); + + mockRpc.push([ + url, + { + method: 'requestAirdrop', + params: [accountFrom.publicKey.toBase58(), 12], + }, + { + error: null, + result: + '0WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', + }, + ]); + await connection.requestAirdrop(accountFrom.publicKey, 12); + + mockRpc.push([ + url, + { + method: 'requestAirdrop', + params: [accountTo.publicKey.toBase58(), 21], + }, + { + error: null, + result: + '8WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', + }, + ]); + await connection.requestAirdrop(accountTo.publicKey, 21); + + mockGetRecentBlockhash(); + mockRpc.push([ + url, + { + method: 'sendTransaction', + }, + { + error: null, + result: + '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', + }, + ]); + + const transaction = SystemProgram.transfer( + accountFrom.publicKey, + accountTo.publicKey, + 10, + ); + + const signature = await connection.sendTransaction( + transaction, + accountPayer, + accountFrom, + ); + + mockRpc.push([ + url, + { + method: 'confirmTransaction', + params: [ + '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', + ], + }, + { + error: null, + result: true, + }, + ]); + + let i = 0; + for (;;) { + if (await connection.confirmTransaction(signature)) { + break; + } + + expect(mockRpcEnabled).toBe(false); + expect(++i).toBeLessThan(10); + await sleep(500); + } + + mockRpc.push([ + url, + { + method: 'getSignatureStatus', + params: [ + '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', + ], + }, + { + error: null, + result: {Ok: null}, + }, + ]); + await expect(connection.getSignatureStatus(signature)).resolves.toEqual({ + Ok: null, + }); + + mockRpc.push([ + url, + { + method: 'getBalance', + params: [accountPayer.publicKey.toBase58()], + }, + { + error: null, + result: 99, + }, + ]); + + // accountPayer should be less less than 100 as it paid for the transaction + // (exact amount less depends on the current cluster fees) + const balance = await connection.getBalance(accountPayer.publicKey); + expect(balance).toBeGreaterThan(0); + expect(balance).toBeLessThanOrEqual(99); + + // accountFrom should have exactly 2, since it didn't pay for the transaction + mockRpc.push([ + url, + { + method: 'getBalance', + params: [accountFrom.publicKey.toBase58()], + }, + { + error: null, + result: 2, + }, + ]); + expect(await connection.getBalance(accountFrom.publicKey)).toBe(2); +});