diff --git a/src/eosjs-api.ts b/src/eosjs-api.ts index 3a8f0487a..d8e69293b 100644 --- a/src/eosjs-api.ts +++ b/src/eosjs-api.ts @@ -23,9 +23,11 @@ import { import { JsonRpc } from './eosjs-jsonrpc'; import { Abi, + BlockTaposInfo, GetInfoResult, PushTransactionArgs, GetBlockHeaderStateResult, + GetBlockInfoResult, GetBlockResult } from './eosjs-rpc-interfaces'; import * as ser from './eosjs-serialize'; @@ -349,8 +351,7 @@ export class Api { { sign, requiredKeys, authorization = [] }: QueryConfig ): Promise { const info = await this.rpc.get_info(); - // TODO: replace get_block; needs rodeos changes - const refBlock = await this.rpc.get_block(info.last_irreversible_block_num); + const refBlock = await this.tryRefBlockFromGetInfo(info); const queryBuffer = new ser.SerialBuffer({ textEncoder: this.textEncoder, textDecoder: this.textDecoder }); ser.serializeQuery(queryBuffer, query); @@ -439,13 +440,16 @@ export class Api { if (!info) { info = await this.rpc.get_info(); } + if (useLastIrreversible) { + const block = await this.tryRefBlockFromGetInfo(info); + return { ...ser.transactionHeader(block, expireSeconds), ...transaction }; + } - const taposBlockNumber: number = useLastIrreversible - ? info.last_irreversible_block_num : info.head_block_num - blocksBehind; + const taposBlockNumber: number = info.head_block_num - blocksBehind; const refBlock: GetBlockHeaderStateResult | GetBlockResult = taposBlockNumber <= info.last_irreversible_block_num - ? await this.rpc.get_block(taposBlockNumber) + ? await this.tryGetBlockInfo(taposBlockNumber) : await this.tryGetBlockHeaderState(taposBlockNumber); return { ...ser.transactionHeader(refBlock, expireSeconds), ...transaction }; @@ -461,7 +465,36 @@ export class Api { try { return await this.rpc.get_block_header_state(taposBlockNumber); } catch (error) { - return await this.rpc.get_block(taposBlockNumber); + return await this.tryGetBlockInfo(taposBlockNumber); + } + } + + private async tryGetBlockInfo(blockNumber: number): Promise { + try { + return await this.rpc.get_block_info(blockNumber); + } catch (error) { + return await this.rpc.get_block(blockNumber); + } + } + + private async tryRefBlockFromGetInfo(info: GetInfoResult): Promise { + if ( + info.hasOwnProperty('last_irreversible_block_id') && + info.hasOwnProperty('last_irreversible_block_num') && + info.hasOwnProperty('last_irreversible_block_time') + ) { + return { + block_num: info.last_irreversible_block_num, + id: info.last_irreversible_block_id, + timestamp: info.last_irreversible_block_time, + }; + } else { + const block = await this.tryGetBlockInfo(info.last_irreversible_block_num); + return { + block_num: block.block_num, + id: block.id, + timestamp: block.timestamp, + }; } } diff --git a/src/eosjs-jsonrpc.ts b/src/eosjs-jsonrpc.ts index ef9848014..3edd1c122 100644 --- a/src/eosjs-jsonrpc.ts +++ b/src/eosjs-jsonrpc.ts @@ -7,10 +7,12 @@ import { AbiProvider, AuthorityProvider, AuthorityProviderArgs, BinaryAbi } from import { base64ToBinary, convertLegacyPublicKeys } from './eosjs-numeric'; import { GetAbiResult, + GetBlockInfoResult, GetBlockResult, GetCodeResult, GetInfoResult, GetRawCodeAndAbiResult, + GetRawAbiResult, PushTransactionArgs, GetBlockHeaderStateResult } from './eosjs-rpc-interfaces'; @@ -88,6 +90,11 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { return await this.fetch('/v1/chain/get_block_header_state', { block_num_or_id: blockNumOrId }); } + /** Raw call to `/v1/chain/get_block_info` */ + public async get_block_info(blockNum: number): Promise { + return await this.fetch('/v1/chain/get_block_info', { block_num: blockNum }); + } + /** Raw call to `/v1/chain/get_block` */ public async get_block(blockNumOrId: number | string): Promise { return await this.fetch('/v1/chain/get_block', { block_num_or_id: blockNumOrId }); @@ -132,11 +139,15 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { } /** calls `/v1/chain/get_raw_code_and_abi` and pulls out unneeded raw wasm code */ - // TODO: use `/v1/chain/get_raw_abi` directly when it becomes available public async getRawAbi(accountName: string): Promise { - const rawCodeAndAbi = await this.get_raw_code_and_abi(accountName); - const abi = base64ToBinary(rawCodeAndAbi.abi); - return { accountName: rawCodeAndAbi.account_name, abi }; + const rawAbi = await this.get_raw_abi(accountName); + const abi = base64ToBinary(rawAbi.abi); + return { accountName: rawAbi.account_name, abi }; + } + + /** Raw call to `/v1/chain/get_raw_abi` */ + public async get_raw_abi(accountName: string): Promise { + return await this.fetch('/v1/chain/get_raw_abi', { account_name: accountName }); } /** Raw call to `/v1/chain/get_scheduled_transactions` */ diff --git a/src/eosjs-rpc-interfaces.ts b/src/eosjs-rpc-interfaces.ts index 7169a9e1f..80162e867 100644 --- a/src/eosjs-rpc-interfaces.ts +++ b/src/eosjs-rpc-interfaces.ts @@ -38,6 +38,21 @@ export interface GetAbiResult { abi: Abi; } +/** Return value of `/v1/chain/get_block_info` */ +export interface GetBlockInfoResult { + timestamp: string; + producer: string; + confirmed: number; + previous: string; + transaction_mroot: string; + action_mroot: string; + schedule_version: number; + producer_signature: string; + id: string; + block_num: number; + ref_block_prefix: number; +} + /** Return value of `/v1/chain/get_block` */ export interface GetBlockResult { timestamp: string; @@ -101,6 +116,7 @@ export interface GetInfoResult { head_block_num: number; last_irreversible_block_num: number; last_irreversible_block_id: string; + last_irreversible_block_time: string; head_block_id: string; head_block_time: string; head_block_producer: string; @@ -117,6 +133,13 @@ export interface GetRawCodeAndAbiResult { abi: string; } +export interface GetRawAbiResult { + account_name: string; + code_hash: string; + abi_hash: string; + abi: string; +} + /** Arguments for `push_transaction` */ export interface PushTransactionArgs { signatures: string[]; diff --git a/src/tests/eosjs-api.test.ts b/src/tests/eosjs-api.test.ts index 49a190d00..a196807c0 100644 --- a/src/tests/eosjs-api.test.ts +++ b/src/tests/eosjs-api.test.ts @@ -135,7 +135,7 @@ describe('eosjs-api', () => { const fetch = async (input: any, init: any): Promise => ({ ok: true, json: async () => { - if (input === '/v1/chain/get_raw_code_and_abi') { + if (input === '/v1/chain/get_raw_abi') { return { account_name: 'testeostoken', abi: 'DmVvc2lvOjphYmkvMS4wAQxhY2NvdW50X25hbWUEbmFtZQUIdHJhbnNmZXIABARmcm9tDGFjY291bnRfbmFtZQJ0bwxhY2NvdW50X25hbWUIcXVhbnRpdHkFYXNzZXQEbWVtbwZzdHJpbmcGY3JlYXRlAAIGaXNzdWVyDGFjY291bnRfbmFtZQ5tYXhpbXVtX3N1cHBseQVhc3NldAVpc3N1ZQADAnRvDGFjY291bnRfbmFtZQhxdWFudGl0eQVhc3NldARtZW1vBnN0cmluZwdhY2NvdW50AAEHYmFsYW5jZQVhc3NldA5jdXJyZW5jeV9zdGF0cwADBnN1cHBseQVhc3NldAptYXhfc3VwcGx5BWFzc2V0Bmlzc3VlcgxhY2NvdW50X25hbWUDAAAAVy08zc0IdHJhbnNmZXLnBSMjIFRyYW5zZmVyIFRlcm1zICYgQ29uZGl0aW9ucwoKSSwge3tmcm9tfX0sIGNlcnRpZnkgdGhlIGZvbGxvd2luZyB0byBiZSB0cnVlIHRvIHRoZSBiZXN0IG9mIG15IGtub3dsZWRnZToKCjEuIEkgY2VydGlmeSB0aGF0IHt7cXVhbnRpdHl9fSBpcyBub3QgdGhlIHByb2NlZWRzIG9mIGZyYXVkdWxlbnQgb3IgdmlvbGVudCBhY3Rpdml0aWVzLgoyLiBJIGNlcnRpZnkgdGhhdCwgdG8gdGhlIGJlc3Qgb2YgbXkga25vd2xlZGdlLCB7e3RvfX0gaXMgbm90IHN1cHBvcnRpbmcgaW5pdGlhdGlvbiBvZiB2aW9sZW5jZSBhZ2FpbnN0IG90aGVycy4KMy4gSSBoYXZlIGRpc2Nsb3NlZCBhbnkgY29udHJhY3R1YWwgdGVybXMgJiBjb25kaXRpb25zIHdpdGggcmVzcGVjdCB0byB7e3F1YW50aXR5fX0gdG8ge3t0b319LgoKSSB1bmRlcnN0YW5kIHRoYXQgZnVuZHMgdHJhbnNmZXJzIGFyZSBub3QgcmV2ZXJzaWJsZSBhZnRlciB0aGUge3t0cmFuc2FjdGlvbi5kZWxheX19IHNlY29uZHMgb3Igb3RoZXIgZGVsYXkgYXMgY29uZmlndXJlZCBieSB7e2Zyb219fSdzIHBlcm1pc3Npb25zLgoKSWYgdGhpcyBhY3Rpb24gZmFpbHMgdG8gYmUgaXJyZXZlcnNpYmx5IGNvbmZpcm1lZCBhZnRlciByZWNlaXZpbmcgZ29vZHMgb3Igc2VydmljZXMgZnJvbSAne3t0b319JywgSSBhZ3JlZSB0byBlaXRoZXIgcmV0dXJuIHRoZSBnb29kcyBvciBzZXJ2aWNlcyBvciByZXNlbmQge3txdWFudGl0eX19IGluIGEgdGltZWx5IG1hbm5lci4KAAAAAAClMXYFaXNzdWUAAAAAAKhs1EUGY3JlYXRlAAIAAAA4T00RMgNpNjQBCGN1cnJlbmN5AQZ1aW50NjQHYWNjb3VudAAAAAAAkE3GA2k2NAEIY3VycmVuY3kBBnVpbnQ2NA5jdXJyZW5jeV9zdGF0cwAAAA===', // eslint-disable-line diff --git a/src/tests/eosjs-jsonrpc.test.ts b/src/tests/eosjs-jsonrpc.test.ts index c57d6527b..3b02645e7 100644 --- a/src/tests/eosjs-jsonrpc.test.ts +++ b/src/tests/eosjs-jsonrpc.test.ts @@ -140,6 +140,25 @@ describe('JSON RPC', () => { expect(fetch).toBeCalledWith(endpoint + expPath, expParams); }); + it('calls get_block_info', async () => { + const expPath = '/v1/chain/get_block_info'; + const blockNum = 1234; + const expReturn = { data: '12345' }; + const expParams = { + body: JSON.stringify({ + block_num: blockNum, + }), + method: 'POST', + }; + + fetchMock.once(JSON.stringify(expReturn)); + + const response = await jsonRpc.get_block_info(blockNum); + + expect(response).toEqual(expReturn); + expect(fetch).toBeCalledWith(endpoint + expPath, expParams); + }); + it('calls get_block', async () => { const expPath = '/v1/chain/get_block'; const blockNumOrId = 1234; diff --git a/src/tests/node.js b/src/tests/node.js index edc57750e..98afd5095 100644 --- a/src/tests/node.js +++ b/src/tests/node.js @@ -40,7 +40,7 @@ const transactWithConfig = async (config, memo, from = 'bob', to = 'alice') => { const transactWithoutConfig = async () => { const transactionResponse = await transactWithConfig({ blocksBehind: 3, expireSeconds: 30}, 'transactWithoutConfig'); - const blockInfo = await rpc.get_block(transactionResponse.processed.block_num - 3); + const blockInfo = await rpc.get_block_info(transactionResponse.processed.block_num - 3); const currentDate = new Date(); const timePlusTen = currentDate.getTime() + 10000; const timeInISOString = (new Date(timePlusTen)).toISOString(); @@ -196,7 +196,7 @@ const transactShouldFail = async () => await api.transact({ }] }); -const rpcShouldFail = async () => await rpc.get_block(-1); +const rpcShouldFail = async () => await rpc.get_block_info(-1); module.exports = { transactWithConfig, diff --git a/src/tests/web.html b/src/tests/web.html index be5aea583..945794635 100644 --- a/src/tests/web.html +++ b/src/tests/web.html @@ -90,7 +90,7 @@ const transactWithoutConfig = async () => { const transactionResponse = await transactWithConfig({ blocksBehind: 3, expireSeconds: 30 }, 'transactWithoutConfig'); - const blockInfo = await rpc.get_block(transactionResponse.processed.block_num - 3); + const blockInfo = await rpc.get_block_info(transactionResponse.processed.block_num - 3); const currentDate = new Date(); const timePlusTen = currentDate.getTime() + 10000; const timeInISOString = (new Date(timePlusTen)).toISOString(); @@ -509,7 +509,7 @@ return false; } - const rpcShouldFail = async () => await rpc.get_block(-1); + const rpcShouldFail = async () => await rpc.get_block_info(-1); const testRpcShouldFail = async (e) => { resultsLabel = e.target;