2020-01-02 18:54:43 -07:00
|
|
|
// @flow
|
|
|
|
|
|
|
|
import bs58 from 'bs58';
|
|
|
|
|
2020-05-05 13:30:55 +08:00
|
|
|
import {Account, Connection, SystemProgram, PublicKey} from '../src';
|
2020-03-05 09:44:56 -07:00
|
|
|
import {NONCE_ACCOUNT_LENGTH} from '../src/nonce-account';
|
2020-01-02 18:54:43 -07:00
|
|
|
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
|
|
|
|
import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash';
|
|
|
|
import {url} from './url';
|
|
|
|
|
|
|
|
if (!mockRpcEnabled) {
|
|
|
|
// Testing max commitment level takes around 20s to complete
|
|
|
|
jest.setTimeout(30000);
|
|
|
|
}
|
|
|
|
|
2020-05-05 13:30:55 +08:00
|
|
|
const expectedData = (authorizedPubkey: PublicKey): string => {
|
|
|
|
const expectedData = Buffer.alloc(NONCE_ACCOUNT_LENGTH);
|
|
|
|
expectedData.writeInt32LE(0, 0); // Version, 4 bytes
|
|
|
|
expectedData.writeInt32LE(1, 4); // State, 4 bytes
|
|
|
|
authorizedPubkey.toBuffer().copy(expectedData, 8); // authorizedPubkey, 32 bytes
|
|
|
|
const mockNonce = new Account();
|
|
|
|
mockNonce.publicKey.toBuffer().copy(expectedData, 40); // Hash, 32 bytes
|
|
|
|
expectedData.writeUInt16LE(5000, 72); // feeCalculator, 8 bytes
|
|
|
|
return bs58.encode(expectedData);
|
|
|
|
};
|
|
|
|
|
2020-01-02 18:54:43 -07:00
|
|
|
test('create and query nonce account', async () => {
|
|
|
|
const from = new Account();
|
|
|
|
const nonceAccount = new Account();
|
|
|
|
const connection = new Connection(url, 'recent');
|
|
|
|
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'getMinimumBalanceForRentExemption',
|
2020-03-05 09:44:56 -07:00
|
|
|
params: [NONCE_ACCOUNT_LENGTH, {commitment: 'recent'}],
|
2020-01-02 18:54:43 -07:00
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result: 50,
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
const minimumAmount = await connection.getMinimumBalanceForRentExemption(
|
2020-03-05 09:44:56 -07:00
|
|
|
NONCE_ACCOUNT_LENGTH,
|
2020-01-02 18:54:43 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'requestAirdrop',
|
|
|
|
params: [
|
|
|
|
from.publicKey.toBase58(),
|
|
|
|
minimumAmount * 2,
|
|
|
|
{commitment: 'recent'},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result:
|
|
|
|
'1WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
await connection.requestAirdrop(from.publicKey, minimumAmount * 2);
|
|
|
|
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'getBalance',
|
|
|
|
params: [from.publicKey.toBase58(), {commitment: 'recent'}],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
2020-01-08 13:59:58 -07:00
|
|
|
result: {
|
|
|
|
context: {
|
|
|
|
slot: 11,
|
|
|
|
},
|
|
|
|
value: minimumAmount * 2,
|
|
|
|
},
|
2020-01-02 18:54:43 -07:00
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
const balance = await connection.getBalance(from.publicKey);
|
|
|
|
expect(balance).toBe(minimumAmount * 2);
|
|
|
|
|
|
|
|
mockGetRecentBlockhash('recent');
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'sendTransaction',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result:
|
|
|
|
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
2020-03-03 16:05:50 +08:00
|
|
|
const transaction = SystemProgram.createNonceAccount({
|
|
|
|
fromPubkey: from.publicKey,
|
|
|
|
noncePubkey: nonceAccount.publicKey,
|
|
|
|
authorizedPubkey: from.publicKey,
|
|
|
|
lamports: minimumAmount,
|
|
|
|
});
|
2020-05-20 17:13:21 +08:00
|
|
|
await connection.sendTransaction(transaction, [from, nonceAccount]);
|
2020-01-02 18:54:43 -07:00
|
|
|
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'getAccountInfo',
|
|
|
|
params: [nonceAccount.publicKey.toBase58(), {commitment: 'recent'}],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result: {
|
2020-01-08 13:59:58 -07:00
|
|
|
context: {
|
|
|
|
slot: 11,
|
|
|
|
},
|
|
|
|
value: {
|
2020-01-15 14:04:26 -07:00
|
|
|
owner: '11111111111111111111111111111111',
|
2020-01-08 13:59:58 -07:00
|
|
|
lamports: minimumAmount,
|
2020-05-05 13:30:55 +08:00
|
|
|
data: expectedData(from.publicKey),
|
2020-01-08 13:59:58 -07:00
|
|
|
executable: false,
|
|
|
|
},
|
2020-01-02 18:54:43 -07:00
|
|
|
},
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
//
|
2020-05-05 13:30:55 +08:00
|
|
|
const nonceAccountData = await connection.getNonce(nonceAccount.publicKey);
|
|
|
|
if (nonceAccountData === null) {
|
|
|
|
expect(nonceAccountData).not.toBeNull();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
expect(nonceAccountData.authorizedPubkey).toEqual(from.publicKey);
|
|
|
|
expect(bs58.decode(nonceAccountData.nonce).length).toBeGreaterThan(30);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('create and query nonce account with seed', async () => {
|
|
|
|
const from = new Account();
|
|
|
|
const seed = 'seed';
|
|
|
|
const noncePubkey = await PublicKey.createWithSeed(
|
|
|
|
from.publicKey,
|
|
|
|
seed,
|
|
|
|
SystemProgram.programId,
|
|
|
|
);
|
|
|
|
const connection = new Connection(url, 'recent');
|
|
|
|
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'getMinimumBalanceForRentExemption',
|
|
|
|
params: [NONCE_ACCOUNT_LENGTH, {commitment: 'recent'}],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result: 50,
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
const minimumAmount = await connection.getMinimumBalanceForRentExemption(
|
|
|
|
NONCE_ACCOUNT_LENGTH,
|
2020-01-02 18:54:43 -07:00
|
|
|
);
|
2020-05-05 13:30:55 +08:00
|
|
|
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'requestAirdrop',
|
|
|
|
params: [
|
|
|
|
from.publicKey.toBase58(),
|
|
|
|
minimumAmount * 2,
|
|
|
|
{commitment: 'recent'},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result:
|
|
|
|
'1WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
await connection.requestAirdrop(from.publicKey, minimumAmount * 2);
|
|
|
|
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'getBalance',
|
|
|
|
params: [from.publicKey.toBase58(), {commitment: 'recent'}],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result: {
|
|
|
|
context: {
|
|
|
|
slot: 11,
|
|
|
|
},
|
|
|
|
value: minimumAmount * 2,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
const balance = await connection.getBalance(from.publicKey);
|
|
|
|
expect(balance).toBe(minimumAmount * 2);
|
|
|
|
|
|
|
|
mockGetRecentBlockhash('recent');
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'sendTransaction',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result:
|
|
|
|
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
|
|
|
const transaction = SystemProgram.createNonceAccount({
|
|
|
|
fromPubkey: from.publicKey,
|
|
|
|
noncePubkey: noncePubkey,
|
|
|
|
basePubkey: from.publicKey,
|
|
|
|
seed,
|
|
|
|
authorizedPubkey: from.publicKey,
|
|
|
|
lamports: minimumAmount,
|
|
|
|
});
|
2020-05-20 17:13:21 +08:00
|
|
|
await connection.sendTransaction(transaction, [from]);
|
2020-05-05 13:30:55 +08:00
|
|
|
|
|
|
|
mockRpc.push([
|
|
|
|
url,
|
|
|
|
{
|
|
|
|
method: 'getAccountInfo',
|
|
|
|
params: [noncePubkey.toBase58(), {commitment: 'recent'}],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
error: null,
|
|
|
|
result: {
|
|
|
|
context: {
|
|
|
|
slot: 11,
|
|
|
|
},
|
|
|
|
value: {
|
|
|
|
owner: '11111111111111111111111111111111',
|
|
|
|
lamports: minimumAmount,
|
|
|
|
data: expectedData(from.publicKey),
|
|
|
|
executable: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
//
|
|
|
|
const nonceAccountData = await connection.getNonce(noncePubkey);
|
2020-04-05 16:18:45 +08:00
|
|
|
if (nonceAccountData === null) {
|
|
|
|
expect(nonceAccountData).not.toBeNull();
|
|
|
|
return;
|
|
|
|
}
|
2020-01-02 18:54:43 -07:00
|
|
|
expect(nonceAccountData.authorizedPubkey).toEqual(from.publicKey);
|
|
|
|
expect(bs58.decode(nonceAccountData.nonce).length).toBeGreaterThan(30);
|
|
|
|
});
|