feat: add unstable API for dynamic program loading

This commit is contained in:
Michael Vines 2018-10-10 15:19:59 -07:00
parent 715556a611
commit 1436eca398
6 changed files with 118 additions and 34 deletions

View File

@ -5,4 +5,4 @@ export {Connection} from './connection';
export {PublicKey} from './publickey';
export {SystemProgram} from './system-program';
export {Transaction} from './transaction';
export {Token} from './token-program';
export {Token, TokenAmount} from './token-program';

View File

@ -105,4 +105,35 @@ export class SystemProgram {
userdata,
});
}
/**
* Load a dynamic program. Unstable API, will change
*
* @private
*/
static load(from: PublicKey, programId: PublicKey, name: string): Transaction {
const userdataLayout = BufferLayout.struct([
BufferLayout.u32('instruction'),
Layout.publicKey('programId'),
Layout.rustString('name'),
]);
let userdata = Buffer.alloc(1024);
const encodeLength = userdataLayout.encode(
{
instruction: 3, // Load instruction
programId: programId.toBuffer(),
name,
},
userdata,
);
userdata = userdata.slice(0, encodeLength);
return new Transaction({
fee: 0,
keys: [from],
programId: SystemProgram.programId,
userdata,
});
}
}

View File

@ -1,10 +1,12 @@
// @flow
import {Account} from '../src/account';
import {Connection} from '../src/connection';
import {SystemProgram} from '../src/system-program';
import {
Account,
Connection,
SystemProgram,
} from '../src';
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
import {url} from './url.js';
import {url} from './url';
if (!mockRpcEnabled) {
// The default of 5 seconds is too slow for live testing sometimes

View File

@ -0,0 +1,32 @@
// @flow
import {
Account,
Connection,
} from '../src';
import {mockRpc} from './__mocks__/node-fetch';
import {url} from './url';
export async function newAccountWithTokens(connection: Connection, amount: number = 10): Promise<Account> {
const account = new Account();
{
mockRpc.push([
url,
{
method: 'requestAirdrop',
params: [account.publicKey.toBase58(), amount],
},
{
error: null,
// Signature doesn't matter
result: '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
}
]);
}
await connection.requestAirdrop(account.publicKey, amount);
return account;
}

View File

@ -1,6 +1,15 @@
// @flow
import {Account, SystemProgram, BudgetProgram} from '../src';
import {
Account,
BudgetProgram,
Connection,
SystemProgram,
Transaction,
} from '../src';
import {mockRpcEnabled} from './__mocks__/node-fetch';
import {url} from './url';
import {newAccountWithTokens} from './new-account-with-tokens';
test('createAccount', () => {
const from = new Account();
@ -52,4 +61,33 @@ test('assign', () => {
// TODO: Validate transaction contents more
});
test('unstable - load', async () => {
if (mockRpcEnabled) {
console.log('non-live test skipped');
return;
}
const connection = new Connection(url);
const from = await newAccountWithTokens(connection);
const noopProgramId = (new Account()).publicKey;
const loadTransaction = SystemProgram.load(
from.publicKey,
noopProgramId,
'noop',
);
let signature = await connection.sendTransaction(from, loadTransaction);
expect(connection.confirmTransaction(signature)).resolves.toBe(true);
const noopTransaction = new Transaction({
fee: 0,
keys: [from.publicKey],
programId: noopProgramId,
});
signature = await connection.sendTransaction(from, noopTransaction);
expect(connection.confirmTransaction(signature)).resolves.toBe(true);
});

View File

@ -1,12 +1,14 @@
// @flow
import {Account} from '../src/account';
import {Connection} from '../src/connection';
import {Token, TokenAmount} from '../src/token-program';
import {PublicKey} from '../src/publickey';
import {
Connection,
PublicKey,
Token,
TokenAmount,
} from '../src';
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
import {url} from './url.js';
import type {SignatureStatus} from '../src/connection';
import {url} from './url';
import {newAccountWithTokens} from './new-account-with-tokens';
if (!mockRpcEnabled) {
// The default of 5 seconds is too slow for live testing sometimes
@ -27,7 +29,7 @@ function mockGetLastId() {
]);
}
function mockGetSignatureStatus(result: SignatureStatus = 'Confirmed') {
function mockGetSignatureStatus(result: string = 'Confirmed') {
mockRpc.push([
url,
{
@ -53,27 +55,6 @@ function mockSendTransaction() {
}
async function newAccountWithTokens(connection: Connection, amount: number = 10): Promise<Account> {
const account = new Account();
{
mockRpc.push([
url,
{
method: 'requestAirdrop',
params: [account.publicKey.toBase58(), amount],
},
{
error: null,
result: '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
}
]);
}
await connection.requestAirdrop(account.publicKey, amount);
return account;
}
// A token created by the first test and used by all subsequent tests
let testToken: Token;