refactor: employ prettier

This commit is contained in:
Michael Vines 2018-11-04 11:41:21 -08:00
parent 9a043344d5
commit 1d6abb17cf
35 changed files with 1498 additions and 856 deletions

View File

@ -1,61 +1,50 @@
module.exports = { // eslint-disable-line import/no-commonjs module.exports = {
'env': { // eslint-disable-line import/no-commonjs
'browser': true, env: {
'es6': true, browser: true,
'node': true, es6: true,
node: true,
}, },
'extends': [ extends: [
'eslint:recommended', 'eslint:recommended',
'plugin:import/errors', 'plugin:import/errors',
'plugin:import/warnings', 'plugin:import/warnings',
], ],
'parser': 'babel-eslint', parser: 'babel-eslint',
'parserOptions': { parserOptions: {
'sourceType': 'module', sourceType: 'module',
'ecmaVersion': 8, ecmaVersion: 8,
}, },
'rules': { rules: {
'no-trailing-spaces': [ 'no-trailing-spaces': ['error'],
'error', 'import/first': ['error'],
], 'import/no-commonjs': ['error'],
'import/first': [
'error',
],
'import/no-commonjs': [
'error',
],
'import/order': [ 'import/order': [
'error', 'error',
{ {
'groups': [ groups: [
['internal', 'external', 'builtin'], ['internal', 'external', 'builtin'],
['index', 'sibling', 'parent'] ['index', 'sibling', 'parent'],
], ],
'newlines-between': 'always', 'newlines-between': 'always',
}, },
], ],
'indent': [ indent: [
'error', 'error',
2, 2,
{'MemberExpression': 0}, {
MemberExpression: 1,
SwitchCase: 1,
},
], ],
'linebreak-style': [ 'linebreak-style': ['error', 'unix'],
'no-console': [0],
quotes: [
'error', 'error',
'unix', 'single',
], {avoidEscape: true, allowTemplateLiterals: true},
'no-console': [
0
],
'quotes': [
'error',
'single', {'avoidEscape': true, 'allowTemplateLiterals': true},
],
'require-await': [
'error'
],
'semi': [
'error',
'always',
], ],
'require-await': ['error'],
semi: ['error', 'always'],
}, },
}; };

7
web3.js/.prettierrc.yaml Normal file
View File

@ -0,0 +1,7 @@
arrowParens: "avoid"
bracketSpacing: false
jsxBracketSameLine: false
semi: true
singleQuote: true
tabWidth: 2
trailingComma: "all"

View File

