solana/web3.js/test/connection.test.js

541 lines
12 KiB
JavaScript
Raw Normal View History

2018-08-23 10:52:48 -07:00
// @flow
import {
Account,
Connection,
2018-10-26 21:37:39 -07:00
BpfLoader,
Loader,
SystemProgram,
2018-10-26 21:37:39 -07:00
sendAndConfirmTransaction,
} from '../src';
import {DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND} from '../src/timing';
2018-10-10 14:00:59 -07:00
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
2019-03-04 08:06:33 -08:00
import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash';
import {url} from './url';
import {sleep} from '../src/util/sleep';
2018-08-23 10:52:48 -07:00
2018-10-10 14:00:59 -07:00
if (!mockRpcEnabled) {
// The default of 5 seconds is too slow for live testing sometimes
2018-10-24 08:41:13 -07:00
jest.setTimeout(15000);
2018-10-10 14:00:59 -07:00
}
2018-08-24 11:12:48 -07:00
const errorMessage = 'Invalid request';
const errorResponse = {
error: {
message: errorMessage,
},
result: undefined,
};
2018-09-20 15:08:52 -07:00
test('get account info - error', () => {
const account = new Account();
const connection = new Connection(url);
mockRpc.push([
url,
{
method: 'getAccountInfo',
2018-09-30 18:42:45 -07:00
params: [account.publicKey.toBase58()],
2018-09-20 15:08:52 -07:00
},
errorResponse,
]);
2018-11-04 11:41:21 -08:00
expect(connection.getAccountInfo(account.publicKey)).rejects.toThrow(
errorMessage,
);
2018-09-20 15:08:52 -07:00
});
2018-08-24 10:39:51 -07:00
test('get balance', async () => {
2018-08-23 10:52:48 -07:00
const account = new Account();
const connection = new Connection(url);
2018-08-24 10:39:51 -07:00
mockRpc.push([
url,
{
method: 'getBalance',
2018-09-30 18:42:45 -07:00
params: [account.publicKey.toBase58()],
2018-08-24 10:39:51 -07:00
},
{
error: null,
result: 0,
2018-11-04 11:41:21 -08:00
},
2018-08-24 10:39:51 -07:00
]);
2018-08-23 10:52:48 -07:00
const balance = await connection.getBalance(account.publicKey);
expect(balance).toBeGreaterThanOrEqual(0);
});
2018-08-24 11:12:48 -07:00
test('confirm transaction - error', () => {
2018-08-23 10:52:48 -07:00
const connection = new Connection(url);
2018-08-24 10:39:51 -07:00
const badTransactionSignature = 'bad transaction signature';
mockRpc.push([
url,
{
method: 'confirmTransaction',
params: [badTransactionSignature],
},
2018-08-24 11:12:48 -07:00
errorResponse,
2018-11-04 11:41:21 -08:00
]);
2018-08-24 10:39:51 -07:00
2018-11-04 11:41:21 -08:00
expect(
connection.confirmTransaction(badTransactionSignature),
).rejects.toThrow(errorMessage);
2018-09-26 19:16:17 -07:00
mockRpc.push([
url,
{
method: 'getSignatureStatus',
params: [badTransactionSignature],
},
errorResponse,
2018-11-04 11:41:21 -08:00
]);
2018-09-26 19:16:17 -07:00
2018-11-04 11:41:21 -08:00
expect(
connection.getSignatureStatus(badTransactionSignature),
).rejects.toThrow(errorMessage);
2018-08-23 10:52:48 -07:00
});
2018-08-24 10:39:51 -07:00
test('get transaction count', async () => {
2018-08-23 10:52:48 -07:00
const connection = new Connection(url);
2018-08-24 10:39:51 -07:00
mockRpc.push([
url,
{
method: 'getTransactionCount',
params: [],
},
{
error: null,
result: 1000000,
2018-11-04 11:41:21 -08:00
},
]);
2018-08-24 10:39:51 -07:00
2018-08-23 10:52:48 -07:00
const count = await connection.getTransactionCount();
expect(count).toBeGreaterThanOrEqual(0);
});
test('get recent blockhash', async () => {
2018-08-23 10:52:48 -07:00
const connection = new Connection(url);
2019-03-04 08:06:33 -08:00
mockGetRecentBlockhash();
2018-08-24 10:39:51 -07:00
2019-03-04 08:06:33 -08:00
const recentBlockhash = await connection.getRecentBlockhash();
expect(recentBlockhash.length).toBeGreaterThanOrEqual(43);
2018-08-23 10:52:48 -07:00
});
2018-08-24 10:39:51 -07:00
test('request airdrop', async () => {
2018-08-23 16:39:52 -07:00
const account = new Account();
const connection = new Connection(url);
2018-08-24 10:39:51 -07:00
mockRpc.push([
url,
{
method: 'requestAirdrop',
2018-09-30 18:42:45 -07:00
params: [account.publicKey.toBase58(), 40],
2018-08-24 10:39:51 -07:00
},
{
error: null,
2018-11-04 11:41:21 -08:00
result:
'1WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
2018-08-24 10:39:51 -07:00
]);
mockRpc.push([
url,
{
method: 'requestAirdrop',
2018-09-30 18:42:45 -07:00
params: [account.publicKey.toBase58(), 2],
2018-08-24 10:39:51 -07:00
},
{
error: null,
2018-11-04 11:41:21 -08:00
result:
'2WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
2018-08-23 16:39:52 -07:00
]);
2018-08-24 10:39:51 -07:00
mockRpc.push([
url,
{
method: 'getBalance',
2018-09-30 18:42:45 -07:00
params: [account.publicKey.toBase58()],
2018-08-24 10:39:51 -07:00
},
{
error: null,
result: 42,
2018-11-04 11:41:21 -08:00
},
2018-08-24 10:39:51 -07:00
]);
await connection.requestAirdrop(account.publicKey, 40);
await connection.requestAirdrop(account.publicKey, 2);
2018-08-23 16:39:52 -07:00
const balance = await connection.getBalance(account.publicKey);
expect(balance).toBe(42);
2018-09-20 15:08:52 -07:00
mockRpc.push([
url,
{
method: 'getAccountInfo',
2018-09-30 18:42:45 -07:00
params: [account.publicKey.toBase58()],
2018-09-20 15:08:52 -07:00
},
{
error: null,
result: {
owner: [
2018-11-04 11:41:21 -08:00
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2018-09-20 15:08:52 -07:00
],
2019-03-05 17:52:13 -08:00
lamports: 42,
2019-03-14 13:27:47 -07:00
data: [],
executable: false,
2018-11-04 11:41:21 -08:00
},
},
2018-09-20 15:08:52 -07:00
]);
const accountInfo = await connection.getAccountInfo(account.publicKey);
2019-03-05 17:52:13 -08:00
expect(accountInfo.lamports).toBe(42);
2019-03-14 13:27:47 -07:00
expect(accountInfo.data).toHaveLength(0);
expect(accountInfo.owner).toEqual(SystemProgram.programId);
2018-08-24 11:12:48 -07:00
});
test('transaction', async () => {
const accountFrom = new Account();
const accountTo = new Account();
const connection = new Connection(url);
2018-08-24 10:39:51 -07:00
mockRpc.push([
url,
{
method: 'requestAirdrop',
2018-09-30 18:42:45 -07:00
params: [accountFrom.publicKey.toBase58(), 12],
2018-08-24 10:39:51 -07:00
},
{
error: null,
2018-11-04 11:41:21 -08:00
result:
'0WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
2018-08-24 10:39:51 -07:00
]);
mockRpc.push([
url,
{
method: 'getBalance',
2018-09-30 18:42:45 -07:00
params: [accountFrom.publicKey.toBase58()],
},
{
error: null,
result: 12,
2018-11-04 11:41:21 -08:00
},
]);
await connection.requestAirdrop(accountFrom.publicKey, 12);
expect(await connection.getBalance(accountFrom.publicKey)).toBe(12);
2018-08-24 10:39:51 -07:00
mockRpc.push([
url,
{
method: 'requestAirdrop',
2018-09-30 18:42:45 -07:00
params: [accountTo.publicKey.toBase58(), 21],
},
{
error: null,
2018-11-04 11:41:21 -08:00
result:
'8WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
]);
mockRpc.push([
url,
{
method: 'getBalance',
2018-09-30 18:42:45 -07:00
params: [accountTo.publicKey.toBase58()],
},
{
error: null,
result: 21,
2018-11-04 11:41:21 -08:00
},
]);
await connection.requestAirdrop(accountTo.publicKey, 21);
expect(await connection.getBalance(accountTo.publicKey)).toBe(21);
2018-08-24 10:39:51 -07:00
2019-03-04 08:06:33 -08:00
mockGetRecentBlockhash();
mockRpc.push([
url,
{
method: 'sendTransaction',
},
{
error: null,
2018-11-04 11:41:21 -08:00
result:
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
]);
2018-09-14 08:27:40 -07:00
2018-09-20 10:10:46 -07:00
const transaction = SystemProgram.move(
2018-09-14 08:27:40 -07:00
accountFrom.publicKey,
accountTo.publicKey,
2018-11-04 11:41:21 -08:00
10,
2018-09-14 08:27:40 -07:00
);
transaction.fee = 0;
const signature = await connection.sendTransaction(transaction, accountFrom);
mockRpc.push([
url,
{
method: 'confirmTransaction',
params: [
2018-11-04 11:41:21 -08:00
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
],
},
{
error: null,
result: true,
2018-11-04 11:41:21 -08:00
},
]);
let i = 0;
for (;;) {
if (await connection.confirmTransaction(signature)) {
break;
}
expect(mockRpcEnabled).toBe(false);
expect(++i).toBeLessThan(10);
await sleep(500);
}
2018-09-26 19:16:17 -07:00
mockRpc.push([
url,
{
method: 'getSignatureStatus',
params: [
2018-11-04 11:41:21 -08:00
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
2018-09-26 19:16:17 -07:00
],
},
{
error: null,
result: 'Confirmed',
2018-11-04 11:41:21 -08:00
},
]);
await expect(connection.getSignatureStatus(signature)).resolves.toBe(
'Confirmed',
2018-09-26 19:16:17 -07:00
);
mockRpc.push([
url,
{
method: 'getBalance',
2018-09-30 18:42:45 -07:00
params: [accountFrom.publicKey.toBase58()],
},
{
error: null,
result: 2,
2018-11-04 11:41:21 -08:00
},
]);
expect(await connection.getBalance(accountFrom.publicKey)).toBe(2);
2018-08-23 10:52:48 -07:00
mockRpc.push([
url,
{
method: 'getBalance',
2018-09-30 18:42:45 -07:00
params: [accountTo.publicKey.toBase58()],
},
{
error: null,
result: 31,
2018-11-04 11:41:21 -08:00
},
]);
expect(await connection.getBalance(accountTo.publicKey)).toBe(31);
});
test('multi-instruction transaction', async () => {
if (mockRpcEnabled) {
console.log('non-live test skipped');
return;
}
const accountFrom = new Account();
const accountTo = new Account();
const connection = new Connection(url);
await connection.requestAirdrop(accountFrom.publicKey, 12);
expect(await connection.getBalance(accountFrom.publicKey)).toBe(12);
await connection.requestAirdrop(accountTo.publicKey, 21);
expect(await connection.getBalance(accountTo.publicKey)).toBe(21);
// 1. Move(accountFrom, accountTo)
// 2. Move(accountTo, accountFrom)
const transaction = SystemProgram.move(
accountFrom.publicKey,
accountTo.publicKey,
2018-11-04 11:41:21 -08:00
10,
).add(SystemProgram.move(accountTo.publicKey, accountFrom.publicKey, 10));
transaction.fee = 0;
2018-11-26 15:53:27 -08:00
const signature = await connection.sendTransaction(
transaction,
accountFrom,
accountTo,
);
let i = 0;
for (;;) {
if (await connection.confirmTransaction(signature)) {
break;
}
expect(mockRpcEnabled).toBe(false);
expect(++i).toBeLessThan(10);
await sleep(500);
}
2018-11-04 11:41:21 -08:00
await expect(connection.getSignatureStatus(signature)).resolves.toBe(
'Confirmed',
);
expect(await connection.getBalance(accountFrom.publicKey)).toBe(12);
expect(await connection.getBalance(accountTo.publicKey)).toBe(21);
});
2018-10-26 21:37:39 -07:00
test('account change notification', async () => {
if (mockRpcEnabled) {
console.log('non-live test skipped');
return;
}
const connection = new Connection(url);
const owner = new Account();
const programAccount = new Account();
const mockCallback = jest.fn();
2018-11-04 11:41:21 -08:00
const subscriptionId = connection.onAccountChange(
programAccount.publicKey,
mockCallback,
);
2018-10-26 21:37:39 -07:00
await connection.requestAirdrop(owner.publicKey, 42);
const transaction = SystemProgram.createAccount(
owner.publicKey,
programAccount.publicKey,
42,
3,
BpfLoader.programId,
);
transaction.fee = 0;
await sendAndConfirmTransaction(connection, transaction, owner);
2018-10-26 21:37:39 -07:00
const loader = new Loader(connection, BpfLoader.programId);
await loader.load(programAccount, [1, 2, 3]);
// Wait for mockCallback to receive a call
let i = 0;
for (;;) {
if (mockCallback.mock.calls.length === 1) {
break;
}
if (++i === 5) {
console.log(JSON.stringify(mockCallback.mock.calls));
throw new Error('mockCallback should be called twice');
}
// Sleep for a 1/4 of a slot, notifications only occur after a block is
// processed
await sleep((250 * DEFAULT_TICKS_PER_SLOT) / NUM_TICKS_PER_SECOND);
}
2018-10-26 21:37:39 -07:00
2018-11-16 19:29:14 -08:00
await connection.removeAccountChangeListener(subscriptionId);
2019-03-05 17:52:13 -08:00
expect(mockCallback.mock.calls[0][0].lamports).toBe(41);
expect(mockCallback.mock.calls[0][0].owner).toEqual(BpfLoader.programId);
2018-10-26 21:37:39 -07:00
expect(mockCallback.mock.calls[0][0].executable).toBe(false);
2019-03-14 13:27:47 -07:00
expect(mockCallback.mock.calls[0][0].data).toEqual(
2018-11-04 11:41:21 -08:00
Buffer.from([1, 2, 3]),
);
2018-10-26 21:37:39 -07:00
});
2019-03-08 16:02:39 -08:00
test('program account change notification', async () => {
if (mockRpcEnabled) {
console.log('non-live test skipped');
return;
}
const connection = new Connection(url);
const owner = new Account();
const programAccount = new Account();
const mockCallback = jest.fn();
const subscriptionId = connection.onProgramAccountChange(
BpfLoader.programId,
mockCallback,
);
await connection.requestAirdrop(owner.publicKey, 42);
const transaction = SystemProgram.createAccount(
owner.publicKey,
programAccount.publicKey,
42,
3,
BpfLoader.programId,
);
transaction.fee = 0;
await sendAndConfirmTransaction(connection, transaction, owner);
const loader = new Loader(connection, BpfLoader.programId);
await loader.load(programAccount, [1, 2, 3]);
// Wait for mockCallback to receive a call
let i = 0;
for (;;) {
if (mockCallback.mock.calls.length === 1) {
break;
}
if (++i === 5) {
console.log(JSON.stringify(mockCallback.mock.calls));
throw new Error('mockCallback should be called twice');
}
// Sleep for a 1/4 of a slot, notifications only occur after a block is
// processed
await sleep((250 * DEFAULT_TICKS_PER_SLOT) / NUM_TICKS_PER_SECOND);
}
await connection.removeProgramAccountChangeListener(subscriptionId);
expect(mockCallback.mock.calls[0][0].accountId).toEqual(
programAccount.publicKey.toString(),
);
expect(mockCallback.mock.calls[0][0].accountInfo.lamports).toBe(41);
expect(mockCallback.mock.calls[0][0].accountInfo.owner).toEqual(
BpfLoader.programId,
);
expect(mockCallback.mock.calls[0][0].accountInfo.executable).toBe(false);
2019-03-14 13:27:47 -07:00
expect(mockCallback.mock.calls[0][0].accountInfo.data).toEqual(
2019-03-08 16:02:39 -08:00
Buffer.from([1, 2, 3]),
);
});