fix: expose getProgramAccounts RPC method
This commit is contained in:
parent
c14a44b8b4
commit
0e7c8cd01f
|
@ -87,6 +87,9 @@ declare module '@solana/web3.js' {
|
||||||
declare export class Connection {
|
declare export class Connection {
|
||||||
constructor(endpoint: string): Connection;
|
constructor(endpoint: string): Connection;
|
||||||
getAccountInfo(publicKey: PublicKey): Promise<AccountInfo>;
|
getAccountInfo(publicKey: PublicKey): Promise<AccountInfo>;
|
||||||
|
getProgramAccounts(
|
||||||
|
programId: PublicKey,
|
||||||
|
): Promise<Array<[PublicKey, AccountInfo]>>;
|
||||||
getBalance(publicKey: PublicKey): Promise<number>;
|
getBalance(publicKey: PublicKey): Promise<number>;
|
||||||
getClusterNodes(): Promise<Array<ContactInfo>>;
|
getClusterNodes(): Promise<Array<ContactInfo>>;
|
||||||
getEpochVoteAccounts(): Promise<Array<VoteAccountInfo>>;
|
getEpochVoteAccounts(): Promise<Array<VoteAccountInfo>>;
|
||||||
|
|
|
@ -6561,7 +6561,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"marked": {
|
"marked": {
|
||||||
"version": "0.3.19",
|
"version": "0.3.19",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
|
"resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
|
||||||
"integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
|
"integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -6825,7 +6825,7 @@
|
||||||
},
|
},
|
||||||
"marked": {
|
"marked": {
|
||||||
"version": "0.3.19",
|
"version": "0.3.19",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
|
"resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz",
|
||||||
"integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
|
"integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -13022,7 +13022,7 @@
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -17988,7 +17988,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
"localnet:logs": "bin/localnet.sh logs -f",
|
"localnet:logs": "bin/localnet.sh logs -f",
|
||||||
"localnet:up": "bin/localnet.sh up $npm_package_testnetDefaultChannel",
|
"localnet:up": "bin/localnet.sh up $npm_package_testnetDefaultChannel",
|
||||||
"localnet:update": "bin/localnet.sh update $npm_package_testnetDefaultChannel",
|
"localnet:update": "bin/localnet.sh update $npm_package_testnetDefaultChannel",
|
||||||
"ok": "run-s --serial lint flow test doc",
|
"ok": "run-s lint flow test doc",
|
||||||
"prepare": "run-s clean bpf-sdk:install bpf-sdk:remove-symlinks build",
|
"prepare": "run-s clean bpf-sdk:install bpf-sdk:remove-symlinks build",
|
||||||
"pretty": "prettier --write '{,{examples,src,test}/**/}*.js'",
|
"pretty": "prettier --write '{,{examples,src,test}/**/}*.js'",
|
||||||
"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",
|
||||||
|
|
|
@ -148,6 +148,13 @@ const ProgramAccountNotificationResult = struct({
|
||||||
result: ProgramAccountInfoResult,
|
result: ProgramAccountInfoResult,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected JSON RPC response for the "getProgramAccounts" message
|
||||||
|
*/
|
||||||
|
const GetProgramAccountsRpcResult = jsonRpcResult(
|
||||||
|
struct.list([ProgramAccountInfoResult]),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected JSON RPC response for the "confirmTransaction" message
|
* Expected JSON RPC response for the "confirmTransaction" message
|
||||||
*/
|
*/
|
||||||
|
@ -338,6 +345,11 @@ export type TransactionError = {|
|
||||||
*/
|
*/
|
||||||
type BlockhashAndFeeCalculator = [Blockhash, FeeCalculator]; // This type exists to workaround an esdoc parse error
|
type BlockhashAndFeeCalculator = [Blockhash, FeeCalculator]; // This type exists to workaround an esdoc parse error
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
type PublicKeyAndAccount = [PublicKey, AccountInfo]; // This type exists to workaround an esdoc parse error
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A connection to a fullnode JSON RPC endpoint
|
* A connection to a fullnode JSON RPC endpoint
|
||||||
*/
|
*/
|
||||||
|
@ -435,6 +447,36 @@ export class Connection {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch all the accounts owned by the specified program id
|
||||||
|
*/
|
||||||
|
async getProgramAccounts(
|
||||||
|
programId: PublicKey,
|
||||||
|
): Promise<Array<PublicKeyAndAccount>> {
|
||||||
|
const unsafeRes = await this._rpcRequest('getProgramAccounts', [
|
||||||
|
programId.toBase58(),
|
||||||
|
]);
|
||||||
|
const res = GetProgramAccountsRpcResult(unsafeRes);
|
||||||
|
if (res.error) {
|
||||||
|
throw new Error(res.error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
const {result} = res;
|
||||||
|
assert(typeof result !== 'undefined');
|
||||||
|
|
||||||
|
return result.map(result => {
|
||||||
|
return [
|
||||||
|
result[0],
|
||||||
|
{
|
||||||
|
executable: result[1].executable,
|
||||||
|
owner: new PublicKey(result[1].owner),
|
||||||
|
lamports: result[1].lamports,
|
||||||
|
data: Buffer.from(result[1].data),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirm the transaction identified by the specified signature
|
* Confirm the transaction identified by the specified signature
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
import {Account, Connection, BpfLoader, Loader, SystemProgram} from '../src';
|
import {
|
||||||
|
Account,
|
||||||
|
Connection,
|
||||||
|
BpfLoader,
|
||||||
|
Loader,
|
||||||
|
SystemProgram,
|
||||||
|
sendAndConfirmTransaction,
|
||||||
|
} from '../src';
|
||||||
import {DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND} from '../src/timing';
|
import {DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND} from '../src/timing';
|
||||||
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
|
import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch';
|
||||||
import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash';
|
import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash';
|
||||||
|
@ -37,6 +44,48 @@ test('get account info - error', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('get program accounts', async () => {
|
||||||
|
if (mockRpcEnabled) {
|
||||||
|
console.log('non-live test skipped');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = new Connection(url);
|
||||||
|
const account0 = new Account();
|
||||||
|
const account1 = new Account();
|
||||||
|
const programId = new Account();
|
||||||
|
await connection.requestAirdrop(account0.publicKey, 42);
|
||||||
|
await connection.requestAirdrop(account1.publicKey, 84);
|
||||||
|
|
||||||
|
let transaction = SystemProgram.assign(
|
||||||
|
account0.publicKey,
|
||||||
|
programId.publicKey,
|
||||||
|
);
|
||||||
|
await sendAndConfirmTransaction(connection, transaction, account0);
|
||||||
|
|
||||||
|
transaction = SystemProgram.assign(account1.publicKey, programId.publicKey);
|
||||||
|
await sendAndConfirmTransaction(connection, transaction, account1);
|
||||||
|
|
||||||
|
const [, feeCalculator] = await connection.getRecentBlockhash();
|
||||||
|
|
||||||
|
const programAccounts = await connection.getProgramAccounts(
|
||||||
|
programId.publicKey,
|
||||||
|
);
|
||||||
|
expect(programAccounts.length).toBe(2);
|
||||||
|
|
||||||
|
programAccounts.forEach(function(element) {
|
||||||
|
expect([
|
||||||
|
account0.publicKey.toBase58(),
|
||||||
|
account1.publicKey.toBase58(),
|
||||||
|
]).toEqual(expect.arrayContaining([element[0]]));
|
||||||
|
if (element[0] == account0.publicKey) {
|
||||||
|
expect(element[1].lamports).toBe(42 - feeCalculator.lamportsPerSignature);
|
||||||
|
} else {
|
||||||
|
expect(element[1].lamports).toBe(84 - feeCalculator.lamportsPerSignature);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('fullnodeExit', async () => {
|
test('fullnodeExit', async () => {
|
||||||
if (!mockRpcEnabled) {
|
if (!mockRpcEnabled) {
|
||||||
console.log('fullnodeExit skipped on live node');
|
console.log('fullnodeExit skipped on live node');
|
||||||
|
|
Loading…
Reference in New Issue