344 lines
10 KiB
JavaScript
344 lines
10 KiB
JavaScript
// @flow
|
|
|
|
import {
|
|
Account,
|
|
BudgetProgram,
|
|
Connection,
|
|
SystemInstruction,
|
|
SystemProgram,
|
|
Transaction,
|
|
sendAndConfirmRecentTransaction,
|
|
LAMPORTS_PER_SOL,
|
|
} from '../src';
|
|
import {mockRpcEnabled} from './__mocks__/node-fetch';
|
|
import {sleep} from '../src/util/sleep';
|
|
import {url} from './url';
|
|
|
|
if (!mockRpcEnabled) {
|
|
// Testing max commitment level takes around 20s to complete
|
|
jest.setTimeout(30000);
|
|
}
|
|
|
|
test('createAccount', () => {
|
|
const from = new Account();
|
|
const newAccount = new Account();
|
|
let transaction;
|
|
|
|
transaction = SystemProgram.createAccount(
|
|
from.publicKey,
|
|
newAccount.publicKey,
|
|
123,
|
|
BudgetProgram.space,
|
|
BudgetProgram.programId,
|
|
);
|
|
|
|
expect(transaction.keys).toHaveLength(2);
|
|
expect(transaction.programId).toEqual(SystemProgram.programId);
|
|
// TODO: Validate transaction contents more
|
|
});
|
|
|
|
test('transfer', () => {
|
|
const from = new Account();
|
|
const to = new Account();
|
|
let transaction;
|
|
|
|
transaction = SystemProgram.transfer(from.publicKey, to.publicKey, 123);
|
|
|
|
expect(transaction.keys).toHaveLength(2);
|
|
expect(transaction.programId).toEqual(SystemProgram.programId);
|
|
// TODO: Validate transaction contents more
|
|
});
|
|
|
|
test('assign', () => {
|
|
const from = new Account();
|
|
const to = new Account();
|
|
let transaction;
|
|
|
|
transaction = SystemProgram.assign(from.publicKey, to.publicKey);
|
|
|
|
expect(transaction.keys).toHaveLength(1);
|
|
expect(transaction.programId).toEqual(SystemProgram.programId);
|
|
// TODO: Validate transaction contents more
|
|
});
|
|
|
|
test('createAccountWithSeed', () => {
|
|
const from = new Account();
|
|
const newAccount = new Account();
|
|
let transaction;
|
|
|
|
transaction = SystemProgram.createAccountWithSeed(
|
|
from.publicKey,
|
|
newAccount.publicKey,
|
|
from.publicKey,
|
|
'hi there',
|
|
123,
|
|
BudgetProgram.space,
|
|
BudgetProgram.programId,
|
|
);
|
|
|
|
expect(transaction.keys).toHaveLength(2);
|
|
expect(transaction.programId).toEqual(SystemProgram.programId);
|
|
// TODO: Validate transaction contents more
|
|
});
|
|
|
|
test('createNonceAccount', () => {
|
|
const from = new Account();
|
|
const nonceAccount = new Account();
|
|
|
|
const transaction = SystemProgram.createNonceAccount(
|
|
from.publicKey,
|
|
nonceAccount.publicKey,
|
|
from.publicKey,
|
|
123,
|
|
);
|
|
|
|
expect(transaction.instructions).toHaveLength(2);
|
|
expect(transaction.instructions[0].programId).toEqual(
|
|
SystemProgram.programId,
|
|
);
|
|
expect(transaction.instructions[1].programId).toEqual(
|
|
SystemProgram.programId,
|
|
);
|
|
// TODO: Validate transaction contents more
|
|
});
|
|
|
|
test('nonceWithdraw', () => {
|
|
const from = new Account();
|
|
const nonceAccount = new Account();
|
|
const to = new Account();
|
|
|
|
const transaction = SystemProgram.nonceWithdraw(
|
|
nonceAccount.publicKey,
|
|
from.publicKey,
|
|
to.publicKey,
|
|
123,
|
|
);
|
|
|
|
expect(transaction.keys).toHaveLength(5);
|
|
expect(transaction.programId).toEqual(SystemProgram.programId);
|
|
// TODO: Validate transaction contents more
|
|
});
|
|
|
|
test('nonceAuthorize', () => {
|
|
const nonceAccount = new Account();
|
|
const authorized = new Account();
|
|
const newAuthorized = new Account();
|
|
|
|
const transaction = SystemProgram.nonceAuthorize(
|
|
nonceAccount.publicKey,
|
|
authorized.publicKey,
|
|
newAuthorized.publicKey,
|
|
);
|
|
|
|
expect(transaction.keys).toHaveLength(2);
|
|
expect(transaction.programId).toEqual(SystemProgram.programId);
|
|
// TODO: Validate transaction contents more
|
|
});
|
|
|
|
test('SystemInstruction create', () => {
|
|
const from = new Account();
|
|
const to = new Account();
|
|
const program = new Account();
|
|
const amount = 42;
|
|
const space = 100;
|
|
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
|
|
const create = SystemProgram.createAccount(
|
|
from.publicKey,
|
|
to.publicKey,
|
|
amount,
|
|
space,
|
|
program.publicKey,
|
|
);
|
|
const transaction = new Transaction({recentBlockhash}).add(create);
|
|
|
|
const systemInstruction = SystemInstruction.from(transaction.instructions[0]);
|
|
expect(systemInstruction.fromPublicKey).toEqual(from.publicKey);
|
|
expect(systemInstruction.toPublicKey).toEqual(to.publicKey);
|
|
expect(systemInstruction.amount).toEqual(amount);
|
|
expect(systemInstruction.programId).toEqual(SystemProgram.programId);
|
|
});
|
|
|
|
test('SystemInstruction transfer', () => {
|
|
const from = new Account();
|
|
const to = new Account();
|
|
const amount = 42;
|
|
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
|
|
const transfer = SystemProgram.transfer(from.publicKey, to.publicKey, amount);
|
|
const transaction = new Transaction({recentBlockhash}).add(transfer);
|
|
transaction.sign(from);
|
|
|
|
const systemInstruction = SystemInstruction.from(transaction.instructions[0]);
|
|
expect(systemInstruction.fromPublicKey).toEqual(from.publicKey);
|
|
expect(systemInstruction.toPublicKey).toEqual(to.publicKey);
|
|
expect(systemInstruction.amount).toEqual(amount);
|
|
expect(systemInstruction.programId).toEqual(SystemProgram.programId);
|
|
});
|
|
|
|
test('SystemInstruction assign', () => {
|
|
const from = new Account();
|
|
const program = new Account();
|
|
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
|
|
const assign = SystemProgram.assign(from.publicKey, program.publicKey);
|
|
const transaction = new Transaction({recentBlockhash}).add(assign);
|
|
transaction.sign(from);
|
|
|
|
const systemInstruction = SystemInstruction.from(transaction.instructions[0]);
|
|
expect(systemInstruction.fromPublicKey).toBeNull();
|
|
expect(systemInstruction.toPublicKey).toBeNull();
|
|
expect(systemInstruction.amount).toBeNull();
|
|
expect(systemInstruction.programId).toEqual(SystemProgram.programId);
|
|
});
|
|
|
|
test('SystemInstruction createWithSeed', () => {
|
|
const from = new Account();
|
|
const to = new Account();
|
|
const program = new Account();
|
|
const amount = 42;
|
|
const space = 100;
|
|
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
|
|
const create = SystemProgram.createAccountWithSeed(
|
|
from.publicKey,
|
|
to.publicKey,
|
|
from.publicKey,
|
|
'hi there',
|
|
amount,
|
|
space,
|
|
program.publicKey,
|
|
);
|
|
const transaction = new Transaction({recentBlockhash}).add(create);
|
|
|
|
const systemInstruction = SystemInstruction.from(transaction.instructions[0]);
|
|
expect(systemInstruction.fromPublicKey).toEqual(from.publicKey);
|
|
expect(systemInstruction.toPublicKey).toEqual(to.publicKey);
|
|
expect(systemInstruction.amount).toEqual(amount);
|
|
expect(systemInstruction.programId).toEqual(SystemProgram.programId);
|
|
});
|
|
|
|
test('SystemInstruction nonceWithdraw', () => {
|
|
const nonceAccount = new Account();
|
|
const authorized = new Account();
|
|
const to = new Account();
|
|
const amount = 42;
|
|
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
|
|
const nonceWithdraw = SystemProgram.nonceWithdraw(
|
|
nonceAccount.publicKey,
|
|
authorized.publicKey,
|
|
to.publicKey,
|
|
amount,
|
|
);
|
|
const transaction = new Transaction({recentBlockhash}).add(nonceWithdraw);
|
|
|
|
const systemInstruction = SystemInstruction.from(transaction.instructions[0]);
|
|
expect(systemInstruction.fromPublicKey).toEqual(nonceAccount.publicKey);
|
|
expect(systemInstruction.toPublicKey).toEqual(to.publicKey);
|
|
expect(systemInstruction.amount).toEqual(amount);
|
|
expect(systemInstruction.programId).toEqual(SystemProgram.programId);
|
|
});
|
|
|
|
test('non-SystemInstruction error', () => {
|
|
const from = new Account();
|
|
const program = new Account();
|
|
const to = new Account();
|
|
|
|
const badProgramId = {
|
|
keys: [
|
|
{pubkey: from.publicKey, isSigner: true, isWritable: true},
|
|
{pubkey: to.publicKey, isSigner: false, isWritable: true},
|
|
],
|
|
programId: BudgetProgram.programId,
|
|
data: Buffer.from([2, 0, 0, 0]),
|
|
};
|
|
expect(() => {
|
|
new SystemInstruction(badProgramId, 'Create');
|
|
}).toThrow();
|
|
|
|
const amount = 123;
|
|
const recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k'; // Arbitrary known recentBlockhash
|
|
const budgetPay = BudgetProgram.pay(
|
|
from.publicKey,
|
|
program.publicKey,
|
|
to.publicKey,
|
|
amount,
|
|
);
|
|
const transaction = new Transaction({recentBlockhash}).add(budgetPay);
|
|
transaction.sign(from);
|
|
|
|
expect(() => {
|
|
SystemInstruction.from(transaction.instructions[1]);
|
|
}).toThrow();
|
|
|
|
transaction.instructions[0].data[0] = 11;
|
|
expect(() => {
|
|
SystemInstruction.from(transaction.instructions[0]);
|
|
}).toThrow();
|
|
});
|
|
|
|
test('live Nonce actions', async () => {
|
|
if (mockRpcEnabled) {
|
|
console.log('non-live test skipped');
|
|
return;
|
|
}
|
|
|
|
const connection = new Connection(url, 'recent');
|
|
const nonceAccount = new Account();
|
|
const from = new Account();
|
|
const to = new Account();
|
|
const authority = new Account();
|
|
await connection.requestAirdrop(from.publicKey, 2 * LAMPORTS_PER_SOL);
|
|
await connection.requestAirdrop(authority.publicKey, LAMPORTS_PER_SOL);
|
|
|
|
const minimumAmount = await connection.getMinimumBalanceForRentExemption(
|
|
SystemProgram.nonceSpace,
|
|
'recent',
|
|
);
|
|
|
|
let createNonceAccount = SystemProgram.createNonceAccount(
|
|
from.publicKey,
|
|
nonceAccount.publicKey,
|
|
from.publicKey,
|
|
minimumAmount,
|
|
);
|
|
await sendAndConfirmRecentTransaction(
|
|
connection,
|
|
createNonceAccount,
|
|
from,
|
|
nonceAccount,
|
|
);
|
|
const nonceBalance = await connection.getBalance(nonceAccount.publicKey);
|
|
expect(nonceBalance).toEqual(minimumAmount);
|
|
|
|
const nonceQuery1 = await connection.getNonce(nonceAccount.publicKey);
|
|
const nonceQuery2 = await connection.getNonce(nonceAccount.publicKey);
|
|
expect(nonceQuery1.nonce).toEqual(nonceQuery2.nonce);
|
|
|
|
await sleep(500);
|
|
|
|
const advanceNonce = new Transaction().add(
|
|
SystemProgram.nonceAdvance(nonceAccount.publicKey, from.publicKey),
|
|
);
|
|
await sendAndConfirmRecentTransaction(connection, advanceNonce, from);
|
|
|
|
const nonceQuery3 = await connection.getNonce(nonceAccount.publicKey);
|
|
expect(nonceQuery1.nonce).not.toEqual(nonceQuery3.nonce);
|
|
const nonce = nonceQuery3.nonce;
|
|
|
|
await sleep(500);
|
|
|
|
let transfer = SystemProgram.transfer(
|
|
from.publicKey,
|
|
to.publicKey,
|
|
minimumAmount,
|
|
);
|
|
transfer.nonceInfo = {
|
|
nonce,
|
|
nonceInstruction: SystemProgram.nonceAdvance(
|
|
nonceAccount.publicKey,
|
|
from.publicKey,
|
|
),
|
|
};
|
|
|
|
await sendAndConfirmRecentTransaction(connection, transfer, from);
|
|
const toBalance = await connection.getBalance(to.publicKey);
|
|
expect(toBalance).toEqual(minimumAmount);
|
|
});
|