@ -25,18 +25,31 @@ function showBalance() {
connection.getBalance(account2.publicKey), connection.getBalance(account2.publicKey),
connection.getBalance(contractFunds.publicKey), connection.getBalance(contractFunds.publicKey),
connection.getBalance(contractState.publicKey), connection.getBalance(contractState.publicKey),
]).then(([fromBalance, toBalance, contractFundsBalance, contractStateBalance]) => { ]).then(
console.log(`Account1: ${account1.publicKey} has a balance of ${fromBalance}`); ([fromBalance, toBalance, contractFundsBalance, contractStateBalance]) => {
console.log(`Account2: ${account2.publicKey} has a balance of ${toBalance}`); console.log(
console.log(`Contract Funds: ${contractFunds.publicKey} has a balance of ${contractFundsBalance}`); `Account1: ${account1.publicKey} has a balance of ${fromBalance}`,
console.log(`Contract State: ${contractState.publicKey} has a balance of ${contractStateBalance}`); );
}); console.log(
`Account2: ${account2.publicKey} has a balance of ${toBalance}`,
);
console.log(
`Contract Funds: ${
contractFunds.publicKey
} has a balance of ${contractFundsBalance}`,
);
console.log(
`Contract State: ${
contractState.publicKey
} has a balance of ${contractStateBalance}`,
);
},
);
} }
function confirmTransaction(signature) { function confirmTransaction(signature) {
console.log('Confirming transaction:', signature); console.log('Confirming transaction:', signature);
return connection.getSignatureStatus(signature) return connection.getSignatureStatus(signature).then(confirmation => {
.then((confirmation) => {
if (confirmation !== 'Confirmed') { if (confirmation !== 'Confirmed') {
throw new Error(`Transaction was not confirmed (${confirmation})`); throw new Error(`Transaction was not confirmed (${confirmation})`);
} }
@ -46,69 +59,73 @@ function confirmTransaction(signature) {
function airDrop() { function airDrop() {
console.log(`\n== Requesting airdrop of 100 to ${account1.publicKey}`); console.log(`\n== Requesting airdrop of 100 to ${account1.publicKey}`);
return connection.requestAirdrop(account1.publicKey, 100) return connection
.then(confirmTransaction); .requestAirdrop(account1.publicKey, 100)
.then(confirmTransaction);
} }
showBalance() showBalance()
.then(airDrop) .then(airDrop)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log(`\n== Creating account for the contract funds`); console.log(`\n== Creating account for the contract funds`);
const transaction = solanaWeb3.SystemProgram.createAccount( const transaction = solanaWeb3.SystemProgram.createAccount(
account1.publicKey, account1.publicKey,
contractFunds.publicKey, contractFunds.publicKey,
50, // number of tokens to transfer 50, // number of tokens to transfer
0, 0,
solanaWeb3.BudgetProgram.programId, solanaWeb3.BudgetProgram.programId,
); );
return connection.sendTransaction(account1, transaction); return connection.sendTransaction(account1, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log(`\n== Creating account for the contract state`); console.log(`\n== Creating account for the contract state`);
const transaction = solanaWeb3.SystemProgram.createAccount( const transaction = solanaWeb3.SystemProgram.createAccount(
account1.publicKey, account1.publicKey,
contractState.publicKey, contractState.publicKey,
1, // account1 pays 1 token to hold the contract state 1, // account1 pays 1 token to hold the contract state
solanaWeb3.BudgetProgram.space, solanaWeb3.BudgetProgram.space,
solanaWeb3.BudgetProgram.programId, solanaWeb3.BudgetProgram.programId,
); );
return connection.sendTransaction(account1, transaction); return connection.sendTransaction(account1, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log(`\n== Initializing contract`); console.log(`\n== Initializing contract`);
const transaction = solanaWeb3.BudgetProgram.pay( const transaction = solanaWeb3.BudgetProgram.pay(
contractFunds.publicKey, contractFunds.publicKey,
contractState.publicKey, contractState.publicKey,
account2.publicKey, account2.publicKey,
50, 50,
solanaWeb3.BudgetProgram.timestampCondition(account1.publicKey, new Date('2050')), solanaWeb3.BudgetProgram.timestampCondition(
); account1.publicKey,
return connection.sendTransaction(contractFunds, transaction); new Date('2050'),
}) ),
.then(confirmTransaction) );
.then(showBalance) return connection.sendTransaction(contractFunds, transaction);
.then(() => { })
console.log(`\n== Witness contract`); .then(confirmTransaction)
const transaction = solanaWeb3.BudgetProgram.applyTimestamp( .then(showBalance)
account1.publicKey, .then(() => {
contractState.publicKey, console.log(`\n== Witness contract`);
account2.publicKey, const transaction = solanaWeb3.BudgetProgram.applyTimestamp(
new Date('2050'), account1.publicKey,
); contractState.publicKey,
return connection.sendTransaction(account1, transaction); account2.publicKey,
}) new Date('2050'),
.then(confirmTransaction) );
.then(showBalance) return connection.sendTransaction(account1, transaction);
})
.then(confirmTransaction)
.then(showBalance)
.then(() => { .then(() => {
console.log('\nDone'); console.log('\nDone');
}) })
.catch((err) => { .catch(err => {
console.log(err); console.log(err);
}); });

View File

@ -26,18 +26,31 @@ function showBalance() {
connection.getBalance(account2.publicKey), connection.getBalance(account2.publicKey),
connection.getBalance(contractFunds.publicKey), connection.getBalance(contractFunds.publicKey),
connection.getBalance(contractState.publicKey), connection.getBalance(contractState.publicKey),
]).then(([fromBalance, toBalance, contractFundsBalance, contractStateBalance]) => { ]).then(
console.log(`Account1: ${account1.publicKey} has a balance of ${fromBalance}`); ([fromBalance, toBalance, contractFundsBalance, contractStateBalance]) => {
console.log(`Account2: ${account2.publicKey} has a balance of ${toBalance}`); console.log(
console.log(`Contract Funds: ${contractFunds.publicKey} has a balance of ${contractFundsBalance}`); `Account1: ${account1.publicKey} has a balance of ${fromBalance}`,
console.log(`Contract State: ${contractState.publicKey} has a balance of ${contractStateBalance}`); );
}); console.log(
`Account2: ${account2.publicKey} has a balance of ${toBalance}`,
);
console.log(
`Contract Funds: ${
contractFunds.publicKey
} has a balance of ${contractFundsBalance}`,
);
console.log(
`Contract State: ${
contractState.publicKey
} has a balance of ${contractStateBalance}`,
);
},
);
} }
function confirmTransaction(signature) { function confirmTransaction(signature) {
console.log('Confirming transaction:', signature); console.log('Confirming transaction:', signature);
return connection.getSignatureStatus(signature) return connection.getSignatureStatus(signature).then(confirmation => {
.then((confirmation) => {
if (confirmation !== 'Confirmed') { if (confirmation !== 'Confirmed') {
throw new Error(`Transaction was not confirmed (${confirmation})`); throw new Error(`Transaction was not confirmed (${confirmation})`);
} }
@ -47,100 +60,101 @@ function confirmTransaction(signature) {
function airDrop() { function airDrop() {
console.log(`\n== Requesting airdrop of 100 to ${account1.publicKey}`); console.log(`\n== Requesting airdrop of 100 to ${account1.publicKey}`);
return connection.requestAirdrop(account1.publicKey, 100) return connection
.then(confirmTransaction); .requestAirdrop(account1.publicKey, 100)
.then(confirmTransaction);
} }
showBalance() showBalance()
.then(airDrop) .then(airDrop)
.then(() => { .then(() => {
console.log(`\n== Move 1 token to approver1`); console.log(`\n== Move 1 token to approver1`);
const transaction = solanaWeb3.SystemProgram.move( const transaction = solanaWeb3.SystemProgram.move(
account1.publicKey, account1.publicKey,
approver1.publicKey, approver1.publicKey,
1, 1,
); );
return connection.sendTransaction(account1, transaction); return connection.sendTransaction(account1, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(() => { .then(() => {
console.log(`\n== Move 1 token to approver2`); console.log(`\n== Move 1 token to approver2`);
const transaction = solanaWeb3.SystemProgram.move( const transaction = solanaWeb3.SystemProgram.move(
account1.publicKey, account1.publicKey,
approver2.publicKey, approver2.publicKey,
1, 1,
); );
return connection.sendTransaction(account1, transaction); return connection.sendTransaction(account1, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log(`\n== Creating account for the contract funds`); console.log(`\n== Creating account for the contract funds`);
const transaction = solanaWeb3.SystemProgram.createAccount( const transaction = solanaWeb3.SystemProgram.createAccount(
account1.publicKey, account1.publicKey,
contractFunds.publicKey, contractFunds.publicKey,
50, // number of tokens to transfer 50, // number of tokens to transfer
0, 0,
solanaWeb3.BudgetProgram.programId, solanaWeb3.BudgetProgram.programId,
); );
return connection.sendTransaction(account1, transaction); return connection.sendTransaction(account1, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log(`\n== Creating account for the contract state`); console.log(`\n== Creating account for the contract state`);
const transaction = solanaWeb3.SystemProgram.createAccount( const transaction = solanaWeb3.SystemProgram.createAccount(
account1.publicKey, account1.publicKey,
contractState.publicKey, contractState.publicKey,
1, // account1 pays 1 token to hold the contract state 1, // account1 pays 1 token to hold the contract state
solanaWeb3.BudgetProgram.space, solanaWeb3.BudgetProgram.space,
solanaWeb3.BudgetProgram.programId, solanaWeb3.BudgetProgram.programId,
); );
return connection.sendTransaction(account1, transaction); return connection.sendTransaction(account1, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log(`\n== Initializing contract`); console.log(`\n== Initializing contract`);
const transaction = solanaWeb3.BudgetProgram.payOnBoth( const transaction = solanaWeb3.BudgetProgram.payOnBoth(
contractFunds.publicKey, contractFunds.publicKey,
contractState.publicKey, contractState.publicKey,
account2.publicKey, account2.publicKey,
50, 50,
solanaWeb3.BudgetProgram.signatureCondition(approver1.publicKey), solanaWeb3.BudgetProgram.signatureCondition(approver1.publicKey),
solanaWeb3.BudgetProgram.signatureCondition(approver2.publicKey), solanaWeb3.BudgetProgram.signatureCondition(approver2.publicKey),
); );
return connection.sendTransaction(contractFunds, transaction); return connection.sendTransaction(contractFunds, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log(`\n== Apply approver 1`); console.log(`\n== Apply approver 1`);
const transaction = solanaWeb3.BudgetProgram.applySignature( const transaction = solanaWeb3.BudgetProgram.applySignature(
approver1.publicKey, approver1.publicKey,
contractState.publicKey, contractState.publicKey,
account2.publicKey, account2.publicKey,
); );
return connection.sendTransaction(approver1, transaction); return connection.sendTransaction(approver1, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log(`\n== Apply approver 2`); console.log(`\n== Apply approver 2`);
const transaction = solanaWeb3.BudgetProgram.applySignature( const transaction = solanaWeb3.BudgetProgram.applySignature(
approver2.publicKey, approver2.publicKey,
contractState.publicKey, contractState.publicKey,
account2.publicKey, account2.publicKey,
); );
return connection.sendTransaction(approver2, transaction); return connection.sendTransaction(approver2, transaction);
}) })
.then(confirmTransaction) .then(confirmTransaction)
.then(showBalance) .then(showBalance)
.then(() => { .then(() => {
console.log('\nDone'); console.log('\nDone');
}) })
.catch((err) => { .catch(err => {
console.log(err); console.log(err);
}); });

View File

@ -13,7 +13,6 @@ url = 'http://localhost:8899';
//url = 'http://testnet.solana.com:8899'; //url = 'http://testnet.solana.com:8899';
const connection = new solanaWeb3.Connection(url); const connection = new solanaWeb3.Connection(url);
connection.getBalance(account.publicKey) connection.getBalance(account.publicKey).then(balance => {
.then((balance) => {
console.log(`${account.publicKey} has a balance of ${balance}`); console.log(`${account.publicKey} has a balance of ${balance}`);
}); });

View File

@ -34,16 +34,17 @@ declare module '@solana/web3.js' {
// === src/connection.js === // === src/connection.js ===
declare export type AccountInfo = { declare export type AccountInfo = {
executable: boolean; executable: boolean,
loaderProgramId: PublicKey, loaderProgramId: PublicKey,
programId: PublicKey, programId: PublicKey,
tokens: number, tokens: number,
userdata: Buffer, userdata: Buffer,
} };
declare type AccountChangeCallback = (accountInfo: AccountInfo) => void; declare type AccountChangeCallback = (accountInfo: AccountInfo) => void;
declare export type SignatureStatus = 'Confirmed' declare export type SignatureStatus =
| 'Confirmed'
| 'AccountInUse' | 'AccountInUse'
| 'SignatureNotFound' | 'SignatureNotFound'
| 'ProgramRuntimeError' | 'ProgramRuntimeError'
@ -54,13 +55,24 @@ declare module '@solana/web3.js' {
getBalance(publicKey: PublicKey): Promise<number>; getBalance(publicKey: PublicKey): Promise<number>;
getAccountInfo(publicKey: PublicKey): Promise<AccountInfo>; getAccountInfo(publicKey: PublicKey): Promise<AccountInfo>;
confirmTransaction(signature: TransactionSignature): Promise<boolean>; confirmTransaction(signature: TransactionSignature): Promise<boolean>;
getSignatureStatus(signature: TransactionSignature): Promise<SignatureStatus>; getSignatureStatus(
signature: TransactionSignature,
): Promise<SignatureStatus>;
getTransactionCount(): Promise<number>; getTransactionCount(): Promise<number>;
getLastId(): Promise<TransactionId>; getLastId(): Promise<TransactionId>;
getFinality(): Promise<number>; getFinality(): Promise<number>;
requestAirdrop(to: PublicKey, amount: number): Promise<TransactionSignature>; requestAirdrop(
sendTransaction(from: Account, transaction: Transaction): Promise<TransactionSignature>; to: PublicKey,
onAccountChange(publickey: PublicKey, callback: AccountChangeCallback): number; amount: number,
): Promise<TransactionSignature>;
sendTransaction(
from: Account,
transaction: Transaction,
): Promise<TransactionSignature>;
onAccountChange(
publickey: PublicKey,
callback: AccountChangeCallback,
): number;
removeAccountChangeListener(id: number): Promise<void>; removeAccountChangeListener(id: number): Promise<void>;
} }
@ -73,7 +85,7 @@ declare module '@solana/web3.js' {
newAccount: PublicKey, newAccount: PublicKey,
tokens: number, tokens: number,
space: number, space: number,
programId: PublicKey programId: PublicKey,
): Transaction; ): Transaction;
static move(from: PublicKey, to: PublicKey, amount: number): Transaction; static move(from: PublicKey, to: PublicKey, amount: number): Transaction;
static assign(from: PublicKey, programId: PublicKey): Transaction; static assign(from: PublicKey, programId: PublicKey): Transaction;
@ -85,9 +97,9 @@ declare module '@solana/web3.js' {
declare export type TransactionId = string; declare export type TransactionId = string;
declare type TransactionInstructionCtorFields = {| declare type TransactionInstructionCtorFields = {|
keys?: Array<PublicKey>; keys?: Array<PublicKey>,
programId?: PublicKey; programId?: PublicKey,
userdata?: Buffer; userdata?: Buffer,
|}; |};
declare export class TransactionInstruction { declare export class TransactionInstruction {
@ -98,7 +110,7 @@ declare module '@solana/web3.js' {
} }
declare type TransactionCtorFields = {| declare type TransactionCtorFields = {|
fee?: number; fee?: number,
|}; |};
declare export class Transaction { declare export class Transaction {
@ -107,7 +119,9 @@ declare module '@solana/web3.js' {
instructions: Array<TransactionInstruction>; instructions: Array<TransactionInstruction>;
constructor(opts?: TransactionCtorFields): Transaction; constructor(opts?: TransactionCtorFields): Transaction;
add(item: TransactionInstruction | TransactionInstructionCtorFields): Transaction; add(
item: TransactionInstruction | TransactionInstructionCtorFields,
): Transaction;
sign(from: Account): void; sign(from: Account): void;
serialize(): Buffer; serialize(): Buffer;
} }
@ -125,12 +139,12 @@ declare module '@solana/web3.js' {
symbol: string, symbol: string,
|}; |};
declare export type TokenAccountInfo = {| declare export type TokenAccountInfo = {|
token: PublicKey; token: PublicKey,
owner: PublicKey; owner: PublicKey,
amount: TokenAmount; amount: TokenAmount,
source: null | PublicKey; source: null | PublicKey,
originalAmount: TokenAmount; originalAmount: TokenAmount,
|} |};
declare type TokenAndPublicKey = [Token, PublicKey]; declare type TokenAndPublicKey = [Token, PublicKey];
declare export class Token { declare export class Token {
@ -147,7 +161,7 @@ declare module '@solana/web3.js' {
programId?: PublicKey, programId?: PublicKey,
): Promise<TokenAndPublicKey>; ): Promise<TokenAndPublicKey>;
constructor(connection: Connection, token: PublicKey) : Token; constructor(connection: Connection, token: PublicKey): Token;
newAccount(owner: Account, source?: PublicKey): Promise<PublicKey>; newAccount(owner: Account, source?: PublicKey): Promise<PublicKey>;
tokenInfo(): Promise<TokenInfo>; tokenInfo(): Promise<TokenInfo>;
accountInfo(account: PublicKey): Promise<TokenAccountInfo>; accountInfo(account: PublicKey): Promise<TokenAccountInfo>;
@ -161,17 +175,17 @@ declare module '@solana/web3.js' {
owner: Account, owner: Account,
account: PublicKey, account: PublicKey,
delegate: PublicKey, delegate: PublicKey,
amount: number | TokenAmount amount: number | TokenAmount,
): Promise<void>; ): Promise<void>;
revoke( revoke(
owner: Account, owner: Account,
account: PublicKey, account: PublicKey,
delegate: PublicKey delegate: PublicKey,
): Promise<void>; ): Promise<void>;
setOwner( setOwner(
owner: Account, owner: Account,
account: PublicKey, account: PublicKey,
newOwner: PublicKey newOwner: PublicKey,
): Promise<void>; ): Promise<void>;
transferInstruction( transferInstruction(
@ -184,7 +198,7 @@ declare module '@solana/web3.js' {
owner: PublicKey, owner: PublicKey,
account: PublicKey, account: PublicKey,
delegate: PublicKey, delegate: PublicKey,
amount: number | TokenAmount amount: number | TokenAmount,
): TransactionInstruction; ): TransactionInstruction;
revokeInstruction( revokeInstruction(
owner: PublicKey, owner: PublicKey,
@ -200,7 +214,7 @@ declare module '@solana/web3.js' {
// === src/loader.js === // === src/loader.js ===
declare export class Loader { declare export class Loader {
constructor(connection: Connection, programId: PublicKey) : Loader; constructor(connection: Connection, programId: PublicKey): Loader;
load(program: Account, offset: number, bytes: Array<number>): Promise<void>; load(program: Account, offset: number, bytes: Array<number>): Promise<void>;
finalize(program: Account): Promise<void>; finalize(program: Account): Promise<void>;
} }
@ -215,7 +229,6 @@ declare module '@solana/web3.js' {
): Promise<PublicKey>; ): Promise<PublicKey>;
} }
// === src/native-loader.js === // === src/native-loader.js ===
declare export class NativeLoader { declare export class NativeLoader {
static programId: PublicKey; static programId: PublicKey;

View File

@ -4522,6 +4522,23 @@
} }
} }
}, },
"eslint-config-prettier": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz",
"integrity": "sha512-QYGfmzuc4q4J6XIhlp8vRKdI/fI0tQfQPy1dME3UOLprE+v4ssH/3W9LM2Q7h5qBcy5m0ehCrBDU2YF8q6OY8w==",
"dev": true,
"requires": {
"get-stdin": "6.0.0"
},
"dependencies": {
"get-stdin": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
"integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
"dev": true
}
}
},
"eslint-import-resolver-node": { "eslint-import-resolver-node": {
"version": "0.3.2", "version": "0.3.2",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
@ -4608,6 +4625,15 @@
"integrity": "sha512-OcVizyXljSps3nVfuPomfK8RKt7jvDsIsDrO7l1ZA4bDbiO9bEGWpsdU/x5F0pymVDG7ME88VlTboxbYJumLGQ==", "integrity": "sha512-OcVizyXljSps3nVfuPomfK8RKt7jvDsIsDrO7l1ZA4bDbiO9bEGWpsdU/x5F0pymVDG7ME88VlTboxbYJumLGQ==",
"dev": true "dev": true
}, },
"eslint-plugin-prettier": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.0.tgz",
"integrity": "sha512-4g11opzhqq/8+AMmo5Vc2Gn7z9alZ4JqrbZ+D4i8KlSyxeQhZHlmIrY8U9Akf514MoEhogPa87Jgkq87aZ2Ohw==",
"dev": true,
"requires": {
"prettier-linter-helpers": "1.0.0"
}
},
"eslint-scope": { "eslint-scope": {
"version": "3.7.1", "version": "3.7.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
@ -4788,6 +4814,12 @@
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
"dev": true "dev": true
}, },
"fast-diff": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"dev": true
},
"fast-glob": { "fast-glob": {
"version": "2.2.2", "version": "2.2.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz",
@ -12980,6 +13012,21 @@
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
"dev": true "dev": true
}, },
"prettier": {
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.3.tgz",
"integrity": "sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==",
"dev": true
},
"prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"dev": true,
"requires": {
"fast-diff": "1.2.0"
}
},
"private": { "private": {
"version": "0.1.8", "version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",

View File

@ -48,14 +48,15 @@
"flow": "flow stop; flow-typed install jest@22 && flow", "flow": "flow stop; flow-typed install jest@22 && flow",
"flow:watch": "flow stop; watch 'flow' . --wait=1 --ignoreDirectoryPattern=/doc/", "flow:watch": "flow stop; watch 'flow' . --wait=1 --ignoreDirectoryPattern=/doc/",
"flow:stop": "flow stop", "flow:stop": "flow stop",
"lint": "eslint .", "lint": "npm run pretty && eslint .",
"lint:fix": "npm run lint -- --fix", "lint:fix": "npm run lint -- --fix",
"lint:watch": "watch 'npm run lint:fix' . --wait=1 --ignoreDirectoryPattern=/doc/", "lint:watch": "watch 'npm run lint:fix' . --wait=1 --ignoreDirectoryPattern=/doc/",
"localnet:up": "bin/localnet.sh up", "localnet:up": "bin/localnet.sh up",
"localnet:down": "bin/localnet.sh down", "localnet:down": "bin/localnet.sh down",
"localnet:update": "bin/localnet.sh update", "localnet:update": "bin/localnet.sh update",
"localnet:logs": "bin/localnet.sh logs -f", "localnet:logs": "bin/localnet.sh logs -f",
"ok": "npm run lint && npm run flow && npm run test && npm run doc", "ok": "npm run pretty && npm run lint && npm run flow && npm run test && npm run doc",
"pretty": "prettier --write '{,{examples,src,test}/**/}*.js'",
"prepare": "npm run clean && npm run ok && npm run fetch-bpf-sdk && npm run build", "prepare": "npm run clean && npm run ok && npm run fetch-bpf-sdk && npm run build",
"examples": "set -ex; for example in examples/*.js; do node $example; done", "examples": "set -ex; for example in examples/*.js; do node $example; done",
"re": "semantic-release --repository-url git@github.com:solana-labs/solana-web3.js.git" "re": "semantic-release --repository-url git@github.com:solana-labs/solana-web3.js.git"
@ -91,13 +92,16 @@
"esdoc-importpath-plugin": "^1.0.2", "esdoc-importpath-plugin": "^1.0.2",
"esdoc-standard-plugin": "^1.0.0", "esdoc-standard-plugin": "^1.0.0",
"eslint": "5.6.0", "eslint": "5.6.0",
"eslint-config-prettier": "^3.1.0",
"eslint-plugin-import": "2.14.0", "eslint-plugin-import": "2.14.0",
"eslint-plugin-jest": "21.22.1", "eslint-plugin-jest": "21.22.1",
"eslint-plugin-prettier": "^3.0.0",
"flow-bin": "0.84.0", "flow-bin": "0.84.0",
"flow-typed": "2.5.1", "flow-typed": "2.5.1",
"fs-file-tree": "1.0.6", "fs-file-tree": "1.0.6",
"jest": "23.6.0", "jest": "23.6.0",
"marked": "^0.5.1", "marked": "^0.5.1",
"prettier": "^1.14.3",
"rimraf": "2.6.2", "rimraf": "2.6.2",
"rollup": "0.66.2", "rollup": "0.66.2",
"rollup-plugin-babel": "3.0.3", "rollup-plugin-babel": "3.0.3",

View File

@ -1,11 +1,11 @@
import babel from 'rollup-plugin-babel'; import babel from 'rollup-plugin-babel';
import builtins from 'rollup-plugin-node-builtins'; import builtins from 'rollup-plugin-node-builtins';
import commonjs from 'rollup-plugin-commonjs'; import commonjs from 'rollup-plugin-commonjs';
import globals from 'rollup-plugin-node-globals'; import globals from 'rollup-plugin-node-globals';
import json from 'rollup-plugin-json'; import json from 'rollup-plugin-json';
import nodeResolve from 'rollup-plugin-node-resolve'; import nodeResolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace'; import replace from 'rollup-plugin-replace';
import uglify from 'rollup-plugin-uglify'; import uglify from 'rollup-plugin-uglify';
const env = process.env.NODE_ENV; const env = process.env.NODE_ENV;
@ -39,72 +39,71 @@ function generateConfig(configType) {
} }
switch (configType) { switch (configType) {
case 'browser': case 'browser':
config.output = [ config.output = [
{ {
file: 'lib/index.iife.js', file: 'lib/index.iife.js',
format: 'iife', format: 'iife',
name: 'solanaWeb3', name: 'solanaWeb3',
}, },
]; ];
config.plugins.push(builtins()); config.plugins.push(builtins());
config.plugins.push(globals()); config.plugins.push(globals());
config.plugins.push(nodeResolve({ config.plugins.push(
browser: true, nodeResolve({
})); browser: true,
break; }),
case 'node': );
config.output = [ break;
{ case 'node':
file: 'lib/index.cjs.js', config.output = [
format: 'cjs', {
}, file: 'lib/index.cjs.js',
{ format: 'cjs',
file: 'lib/index.esm.js', },
format: 'es', {
}, file: 'lib/index.esm.js',
]; format: 'es',
},
];
// Quash 'Unresolved dependencies' complaints for modules listed in the // Quash 'Unresolved dependencies' complaints for modules listed in the
// package.json "dependencies" section. Unfortunately this list is manually // package.json "dependencies" section. Unfortunately this list is manually
// maintained. // maintained.
config.external = [ config.external = [
'assert', 'assert',
'babel-runtime/core-js/get-iterator', 'babel-runtime/core-js/get-iterator',
'babel-runtime/core-js/json/stringify', 'babel-runtime/core-js/json/stringify',
'babel-runtime/core-js/object/assign', 'babel-runtime/core-js/object/assign',
'babel-runtime/core-js/object/get-prototype-of', 'babel-runtime/core-js/object/get-prototype-of',
'babel-runtime/core-js/object/keys', 'babel-runtime/core-js/object/keys',
'babel-runtime/core-js/promise', 'babel-runtime/core-js/promise',
'babel-runtime/helpers/asyncToGenerator', 'babel-runtime/helpers/asyncToGenerator',
'babel-runtime/helpers/classCallCheck', 'babel-runtime/helpers/classCallCheck',
'babel-runtime/helpers/createClass', 'babel-runtime/helpers/createClass',
'babel-runtime/helpers/get', 'babel-runtime/helpers/get',
'babel-runtime/helpers/inherits', 'babel-runtime/helpers/inherits',
'babel-runtime/helpers/possibleConstructorReturn', 'babel-runtime/helpers/possibleConstructorReturn',
'babel-runtime/helpers/toConsumableArray', 'babel-runtime/helpers/toConsumableArray',
'babel-runtime/helpers/typeof', 'babel-runtime/helpers/typeof',
'babel-runtime/regenerator', 'babel-runtime/regenerator',
'bn.js', 'bn.js',
'bs58', 'bs58',
'buffer-layout', 'buffer-layout',
'elfy', 'elfy',
'jayson/lib/client/browser', 'jayson/lib/client/browser',
'node-fetch', 'node-fetch',
'rpc-websockets', 'rpc-websockets',
'superstruct', 'superstruct',
'tweetnacl', 'tweetnacl',
'url', 'url',
]; ];
break; break;
default: default:
throw new Error(`Unknown configType: ${configType}`); throw new Error(`Unknown configType: ${configType}`);
} }
return config; return config;
} }
export default [ export default [generateConfig('node'), generateConfig('browser')];
generateConfig('node'),
generateConfig('browser'),
];

View File

@ -40,4 +40,3 @@ export class Account {
return this._keypair.secretKey; return this._keypair.secretKey;
} }
} }

View File

@ -17,7 +17,9 @@ export class BpfLoader {
* Public key that identifies the BpfLoader * Public key that identifies the BpfLoader
*/ */
static get programId(): PublicKey { static get programId(): PublicKey {
return new PublicKey('0x8000000000000000000000000000000000000000000000000000000000000000'); return new PublicKey(
'0x8000000000000000000000000000000000000000000000000000000000000000',
);
} }
/** /**
@ -35,7 +37,9 @@ export class BpfLoader {
const programAccount = new Account(); const programAccount = new Account();
const elf = elfy.parse(elfBytes); const elf = elfy.parse(elfBytes);
const section = elf.body.sections.find(section => section.name === '.text.entrypoint'); const section = elf.body.sections.find(
section => section.name === '.text.entrypoint',
);
const transaction = SystemProgram.createAccount( const transaction = SystemProgram.createAccount(
owner.publicKey, owner.publicKey,

View File

@ -15,8 +15,8 @@ import * as Layout from './layout';
* @property {PublicKey} from Public key from which `applySignature()` will be accepted from * @property {PublicKey} from Public key from which `applySignature()` will be accepted from
*/ */
export type SignatureCondition = { export type SignatureCondition = {
type: 'signature'; type: 'signature',
from: PublicKey; from: PublicKey,
}; };
/** /**
@ -29,9 +29,9 @@ export type SignatureCondition = {
* @property {Date} when The timestamp that was observed * @property {Date} when The timestamp that was observed
*/ */
export type TimestampCondition = { export type TimestampCondition = {
type: 'timestamp'; type: 'timestamp',
from: PublicKey; from: PublicKey,
when: Date; when: Date,
}; };
/** /**
@ -42,9 +42,9 @@ export type TimestampCondition = {
* @property {PublicKey} to Public key of the recipient * @property {PublicKey} to Public key of the recipient
*/ */
export type Payment = { export type Payment = {
amount: number; amount: number,
to: PublicKey; to: PublicKey,
} };
/** /**
* A condition that can unlock a payment * A condition that can unlock a payment
@ -67,9 +67,7 @@ function serializePayment(payment: Payment): Buffer {
/** /**
* @private * @private
*/ */
function serializeDate( function serializeDate(when: Date): Buffer {
when: Date
): Buffer {
const userdata = Buffer.alloc(8 + 20); const userdata = Buffer.alloc(8 + 20);
userdata.writeUInt32LE(20, 0); // size of timestamp as u64 userdata.writeUInt32LE(20, 0); // size of timestamp as u64
@ -81,13 +79,20 @@ function serializeDate(
return number; return number;
} }
return date.getUTCFullYear() + return (
'-' + pad(date.getUTCMonth() + 1) + date.getUTCFullYear() +
'-' + pad(date.getUTCDate()) + '-' +
'T' + pad(date.getUTCHours()) + pad(date.getUTCMonth() + 1) +
':' + pad(date.getUTCMinutes()) + '-' +
':' + pad(date.getUTCSeconds()) + pad(date.getUTCDate()) +
'Z'; 'T' +
pad(date.getUTCHours()) +
':' +
pad(date.getUTCMinutes()) +
':' +
pad(date.getUTCSeconds()) +
'Z'
);
} }
userdata.write(iso(when), 8); userdata.write(iso(when), 8);
return userdata; return userdata;
@ -97,52 +102,50 @@ function serializeDate(
* @private * @private
*/ */
function serializeCondition(condition: BudgetCondition) { function serializeCondition(condition: BudgetCondition) {
switch(condition.type) { switch (condition.type) {
case 'timestamp': case 'timestamp': {
{ const date = serializeDate(condition.when);
const date = serializeDate(condition.when); const from = condition.from.toBuffer();
const from = condition.from.toBuffer();
const userdata = Buffer.alloc(4 + date.length + from.length); const userdata = Buffer.alloc(4 + date.length + from.length);
userdata.writeUInt32LE(0, 0); // Condition enum = Timestamp userdata.writeUInt32LE(0, 0); // Condition enum = Timestamp
date.copy(userdata, 4); date.copy(userdata, 4);
from.copy(userdata, 4 + date.length); from.copy(userdata, 4 + date.length);
return userdata; return userdata;
} }
case 'signature': case 'signature': {
{ const userdataLayout = BufferLayout.struct([
const userdataLayout = BufferLayout.struct([ BufferLayout.u32('condition'),
BufferLayout.u32('condition'), Layout.publicKey('from'),
Layout.publicKey('from'), ]);
]);
const from = condition.from.toBuffer(); const from = condition.from.toBuffer();
const userdata = Buffer.alloc(4 + from.length); const userdata = Buffer.alloc(4 + from.length);
userdataLayout.encode( userdataLayout.encode(
{ {
instruction: 1, // Signature instruction: 1, // Signature
from from,
}, },
userdata, userdata,
); );
return userdata; return userdata;
} }
default: default:
throw new Error(`Unknown condition type: ${condition.type}`); throw new Error(`Unknown condition type: ${condition.type}`);
} }
} }
/** /**
* Factory class for transactions to interact with the Budget program * Factory class for transactions to interact with the Budget program
*/ */
export class BudgetProgram { export class BudgetProgram {
/** /**
* Public key that identifies the Budget program * Public key that identifies the Budget program
*/ */
static get programId(): PublicKey { static get programId(): PublicKey {
return new PublicKey('0x8100000000000000000000000000000000000000000000000000000000000000'); return new PublicKey(
'0x8100000000000000000000000000000000000000000000000000000000000000',
);
} }
/** /**
@ -152,11 +155,10 @@ export class BudgetProgram {
return 128; return 128;
} }
/** /**
* Creates a timestamp condition * Creates a timestamp condition
*/ */
static timestampCondition(from: PublicKey, when: Date) : TimestampCondition { static timestampCondition(from: PublicKey, when: Date): TimestampCondition {
return { return {
type: 'timestamp', type: 'timestamp',
from, from,
@ -167,7 +169,7 @@ export class BudgetProgram {
/** /**
* Creates a signature condition * Creates a signature condition
*/ */
static signatureCondition(from: PublicKey) : SignatureCondition { static signatureCondition(from: PublicKey): SignatureCondition {
return { return {
type: 'signature', type: 'signature',
from, from,
@ -190,64 +192,68 @@ export class BudgetProgram {
pos += 4; pos += 4;
switch (conditions.length) { switch (conditions.length) {
case 0: case 0:
userdata.writeUInt32LE(0, pos); // Budget enum = Pay userdata.writeUInt32LE(0, pos); // Budget enum = Pay
pos += 4; pos += 4;
{ {
const payment = serializePayment({amount, to}); const payment = serializePayment({amount, to});
payment.copy(userdata, pos); payment.copy(userdata, pos);
pos += payment.length; pos += payment.length;
} }
return new Transaction().add({ return new Transaction().add({
keys: [from, to], keys: [from, to],
programId: this.programId, programId: this.programId,
userdata: userdata.slice(0, pos), userdata: userdata.slice(0, pos),
}); });
case 1: case 1:
userdata.writeUInt32LE(1, pos); // Budget enum = After userdata.writeUInt32LE(1, pos); // Budget enum = After
pos += 4; pos += 4;
{ {
const condition = conditions[0]; const condition = conditions[0];
const conditionData = serializeCondition(condition); const conditionData = serializeCondition(condition);
conditionData.copy(userdata, pos); conditionData.copy(userdata, pos);
pos += conditionData.length; pos += conditionData.length;
const paymentData = serializePayment({amount, to}); const paymentData = serializePayment({amount, to});
paymentData.copy(userdata, pos); paymentData.copy(userdata, pos);
pos += paymentData.length; pos += paymentData.length;
} }
return new Transaction().add({ return new Transaction().add({
keys: [from, program, to], keys: [from, program, to],
programId: this.programId, programId: this.programId,
userdata: userdata.slice(0, pos), userdata: userdata.slice(0, pos),
}); });
case 2: case 2:
userdata.writeUInt32LE(2, pos); // Budget enum = Or userdata.writeUInt32LE(2, pos); // Budget enum = Or
pos += 4; pos += 4;
for (let condition of conditions) { for (let condition of conditions) {
const conditionData = serializeCondition(condition); const conditionData = serializeCondition(condition);
conditionData.copy(userdata, pos); conditionData.copy(userdata, pos);
pos += conditionData.length; pos += conditionData.length;
const paymentData = serializePayment({amount, to}); const paymentData = serializePayment({amount, to});
paymentData.copy(userdata, pos); paymentData.copy(userdata, pos);
pos += paymentData.length; pos += paymentData.length;
} }
return new Transaction().add({ return new Transaction().add({
keys: [from, program, to], keys: [from, program, to],
programId: this.programId, programId: this.programId,
userdata: userdata.slice(0, pos), userdata: userdata.slice(0, pos),
}); });
default: default:
throw new Error(`A maximum of two conditions are support: ${conditions.length} provided`); throw new Error(
`A maximum of two conditions are support: ${
conditions.length
} provided`,
);
} }
} }
@ -287,12 +293,16 @@ export class BudgetProgram {
}); });
} }
/** /**
* Generates a transaction that applies a timestamp, which could enable a * Generates a transaction that applies a timestamp, which could enable a
* pending payment to proceed. * pending payment to proceed.
*/ */
static applyTimestamp(from: PublicKey, program: PublicKey, to: PublicKey, when: Date): Transaction { static applyTimestamp(
from: PublicKey,
program: PublicKey,
to: PublicKey,
when: Date,
): Transaction {
const whenData = serializeDate(when); const whenData = serializeDate(when);
const userdata = Buffer.alloc(4 + whenData.length); const userdata = Buffer.alloc(4 + whenData.length);
@ -310,7 +320,11 @@ export class BudgetProgram {
* Generates a transaction that applies a signature, which could enable a * Generates a transaction that applies a signature, which could enable a
* pending payment to proceed. * pending payment to proceed.
*/ */
static applySignature(from: PublicKey, program: PublicKey, to: PublicKey): Transaction { static applySignature(
from: PublicKey,
program: PublicKey,
to: PublicKey,
): Transaction {
const userdataLayout = BufferLayout.struct([ const userdataLayout = BufferLayout.struct([
BufferLayout.u32('instruction'), BufferLayout.u32('instruction'),
]); ]);

View File

@ -1,10 +1,7 @@
// @flow // @flow
import assert from 'assert'; import assert from 'assert';
import { import {parse as urlParse, format as urlFormat} from 'url';
parse as urlParse,
format as urlFormat,
} from 'url';
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import jayson from 'jayson/lib/client/browser'; import jayson from 'jayson/lib/client/browser';
import {struct} from 'superstruct'; import {struct} from 'superstruct';
@ -16,29 +13,26 @@ import {sleep} from './util/sleep';
import type {Account} from './account'; import type {Account} from './account';
import type {TransactionSignature, TransactionId} from './transaction'; import type {TransactionSignature, TransactionId} from './transaction';
type RpcRequest = (methodName: string, args: Array<any>) => any; type RpcRequest = (methodName: string, args: Array<any>) => any;
function createRpcRequest(url): RpcRequest { function createRpcRequest(url): RpcRequest {
const server = jayson( const server = jayson(async (request, callback) => {
async (request, callback) => { const options = {
const options = { method: 'POST',
method: 'POST', body: request,
body: request, headers: {
headers: { 'Content-Type': 'application/json',
'Content-Type': 'application/json', },
} };
};
try { try {
const res = await fetch(url, options); const res = await fetch(url, options);
const text = await res.text(); const text = await res.text();
callback(null, text); callback(null, text);
} catch (err) { } catch (err) {
callback(err); callback(err);
}
} }
); });
return (method, args) => { return (method, args) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -53,7 +47,6 @@ function createRpcRequest(url): RpcRequest {
}; };
} }
/** /**
* Expected JSON RPC response for the "getBalance" message * Expected JSON RPC response for the "getBalance" message
*/ */
@ -64,7 +57,6 @@ const GetBalanceRpcResult = struct({
result: 'number?', result: 'number?',
}); });
/** /**
* @private * @private
*/ */
@ -74,7 +66,7 @@ function jsonRpcResult(resultDescription: any) {
struct({ struct({
jsonrpc: jsonRpcVersion, jsonrpc: jsonRpcVersion,
id: 'string', id: 'string',
error: 'any' error: 'any',
}), }),
struct({ struct({
jsonrpc: jsonRpcVersion, jsonrpc: jsonRpcVersion,
@ -117,13 +109,15 @@ const ConfirmTransactionRpcResult = jsonRpcResult('boolean');
/** /**
* Expected JSON RPC response for the "getSignatureStatus" message * Expected JSON RPC response for the "getSignatureStatus" message
*/ */
const GetSignatureStatusRpcResult = jsonRpcResult(struct.enum([ const GetSignatureStatusRpcResult = jsonRpcResult(
'AccountInUse', struct.enum([
'Confirmed', 'AccountInUse',
'GenericFailure', 'Confirmed',
'ProgramRuntimeError', 'GenericFailure',
'SignatureNotFound', 'ProgramRuntimeError',
])); 'SignatureNotFound',
]),
);
/** /**
* Expected JSON RPC response for the "getTransactionCount" message * Expected JSON RPC response for the "getTransactionCount" message
@ -159,11 +153,11 @@ const SendTokensRpcResult = jsonRpcResult('string');
* @property {?Buffer} userdata Optional userdata assigned to the account * @property {?Buffer} userdata Optional userdata assigned to the account
*/ */
type AccountInfo = { type AccountInfo = {
executable: boolean; executable: boolean,
programId: PublicKey, programId: PublicKey,
tokens: number, tokens: number,
userdata: Buffer, userdata: Buffer,
} };
/** /**
* Callback function for account change notifications * Callback function for account change notifications
@ -174,17 +168,18 @@ export type AccountChangeCallback = (accountInfo: AccountInfo) => void;
* @private * @private
*/ */
type AccountSubscriptionInfo = { type AccountSubscriptionInfo = {
publicKey: string; // PublicKey of the account as a base 58 string publicKey: string, // PublicKey of the account as a base 58 string
callback: AccountChangeCallback, callback: AccountChangeCallback,
subscriptionId: null | number; // null when there's no current server subscription id subscriptionId: null | number, // null when there's no current server subscription id
} };
/** /**
* Possible signature status values * Possible signature status values
* *
* @typedef {string} SignatureStatus * @typedef {string} SignatureStatus
*/ */
export type SignatureStatus = 'Confirmed' export type SignatureStatus =
| 'Confirmed'
| 'AccountInUse' | 'AccountInUse'
| 'SignatureNotFound' | 'SignatureNotFound'
| 'ProgramRuntimeError' | 'ProgramRuntimeError'
@ -203,7 +198,7 @@ export class Connection {
seconds: number, seconds: number,
transactionSignatures: Array<string>, transactionSignatures: Array<string>,
}; };
_disableLastIdCaching: boolean = false _disableLastIdCaching: boolean = false;
_accountChangeSubscriptions: {[number]: AccountSubscriptionInfo} = {}; _accountChangeSubscriptions: {[number]: AccountSubscriptionInfo} = {};
_accountChangeSubscriptionCounter: number = 0; _accountChangeSubscriptionCounter: number = 0;
@ -228,27 +223,26 @@ export class Connection {
if (url.port === '1') { if (url.port === '1') {
url.port = url.protocol === 'wss:' ? '8901' : '8900'; url.port = url.protocol === 'wss:' ? '8901' : '8900';
} }
this._rpcWebSocket = new RpcWebSocketClient( this._rpcWebSocket = new RpcWebSocketClient(urlFormat(url), {
urlFormat(url), autoconnect: false,
{ max_reconnects: Infinity,
autoconnect: false, });
max_reconnects: Infinity,
}
);
this._rpcWebSocket.on('open', this._wsOnOpen.bind(this)); this._rpcWebSocket.on('open', this._wsOnOpen.bind(this));
this._rpcWebSocket.on('error', this._wsOnError.bind(this)); this._rpcWebSocket.on('error', this._wsOnError.bind(this));
this._rpcWebSocket.on('close', this._wsOnClose.bind(this)); this._rpcWebSocket.on('close', this._wsOnClose.bind(this));
this._rpcWebSocket.on('accountNotification', this._wsOnAccountNotification.bind(this)); this._rpcWebSocket.on(
'accountNotification',
this._wsOnAccountNotification.bind(this),
);
} }
/** /**
* Fetch the balance for the specified public key * Fetch the balance for the specified public key
*/ */
async getBalance(publicKey: PublicKey): Promise<number> { async getBalance(publicKey: PublicKey): Promise<number> {
const unsafeRes = await this._rpcRequest( const unsafeRes = await this._rpcRequest('getBalance', [
'getBalance', publicKey.toBase58(),
[publicKey.toBase58()] ]);
);
const res = GetBalanceRpcResult(unsafeRes); const res = GetBalanceRpcResult(unsafeRes);
if (res.error) { if (res.error) {
throw new Error(res.error.message); throw new Error(res.error.message);
@ -261,10 +255,9 @@ export class Connection {
* Fetch all the account info for the specified public key * Fetch all the account info for the specified public key
*/ */
async getAccountInfo(publicKey: PublicKey): Promise<AccountInfo> { async getAccountInfo(publicKey: PublicKey): Promise<AccountInfo> {
const unsafeRes = await this._rpcRequest( const unsafeRes = await this._rpcRequest('getAccountInfo', [
'getAccountInfo', publicKey.toBase58(),
[publicKey.toBase58()] ]);
);
const res = GetAccountInfoRpcResult(unsafeRes); const res = GetAccountInfoRpcResult(unsafeRes);
if (res.error) { if (res.error) {
throw new Error(res.error.message); throw new Error(res.error.message);
@ -286,10 +279,7 @@ export class Connection {
* Confirm the transaction identified by the specified signature * Confirm the transaction identified by the specified signature
*/ */
async confirmTransaction(signature: TransactionSignature): Promise<boolean> { async confirmTransaction(signature: TransactionSignature): Promise<boolean> {
const unsafeRes = await this._rpcRequest( const unsafeRes = await this._rpcRequest('confirmTransaction', [signature]);
'confirmTransaction',
[signature]
);
const res = ConfirmTransactionRpcResult(unsafeRes); const res = ConfirmTransactionRpcResult(unsafeRes);
if (res.error) { if (res.error) {
throw new Error(res.error.message); throw new Error(res.error.message);
@ -301,7 +291,9 @@ export class Connection {
/** /**
* Fetch the current transaction count of the network * Fetch the current transaction count of the network
*/ */
async getSignatureStatus(signature: TransactionSignature): Promise<SignatureStatus> { async getSignatureStatus(
signature: TransactionSignature,
): Promise<SignatureStatus> {
const unsafeRes = await this._rpcRequest('getSignatureStatus', [signature]); const unsafeRes = await this._rpcRequest('getSignatureStatus', [signature]);
const res = GetSignatureStatusRpcResult(unsafeRes); const res = GetSignatureStatusRpcResult(unsafeRes);
if (res.error) { if (res.error) {
@ -311,7 +303,6 @@ export class Connection {
return res.result; return res.result;
} }
/** /**
* Fetch the current transaction count of the network * Fetch the current transaction count of the network
*/ */
@ -354,8 +345,14 @@ export class Connection {
/** /**
* Request an allocation of tokens to the specified account * Request an allocation of tokens to the specified account
*/ */
async requestAirdrop(to: PublicKey, amount: number): Promise<TransactionSignature> { async requestAirdrop(
const unsafeRes = await this._rpcRequest('requestAirdrop', [to.toBase58(), amount]); to: PublicKey,
amount: number,
): Promise<TransactionSignature> {
const unsafeRes = await this._rpcRequest('requestAirdrop', [
to.toBase58(),
amount,
]);
const res = RequestAirdropRpcResult(unsafeRes); const res = RequestAirdropRpcResult(unsafeRes);
if (res.error) { if (res.error) {
throw new Error(res.error.message); throw new Error(res.error.message);
@ -367,13 +364,17 @@ export class Connection {
/** /**
* Sign and send a transaction * Sign and send a transaction
*/ */
async sendTransaction(from: Account, transaction: Transaction): Promise<TransactionSignature> { async sendTransaction(
from: Account,
transaction: Transaction,
): Promise<TransactionSignature> {
for (;;) { for (;;) {
// Attempt to use the previous last id for up to 1 second // Attempt to use the previous last id for up to 1 second
const seconds = (new Date()).getSeconds(); const seconds = new Date().getSeconds();
if ( (this._lastIdInfo.lastId != null) && if (
(this._lastIdInfo.seconds === seconds) ) { this._lastIdInfo.lastId != null &&
this._lastIdInfo.seconds === seconds
) {
transaction.lastId = this._lastIdInfo.lastId; transaction.lastId = this._lastIdInfo.lastId;
transaction.sign(from); transaction.sign(from);
if (!transaction.signature) { if (!transaction.signature) {
@ -401,13 +402,15 @@ export class Connection {
if (this._lastIdInfo.lastId != lastId) { if (this._lastIdInfo.lastId != lastId) {
this._lastIdInfo = { this._lastIdInfo = {
lastId, lastId,
seconds: (new Date()).getSeconds(), seconds: new Date().getSeconds(),
transactionSignatures: [], transactionSignatures: [],
}; };
break; break;
} }
if (attempts === 8) { if (attempts === 8) {
throw new Error(`Unable to obtain a new last id after ${Date.now() - startTime}ms`); throw new Error(
`Unable to obtain a new last id after ${Date.now() - startTime}ms`,
);
} }
await sleep(250); await sleep(250);
++attempts; ++attempts;
@ -415,7 +418,9 @@ export class Connection {
} }
const wireTransaction = transaction.serialize(); const wireTransaction = transaction.serialize();
const unsafeRes = await this._rpcRequest('sendTransaction', [[...wireTransaction]]); const unsafeRes = await this._rpcRequest('sendTransaction', [
[...wireTransaction],
]);
const res = SendTokensRpcResult(unsafeRes); const res = SendTokensRpcResult(unsafeRes);
if (res.error) { if (res.error) {
throw new Error(res.error.message); throw new Error(res.error.message);
@ -501,13 +506,15 @@ export class Connection {
const {subscriptionId, publicKey} = this._accountChangeSubscriptions[id]; const {subscriptionId, publicKey} = this._accountChangeSubscriptions[id];
if (subscriptionId === null) { if (subscriptionId === null) {
try { try {
this._accountChangeSubscriptions[id].subscriptionId = this._accountChangeSubscriptions[
await this._rpcWebSocket.call( id
'accountSubscribe', ].subscriptionId = await this._rpcWebSocket.call('accountSubscribe', [
[publicKey] publicKey,
); ]);
} catch (err) { } catch (err) {
console.log(`accountSubscribe error for ${publicKey}: ${err.message}`); console.log(
`accountSubscribe error for ${publicKey}: ${err.message}`,
);
} }
} }
} }
@ -520,12 +527,15 @@ export class Connection {
* @param callback Function to invoke whenever the account is changed * @param callback Function to invoke whenever the account is changed
* @return subscription id * @return subscription id
*/ */
onAccountChange(publicKey: PublicKey, callback: AccountChangeCallback): number { onAccountChange(
publicKey: PublicKey,
callback: AccountChangeCallback,
): number {
const id = ++this._accountChangeSubscriptionCounter; const id = ++this._accountChangeSubscriptionCounter;
this._accountChangeSubscriptions[id] = { this._accountChangeSubscriptions[id] = {
publicKey: publicKey.toBase58(), publicKey: publicKey.toBase58(),
callback, callback,
subscriptionId: null subscriptionId: null,
}; };
this._updateSubscriptions(); this._updateSubscriptions();
return id; return id;
@ -552,5 +562,4 @@ export class Connection {
throw new Error(`Unknown account change id: ${id}`); throw new Error(`Unknown account change id: ${id}`);
} }
} }
} }

View File

@ -2,7 +2,6 @@
import * as BufferLayout from 'buffer-layout'; import * as BufferLayout from 'buffer-layout';
/** /**
* Layout for a public key * Layout for a public key
*/ */
@ -17,7 +16,6 @@ export const uint64 = (property: string = 'uint64'): Object => {
return BufferLayout.blob(8, property); return BufferLayout.blob(8, property);
}; };
/** /**
* Layout for a Rust String type * Layout for a Rust String type
*/ */
@ -26,10 +24,7 @@ export const rustString = (property: string = 'string') => {
[ [
BufferLayout.u32('length'), BufferLayout.u32('length'),
BufferLayout.u32('lengthPadding'), BufferLayout.u32('lengthPadding'),
BufferLayout.blob( BufferLayout.blob(BufferLayout.offset(BufferLayout.u32(), -8), 'chars'),
BufferLayout.offset(BufferLayout.u32(), -8),
'chars',
),
], ],
property, property,
); );

View File

@ -45,7 +45,9 @@ export class Loader {
BufferLayout.u32('bytesLengthPadding'), BufferLayout.u32('bytesLengthPadding'),
BufferLayout.seq( BufferLayout.seq(
BufferLayout.u8('byte'), BufferLayout.u8('byte'),
BufferLayout.offset(BufferLayout.u32(), -8), 'bytes'), BufferLayout.offset(BufferLayout.u32(), -8),
'bytes',
),
]); ]);
const chunkSize = 256; const chunkSize = 256;
@ -69,7 +71,9 @@ export class Loader {
programId: this.programId, programId: this.programId,
userdata, userdata,
}); });
transactions.push(sendAndConfirmTransaction(this.connection, program, transaction)); transactions.push(
sendAndConfirmTransaction(this.connection, program, transaction),
);
// Run up to 8 Loads in parallel to prevent too many parallel transactions from // Run up to 8 Loads in parallel to prevent too many parallel transactions from
// getting rejected with AccountInUse. // getting rejected with AccountInUse.

View File

@ -15,7 +15,9 @@ export class NativeLoader {
* Public key that identifies the NativeLoader * Public key that identifies the NativeLoader
*/ */
static get programId(): PublicKey { static get programId(): PublicKey {
return new PublicKey('0x100000000000000000000000000000000000000000000000000000000000000'); return new PublicKey(
'0x100000000000000000000000000000000000000000000000000000000000000',
);
} }
/** /**

View File

@ -72,4 +72,3 @@ export class PublicKey {
return this.toBase58(); return this.toBase58();
} }
} }

View File

@ -14,7 +14,9 @@ export class SystemProgram {
* Public key that identifies the System program * Public key that identifies the System program
*/ */
static get programId(): PublicKey { static get programId(): PublicKey {
return new PublicKey('0x000000000000000000000000000000000000000000000000000000000000000'); return new PublicKey(
'0x000000000000000000000000000000000000000000000000000000000000000',
);
} }
/** /**
@ -25,9 +27,8 @@ export class SystemProgram {
newAccount: PublicKey, newAccount: PublicKey,
tokens: number, tokens: number,
space: number, space: number,
programId: PublicKey programId: PublicKey,
): Transaction { ): Transaction {
const userdataLayout = BufferLayout.struct([ const userdataLayout = BufferLayout.struct([
BufferLayout.u32('instruction'), BufferLayout.u32('instruction'),
BufferLayout.ns64('tokens'), BufferLayout.ns64('tokens'),

View File

@ -40,13 +40,15 @@ export class TokenAmount extends BN {
static fromBuffer(buffer: Buffer): TokenAmount { static fromBuffer(buffer: Buffer): TokenAmount {
assert(buffer.length === 8, `Invalid buffer length: ${buffer.length}`); assert(buffer.length === 8, `Invalid buffer length: ${buffer.length}`);
return new BN( return new BN(
[...buffer].reverse().map(i => `00${i.toString(16)}`.slice(-2)).join(''), [...buffer]
16 .reverse()
.map(i => `00${i.toString(16)}`.slice(-2))
.join(''),
16,
); );
} }
} }
/** /**
* Information about a token * Information about a token
*/ */
@ -129,20 +131,19 @@ const TokenAccountInfoLayout = BufferLayout.struct([
Layout.uint64('originalAmount'), Layout.uint64('originalAmount'),
]); ]);
type TokenAndPublicKey = [Token, PublicKey]; // This type exists to workaround an esdoc parse error type TokenAndPublicKey = [Token, PublicKey]; // This type exists to workaround an esdoc parse error
/** /**
* The built-in token program * The built-in token program
*/ */
export const SYSTEM_TOKEN_PROGRAM_ID = new PublicKey('0x8300000000000000000000000000000000000000000000000000000000000000'); export const SYSTEM_TOKEN_PROGRAM_ID = new PublicKey(
'0x8300000000000000000000000000000000000000000000000000000000000000',
);
/** /**
* An ERC20-like Token * An ERC20-like Token
*/ */
export class Token { export class Token {
/** /**
* @private * @private
*/ */
@ -165,7 +166,11 @@ export class Token {
* @param token Public key of the token * @param token Public key of the token
* @param programId Optional token programId, uses the system programId by default * @param programId Optional token programId, uses the system programId by default
*/ */
constructor(connection: Connection, token: PublicKey, programId: PublicKey = SYSTEM_TOKEN_PROGRAM_ID) { constructor(
connection: Connection,
token: PublicKey,
programId: PublicKey = SYSTEM_TOKEN_PROGRAM_ID,
) {
Object.assign(this, {connection, token, programId}); Object.assign(this, {connection, token, programId});
} }
@ -249,7 +254,10 @@ export class Token {
* may transfer tokens from this `source` account * may transfer tokens from this `source` account
* @return Public key of the new empty token account * @return Public key of the new empty token account
*/ */
async newAccount(owner: Account, source: null | PublicKey = null): Promise<PublicKey> { async newAccount(
owner: Account,
source: null | PublicKey = null,
): Promise<PublicKey> {
const tokenAccount = new Account(); const tokenAccount = new Account();
let transaction; let transaction;
@ -297,7 +305,9 @@ export class Token {
async tokenInfo(): Promise<TokenInfo> { async tokenInfo(): Promise<TokenInfo> {
const accountInfo = await this.connection.getAccountInfo(this.token); const accountInfo = await this.connection.getAccountInfo(this.token);
if (!accountInfo.programId.equals(this.programId)) { if (!accountInfo.programId.equals(this.programId)) {
throw new Error(`Invalid token programId: ${JSON.stringify(accountInfo.programId)}`); throw new Error(
`Invalid token programId: ${JSON.stringify(accountInfo.programId)}`,
);
} }
const userdata = Buffer.from(accountInfo.userdata); const userdata = Buffer.from(accountInfo.userdata);
@ -310,7 +320,6 @@ export class Token {
return tokenInfo; return tokenInfo;
} }
/** /**
* Retrieve account information * Retrieve account information
* *
@ -336,12 +345,16 @@ export class Token {
tokenAccountInfo.originalAmount = new TokenAmount(); tokenAccountInfo.originalAmount = new TokenAmount();
} else { } else {
tokenAccountInfo.source = new PublicKey(tokenAccountInfo.source); tokenAccountInfo.source = new PublicKey(tokenAccountInfo.source);
tokenAccountInfo.originalAmount = TokenAmount.fromBuffer(tokenAccountInfo.originalAmount); tokenAccountInfo.originalAmount = TokenAmount.fromBuffer(
tokenAccountInfo.originalAmount,
);
} }
if (!tokenAccountInfo.token.equals(this.token)) { if (!tokenAccountInfo.token.equals(this.token)) {
throw new Error( throw new Error(
`Invalid token account token: ${JSON.stringify(tokenAccountInfo.token)} !== ${JSON.stringify(this.token)}` `Invalid token account token: ${JSON.stringify(
tokenAccountInfo.token,
)} !== ${JSON.stringify(this.token)}`,
); );
} }
return tokenAccountInfo; return tokenAccountInfo;
@ -370,7 +383,7 @@ export class Token {
source, source,
destination, destination,
amount, amount,
) ),
), ),
); );
} }
@ -387,18 +400,13 @@ export class Token {
owner: Account, owner: Account,
account: PublicKey, account: PublicKey,
delegate: PublicKey, delegate: PublicKey,
amount: number | TokenAmount amount: number | TokenAmount,
): Promise<void> { ): Promise<void> {
await sendAndConfirmTransaction( await sendAndConfirmTransaction(
this.connection, this.connection,
owner, owner,
new Transaction().add( new Transaction().add(
this.approveInstruction( this.approveInstruction(owner.publicKey, account, delegate, amount),
owner.publicKey,
account,
delegate,
amount,
)
), ),
); );
} }
@ -413,7 +421,7 @@ export class Token {
revoke( revoke(
owner: Account, owner: Account,
account: PublicKey, account: PublicKey,
delegate: PublicKey delegate: PublicKey,
): Promise<void> { ): Promise<void> {
return this.approve(owner, account, delegate, 0); return this.approve(owner, account, delegate, 0);
} }
@ -434,11 +442,7 @@ export class Token {
this.connection, this.connection,
owner, owner,
new Transaction().add( new Transaction().add(
this.setOwnerInstruction( this.setOwnerInstruction(owner.publicKey, account, newOwner),
owner.publicKey,
account,
newOwner
)
), ),
); );
} }
@ -471,7 +475,7 @@ export class Token {
userdataLayout.encode( userdataLayout.encode(
{ {
instruction: 2, // Transfer instruction instruction: 2, // Transfer instruction
amount: (new TokenAmount(amount)).toBuffer(), amount: new TokenAmount(amount).toBuffer(),
}, },
userdata, userdata,
); );
@ -499,7 +503,7 @@ export class Token {
owner: PublicKey, owner: PublicKey,
account: PublicKey, account: PublicKey,
delegate: PublicKey, delegate: PublicKey,
amount: number | TokenAmount amount: number | TokenAmount,
): TransactionInstruction { ): TransactionInstruction {
const userdataLayout = BufferLayout.struct([ const userdataLayout = BufferLayout.struct([
BufferLayout.u32('instruction'), BufferLayout.u32('instruction'),
@ -510,7 +514,7 @@ export class Token {
userdataLayout.encode( userdataLayout.encode(
{ {
instruction: 3, // Approve instruction instruction: 3, // Approve instruction
amount: (new TokenAmount(amount)).toBuffer(), amount: new TokenAmount(amount).toBuffer(),
}, },
userdata, userdata,
); );
@ -568,5 +572,3 @@ export class Token {
}); });
} }
} }

View File

@ -28,12 +28,11 @@ export type TransactionId = string;
* @property {?Buffer} userdata * @property {?Buffer} userdata
*/ */
type TransactionInstructionCtorFields = {| type TransactionInstructionCtorFields = {|
keys?: Array<PublicKey>; keys?: Array<PublicKey>,
programId?: PublicKey; programId?: PublicKey,
userdata?: Buffer; userdata?: Buffer,
|}; |};
/** /**
* Transaction Instruction class * Transaction Instruction class
*/ */
@ -58,7 +57,6 @@ export class TransactionInstruction {
} }
} }
/** /**
* List of Transaction object fields that may be initialized at construction * List of Transaction object fields that may be initialized at construction
* *
@ -70,21 +68,19 @@ export class TransactionInstruction {
* @property {?Buffer} userdata * @property {?Buffer} userdata
*/ */
type TransactionCtorFields = {| type TransactionCtorFields = {|
fee?: number; fee?: number,
|}; |};
/** /**
* Transaction class * Transaction class
*/ */
export class Transaction { export class Transaction {
/** /**
* Current signature of the transaction. Typically created by invoking the * Current signature of the transaction. Typically created by invoking the
* `sign()` method * `sign()` method
*/ */
signature: ?Buffer; signature: ?Buffer;
/** /**
* The instructions to atomically execute * The instructions to atomically execute
*/ */
@ -140,9 +136,7 @@ export class Transaction {
programIds.push(programId); programIds.push(programId);
} }
instruction.keys instruction.keys.map(key => key.toString()).forEach(key => {
.map(key => key.toString())
.forEach(key => {
if (!keys.includes(key)) { if (!keys.includes(key)) {
keys.push(key); keys.push(key);
} }
@ -171,14 +165,14 @@ export class Transaction {
BufferLayout.seq( BufferLayout.seq(
BufferLayout.u8('keyIndex'), BufferLayout.u8('keyIndex'),
BufferLayout.offset(BufferLayout.u32(), -8), BufferLayout.offset(BufferLayout.u32(), -8),
'keyIndices' 'keyIndices',
), ),
BufferLayout.u32('userdataLength'), BufferLayout.u32('userdataLength'),
BufferLayout.u32('userdataLengthPadding'), BufferLayout.u32('userdataLengthPadding'),
BufferLayout.seq( BufferLayout.seq(
BufferLayout.u8('userdatum'), BufferLayout.u8('userdatum'),
BufferLayout.offset(BufferLayout.u32(), -8), BufferLayout.offset(BufferLayout.u32(), -8),
'userdata' 'userdata',
), ),
]); ]);
@ -188,7 +182,7 @@ export class Transaction {
BufferLayout.seq( BufferLayout.seq(
Layout.publicKey('key'), Layout.publicKey('key'),
BufferLayout.offset(BufferLayout.u32(), -8), BufferLayout.offset(BufferLayout.u32(), -8),
'keys' 'keys',
), ),
Layout.publicKey('lastId'), Layout.publicKey('lastId'),
BufferLayout.ns64('fee'), BufferLayout.ns64('fee'),
@ -198,7 +192,7 @@ export class Transaction {
BufferLayout.seq( BufferLayout.seq(
Layout.publicKey('programId'), Layout.publicKey('programId'),
BufferLayout.offset(BufferLayout.u32(), -8), BufferLayout.offset(BufferLayout.u32(), -8),
'programIds' 'programIds',
), ),
BufferLayout.u32('instructionsLength'), BufferLayout.u32('instructionsLength'),
@ -206,15 +200,17 @@ export class Transaction {
BufferLayout.seq( BufferLayout.seq(
instructionLayout, instructionLayout,
BufferLayout.offset(BufferLayout.u32(), -8), BufferLayout.offset(BufferLayout.u32(), -8),
'instructions' 'instructions',
), ),
]); ]);
const transaction = { const transaction = {
keys: keys.map((key) => (new PublicKey(key)).toBuffer()), keys: keys.map(key => new PublicKey(key).toBuffer()),
lastId: Buffer.from(bs58.decode(lastId)), lastId: Buffer.from(bs58.decode(lastId)),
fee: this.fee, fee: this.fee,
programIds: programIds.map(programId => (new PublicKey(programId)).toBuffer()), programIds: programIds.map(programId =>
new PublicKey(programId).toBuffer(),
),
instructions, instructions,
}; };
@ -248,9 +244,7 @@ export class Transaction {
} }
const signData = this._getSignData(); const signData = this._getSignData();
const wireTransaction = Buffer.alloc( const wireTransaction = Buffer.alloc(signature.length + signData.length);
signature.length + signData.length
);
Buffer.from(signature).copy(wireTransaction, 0); Buffer.from(signature).copy(wireTransaction, 0);
signData.copy(wireTransaction, signature.length); signData.copy(wireTransaction, signature.length);
@ -283,6 +277,4 @@ export class Transaction {
assert(this.instructions.length === 1); assert(this.instructions.length === 1);
return this.instructions[0].userdata; return this.instructions[0].userdata;
} }
} }

View File

@ -13,9 +13,8 @@ export async function sendAndConfirmTransaction(
connection: Connection, connection: Connection,
from: Account, from: Account,
transaction: Transaction, transaction: Transaction,
runtimeErrorOk: boolean = false runtimeErrorOk: boolean = false,
): Promise<?TransactionSignature> { ): Promise<?TransactionSignature> {
let sendRetries = 10; let sendRetries = 10;
let signature; let signature;
for (;;) { for (;;) {
@ -34,12 +33,18 @@ export async function sendAndConfirmTransaction(
await sleep(500); await sleep(500);
if (--statusRetries <= 0) { if (--statusRetries <= 0) {
const duration = (Date.now() - start) / 1000; const duration = (Date.now() - start) / 1000;
throw new Error(`Transaction '${signature}' was not confirmed in ${duration.toFixed(2)} seconds (${status})`); throw new Error(
`Transaction '${signature}' was not confirmed in ${duration.toFixed(
2,
)} seconds (${status})`,
);
} }
} }
if ( (status === 'Confirmed') || if (
(status === 'ProgramRuntimeError' && runtimeErrorOk) ) { status === 'Confirmed' ||
(status === 'ProgramRuntimeError' && runtimeErrorOk)
) {
break; break;
} }
@ -53,4 +58,3 @@ export async function sendAndConfirmTransaction(
return signature; return signature;
} }

View File

@ -1,6 +1,4 @@
module.exports = { // eslint-disable-line import/no-commonjs module.exports = {
'extends': [ // eslint-disable-line import/no-commonjs
"plugin:jest/recommended", extends: ['plugin:jest/recommended', '../.eslintrc.js'],
"../.eslintrc.js",
]
}; };

View File

@ -3,17 +3,17 @@
import fetch from 'node-fetch'; import fetch from 'node-fetch';
type RpcRequest = { type RpcRequest = {
method: string; method: string,
params?: Array<any>; params?: Array<any>,
}; };
type RpcResponseError = { type RpcResponseError = {
message: string; message: string,
} };
type RpcResponseResult = any; type RpcResponseResult = any;
type RpcResponse = { type RpcResponse = {
error: ?RpcResponseError; error: ?RpcResponseError,
result: ?RpcResponseResult; result: ?RpcResponseResult,
}; };
export const mockRpc: Array<[string, RpcRequest, RpcResponse]> = []; export const mockRpc: Array<[string, RpcRequest, RpcResponse]> = [];
@ -26,56 +26,58 @@ let mockNotice = true;
// Suppress lint: 'JestMockFn' is not defined // Suppress lint: 'JestMockFn' is not defined
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
const mock: JestMockFn<any, any> = jest.fn( const mock: JestMockFn<any, any> = jest.fn((fetchUrl, fetchOptions) => {
(fetchUrl, fetchOptions) => { if (!mockRpcEnabled) {
if (!mockRpcEnabled) { if (mockNotice) {
if (mockNotice) { console.log(
console.log(`Note: node-fetch mock is disabled, testing live against ${fetchUrl}`); `Note: node-fetch mock is disabled, testing live against ${fetchUrl}`,
mockNotice = false; );
} mockNotice = false;
return fetch(fetchUrl, fetchOptions);
} }
return fetch(fetchUrl, fetchOptions);
}
expect(mockRpc.length).toBeGreaterThanOrEqual(1); expect(mockRpc.length).toBeGreaterThanOrEqual(1);
const [mockUrl, mockRequest, mockResponse] = mockRpc.shift(); const [mockUrl, mockRequest, mockResponse] = mockRpc.shift();
expect(fetchUrl).toBe(mockUrl); expect(fetchUrl).toBe(mockUrl);
expect(fetchOptions).toMatchObject({ expect(fetchOptions).toMatchObject({
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json',
}, },
}); });
expect(fetchOptions.body).toBeDefined(); expect(fetchOptions.body).toBeDefined();
const body = JSON.parse(fetchOptions.body); const body = JSON.parse(fetchOptions.body);
expect(body).toMatchObject(Object.assign( expect(body).toMatchObject(
Object.assign(
{}, {},
{ {
jsonrpc: '2.0', jsonrpc: '2.0',
method: 'invalid', method: 'invalid',
}, },
mockRequest mockRequest,
)); ),
);
const response = Object.assign( const response = Object.assign(
{}, {},
{ {
jsonrpc: '2.0', jsonrpc: '2.0',
id: body.id, id: body.id,
error: { error: {
message: 'invalid error message', message: 'invalid error message',
},
result: 'invalid response',
}, },
mockResponse, result: 'invalid response',
); },
return { mockResponse,
text: () => { );
return Promise.resolve(JSON.stringify(response)); return {
}, text: () => {
}; return Promise.resolve(JSON.stringify(response));
} },
); };
});
export default mock; export default mock;

View File

@ -13,7 +13,10 @@ export class Client {
//console.log('MockClient', url, options); //console.log('MockClient', url, options);
if (!mockRpcEnabled) { if (!mockRpcEnabled) {
if (mockNotice) { if (mockNotice) {
console.log('Note: rpc-websockets mock is disabled, testing live against', url); console.log(
'Note: rpc-websockets mock is disabled, testing live against',
url,
);
mockNotice = false; mockNotice = false;
} }
this.client = new RpcWebSocketClient(url, options); this.client = new RpcWebSocketClient(url, options);

View File

@ -10,12 +10,73 @@ test('generate new account', () => {
test('account from secret key', () => { test('account from secret key', () => {
const secretKey = Buffer.from([ const secretKey = Buffer.from([
153, 218, 149, 89, 225, 94, 145, 62, 233, 171, 46, 83, 227, 153,
223, 173, 87, 93, 163, 59, 73, 190, 17, 37, 187, 146, 46, 51, 218,
73, 79, 73, 136, 40, 27, 47, 73, 9, 110, 62, 93, 189, 15, 207, 149,
169, 192, 192, 205, 146, 217, 171, 59, 33, 84, 75, 52, 213, 221, 89,
74, 101, 217, 139, 135, 139, 153, 34 225,
94,
145,
62,
233,
171,
46,
83,
227,
223,
173,
87,
93,
163,
59,
73,
190,
17,
37,
187,
146,
46,
51,
73,
79,
73,
136,
40,
27,
47,
73,
9,
110,
62,
93,
189,
15,
207,
169,
192,
192,
205,
146,
217,
171,
59,
33,
84,
75,
52,
213,
221,
74,
101,
217,
139,
135,
139,
153,
34,
]); ]);
const account = new Account(secretKey); const account = new Account(secretKey);
expect(account.publicKey.toBase58()).toBe('2q7pyhPwAwZ3QMfZrnAbDhnh9mDUqycszcpf86VgQxhF'); expect(account.publicKey.toBase58()).toBe(
'2q7pyhPwAwZ3QMfZrnAbDhnh9mDUqycszcpf86VgQxhF',
);
}); });

View File

@ -33,4 +33,3 @@ test('load BPF program', async () => {
}); });
await sendAndConfirmTransaction(connection, from, transaction); await sendAndConfirmTransaction(connection, from, transaction);
}); });

View File

@ -74,4 +74,3 @@ test('apply', () => {
expect(transaction.keys).toHaveLength(3); expect(transaction.keys).toHaveLength(3);
// TODO: Validate transaction contents more // TODO: Validate transaction contents more
}); });

View File

@ -17,7 +17,6 @@ if (!mockRpcEnabled) {
jest.setTimeout(15000); jest.setTimeout(15000);
} }
const errorMessage = 'Invalid request'; const errorMessage = 'Invalid request';
const errorResponse = { const errorResponse = {
error: { error: {
@ -26,7 +25,6 @@ const errorResponse = {
result: undefined, result: undefined,
}; };
test('get account info - error', () => { test('get account info - error', () => {
const account = new Account(); const account = new Account();
const connection = new Connection(url); const connection = new Connection(url);
@ -40,11 +38,11 @@ test('get account info - error', () => {
errorResponse, errorResponse,
]); ]);
expect(connection.getAccountInfo(account.publicKey)) expect(connection.getAccountInfo(account.publicKey)).rejects.toThrow(
.rejects.toThrow(errorMessage); errorMessage,
);
}); });
test('get balance', async () => { test('get balance', async () => {
const account = new Account(); const account = new Account();
const connection = new Connection(url); const connection = new Connection(url);
@ -58,7 +56,7 @@ test('get balance', async () => {
{ {
error: null, error: null,
result: 0, result: 0,
} },
]); ]);
const balance = await connection.getBalance(account.publicKey); const balance = await connection.getBalance(account.publicKey);
@ -77,11 +75,11 @@ test('confirm transaction - error', () => {
params: [badTransactionSignature], params: [badTransactionSignature],
}, },
errorResponse, errorResponse,
] ]);
);
expect(connection.confirmTransaction(badTransactionSignature)) expect(
.rejects.toThrow(errorMessage); connection.confirmTransaction(badTransactionSignature),
).rejects.toThrow(errorMessage);
mockRpc.push([ mockRpc.push([
url, url,
@ -90,14 +88,13 @@ test('confirm transaction - error', () => {
params: [badTransactionSignature], params: [badTransactionSignature],
}, },
errorResponse, errorResponse,
] ]);
);
expect(connection.getSignatureStatus(badTransactionSignature)) expect(
.rejects.toThrow(errorMessage); connection.getSignatureStatus(badTransactionSignature),
).rejects.toThrow(errorMessage);
}); });
test('get transaction count', async () => { test('get transaction count', async () => {
const connection = new Connection(url); const connection = new Connection(url);
@ -110,9 +107,8 @@ test('get transaction count', async () => {
{ {
error: null, error: null,
result: 1000000, result: 1000000,
} },
] ]);
);
const count = await connection.getTransactionCount(); const count = await connection.getTransactionCount();
expect(count).toBeGreaterThanOrEqual(0); expect(count).toBeGreaterThanOrEqual(0);
@ -139,9 +135,8 @@ test('get finality', async () => {
{ {
error: null, error: null,
result: 123, result: 123,
} },
] ]);
);
const finality = await connection.getFinality(); const finality = await connection.getFinality();
expect(finality).toBeGreaterThanOrEqual(0); expect(finality).toBeGreaterThanOrEqual(0);
@ -159,8 +154,9 @@ test('request airdrop', async () => {
}, },
{ {
error: null, error: null,
result: '1WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', result:
} '1WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
]); ]);
mockRpc.push([ mockRpc.push([
url, url,
@ -170,8 +166,9 @@ test('request airdrop', async () => {
}, },
{ {
error: null, error: null,
result: '2WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', result:
} '2WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
]); ]);
mockRpc.push([ mockRpc.push([
url, url,
@ -182,7 +179,7 @@ test('request airdrop', async () => {
{ {
error: null, error: null,
result: 42, result: 42,
} },
]); ]);
await connection.requestAirdrop(account.publicKey, 40); await connection.requestAirdrop(account.publicKey, 40);
@ -201,18 +198,78 @@ test('request airdrop', async () => {
error: null, error: null,
result: { result: {
program_id: [ program_id: [
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, 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,
], ],
tokens: 42, tokens: 42,
userdata: [], userdata: [],
executable: false, executable: false,
loader_program_id: [ loader_program_id: [
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, 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,
], ],
} },
} },
]); ]);
const accountInfo = await connection.getAccountInfo(account.publicKey); const accountInfo = await connection.getAccountInfo(account.publicKey);
@ -234,8 +291,9 @@ test('transaction', async () => {
}, },
{ {
error: null, error: null,
result: '0WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', result:
} '0WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
]); ]);
mockRpc.push([ mockRpc.push([
url, url,
@ -246,7 +304,7 @@ test('transaction', async () => {
{ {
error: null, error: null,
result: 12, result: 12,
} },
]); ]);
await connection.requestAirdrop(accountFrom.publicKey, 12); await connection.requestAirdrop(accountFrom.publicKey, 12);
expect(await connection.getBalance(accountFrom.publicKey)).toBe(12); expect(await connection.getBalance(accountFrom.publicKey)).toBe(12);
@ -259,8 +317,9 @@ test('transaction', async () => {
}, },
{ {
error: null, error: null,
result: '8WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', result:
} '8WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
]); ]);
mockRpc.push([ mockRpc.push([
url, url,
@ -271,7 +330,7 @@ test('transaction', async () => {
{ {
error: null, error: null,
result: 21, result: 21,
} },
]); ]);
await connection.requestAirdrop(accountTo.publicKey, 21); await connection.requestAirdrop(accountTo.publicKey, 21);
expect(await connection.getBalance(accountTo.publicKey)).toBe(21); expect(await connection.getBalance(accountTo.publicKey)).toBe(21);
@ -284,15 +343,15 @@ test('transaction', async () => {
}, },
{ {
error: null, error: null,
result: '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', result:
} '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
] },
); ]);
const transaction = SystemProgram.move( const transaction = SystemProgram.move(
accountFrom.publicKey, accountFrom.publicKey,
accountTo.publicKey, accountTo.publicKey,
10 10,
); );
const signature = await connection.sendTransaction(accountFrom, transaction); const signature = await connection.sendTransaction(accountFrom, transaction);
@ -301,15 +360,14 @@ test('transaction', async () => {
{ {
method: 'confirmTransaction', method: 'confirmTransaction',
params: [ params: [
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk' '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
], ],
}, },
{ {
error: null, error: null,
result: true, result: true,
} },
] ]);
);
let i = 0; let i = 0;
for (;;) { for (;;) {
@ -327,16 +385,17 @@ test('transaction', async () => {
{ {
method: 'getSignatureStatus', method: 'getSignatureStatus',
params: [ params: [
'3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk' '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
], ],
}, },
{ {
error: null, error: null,
result: 'Confirmed', result: 'Confirmed',
} },
] ]);
await expect(connection.getSignatureStatus(signature)).resolves.toBe(
'Confirmed',
); );
await expect(connection.getSignatureStatus(signature)).resolves.toBe('Confirmed');
mockRpc.push([ mockRpc.push([
url, url,
@ -347,7 +406,7 @@ test('transaction', async () => {
{ {
error: null, error: null,
result: 2, result: 2,
} },
]); ]);
expect(await connection.getBalance(accountFrom.publicKey)).toBe(2); expect(await connection.getBalance(accountFrom.publicKey)).toBe(2);
@ -360,12 +419,11 @@ test('transaction', async () => {
{ {
error: null, error: null,
result: 31, result: 31,
} },
]); ]);
expect(await connection.getBalance(accountTo.publicKey)).toBe(31); expect(await connection.getBalance(accountTo.publicKey)).toBe(31);
}); });
test('multi-instruction transaction', async () => { test('multi-instruction transaction', async () => {
if (mockRpcEnabled) { if (mockRpcEnabled) {
console.log('non-live test skipped'); console.log('non-live test skipped');
@ -387,13 +445,8 @@ test('multi-instruction transaction', async () => {
const transaction = SystemProgram.move( const transaction = SystemProgram.move(
accountFrom.publicKey, accountFrom.publicKey,
accountTo.publicKey, accountTo.publicKey,
10 10,
) ).add(SystemProgram.move(accountTo.publicKey, accountFrom.publicKey, 10));
.add(SystemProgram.move(
accountTo.publicKey,
accountFrom.publicKey,
10
));
const signature = await connection.sendTransaction(accountFrom, transaction); const signature = await connection.sendTransaction(accountFrom, transaction);
let i = 0; let i = 0;
@ -406,13 +459,14 @@ test('multi-instruction transaction', async () => {
expect(++i).toBeLessThan(10); expect(++i).toBeLessThan(10);
await sleep(500); await sleep(500);
} }
await expect(connection.getSignatureStatus(signature)).resolves.toBe('Confirmed'); await expect(connection.getSignatureStatus(signature)).resolves.toBe(
'Confirmed',
);
expect(await connection.getBalance(accountFrom.publicKey)).toBe(12); expect(await connection.getBalance(accountFrom.publicKey)).toBe(12);
expect(await connection.getBalance(accountTo.publicKey)).toBe(21); expect(await connection.getBalance(accountTo.publicKey)).toBe(21);
}); });
test('account change notification', async () => { test('account change notification', async () => {
if (mockRpcEnabled) { if (mockRpcEnabled) {
console.log('non-live test skipped'); console.log('non-live test skipped');
@ -425,7 +479,10 @@ test('account change notification', async () => {
const mockCallback = jest.fn(); const mockCallback = jest.fn();
const subscriptionId = connection.onAccountChange(programAccount.publicKey, mockCallback); const subscriptionId = connection.onAccountChange(
programAccount.publicKey,
mockCallback,
);
await connection.requestAirdrop(owner.publicKey, 42); await connection.requestAirdrop(owner.publicKey, 42);
const transaction = SystemProgram.createAccount( const transaction = SystemProgram.createAccount(
@ -442,7 +499,6 @@ test('account change notification', async () => {
await connection.removeAccountChangeListener(subscriptionId); await connection.removeAccountChangeListener(subscriptionId);
// mockCallback should be called twice // mockCallback should be called twice
// //
// retry a couple times if needed // retry a couple times if needed
@ -462,10 +518,13 @@ test('account change notification', async () => {
// First mockCallback call is due to SystemProgram.createAccount() // First mockCallback call is due to SystemProgram.createAccount()
expect(mockCallback.mock.calls[0][0].tokens).toBe(42); expect(mockCallback.mock.calls[0][0].tokens).toBe(42);
expect(mockCallback.mock.calls[0][0].executable).toBe(false); expect(mockCallback.mock.calls[0][0].executable).toBe(false);
expect(mockCallback.mock.calls[0][0].userdata).toEqual(Buffer.from([0, 0, 0])); expect(mockCallback.mock.calls[0][0].userdata).toEqual(
Buffer.from([0, 0, 0]),
);
expect(mockCallback.mock.calls[0][0].programId).toEqual(BpfLoader.programId); expect(mockCallback.mock.calls[0][0].programId).toEqual(BpfLoader.programId);
// Second mockCallback call is due to loader.load() // Second mockCallback call is due to loader.load()
expect(mockCallback.mock.calls[1][0].userdata).toEqual(Buffer.from([1, 2, 3])); expect(mockCallback.mock.calls[1][0].userdata).toEqual(
Buffer.from([1, 2, 3]),
);
}); });

View File

@ -1,8 +1,6 @@
// @flow // @flow
import { import {Account} from '../../src';
Account,
} from '../../src';
import {url} from '../url'; import {url} from '../url';
import {mockRpc} from '../__mocks__/node-fetch'; import {mockRpc} from '../__mocks__/node-fetch';
@ -18,6 +16,6 @@ export function mockGetLastId() {
{ {
error: null, error: null,
result: lastId.publicKey.toBase58(), result: lastId.publicKey.toBase58(),
} },
]); ]);
} }

View File

@ -31,4 +31,3 @@ test('load native program', async () => {
await sendAndConfirmTransaction(connection, from, transaction); await sendAndConfirmTransaction(connection, from, transaction);
}); });

View File

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

View File

@ -4,39 +4,113 @@ import {PublicKey} from '../src/publickey';
test('invalid', () => { test('invalid', () => {
expect(() => { expect(() => {
new PublicKey([ new PublicKey([
3, 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 3,
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,
]); ]);
}).toThrow(); }).toThrow();
expect(() => { expect(() => {
new PublicKey('0x300000000000000000000000000000000000000000000000000000000000000000000'); new PublicKey(
'0x300000000000000000000000000000000000000000000000000000000000000000000',
);
}).toThrow(); }).toThrow();
expect(() => { expect(() => {
new PublicKey('135693854574979916511997248057056142015550763280047535983739356259273198796800000'); new PublicKey(
'135693854574979916511997248057056142015550763280047535983739356259273198796800000',
);
}).toThrow(); }).toThrow();
}); });
test('equals', () => { test('equals', () => {
const arrayKey = new PublicKey([ const arrayKey = new PublicKey([
3, 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, 3,
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,
]); ]);
const hexKey = new PublicKey('0x300000000000000000000000000000000000000000000000000000000000000'); const hexKey = new PublicKey(
const base56Key = new PublicKey('CiDwVBFgWV9E5MvXWoLgnEgn2hK7rJikbvfWavzAQz3'); '0x300000000000000000000000000000000000000000000000000000000000000',
);
const base56Key = new PublicKey(
'CiDwVBFgWV9E5MvXWoLgnEgn2hK7rJikbvfWavzAQz3',
);
expect(arrayKey.equals(hexKey)).toBe(true); expect(arrayKey.equals(hexKey)).toBe(true);
expect(arrayKey.equals(base56Key)).toBe(true); expect(arrayKey.equals(base56Key)).toBe(true);
}); });
test('isPublicKey', () => { test('isPublicKey', () => {
const key = new PublicKey('0x100000000000000000000000000000000000000000000000000000000000000'); const key = new PublicKey(
'0x100000000000000000000000000000000000000000000000000000000000000',
);
expect(PublicKey.isPublicKey(key)).toBe(true); expect(PublicKey.isPublicKey(key)).toBe(true);
expect(PublicKey.isPublicKey({})).toBe(false); expect(PublicKey.isPublicKey({})).toBe(false);
}); });
test('toBase58', () => { test('toBase58', () => {
const key = new PublicKey('0x300000000000000000000000000000000000000000000000000000000000000'); const key = new PublicKey(
'0x300000000000000000000000000000000000000000000000000000000000000',
);
expect(key.toBase58()).toBe('CiDwVBFgWV9E5MvXWoLgnEgn2hK7rJikbvfWavzAQz3'); expect(key.toBase58()).toBe('CiDwVBFgWV9E5MvXWoLgnEgn2hK7rJikbvfWavzAQz3');
expect(key.toString()).toBe('CiDwVBFgWV9E5MvXWoLgnEgn2hK7rJikbvfWavzAQz3'); expect(key.toString()).toBe('CiDwVBFgWV9E5MvXWoLgnEgn2hK7rJikbvfWavzAQz3');
@ -48,28 +122,92 @@ test('toBase58', () => {
expect(key3.toBase58()).toBe('11111111111111111111111111111111'); expect(key3.toBase58()).toBe('11111111111111111111111111111111');
const key4 = new PublicKey([ const key4 = new PublicKey([
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, 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,
]); ]);
expect(key4.toBase58()).toBe('11111111111111111111111111111111'); expect(key4.toBase58()).toBe('11111111111111111111111111111111');
}); });
test('toBuffer', () => { test('toBuffer', () => {
const key = new PublicKey('0x300000000000000000000000000000000000000000000000000000000000000'); const key = new PublicKey(
'0x300000000000000000000000000000000000000000000000000000000000000',
);
expect(key.toBuffer()).toHaveLength(32); expect(key.toBuffer()).toHaveLength(32);
expect(key.toBase58()).toBe('CiDwVBFgWV9E5MvXWoLgnEgn2hK7rJikbvfWavzAQz3'); expect(key.toBase58()).toBe('CiDwVBFgWV9E5MvXWoLgnEgn2hK7rJikbvfWavzAQz3');
const key2 = new PublicKey('0x000000000000000000000000000000000000000000000000000000000000000'); const key2 = new PublicKey(
'0x000000000000000000000000000000000000000000000000000000000000000',
);
expect(key2.toBuffer()).toHaveLength(32); expect(key2.toBuffer()).toHaveLength(32);
expect(key2.toBase58()).toBe('11111111111111111111111111111111'); expect(key2.toBase58()).toBe('11111111111111111111111111111111');
}); });
test('equals (II)', () => { test('equals (II)', () => {
const key1 = new PublicKey([ const key1 = new PublicKey([
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, 1, 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,
1,
]); ]);
const key2 = new PublicKey(key1.toBuffer()); const key2 = new PublicKey(key1.toBuffer());
expect(key1.equals(key2)).toBe(true); expect(key1.equals(key2)).toBe(true);
}); });

View File

@ -1,10 +1,6 @@
// @flow // @flow
import { import {Account, BudgetProgram, SystemProgram} from '../src';
Account,
BudgetProgram,
SystemProgram,
} from '../src';
test('createAccount', () => { test('createAccount', () => {
const from = new Account(); const from = new Account();
@ -29,30 +25,21 @@ test('move', () => {
const to = new Account(); const to = new Account();
let transaction; let transaction;
transaction = SystemProgram.move( transaction = SystemProgram.move(from.publicKey, to.publicKey, 123);
from.publicKey,
to.publicKey,
123,
);
expect(transaction.keys).toHaveLength(2); expect(transaction.keys).toHaveLength(2);
expect(transaction.programId).toEqual(SystemProgram.programId); expect(transaction.programId).toEqual(SystemProgram.programId);
// TODO: Validate transaction contents more // TODO: Validate transaction contents more
}); });
test('assign', () => { test('assign', () => {
const from = new Account(); const from = new Account();
const to = new Account(); const to = new Account();
let transaction; let transaction;
transaction = SystemProgram.assign( transaction = SystemProgram.assign(from.publicKey, to.publicKey);
from.publicKey,
to.publicKey,
);
expect(transaction.keys).toHaveLength(1); expect(transaction.keys).toHaveLength(1);
expect(transaction.programId).toEqual(SystemProgram.programId); expect(transaction.programId).toEqual(SystemProgram.programId);
// TODO: Validate transaction contents more // TODO: Validate transaction contents more
}); });

View File

@ -1,11 +1,6 @@
// @flow // @flow
import { import {Connection, PublicKey, Token, TokenAmount} from '../src';
Connection,
PublicKey,
Token,
TokenAmount,
} from '../src';
import {SYSTEM_TOKEN_PROGRAM_ID} from '../src/token-program'; import {SYSTEM_TOKEN_PROGRAM_ID} from '../src/token-program';
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch'; import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
import {url} from './url'; import {url} from './url';
@ -37,12 +32,12 @@ function mockSendTransaction() {
}, },
{ {
error: null, error: null,
result: '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', result:
} '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk',
},
]); ]);
} }
// A token created by the first test and used by all subsequent tests // A token created by the first test and used by all subsequent tests
let testToken: Token; let testToken: Token;
@ -86,7 +81,7 @@ test('create new token', async () => {
new TokenAmount(10000), new TokenAmount(10000),
'Test token', 'Test token',
'TEST', 'TEST',
2 2,
); );
{ {
@ -104,18 +99,83 @@ test('create new token', async () => {
tokens: 1, tokens: 1,
userdata: [ userdata: [
1, 1,
16, 39, 0, 0, 0, 0, 0, 0, 16,
39,
0,
0,
0,
0,
0,
0,
2, 2,
10, 0, 0, 0, 0, 0, 0, 0, 84, 101, 115, 116, 32, 116, 111, 107, 101, 110, 10,
4, 0, 0, 0, 0, 0, 0, 0, 84, 69, 83, 84 0,
0,
0,
0,
0,
0,
0,
84,
101,
115,
116,
32,
116,
111,
107,
101,
110,
4,
0,
0,
0,
0,
0,
0,
0,
84,
69,
83,
84,
], ],
executable: false, executable: false,
loader_program_id: [ loader_program_id: [
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, 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,
], ],
} },
} },
]); ]);
} }
@ -126,7 +186,6 @@ test('create new token', async () => {
expect(tokenInfo.name).toBe('Test token'); expect(tokenInfo.name).toBe('Test token');
expect(tokenInfo.symbol).toBe('TEST'); expect(tokenInfo.symbol).toBe('TEST');
{ {
// mock Token.accountInfo()'s getAccountInfo // mock Token.accountInfo()'s getAccountInfo
mockRpc.push([ mockRpc.push([
@ -144,16 +203,84 @@ test('create new token', async () => {
2, 2,
...testToken.token.toBuffer(), ...testToken.token.toBuffer(),
...initialOwner.publicKey.toBuffer(), ...initialOwner.publicKey.toBuffer(),
16, 39, 0, 0, 0, 0, 0, 0, 16,
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, 39,
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,
0,
0,
0,
0,
0,
0,
], ],
executable: false, executable: false,
loader_program_id: [ loader_program_id: [
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, 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,
], ],
} },
} },
]); ]);
} }
@ -166,7 +293,6 @@ test('create new token', async () => {
expect(accountInfo.originalAmount.toNumber()).toBe(0); expect(accountInfo.originalAmount.toNumber()).toBe(0);
}); });
test('create new token account', async () => { test('create new token account', async () => {
const connection = new Connection(url); const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled; connection._disableLastIdCaching = mockRpcEnabled;
@ -202,16 +328,53 @@ test('create new token account', async () => {
2, 2,
...testToken.token.toBuffer(), ...testToken.token.toBuffer(),
...destOwner.publicKey.toBuffer(), ...destOwner.publicKey.toBuffer(),
0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
0,
0,
0,
0,
0,
0, 0,
], ],
executable: false, executable: false,
loader_program_id: [ loader_program_id: [
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, 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,
], ],
} },
} },
]); ]);
} }
@ -223,7 +386,6 @@ test('create new token account', async () => {
expect(accountInfo.source).toBe(null); expect(accountInfo.source).toBe(null);
}); });
test('transfer', async () => { test('transfer', async () => {
const connection = new Connection(url); const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled; connection._disableLastIdCaching = mockRpcEnabled;
@ -260,16 +422,53 @@ test('transfer', async () => {
2, 2,
...testToken.token.toBuffer(), ...testToken.token.toBuffer(),
...initialOwner.publicKey.toBuffer(), ...initialOwner.publicKey.toBuffer(),
123, 0, 0, 0, 0, 0, 0, 0, 123,
0,
0,
0,
0,
0,
0,
0,
0, 0,
], ],
executable: false, executable: false,
loader_program_id: [ loader_program_id: [
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, 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,
], ],
} },
} },
]); ]);
// mock Token.transfer() transaction // mock Token.transfer() transaction
@ -278,12 +477,7 @@ test('transfer', async () => {
mockGetSignatureStatus(); mockGetSignatureStatus();
} }
await testToken.transfer( await testToken.transfer(initialOwner, initialOwnerTokenAccount, dest, 123);
initialOwner,
initialOwnerTokenAccount,
dest,
123
);
{ {
// mock Token.accountInfo()'s getAccountInfo // mock Token.accountInfo()'s getAccountInfo
@ -302,16 +496,53 @@ test('transfer', async () => {
2, 2,
...testToken.token.toBuffer(), ...testToken.token.toBuffer(),
...dest.toBuffer(), ...dest.toBuffer(),
123, 0, 0, 0, 0, 0, 0, 0, 123,
0,
0,
0,
0,
0,
0,
0,
0, 0,
], ],
executable: false, executable: false,
loader_program_id: [ loader_program_id: [
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, 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,
], ],
} },
} },
]); ]);
} }
@ -319,7 +550,6 @@ test('transfer', async () => {
expect(destAccountInfo.amount.toNumber()).toBe(123); expect(destAccountInfo.amount.toNumber()).toBe(123);
}); });
test('approve/revoke', async () => { test('approve/revoke', async () => {
const connection = new Connection(url); const connection = new Connection(url);
connection._disableLastIdCaching = mockRpcEnabled; connection._disableLastIdCaching = mockRpcEnabled;
@ -336,7 +566,10 @@ test('approve/revoke', async () => {
mockSendTransaction(); mockSendTransaction();
mockGetSignatureStatus(); mockGetSignatureStatus();
} }
const delegate = await testToken.newAccount(delegateOwner, initialOwnerTokenAccount); const delegate = await testToken.newAccount(
delegateOwner,
initialOwnerTokenAccount,
);
{ {
// mock Token.approve() transaction // mock Token.approve() transaction
@ -349,7 +582,7 @@ test('approve/revoke', async () => {
initialOwner, initialOwner,
initialOwnerTokenAccount, initialOwnerTokenAccount,
delegate, delegate,
456 456,
); );
{ {
@ -369,18 +602,62 @@ test('approve/revoke', async () => {
2, 2,
...testToken.token.toBuffer(), ...testToken.token.toBuffer(),
...delegate.toBuffer(), ...delegate.toBuffer(),
200, 1, 0, 0, 0, 0, 0, 0, 200,
1,
0,
0,
0,
0,
0,
0,
1, 1,
...initialOwnerTokenAccount.toBuffer(), ...initialOwnerTokenAccount.toBuffer(),
200, 1, 0, 0, 0, 0, 0, 0, 200,
1,
0,
0,
0,
0,
0,
0,
], ],
executable: false, executable: false,
loader_program_id: [ loader_program_id: [
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, 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,
], ],
} },
} },
]); ]);
} }
@ -391,7 +668,9 @@ test('approve/revoke', async () => {
if (delegateAccountInfo.source === null) { if (delegateAccountInfo.source === null) {
throw new Error('source should not be null'); throw new Error('source should not be null');
} else { } else {
expect(delegateAccountInfo.source.equals(initialOwnerTokenAccount)).toBe(true); expect(delegateAccountInfo.source.equals(initialOwnerTokenAccount)).toBe(
true,
);
} }
{ {
@ -401,11 +680,7 @@ test('approve/revoke', async () => {
mockGetSignatureStatus(); mockGetSignatureStatus();
} }
await testToken.revoke( await testToken.revoke(initialOwner, initialOwnerTokenAccount, delegate);
initialOwner,
initialOwnerTokenAccount,
delegate,
);
{ {
// mock Token.accountInfo()'s getAccountInfo // mock Token.accountInfo()'s getAccountInfo
@ -424,18 +699,62 @@ test('approve/revoke', async () => {
2, 2,
...testToken.token.toBuffer(), ...testToken.token.toBuffer(),
...delegate.toBuffer(), ...delegate.toBuffer(),
0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
0,
0,
0,
0,
0,
1, 1,
...initialOwnerTokenAccount.toBuffer(), ...initialOwnerTokenAccount.toBuffer(),
0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
0,
0,
0,
0,
0,
], ],
executable: false, executable: false,
loader_program_id: [ loader_program_id: [
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, 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,
], ],
} },
} },
]); ]);
} }
@ -445,11 +764,12 @@ test('approve/revoke', async () => {
if (delegateAccountInfo.source === null) { if (delegateAccountInfo.source === null) {
throw new Error('source should not be null'); throw new Error('source should not be null');
} else { } else {
expect(delegateAccountInfo.source.equals(initialOwnerTokenAccount)).toBe(true); expect(delegateAccountInfo.source.equals(initialOwnerTokenAccount)).toBe(
true,
);
} }
}); });
test('invalid approve', async () => { test('invalid approve', async () => {
if (mockRpcEnabled) { if (mockRpcEnabled) {
console.log('non-live test skipped'); console.log('non-live test skipped');
@ -466,26 +786,15 @@ test('invalid approve', async () => {
// account2 is not a delegate account of account1 // account2 is not a delegate account of account1
await expect( await expect(
testToken.approve( testToken.approve(owner, account1, account2, 123),
owner,
account1,
account2,
123
)
).rejects.toThrow(); ).rejects.toThrow();
// account1Delegate is not a delegate account of account2 // account1Delegate is not a delegate account of account2
await expect( await expect(
testToken.approve( testToken.approve(owner, account2, account1Delegate, 123),
owner,
account2,
account1Delegate,
123
)
).rejects.toThrow(); ).rejects.toThrow();
}); });
test('fail on approve overspend', async () => { test('fail on approve overspend', async () => {
if (mockRpcEnabled) { if (mockRpcEnabled) {
console.log('non-live test skipped'); console.log('non-live test skipped');
@ -507,50 +816,29 @@ test('fail on approve overspend', async () => {
10, 10,
); );
await testToken.approve( await testToken.approve(owner, account1, account1Delegate, 2);
owner,
account1,
account1Delegate,
2
);
let delegateAccountInfo = await testToken.accountInfo(account1Delegate); let delegateAccountInfo = await testToken.accountInfo(account1Delegate);
expect(delegateAccountInfo.amount.toNumber()).toBe(2); expect(delegateAccountInfo.amount.toNumber()).toBe(2);
expect(delegateAccountInfo.originalAmount.toNumber()).toBe(2); expect(delegateAccountInfo.originalAmount.toNumber()).toBe(2);
await testToken.transfer( await testToken.transfer(owner, account1Delegate, account2, 1);
owner,
account1Delegate,
account2,
1,
);
delegateAccountInfo = await testToken.accountInfo(account1Delegate); delegateAccountInfo = await testToken.accountInfo(account1Delegate);
expect(delegateAccountInfo.amount.toNumber()).toBe(1); expect(delegateAccountInfo.amount.toNumber()).toBe(1);
expect(delegateAccountInfo.originalAmount.toNumber()).toBe(2); expect(delegateAccountInfo.originalAmount.toNumber()).toBe(2);
await testToken.transfer( await testToken.transfer(owner, account1Delegate, account2, 1);
owner,
account1Delegate,
account2,
1,
);
delegateAccountInfo = await testToken.accountInfo(account1Delegate); delegateAccountInfo = await testToken.accountInfo(account1Delegate);
expect(delegateAccountInfo.amount.toNumber()).toBe(0); expect(delegateAccountInfo.amount.toNumber()).toBe(0);
expect(delegateAccountInfo.originalAmount.toNumber()).toBe(2); expect(delegateAccountInfo.originalAmount.toNumber()).toBe(2);
await expect( await expect(
testToken.transfer( testToken.transfer(owner, account1Delegate, account2, 1),
owner,
account1Delegate,
account2,
1,
)
).rejects.toThrow(); ).rejects.toThrow();
}); });
test('set owner', async () => { test('set owner', async () => {
if (mockRpcEnabled) { if (mockRpcEnabled) {
console.log('non-live test skipped'); console.log('non-live test skipped');
@ -566,12 +854,11 @@ test('set owner', async () => {
await testToken.setOwner(owner, account, newOwner.publicKey); await testToken.setOwner(owner, account, newOwner.publicKey);
await expect( await expect(
testToken.setOwner(owner, account, newOwner.publicKey) testToken.setOwner(owner, account, newOwner.publicKey),
).rejects.toThrow(); ).rejects.toThrow();
await testToken.setOwner(newOwner, account, owner.publicKey); await testToken.setOwner(newOwner, account, owner.publicKey);
await expect( await expect(
testToken.setOwner(newOwner, account, owner.publicKey) testToken.setOwner(newOwner, account, owner.publicKey),
).rejects.toThrow(); ).rejects.toThrow();
}); });

View File

@ -9,4 +9,3 @@ export const url = 'http://localhost:8899/';
//export const url = 'https://api.testnet.solana.com/'; //export const url = 'https://api.testnet.solana.com/';
//export const url = 'https://api.testnet.solana.com/'; //export const url = 'https://api.testnet.solana.com/';
//export const url = 'http://testnet.solana.com:8899/'; //export const url = 'http://testnet.solana.com:8899/';