refactor: employ prettier
This commit is contained in:
parent
9a043344d5
commit
1d6abb17cf
|
@ -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'],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
arrowParens: "avoid"
|
||||||
|
bracketSpacing: false
|
||||||
|
jsxBracketSameLine: false
|
||||||
|
semi: true
|
||||||
|
singleQuote: true
|
||||||
|
tabWidth: 2
|
||||||
|
trailingComma: "all"
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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}`);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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'),
|
|
||||||
];
|
|
||||||
|
|
|
@ -40,4 +40,3 @@ export class Account {
|
||||||
return this._keypair.secretKey;
|
return this._keypair.secretKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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'),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -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}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -72,4 +72,3 @@ export class PublicKey {
|
||||||
return this.toBase58();
|
return this.toBase58();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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'),
|
||||||
|
|
|
@ -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 {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -33,4 +33,3 @@ test('load BPF program', async () => {
|
||||||
});
|
});
|
||||||
await sendAndConfirmTransaction(connection, from, transaction);
|
await sendAndConfirmTransaction(connection, from, transaction);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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]),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,4 +31,3 @@ test('load native program', async () => {
|
||||||
|
|
||||||
await sendAndConfirmTransaction(connection, from, transaction);
|
await sendAndConfirmTransaction(connection, from, transaction);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -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/';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue