From d387ba176a72ca16f82f446b9ad7385f11a4057c Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Fri, 8 Jan 2021 09:39:56 -0500 Subject: [PATCH 01/15] Replaced any to defined types, added return types for functions --- .eslintrc | 3 +- src/PrivateKey.ts | 6 +- src/eosjs-api-interfaces.ts | 7 +- src/eosjs-api.ts | 13 ++- src/eosjs-ecc-migration.ts | 8 +- src/eosjs-jsonrpc.ts | 47 ++++++---- src/eosjs-jssig.ts | 7 +- src/eosjs-key-conversions.ts | 2 +- src/eosjs-numeric.ts | 42 ++++----- src/eosjs-rpc-interfaces.ts | 176 ++++++++++++++++++++++++++++++++++- src/eosjs-serialize.ts | 157 +++++++++++++++---------------- src/eosjs-webauthn-sig.ts | 7 +- 12 files changed, 335 insertions(+), 140 deletions(-) diff --git a/.eslintrc b/.eslintrc index a0bb5c393..95fcd73ad 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,7 +13,8 @@ "@typescript-eslint/indent": ["error", 4], "@typescript-eslint/no-var-requires": "off", "semi": "off", - "@typescript-eslint/semi": ["error", "always"] + "@typescript-eslint/semi": ["error", "always"], + "@typescript-eslint/explicit-function-return-type": ["error"] } } ] diff --git a/src/PrivateKey.ts b/src/PrivateKey.ts index 2f344005c..b2de91b37 100644 --- a/src/PrivateKey.ts +++ b/src/PrivateKey.ts @@ -33,7 +33,7 @@ export class PrivateKey { } /** Export private key as `elliptic`-format private key */ - public toElliptic() { + public toElliptic(): EC.KeyPair { return this.ec.keyFromPrivate(this.key.data); } @@ -67,10 +67,10 @@ export class PrivateKey { } let tries = 0; let signature: Signature; - const isCanonical = (sigData: Uint8Array) => + const isCanonical = (sigData: Uint8Array): boolean => !(sigData[1] & 0x80) && !(sigData[1] === 0 && !(sigData[2] & 0x80)) && !(sigData[33] & 0x80) && !(sigData[33] === 0 && !(sigData[34] & 0x80)); - const constructSignature = (options: EC.SignOptions) => { + const constructSignature = (options: EC.SignOptions): Signature => { const ellipticPrivateKey = this.toElliptic(); const ellipticSignature = ellipticPrivateKey.sign(data, options); return Signature.fromElliptic(ellipticSignature, this.getType(), this.ec); diff --git a/src/eosjs-api-interfaces.ts b/src/eosjs-api-interfaces.ts index 91feaa527..d2b05286b 100644 --- a/src/eosjs-api-interfaces.ts +++ b/src/eosjs-api-interfaces.ts @@ -5,7 +5,6 @@ import { Abi, PushTransactionArgs } from './eosjs-rpc-interfaces'; import { Anyvar, Authorization, Action, SerializedAction } from './eosjs-serialize'; -import { ActionBuilder } from './eosjs-api'; /** Arguments to `getRequiredKeys` */ export interface AuthorityProviderArgs { @@ -102,6 +101,12 @@ export interface TransactConfig { expireSeconds?: number; } +export interface TransactionHeader { + expiration: string; + ref_block_num: number; + ref_block_prefix: number; +} + export interface AccountDelta { account: string; delta: number; diff --git a/src/eosjs-api.ts b/src/eosjs-api.ts index d8e69293b..c6bba0113 100644 --- a/src/eosjs-api.ts +++ b/src/eosjs-api.ts @@ -31,7 +31,6 @@ import { GetBlockResult } from './eosjs-rpc-interfaces'; import * as ser from './eosjs-serialize'; -import { RpcError } from './eosjs-rpcerror'; const transactionAbi = require('../src/transaction.abi.json'); @@ -436,7 +435,7 @@ export class Api { blocksBehind: number | undefined, useLastIrreversible: boolean | undefined, expireSeconds: number - ) { + ): Promise { if (!info) { info = await this.rpc.get_info(); } @@ -456,7 +455,7 @@ export class Api { } // eventually break out into TransactionValidator class - private hasRequiredTaposFields({ expiration, ref_block_num, ref_block_prefix }: any): boolean { + private hasRequiredTaposFields({ expiration, ref_block_num, ref_block_prefix }: Transaction): boolean { return !!(expiration && typeof(ref_block_num) === 'number' && typeof(ref_block_prefix) === 'number'); } @@ -502,7 +501,7 @@ export class Api { return new ActionBuilder(this, accountName); } - public buildTransaction(cb?: (tx: TransactionBuilder) => void) { + public buildTransaction(cb?: (tx: TransactionBuilder) => void): TransactionBuilder|void { const tx = new TransactionBuilder(this); if (cb) { return cb(tx); @@ -514,7 +513,7 @@ export class Api { export class TransactionBuilder { private api: Api; private actions: ActionBuilder[] = []; - private contextFreeGroups: any[] = []; + private contextFreeGroups: ContextFreeGroupCallback[] = []; constructor(api: Api) { this.api = api; } @@ -525,7 +524,7 @@ export class TransactionBuilder { return actionBuilder; } - public associateContextFree(contextFreeGroup: ContextFreeGroupCallback) { + public associateContextFree(contextFreeGroup: ContextFreeGroupCallback): TransactionBuilder { this.contextFreeGroups.push(contextFreeGroup); return this; } @@ -571,7 +570,7 @@ export class ActionBuilder { this.accountName = accountName; } - public as(actorName: string | ser.Authorization[] = []) { + public as(actorName: string | ser.Authorization[] = []): ActionSerializerType { let authorization: ser.Authorization[] = []; if (actorName && typeof actorName === 'string') { authorization = [{ actor: actorName, permission: 'active'}]; diff --git a/src/eosjs-ecc-migration.ts b/src/eosjs-ecc-migration.ts index 20c2f7298..6f3b82f2e 100644 --- a/src/eosjs-ecc-migration.ts +++ b/src/eosjs-ecc-migration.ts @@ -4,8 +4,8 @@ import {KeyType} from './eosjs-numeric'; import {ec as EC} from 'elliptic'; export const ecc = { - initialize: () => console.error('Method deprecated'), - unsafeRandomKey: () => console.error('Method deprecated'), + initialize: (): void => console.error('Method deprecated'), + unsafeRandomKey: (): void => console.error('Method deprecated'), randomKey: ( cpuEntropyBits?: number, options: { secureEnv?: boolean, ecOptions?: EC.GenKeyPairOptions } = {} ): Promise => { @@ -17,7 +17,7 @@ export const ecc = { const { privateKey } = generateKeyPair(KeyType.k1, options); return Promise.resolve(privateKey.toLegacyString()); }, - seedPrivate: () => console.error('Method deprecated'), + seedPrivate: (): void => console.error('Method deprecated'), privateToPublic: (key: string, pubkey_prefix?: string): string => { if (pubkey_prefix !== undefined) { console.warn('Argument `pubkey_prefix` is deprecated, ' + @@ -54,7 +54,7 @@ export const ecc = { const signature = privKey.sign(data, true, encoding); return signature.toString(); }, - signHash: (dataSha256: string|Buffer, privateKey: string|PrivateKey, encoding: BufferEncoding = 'hex') => { + signHash: (dataSha256: string|Buffer, privateKey: string|PrivateKey, encoding: BufferEncoding = 'hex'): string => { const privKey = typeof privateKey === 'string' ? PrivateKey.fromString(privateKey) : privateKey; const signature = privKey.sign(dataSha256, false, encoding); return signature.toString(); diff --git a/src/eosjs-jsonrpc.ts b/src/eosjs-jsonrpc.ts index 3edd1c122..b0a87c6ac 100644 --- a/src/eosjs-jsonrpc.ts +++ b/src/eosjs-jsonrpc.ts @@ -6,19 +6,32 @@ import { AbiProvider, AuthorityProvider, AuthorityProviderArgs, BinaryAbi } from './eosjs-api-interfaces'; import { base64ToBinary, convertLegacyPublicKeys } from './eosjs-numeric'; import { + Asset, GetAbiResult, + GetAccountResult, GetBlockInfoResult, GetBlockResult, GetCodeResult, + GetCurrencyStatsResult, GetInfoResult, + GetProducerScheduleResult, + GetProducersResult, GetRawCodeAndAbiResult, GetRawAbiResult, + GetScheduledTransactionsResult, + GetTableRowsResult, PushTransactionArgs, - GetBlockHeaderStateResult + GetBlockHeaderStateResult, + GetTableByScopeResult, + DBSizeGetResult, + GetActionsResult, + GetTransactionResult, + GetKeyAccountsResult, + GetControlledAccountsResult } from './eosjs-rpc-interfaces'; import { RpcError } from './eosjs-rpcerror'; -const arrayToHex = (data: Uint8Array) => { +const arrayToHex = (data: Uint8Array): string => { let result = ''; for (const x of data) { result += ('00' + x.toString(16)).slice(-2); @@ -52,7 +65,7 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { } /** Post `body` to `endpoint + path`. Throws detailed error information in `RpcError` when available. */ - public async fetch(path: string, body: any) { + public async fetch(path: string, body: any): Promise { let response; let json; try { @@ -81,7 +94,7 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { } /** Raw call to `/v1/chain/get_account` */ - public async get_account(accountName: string): Promise { + public async get_account(accountName: string): Promise { return await this.fetch('/v1/chain/get_account', { account_name: accountName }); } @@ -109,12 +122,12 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { } /** Raw call to `/v1/chain/get_currency_balance` */ - public async get_currency_balance(code: string, account: string, symbol: string = null): Promise { + public async get_currency_balance(code: string, account: string, symbol: string = null): Promise { return await this.fetch('/v1/chain/get_currency_balance', { code, account, symbol }); } /** Raw call to `/v1/chain/get_currency_stats` */ - public async get_currency_stats(code: string, symbol: string): Promise { + public async get_currency_stats(code: string, symbol: string): Promise { return await this.fetch('/v1/chain/get_currency_stats', { code, symbol }); } @@ -124,12 +137,12 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { } /** Raw call to `/v1/chain/get_producer_schedule` */ - public async get_producer_schedule(): Promise { + public async get_producer_schedule(): Promise { return await this.fetch('/v1/chain/get_producer_schedule', {}); } /** Raw call to `/v1/chain/get_producers` */ - public async get_producers(json = true, lowerBound = '', limit = 50): Promise { + public async get_producers(json = true, lowerBound = '', limit = 50): Promise { return await this.fetch('/v1/chain/get_producers', { json, lower_bound: lowerBound, limit }); } @@ -151,7 +164,7 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { } /** Raw call to `/v1/chain/get_scheduled_transactions` */ - public async get_scheduled_transactions(json = true, lowerBound = '', limit = 50): Promise { + public async get_scheduled_transactions(json = true, lowerBound = '', limit = 50): Promise { return await this.fetch('/v1/chain/get_scheduled_transactions', { json, lower_bound: lowerBound, limit }); } @@ -168,7 +181,7 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { limit = 10, reverse = false, show_payer = false, - }: any): Promise { + }: any): Promise { return await this.fetch( '/v1/chain/get_table_rows', { json, @@ -198,7 +211,7 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { limit = 10, reverse = false, show_payer = false, - }: any): Promise { + }: any): Promise { return await this.fetch( '/v1/chain/get_kv_table_rows', { json, @@ -222,7 +235,7 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { lower_bound = '', upper_bound = '', limit = 10, - }: any): Promise { + }: any): Promise { return await this.fetch( '/v1/chain/get_table_by_scope', { code, @@ -266,25 +279,25 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { } /** Raw call to `/v1/db_size/get` */ - public async db_size_get() { return await this.fetch('/v1/db_size/get', {}); } + public async db_size_get(): Promise { return await this.fetch('/v1/db_size/get', {}); } /** Raw call to `/v1/history/get_actions` */ - public async history_get_actions(accountName: string, pos: number = null, offset: number = null) { + public async history_get_actions(accountName: string, pos: number = null, offset: number = null): Promise { return await this.fetch('/v1/history/get_actions', { account_name: accountName, pos, offset }); } /** Raw call to `/v1/history/get_transaction` */ - public async history_get_transaction(id: string, blockNumHint: number = null) { + public async history_get_transaction(id: string, blockNumHint: number = null): Promise { return await this.fetch('/v1/history/get_transaction', { id, block_num_hint: blockNumHint }); } /** Raw call to `/v1/history/get_key_accounts` */ - public async history_get_key_accounts(publicKey: string) { + public async history_get_key_accounts(publicKey: string): Promise { return await this.fetch('/v1/history/get_key_accounts', { public_key: publicKey }); } /** Raw call to `/v1/history/get_controlled_accounts` */ - public async history_get_controlled_accounts(controllingAccount: string) { + public async history_get_controlled_accounts(controllingAccount: string): Promise { return await this.fetch('/v1/history/get_controlled_accounts', { controlling_account: controllingAccount }); } } // JsonRpc diff --git a/src/eosjs-jssig.ts b/src/eosjs-jssig.ts index 7d5da89e2..0d1671d9d 100644 --- a/src/eosjs-jssig.ts +++ b/src/eosjs-jssig.ts @@ -6,6 +6,7 @@ import { ec } from 'elliptic'; import { SignatureProvider, SignatureProviderArgs } from './eosjs-api-interfaces'; +import { PushTransactionArgs } from './eosjs-rpc-interfaces'; import { PrivateKey, PublicKey, @@ -21,7 +22,7 @@ const digestFromSerializedData = ( chainId: string, serializedTransaction: Uint8Array, serializedContextFreeData?: Uint8Array, - e = defaultEc) => { + e = defaultEc): string => { const signBuf = Buffer.concat([ Buffer.from(chainId, 'hex'), Buffer.from(serializedTransaction), @@ -54,14 +55,14 @@ class JsSignatureProvider implements SignatureProvider { } /** Public keys associated with the private keys that the `SignatureProvider` holds */ - public async getAvailableKeys() { + public async getAvailableKeys(): Promise { return this.availableKeys; } /** Sign a transaction */ public async sign( { chainId, requiredKeys, serializedTransaction, serializedContextFreeData }: SignatureProviderArgs, - ) { + ): Promise { const digest = digestFromSerializedData( chainId, serializedTransaction, serializedContextFreeData, defaultEc); const signatures = [] as string[]; diff --git a/src/eosjs-key-conversions.ts b/src/eosjs-key-conversions.ts index 7feea5991..980cfde71 100644 --- a/src/eosjs-key-conversions.ts +++ b/src/eosjs-key-conversions.ts @@ -37,6 +37,6 @@ export const generateKeyPair = ( return {publicKey, privateKey}; }; -export const sha256 = (data: string|Buffer) => { +export const sha256 = (data: string|Buffer): number[]|string => { return hash.sha256().update(data).digest(); }; diff --git a/src/eosjs-numeric.ts b/src/eosjs-numeric.ts index 8e1fd7ac9..9c5134bc5 100644 --- a/src/eosjs-numeric.ts +++ b/src/eosjs-numeric.ts @@ -10,7 +10,7 @@ const ripemd160 = require('./ripemd').RIPEMD160.hash as (a: Uint8Array) => Array const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; -const create_base58_map = () => { +const create_base58_map = (): number[] => { const base58M = Array(256).fill(-1) as number[]; for (let i = 0; i < base58Chars.length; ++i) { base58M[base58Chars.charCodeAt(i)] = i; @@ -20,7 +20,7 @@ const create_base58_map = () => { const base58Map = create_base58_map(); -const create_base64_map = () => { +const create_base64_map = (): number[] => { const base64M = Array(256).fill(-1) as number[]; for (let i = 0; i < base64Chars.length; ++i) { base64M[base64Chars.charCodeAt(i)] = i; @@ -32,12 +32,12 @@ const create_base64_map = () => { const base64Map = create_base64_map(); /** Is `bignum` a negative number? */ -export const isNegative = (bignum: Uint8Array) => { +export const isNegative = (bignum: Uint8Array): boolean => { return (bignum[bignum.length - 1] & 0x80) !== 0; }; /** Negate `bignum` */ -export const negate = (bignum: Uint8Array) => { +export const negate = (bignum: Uint8Array): void => { let carry = 1; for (let i = 0; i < bignum.length; ++i) { const x = (~bignum[i] & 0xff) + carry; @@ -51,7 +51,7 @@ export const negate = (bignum: Uint8Array) => { * * @param size bignum size (bytes) */ -export const decimalToBinary = (size: number, s: string) => { +export const decimalToBinary = (size: number, s: string): Uint8Array => { const result = new Uint8Array(size); for (let i = 0; i < s.length; ++i) { const srcDigit = s.charCodeAt(i); @@ -76,7 +76,7 @@ export const decimalToBinary = (size: number, s: string) => { * * @param size bignum size (bytes) */ -export const signedDecimalToBinary = (size: number, s: string) => { +export const signedDecimalToBinary = (size: number, s: string): Uint8Array => { const negative = s[0] === '-'; if (negative) { s = s.substr(1); @@ -98,7 +98,7 @@ export const signedDecimalToBinary = (size: number, s: string) => { * * @param minDigits 0-pad result to this many digits */ -export const binaryToDecimal = (bignum: Uint8Array, minDigits = 1) => { +export const binaryToDecimal = (bignum: Uint8Array, minDigits = 1): string => { const result = Array(minDigits).fill('0'.charCodeAt(0)) as number[]; for (let i = bignum.length - 1; i >= 0; --i) { let carry = bignum[i]; @@ -121,7 +121,7 @@ export const binaryToDecimal = (bignum: Uint8Array, minDigits = 1) => { * * @param minDigits 0-pad result to this many digits */ -export const signedBinaryToDecimal = (bignum: Uint8Array, minDigits = 1) => { +export const signedBinaryToDecimal = (bignum: Uint8Array, minDigits = 1): string => { if (isNegative(bignum)) { const x = bignum.slice(); negate(x); @@ -130,7 +130,7 @@ export const signedBinaryToDecimal = (bignum: Uint8Array, minDigits = 1) => { return binaryToDecimal(bignum, minDigits); }; -const base58ToBinaryVarSize = (s: string) => { +const base58ToBinaryVarSize = (s: string): Uint8Array => { const result = [] as number[]; for (let i = 0; i < s.length; ++i) { let carry = base58Map[s.charCodeAt(i)]; @@ -162,7 +162,7 @@ const base58ToBinaryVarSize = (s: string) => { * * @param size bignum size (bytes) */ -export const base58ToBinary = (size: number, s: string) => { +export const base58ToBinary = (size: number, s: string): Uint8Array => { if (!size) { return base58ToBinaryVarSize(s); } @@ -190,7 +190,7 @@ export const base58ToBinary = (size: number, s: string) => { * * @param minDigits 0-pad result to this many digits */ -export const binaryToBase58 = (bignum: Uint8Array, minDigits = 1) => { +export const binaryToBase58 = (bignum: Uint8Array, minDigits = 1): string => { const result = [] as number[]; for (const byte of bignum) { let carry = byte; @@ -216,7 +216,7 @@ export const binaryToBase58 = (bignum: Uint8Array, minDigits = 1) => { }; /** Convert an unsigned base-64 number in `s` to a bignum */ -export const base64ToBinary = (s: string) => { +export const base64ToBinary = (s: string): Uint8Array => { let len = s.length; if ((len & 3) === 1 && s[len - 1] === '=') { len -= 1; @@ -273,7 +273,7 @@ export interface Key { data: Uint8Array; } -const digestSuffixRipemd160 = (data: Uint8Array, suffix: string) => { +const digestSuffixRipemd160 = (data: Uint8Array, suffix: string): ArrayBuffer => { const d = new Uint8Array(data.length + suffix.length); for (let i = 0; i < data.length; ++i) { d[i] = data[i]; @@ -295,7 +295,7 @@ const stringToKey = (s: string, type: KeyType, size: number, suffix: string): Ke return result; }; -const keyToString = (key: Key, suffix: string, prefix: string) => { +const keyToString = (key: Key, suffix: string, prefix: string): string => { const digest = new Uint8Array(digestSuffixRipemd160(key.data, suffix)); const whole = new Uint8Array(key.data.length + 4); for (let i = 0; i < key.data.length; ++i) { @@ -336,7 +336,7 @@ export const stringToPublicKey = (s: string): Key => { }; /** Convert public `key` to legacy string (base-58) form */ -export const publicKeyToLegacyString = (key: Key) => { +export const publicKeyToLegacyString = (key: Key): string => { if (key.type === KeyType.k1 && key.data.length === publicKeyDataSize) { return keyToString(key, '', 'EOS'); } else if (key.type === KeyType.r1 || key.type === KeyType.wa) { @@ -347,7 +347,7 @@ export const publicKeyToLegacyString = (key: Key) => { }; /** Convert `key` to string (base-58) form */ -export const publicKeyToString = (key: Key) => { +export const publicKeyToString = (key: Key): string => { if (key.type === KeyType.k1 && key.data.length === publicKeyDataSize) { return keyToString(key, 'K1', 'PUB_K1_'); } else if (key.type === KeyType.r1 && key.data.length === publicKeyDataSize) { @@ -362,7 +362,7 @@ export const publicKeyToString = (key: Key) => { /** If a key is in the legacy format (`EOS` prefix), then convert it to the new format (`PUB_K1_`). * Leaves other formats untouched */ -export const convertLegacyPublicKey = (s: string) => { +export const convertLegacyPublicKey = (s: string): string => { if (s.substr(0, 3) === 'EOS') { return publicKeyToString(stringToPublicKey(s)); } @@ -372,7 +372,7 @@ export const convertLegacyPublicKey = (s: string) => { /** If a key is in the legacy format (`EOS` prefix), then convert it to the new format (`PUB_K1_`). * Leaves other formats untouched */ -export const convertLegacyPublicKeys = (keys: string[]) => { +export const convertLegacyPublicKeys = (keys: string[]): string[] => { return keys.map(convertLegacyPublicKey); }; @@ -402,7 +402,7 @@ export const stringToPrivateKey = (s: string): Key => { }; /** Convert private `key` to legacy string (base-58) form */ -export const privateKeyToLegacyString = (key: Key) => { +export const privateKeyToLegacyString = (key: Key): string => { if (key.type === KeyType.k1 && key.data.length === privateKeyDataSize) { const whole = [] as number[]; whole.push(128); @@ -429,7 +429,7 @@ export const privateKeyToLegacyString = (key: Key) => { }; /** Convert `key` to string (base-58) form */ -export const privateKeyToString = (key: Key) => { +export const privateKeyToString = (key: Key): string => { if (key.type === KeyType.r1) { return keyToString(key, 'R1', 'PVT_R1_'); } else if (key.type === KeyType.k1) { @@ -456,7 +456,7 @@ export const stringToSignature = (s: string): Key => { }; /** Convert `signature` to string (base-58) form */ -export const signatureToString = (signature: Key) => { +export const signatureToString = (signature: Key): string => { if (signature.type === KeyType.k1) { return keyToString(signature, 'K1', 'SIG_K1_'); } else if (signature.type === KeyType.r1) { diff --git a/src/eosjs-rpc-interfaces.ts b/src/eosjs-rpc-interfaces.ts index 80162e867..bb8068804 100644 --- a/src/eosjs-rpc-interfaces.ts +++ b/src/eosjs-rpc-interfaces.ts @@ -14,6 +14,8 @@ export interface Abi { error_messages: { error_code: string, error_msg: string }[]; abi_extensions: { tag: number, value: string }[]; variants?: { name: string, types: string[] }[]; + action_results?: { name: string, result_type: string }[], + kv_tables?: { [key: string]: { type: string, primary_index: { name: string, type: string }, secondary_indices: { [key: string]: { type: string }}[] } }[], } export interface BlockHeader { @@ -32,12 +34,81 @@ export interface SignedBlockHeader extends BlockHeader { producer_signature: string; } +export interface AccountResourceInfo { + used: number; + available: number; + max: number; + last_usage_update_time?: string; + current_used?: number; +} + +export interface Asset { + amount: number; + symbol: string; +} + +export interface Authority { + threshold: number; + keys: KeyWeight[]; + accounts: PermissionLevelWeight[]; + waits: WaitWeight[]; +} + +export interface KeyWeight { + key: string; + weight: number; +} + +export interface Permission { + perm_name: string; + parent: string; + required_auth: Authority; +} + +export interface PermissionLevel { + actor: string; + permission: string; +} + +export interface PermissionLevelWeight { + permission: PermissionLevel; + weight: number; +} + +export interface WaitWeight { + wait_sec: number; + weight: number; +} + /** Return value of `/v1/chain/get_abi` */ export interface GetAbiResult { account_name: string; abi: Abi; } +/** Return value of `/v1/chain/get_account` */ +export interface GetAccountResult { + account_name: string; + head_block_num: number; + head_block_time: string; + privileged: boolean; + last_code_update: string; + created: string; + core_liquid_balance?: Asset; + ram_quota: number; + net_weight: number; + cpu_weight: number; + net_limit: AccountResourceInfo; + cpu_limit: AccountResourceInfo; + ram_usage: number; + permissions: Permission[]; + total_resources: any; + self_delegated_bandwidth: any; + refund_request: any; + voter_info: any; + rex_info: any; +} + /** Return value of `/v1/chain/get_block_info` */ export interface GetBlockInfoResult { timestamp: string; @@ -76,7 +147,7 @@ export interface BlockTaposInfo { header?: BlockHeader; } -/** Return value of `v1/chain/get_block_header_state */ +/** Return value of `/v1/chain/get_block_header_state` */ export interface GetBlockHeaderStateResult { id: string; header: SignedBlockHeader; @@ -109,6 +180,13 @@ export interface GetCodeResult { abi: Abi; } +/** Return value of `/v1/chain/get_currency_stats` */ +export interface GetCurrencyStatsResult { + supply: Asset; + max_supply: Asset; + issuer: string; +} + /** Return value of `/v1/chain/get_info` */ export interface GetInfoResult { server_version: string; @@ -126,6 +204,20 @@ export interface GetInfoResult { block_net_limit: number; } +/** Return value of /v1/chain/get_producer_schedule */ +export interface GetProducerScheduleResult { + active: any; + pending: any; + proposed: any; +} + +/** Return value of `/v1/chain/get_producers` */ +export interface GetProducersResult { + rows: string[]|object[]; + total_producer_vote_weight: number; + more: string; +} + /** Return value of `/v1/chain/get_raw_code_and_abi` */ export interface GetRawCodeAndAbiResult { account_name: string; @@ -133,6 +225,7 @@ export interface GetRawCodeAndAbiResult { abi: string; } +/** Return value of `/v1/chain/get_raw_abi` */ export interface GetRawAbiResult { account_name: string; code_hash: string; @@ -140,6 +233,34 @@ export interface GetRawAbiResult { abi: string; } +/** Return value of `/v1/chain/get_scheduled_transactions` */ +export interface GetScheduledTransactionsResult { + transactions: any[]; + more: string; +} + +/** Return value of `/v1/chain/get_table_rows` and `/v1/chain/get_kv_table_rows` */ +export interface GetTableRowsResult { + rows: any[]; + more: boolean; + next_key: string; + next_key_bytes: string; +} + +export interface GetTableByScopeResultRow { + code: string; + scope: string; + table: string; + payer: string; + count: number; +} + +/** Return value of `/v1/chain/get_table_by_scope` */ +export interface GetTableByScopeResult { + rows: GetTableByScopeResultRow[]; + more: string; +} + /** Arguments for `push_transaction` */ export interface PushTransactionArgs { signatures: string[]; @@ -147,3 +268,56 @@ export interface PushTransactionArgs { serializedTransaction: Uint8Array; serializedContextFreeData?: Uint8Array; } + +/** Return value of `/v1/chain/push_transaction` */ +export interface PushTransactionResult { + +} + +export interface DBSizeIndexCount { + index: string; + row_count: number; +} + +/** Return value of `/v1/db_size/get` */ +export interface DBSizeGetResult { + free_bytes: number; + used_bytes: number; + size: number; + indices: DBSizeIndexCount[]; +} + +export interface OrderedActionResult { + global_action_seq: number; + account_action_seq: number; + block_num: number; + block_time: string; + action_trace: any; +} + +/** Return value of `/v1/history/get_actions` */ +export interface GetActionsResult { + actions: OrderedActionResult[]; + last_irreversible_block: number; + time_limit_exceeded_error?: boolean; +} + +/** Return value of `/v1/history/get_transaction` */ +export interface GetTransactionResult { + id: string; + trx: any; + block_time: string; + block_num: number; + last_irreversible_block: number; + traces: any[]; +} + +/** Return value of `/v1/history/get_key_accounts` */ +export interface GetKeyAccountsResult { + account_names: string[]; +} + +/** Return value of `/v1/history/get_controlled_accounts` */ +export interface GetControlledAccountsResult { + controlled_accounts: string[]; +} diff --git a/src/eosjs-serialize.ts b/src/eosjs-serialize.ts index c326c14db..725054af7 100644 --- a/src/eosjs-serialize.ts +++ b/src/eosjs-serialize.ts @@ -6,7 +6,8 @@ /* eslint-disable jsdoc/check-indentation */ import * as numeric from './eosjs-numeric'; -import { Abi, BlockTaposInfo, BlockHeaderStateTaposInfo } from './eosjs-rpc-interfaces'; +import { TransactionHeader } from './eosjs-api-interfaces'; +import { Abi, BlockTaposInfo } from './eosjs-rpc-interfaces'; import { Query } from './eosjs-api-interfaces'; /** A field in an abi */ @@ -167,7 +168,7 @@ export class SerialBuffer { } /** Resize `array` if needed to have at least `size` bytes free */ - public reserve(size: number) { + public reserve(size: number): void { if (this.length + size <= this.array.length) { return; } @@ -181,34 +182,34 @@ export class SerialBuffer { } /** Is there data available to read? */ - public haveReadData() { + public haveReadData(): boolean { return this.readPos < this.length; } /** Restart reading from the beginning */ - public restartRead() { + public restartRead(): void { this.readPos = 0; } /** Return data with excess storage trimmed away */ - public asUint8Array() { + public asUint8Array(): Uint8Array { return new Uint8Array(this.array.buffer, this.array.byteOffset, this.length); } /** Append bytes */ - public pushArray(v: number[] | Uint8Array) { + public pushArray(v: number[] | Uint8Array): void { this.reserve(v.length); this.array.set(v, this.length); this.length += v.length; } /** Append bytes */ - public push(...v: number[]) { + public push(...v: number[]): void { this.pushArray(v); } /** Get a single byte */ - public get() { + public get(): number { if (this.readPos < this.length) { return this.array[this.readPos++]; } @@ -216,7 +217,7 @@ export class SerialBuffer { } /** Append bytes in `v`. Throws if `len` doesn't match `v.length` */ - public pushUint8ArrayChecked(v: Uint8Array, len: number) { + public pushUint8ArrayChecked(v: Uint8Array, len: number): void { if (v.length !== len) { throw new Error('Binary data has incorrect size'); } @@ -224,7 +225,7 @@ export class SerialBuffer { } /** Get `len` bytes */ - public getUint8Array(len: number) { + public getUint8Array(len: number): Uint8Array { if (this.readPos + len > this.length) { throw new Error('Read past end of buffer'); } @@ -234,7 +235,7 @@ export class SerialBuffer { } /** Skip `len` bytes */ - public skip(len: number) { + public skip(len: number): void { if (this.readPos + len > this.length) { throw new Error('Read past end of buffer'); } @@ -242,12 +243,12 @@ export class SerialBuffer { } /** Append a `uint16` */ - public pushUint16(v: number) { + public pushUint16(v: number): void { this.push((v >> 0) & 0xff, (v >> 8) & 0xff); } /** Get a `uint16` */ - public getUint16() { + public getUint16(): number { let v = 0; v |= this.get() << 0; v |= this.get() << 8; @@ -255,12 +256,12 @@ export class SerialBuffer { } /** Append a `uint32` */ - public pushUint32(v: number) { + public pushUint32(v: number): void { this.push((v >> 0) & 0xff, (v >> 8) & 0xff, (v >> 16) & 0xff, (v >> 24) & 0xff); } /** Get a `uint32` */ - public getUint32() { + public getUint32(): number { let v = 0; v |= this.get() << 0; v |= this.get() << 8; @@ -270,7 +271,7 @@ export class SerialBuffer { } /** Append a `uint64`. *Caution*: `number` only has 53 bits of precision */ - public pushNumberAsUint64(v: number) { + public pushNumberAsUint64(v: number): void { this.pushUint32(v >>> 0); this.pushUint32(Math.floor(v / 0x10000_0000) >>> 0); } @@ -279,14 +280,14 @@ export class SerialBuffer { * Get a `uint64` as a `number`. *Caution*: `number` only has 53 bits of precision; some values will change. * `numeric.binaryToDecimal(serialBuffer.getUint8Array(8))` recommended instead */ - public getUint64AsNumber() { + public getUint64AsNumber(): number { const low = this.getUint32(); const high = this.getUint32(); return (high >>> 0) * 0x10000_0000 + (low >>> 0); } /** Append a `varuint32` */ - public pushVaruint32(v: number) { + public pushVaruint32(v: number): void { while (true) { if (v >>> 7) { this.push(0x80 | (v & 0x7f)); @@ -299,7 +300,7 @@ export class SerialBuffer { } /** Get a `varuint32` */ - public getVaruint32() { + public getVaruint32(): number { let v = 0; let bit = 0; while (true) { @@ -314,12 +315,12 @@ export class SerialBuffer { } /** Append a `varint32` */ - public pushVarint32(v: number) { + public pushVarint32(v: number): void { this.pushVaruint32((v << 1) ^ (v >> 31)); } /** Get a `varint32` */ - public getVarint32() { + public getVarint32(): number { const v = this.getVaruint32(); if (v & 1) { return ((~v) >> 1) | 0x8000_0000; @@ -329,27 +330,27 @@ export class SerialBuffer { } /** Append a `float32` */ - public pushFloat32(v: number) { + public pushFloat32(v: number): void { this.pushArray(new Uint8Array((new Float32Array([v])).buffer)); } /** Get a `float32` */ - public getFloat32() { + public getFloat32(): number { return new Float32Array(this.getUint8Array(4).slice().buffer)[0]; } /** Append a `float64` */ - public pushFloat64(v: number) { + public pushFloat64(v: number): void { this.pushArray(new Uint8Array((new Float64Array([v])).buffer)); } /** Get a `float64` */ - public getFloat64() { + public getFloat64(): number { return new Float64Array(this.getUint8Array(8).slice().buffer)[0]; } /** Append a `name` */ - public pushName(s: string) { + public pushName(s: string): void { if (typeof s !== 'string') { throw new Error('Expected string containing name'); } @@ -357,7 +358,7 @@ export class SerialBuffer { if (!regex.test(s)) { throw new Error('Name should be less than 13 characters, or less than 14 if last character is between 1-5 or a-j, and only contain the following symbols .12345abcdefghijklmnopqrstuvwxyz'); // eslint-disable-line } - const charToSymbol = (c: number) => { + const charToSymbol = (c: number): number => { if (c >= 'a'.charCodeAt(0) && c <= 'z'.charCodeAt(0)) { return (c - 'a'.charCodeAt(0)) + 6; } @@ -384,7 +385,7 @@ export class SerialBuffer { } /** Get a `name` */ - public getName() { + public getName(): string { const a = this.getUint8Array(8); let result = ''; for (let bit = 63; bit >= 0;) { @@ -410,28 +411,28 @@ export class SerialBuffer { } /** Append length-prefixed binary data */ - public pushBytes(v: number[] | Uint8Array) { + public pushBytes(v: number[] | Uint8Array): void { this.pushVaruint32(v.length); this.pushArray(v); } /** Get length-prefixed binary data */ - public getBytes() { + public getBytes(): Uint8Array { return this.getUint8Array(this.getVaruint32()); } /** Append a string */ - public pushString(v: string) { + public pushString(v: string): void { this.pushBytes(this.textEncoder.encode(v)); } /** Get a string */ - public getString() { + public getString(): string { return this.textDecoder.decode(this.getBytes()); } /** Append a `symbol_code`. Unlike `symbol`, `symbol_code` doesn't include a precision. */ - public pushSymbolCode(name: string) { + public pushSymbolCode(name: string): void { if (typeof name !== 'string') { throw new Error('Expected string containing symbol_code'); } @@ -444,7 +445,7 @@ export class SerialBuffer { } /** Get a `symbol_code`. Unlike `symbol`, `symbol_code` doesn't include a precision. */ - public getSymbolCode() { + public getSymbolCode(): string { const a = this.getUint8Array(8); let len; for (len = 0; len < a.length; ++len) { @@ -457,7 +458,7 @@ export class SerialBuffer { } /** Append a `symbol` */ - public pushSymbol({ name, precision }: { name: string, precision: number }) { + public pushSymbol({ name, precision }: { name: string, precision: number }): void { if (!/^[A-Z]{1,7}$/.test(name)) { throw new Error('Expected symbol to be A-Z and between one and seven characters'); } @@ -484,7 +485,7 @@ export class SerialBuffer { } /** Append an asset */ - public pushAsset(s: string) { + public pushAsset(s: string): void { if (typeof s !== 'string') { throw new Error('Expected string containing asset'); } @@ -519,7 +520,7 @@ export class SerialBuffer { } /** Get an asset */ - public getAsset() { + public getAsset(): string { const amount = this.getUint8Array(8); const { name, precision } = this.getSymbol(); let s = numeric.signedBinaryToDecimal(amount, precision + 1); @@ -530,14 +531,14 @@ export class SerialBuffer { } /** Append a public key */ - public pushPublicKey(s: string) { + public pushPublicKey(s: string): void { const key = numeric.stringToPublicKey(s); this.push(key.type); this.pushArray(key.data); } /** Get a public key */ - public getPublicKey() { + public getPublicKey(): string { const type = this.get(); let data: Uint8Array; if (type === numeric.KeyType.wa) { @@ -552,28 +553,28 @@ export class SerialBuffer { } /** Append a private key */ - public pushPrivateKey(s: string) { + public pushPrivateKey(s: string): void { const key = numeric.stringToPrivateKey(s); this.push(key.type); this.pushArray(key.data); } /** Get a private key */ - public getPrivateKey() { + public getPrivateKey(): string { const type = this.get(); const data = this.getUint8Array(numeric.privateKeyDataSize); return numeric.privateKeyToString({ type, data }); } /** Append a signature */ - public pushSignature(s: string) { + public pushSignature(s: string): void { const key = numeric.stringToSignature(s); this.push(key.type); this.pushArray(key.data); } /** Get a signature */ - public getSignature() { + public getSignature(): string { const type = this.get(); let data: Uint8Array; if (type === numeric.KeyType.wa) { @@ -590,11 +591,11 @@ export class SerialBuffer { } // SerialBuffer /** Is this a supported ABI version? */ -export const supportedAbiVersion = (version: string) => { +export const supportedAbiVersion = (version: string): boolean => { return version.startsWith('eosio::abi/1.'); }; -const checkDateParse = (date: string) => { +const checkDateParse = (date: string): number => { const result = Date.parse(date); if (Number.isNaN(result)) { throw new Error('Invalid time format'); @@ -603,34 +604,34 @@ const checkDateParse = (date: string) => { }; /** Convert date in ISO format to `time_point` (miliseconds since epoch) */ -export const dateToTimePoint = (date: string) => { +export const dateToTimePoint = (date: string): number => { return Math.round(checkDateParse(date + 'Z') * 1000); }; /** Convert `time_point` (miliseconds since epoch) to date in ISO format */ -export const timePointToDate = (us: number) => { +export const timePointToDate = (us: number): string => { const s = (new Date(us / 1000)).toISOString(); return s.substr(0, s.length - 1); }; /** Convert date in ISO format to `time_point_sec` (seconds since epoch) */ -export const dateToTimePointSec = (date: string) => { +export const dateToTimePointSec = (date: string): number => { return Math.round(checkDateParse(date + 'Z') / 1000); }; /** Convert `time_point_sec` (seconds since epoch) to to date in ISO format */ -export const timePointSecToDate = (sec: number) => { +export const timePointSecToDate = (sec: number): string => { const s = (new Date(sec * 1000)).toISOString(); return s.substr(0, s.length - 1); }; /** Convert date in ISO format to `block_timestamp_type` (half-seconds since a different epoch) */ -export const dateToBlockTimestamp = (date: string) => { +export const dateToBlockTimestamp = (date: string): number => { return Math.round((checkDateParse(date + 'Z') - 946684800000) / 500); }; /** Convert `block_timestamp_type` (half-seconds since a different epoch) to to date in ISO format */ -export const blockTimestampToDate = (slot: number) => { +export const blockTimestampToDate = (slot: number): string => { const s = (new Date(slot * 500 + 946684800000)).toISOString(); return s.substr(0, s.length - 1); }; @@ -648,12 +649,12 @@ export const stringToSymbol = (s: string): { name: string, precision: number } = }; /** Convert `Symbol` to `string`. format: `precision,NAME`. */ -export const symbolToString = ({ name, precision }: { name: string, precision: number }) => { +export const symbolToString = ({ name, precision }: { name: string, precision: number }): string => { return precision + ',' + name; }; /** Convert binary data to hex */ -export const arrayToHex = (data: Uint8Array) => { +export const arrayToHex = (data: Uint8Array): string => { let result = ''; for (const x of data) { result += ('00' + x.toString(16)).slice(-2); @@ -662,7 +663,7 @@ export const arrayToHex = (data: Uint8Array) => { }; /** Convert hex to binary data */ -export const hexToUint8Array = (hex: string) => { +export const hexToUint8Array = (hex: string): Uint8Array => { if (typeof hex !== 'string') { throw new Error('Expected string containing hex digits'); } @@ -691,7 +692,7 @@ function deserializeUnknown(buffer: SerialBuffer): SerialBuffer { function serializeStruct( this: Type, buffer: SerialBuffer, data: any, state = new SerializerState(), allowExtensions = true -) { +): void { if (typeof data !== 'object') { throw new Error('expected object containing data: ' + JSON.stringify(data)); } @@ -715,7 +716,7 @@ function serializeStruct( } } -function deserializeStruct(this: Type, buffer: SerialBuffer, state = new SerializerState(), allowExtensions = true) { +function deserializeStruct(this: Type, buffer: SerialBuffer, state = new SerializerState(), allowExtensions = true): any { let result; if (this.base) { result = this.base.deserialize(buffer, state, allowExtensions); @@ -734,7 +735,7 @@ function deserializeStruct(this: Type, buffer: SerialBuffer, state = new Seriali function serializeVariant( this: Type, buffer: SerialBuffer, data: any, state?: SerializerState, allowExtensions?: boolean -) { +): void { if (!Array.isArray(data) || data.length !== 2 || typeof data[0] !== 'string') { throw new Error('expected variant: ["type", value]'); } @@ -746,7 +747,7 @@ function serializeVariant( this.fields[i].type.serialize(buffer, data[1], state, allowExtensions); } -function deserializeVariant(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean) { +function deserializeVariant(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean): any[] { const i = buffer.getVaruint32(); if (i >= this.fields.length) { throw new Error(`type index ${i} is not valid for variant`); @@ -757,14 +758,14 @@ function deserializeVariant(this: Type, buffer: SerialBuffer, state?: Serializer function serializeArray( this: Type, buffer: SerialBuffer, data: any[], state?: SerializerState, allowExtensions?: boolean -) { +): void { buffer.pushVaruint32(data.length); for (const item of data) { this.arrayOf.serialize(buffer, item, state, false); } } -function deserializeArray(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean) { +function deserializeArray(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean): any[] { const len = buffer.getVaruint32(); const result = []; for (let i = 0; i < len; ++i) { @@ -775,7 +776,7 @@ function deserializeArray(this: Type, buffer: SerialBuffer, state?: SerializerSt function serializeOptional( this: Type, buffer: SerialBuffer, data: any, state?: SerializerState, allowExtensions?: boolean -) { +): void { if (data === null || data === undefined) { buffer.push(0); } else { @@ -784,7 +785,7 @@ function serializeOptional( } } -function deserializeOptional(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean) { +function deserializeOptional(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean): any { if (buffer.get()) { return this.optionalOf.deserialize(buffer, state, allowExtensions); } else { @@ -794,17 +795,17 @@ function deserializeOptional(this: Type, buffer: SerialBuffer, state?: Serialize function serializeExtension( this: Type, buffer: SerialBuffer, data: any, state?: SerializerState, allowExtensions?: boolean -) { +): void { this.extensionOf.serialize(buffer, data, state, allowExtensions); } -function deserializeExtension(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean) { +function deserializeExtension(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean): any { return this.extensionOf.deserialize(buffer, state, allowExtensions); } function serializeObject( this: Type, buffer: SerialBuffer, data: any, state?: SerializerState, allowExtensions?: boolean -) { +): void { const entries = Object.entries(data); buffer.pushVaruint32(entries.length); for (const [key, value] of entries) { @@ -815,7 +816,7 @@ function serializeObject( } } -function deserializeObject(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean) { +function deserializeObject(this: Type, buffer: SerialBuffer, state?: SerializerState, allowExtensions?: boolean): any { const len = buffer.getVaruint32(); const result = {} as any; for (let i = 0; i < len; ++i) { @@ -856,7 +857,7 @@ const createType = (attrs: CreateTypeArgs): Type => { }; }; -const checkRange = (orig: number, converted: number) => { +const checkRange = (orig: number, converted: number): number => { if (Number.isNaN(+orig) || Number.isNaN(+converted) || (typeof orig !== 'number' && typeof orig !== 'string')) { throw new Error('Expected number'); } @@ -1285,7 +1286,7 @@ export const getType = (types: Map, name: string): Type => { * @param initialTypes Set of types to build on. * In most cases, it's best to fill this from a fresh call to `getTypesFromAbi()`. */ -export const getTypesFromAbi = (initialTypes: Map, abi?: Abi) => { +export const getTypesFromAbi = (initialTypes: Map, abi?: Abi): Map => { const types = new Map(initialTypes); if (abi && abi.types) { for (const { new_type_name, type } of abi.types) { @@ -1325,12 +1326,12 @@ export const getTypesFromAbi = (initialTypes: Map, abi?: Abi) => { return types; }; // getTypesFromAbi -const reverseHex = (h: string) => { +const reverseHex = (h: string): string => { return h.substr(6, 2) + h.substr(4, 2) + h.substr(2, 2) + h.substr(0, 2); }; /** TAPoS: Return transaction fields which reference `refBlock` and expire `expireSeconds` after `timestamp` */ -export const transactionHeader = (refBlock: BlockTaposInfo, expireSeconds: number) => { +export const transactionHeader = (refBlock: BlockTaposInfo, expireSeconds: number): TransactionHeader => { const timestamp = refBlock.header ? refBlock.header.timestamp : refBlock.timestamp; const prefix = parseInt(reverseHex(refBlock.id.substr(16, 8)), 16); @@ -1397,7 +1398,7 @@ export const deserializeAction = ( }; }; -export const serializeAnyvar = (buffer: SerialBuffer, anyvar: Anyvar) => { +export const serializeAnyvar = (buffer: SerialBuffer, anyvar: Anyvar): void => { let def: AnyvarDef; let value: any; if (anyvar === null) { @@ -1419,7 +1420,7 @@ export const serializeAnyvar = (buffer: SerialBuffer, anyvar: Anyvar) => { def.type.serialize(buffer, value); }; -export const deserializeAnyvar = (buffer: SerialBuffer, state?: SerializerState) => { +export const deserializeAnyvar = (buffer: SerialBuffer, state?: SerializerState): any => { const defIndex = buffer.getVaruint32(); if (defIndex >= anyvarDefsByIndex.length) { throw new Error('Tried to deserialize unknown anyvar type'); @@ -1433,11 +1434,11 @@ export const deserializeAnyvar = (buffer: SerialBuffer, state?: SerializerState) } }; -export const deserializeAnyvarShort = (buffer: SerialBuffer) => { +export const deserializeAnyvarShort = (buffer: SerialBuffer): any => { return deserializeAnyvar(buffer, new SerializerState({ useShortForm: true } as any)); }; -export const serializeAnyObject = (buffer: SerialBuffer, obj: any) => { +export const serializeAnyObject = (buffer: SerialBuffer, obj: any): void => { const entries = Object.entries(obj); buffer.pushVaruint32(entries.length); for (const [key, value] of entries) { @@ -1446,7 +1447,7 @@ export const serializeAnyObject = (buffer: SerialBuffer, obj: any) => { } }; -export const deserializeAnyObject = (buffer: SerialBuffer, state?: SerializerState) => { +export const deserializeAnyObject = (buffer: SerialBuffer, state?: SerializerState): any => { const len = buffer.getVaruint32(); const result = {}; for (let i = 0; i < len; ++i) { @@ -1463,14 +1464,14 @@ export const deserializeAnyObject = (buffer: SerialBuffer, state?: SerializerSta return result; }; -export const serializeAnyArray = (buffer: SerialBuffer, arr: Anyvar[]) => { +export const serializeAnyArray = (buffer: SerialBuffer, arr: Anyvar[]): void => { buffer.pushVaruint32(arr.length); for (const x of arr) { serializeAnyvar(buffer, x); } }; -export const deserializeAnyArray = (buffer: SerialBuffer, state?: SerializerState) => { +export const deserializeAnyArray = (buffer: SerialBuffer, state?: SerializerState): any[] => { const len = buffer.getVaruint32(); const result = []; for (let i = 0; i < len; ++i) { @@ -1545,7 +1546,7 @@ const anyvarDefsByIndex = [ anyvarDefs.asset, ]; -export const serializeQuery = (buffer: SerialBuffer, query: Query) => { +export const serializeQuery = (buffer: SerialBuffer, query: Query): void => { let method: string; let arg: Anyvar; let filter: Query[]; diff --git a/src/eosjs-webauthn-sig.ts b/src/eosjs-webauthn-sig.ts index e369f3a93..ff2a122c7 100644 --- a/src/eosjs-webauthn-sig.ts +++ b/src/eosjs-webauthn-sig.ts @@ -4,6 +4,7 @@ // copyright defined in eosjs/LICENSE.txt import { SignatureProvider, SignatureProviderArgs } from './eosjs-api-interfaces'; +import { PushTransactionArgs } from './eosjs-rpc-interfaces'; import * as ser from './eosjs-serialize'; import * as numeric from './eosjs-numeric'; import { ec } from 'elliptic'; @@ -14,14 +15,14 @@ export class WebAuthnSignatureProvider implements SignatureProvider { public keys = new Map(); /** Public keys that the `SignatureProvider` holds */ - public async getAvailableKeys() { + public async getAvailableKeys(): Promise { return Array.from(this.keys.keys()); } /** Sign a transaction */ public async sign( { chainId, requiredKeys, serializedTransaction, serializedContextFreeData }: SignatureProviderArgs, - ) { + ): Promise { const signBuf = new ser.SerialBuffer(); signBuf.pushArray(ser.hexToUint8Array(chainId)); signBuf.pushArray(serializedTransaction); @@ -48,7 +49,7 @@ export class WebAuthnSignatureProvider implements SignatureProvider { const e = new ec('p256') as any; // https://github.com/indutny/elliptic/pull/232 const pubKey = e.keyFromPublic(numeric.stringToPublicKey(key).data.subarray(0, 33)).getPublic(); - const fixup = (x: Uint8Array) => { + const fixup = (x: Uint8Array): Uint8Array => { const a = Array.from(x); while (a.length < 32) { a.unshift(0); From 7e23808a2f88bdec1469709143545d7f28813303 Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Fri, 8 Jan 2021 09:41:21 -0500 Subject: [PATCH 02/15] In progress test file for testing types --- src/tests/eosjs-type-checks.test.ts | 201 ++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 src/tests/eosjs-type-checks.test.ts diff --git a/src/tests/eosjs-type-checks.test.ts b/src/tests/eosjs-type-checks.test.ts new file mode 100644 index 000000000..029e596f2 --- /dev/null +++ b/src/tests/eosjs-type-checks.test.ts @@ -0,0 +1,201 @@ + +import { JsonRpc } from '../eosjs-jsonrpc'; +import fetch from 'node-fetch'; +import { Abi, Asset, GetAbiResult, GetAccountResult, GetBlockHeaderStateResult, GetInfoResult } from '../eosjs-rpc-interfaces'; +import 'jest-extended'; + +const rpc = new JsonRpc('http://localhost:8888', { fetch }); + +describe('Chain Plugin Endpoints', () => { + it('validates return type of get_abi', async () => { + const result: GetAbiResult = await rpc.get_abi('todo'); + const getAbiResultKeys: any = { + account_name: 'string', + abi: { + version: 'string', + types: { + new_type_name: 'string', + type: 'string', + }, + structs: { + name: 'string', + base: 'string', + fields: { + name: 'string', + type: 'string', + }, + }, + actions: { + name: 'string', + type: 'string', + ricardian_contract: 'string', + }, + tables: { + name: 'string', + type: 'string', + index_type: 'string', + key_names: 'string', + key_types: 'string', + }, + ricardian_clauses: { + id: 'string', + body: 'string', + }, + error_messages: { + error_code: 'string', + error_msg: 'string', + }, + abi_extensions: { + tag: 'number', + value: 'string', + }, + 'variants?': { + name: 'string', + types: 'string', + }, + 'action_results?': { + name: 'string', + result_type: 'string', + }, + 'kv_tables?': { + todo: { // key is dynamic, using result from todo account + type: 'string', + primary_index: { + name: 'string', + type: 'string', + }, + secondary_indices: { + 'todo?': { // key is dynamic + type: 'string', + }, + }, + }, + }, + }, + }; + verifyType(result, getAbiResultKeys); + }); + + it('validates return type of get_account', async () => { + const result: GetAccountResult = await rpc.get_account('eosio'); + const getAccountResultKeys: any = { + account_name: 'string', + head_block_num: 'number', + head_block_time: 'string', + privileged: 'boolean', + last_code_update: 'string', + created: 'string', + 'core_liquid_balance?': { + amount: 'number', + symbol: 'string', + }, + ram_quota: 'number', + net_weight: 'number', + cpu_weight: 'number', + net_limit: { + used: 'number', + available: 'number', + max: 'number', + 'last_usage_update_time?': 'string', + 'current_used?': 'number', + }, + cpu_limit: { + used: 'number', + available: 'number', + max: 'number', + 'last_usage_update_time?': 'string', + 'current_used?': 'number', + }, + ram_usage: 'number', + permissions: { + perm_name: 'string', + parent: 'string', + required_auth: { + threshold: 'number', + keys: { + key: 'string', + weight: 'number', + }, + accounts: { + permission: { + actor: 'string', + permission: 'string', + }, + weight: 'number', + }, + waits: { + wait_sec: 'number', + weight: 'number', + } + } + }, + total_resources: 'any', + self_delegated_bandwidth: 'any', + refund_request: 'any', + voter_info: 'any', + rex_info: 'any', + }; + verifyType(result, getAccountResultKeys); + }); + + it('validates return type of get_block_header_state', async () => { + const info: GetInfoResult = await rpc.get_info(); + const result: GetBlockHeaderStateResult = await rpc.get_block_header_state(info.head_block_id); + const getBlockHeaderStateResultKeys: any = { + id: 'string', + header: { + timestamp: 'string', + producer: 'string', + confirmed: 'number', + previous: 'string', + transaction_mroot: 'string', + action_mroot: 'string', + schedule_version: 'number', + new_producers: 'any', + header_extensions: 'any', + producer_signature: 'string', + }, + pending_schedule: 'any', + activated_protocol_features: 'any', + block_num: 'number', + dpos_proposed_irreversible_blocknum: 'number', + dpos_irreversible_blocknum: 'number', + active_schedule: 'any', + blockroot_merkle: 'any', + producer_to_last_produced: 'any', + producer_to_last_implied_irb: 'any', + block_signing_key: 'string', + confirm_count: 'any', + }; + verifyType(result, getBlockHeaderStateResultKeys); + }); +}); + +const verifyType = (data: any, type: any): void => { + const verifiedKeys: string[] = Object.keys(type).filter((key: string) => { + const formattedKey = key.replace('?', ''); + if (key.includes('?')) { + if (!data.hasOwnProperty(formattedKey)) return false; + } + return true; + }).map((key: string) => { + const formattedKey = key.replace('?', ''); + if (Array.isArray(data[formattedKey])) { + data[formattedKey].forEach((element: any) => { + complexOrPrimative(element, type[key]); + }); + } else { + complexOrPrimative(data[formattedKey], type[key]); + } + return formattedKey; + }); + expect(data).toContainAllKeys(verifiedKeys); +}; + +const complexOrPrimative = (data: any, type: any): void => { + if (typeof type === 'object') { + verifyType(data, type); + } else if (type !== 'any') { + expect(typeof data).toEqual(type); + } +}; From f6c38d137f95e25326bbd2d93c46df9173849024 Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Thu, 14 Jan 2021 16:49:47 -0500 Subject: [PATCH 03/15] More progress in type checking tests --- src/eosjs-jsonrpc.ts | 2 +- src/eosjs-rpc-interfaces.ts | 96 ++++++- src/tests/eosjs-type-checks.test.ts | 426 ++++++++++++++++++++++++++-- 3 files changed, 493 insertions(+), 31 deletions(-) diff --git a/src/eosjs-jsonrpc.ts b/src/eosjs-jsonrpc.ts index b0a87c6ac..4da5cf8e2 100644 --- a/src/eosjs-jsonrpc.ts +++ b/src/eosjs-jsonrpc.ts @@ -122,7 +122,7 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { } /** Raw call to `/v1/chain/get_currency_balance` */ - public async get_currency_balance(code: string, account: string, symbol: string = null): Promise { + public async get_currency_balance(code: string, account: string, symbol: string = null): Promise { return await this.fetch('/v1/chain/get_currency_balance', { code, account, symbol }); } diff --git a/src/eosjs-rpc-interfaces.ts b/src/eosjs-rpc-interfaces.ts index bb8068804..8f3384f2a 100644 --- a/src/eosjs-rpc-interfaces.ts +++ b/src/eosjs-rpc-interfaces.ts @@ -3,6 +3,8 @@ * copyright defined in eosjs/LICENSE.txt */ +import { TransactionReceiptHeader, Transaction } from './eosjs-api-interfaces'; + /** Structured format for abis */ export interface Abi { version: string; @@ -26,7 +28,7 @@ export interface BlockHeader { transaction_mroot: string; action_mroot: string; schedule_version: number; - new_producers: any; + new_producers?: ProducerScheduleType; header_extensions: any; } @@ -121,9 +123,24 @@ export interface GetBlockInfoResult { producer_signature: string; id: string; block_num: number; + ref_block_num: number; ref_block_prefix: number; } +export interface PackedTransaction { + id: string; + signatures: string[]; + compression: number|string; + packed_context_free_data: string; + context_free_data: string[]; + packed_trx: string; + transaction: Transaction; +} + +export interface TransactionReceipt extends TransactionReceiptHeader { + trx: PackedTransaction; +} + /** Return value of `/v1/chain/get_block` */ export interface GetBlockResult { timestamp: string; @@ -133,7 +150,9 @@ export interface GetBlockResult { transaction_mroot: string; action_mroot: string; schedule_version: number; + new_producers?: ProducerScheduleType; producer_signature: string; + transactions: any; id: string; block_num: number; ref_block_prefix: number; @@ -147,21 +166,64 @@ export interface BlockTaposInfo { header?: BlockHeader; } +export interface ProducerKey { + producer_name: string; + block_signing_key: string; +} + +export interface BlockSigningAuthority { + threshold: number; + keys: KeyWeight[]; +} + +export interface ProducerAuthority { + producer_name: string; + // authority: BlockSigningAuthority; + authority: any; +}; + +export interface ProducerAuthoritySchedule { + version: number; + producers: ProducerAuthority[]; +} + +export interface ProducerScheduleType { + version: number; + producers: ProducerKey[]; +} + +export interface ScheduleInfo { + schedule_lib_num: number; + schedule_hash: string; + schedule: ProducerScheduleType; +} + +export interface IncrementalMerkle { + _active_nodes: string[]; + _node_count: number; +} + +export interface ProtocolFeatureActivationSet { + protocol_features: string[] +} + /** Return value of `/v1/chain/get_block_header_state` */ export interface GetBlockHeaderStateResult { id: string; header: SignedBlockHeader; - pending_schedule: any; - activated_protocol_features: any; + pending_schedule: ScheduleInfo; + activated_protocol_features: ProtocolFeatureActivationSet; + additional_signatures: string[]; block_num: number; dpos_proposed_irreversible_blocknum: number; dpos_irreversible_blocknum: number; - active_schedule: any; - blockroot_merkle: any; - producer_to_last_produced: any; - producer_to_last_implied_irb: any; - block_signing_key: string; - confirm_count: any; + active_schedule: ProducerAuthoritySchedule; + blockroot_merkle: IncrementalMerkle; + producer_to_last_produced: Map; + producer_to_last_implied_irb: Map; + // valid_block_signing_authority: BlockSigningAuthority; + valid_block_signing_authority: any; + confirm_count: number[]; } /** Subset of `GetBlockHeaderStateResult` used to calculate TAPoS fields in transactions */ @@ -182,9 +244,11 @@ export interface GetCodeResult { /** Return value of `/v1/chain/get_currency_stats` */ export interface GetCurrencyStatsResult { - supply: Asset; - max_supply: Asset; - issuer: string; + [key: string]: { + supply: string; + max_supply: string; + issuer: string; + } } /** Return value of `/v1/chain/get_info` */ @@ -194,7 +258,7 @@ export interface GetInfoResult { head_block_num: number; last_irreversible_block_num: number; last_irreversible_block_id: string; - last_irreversible_block_time: string; + last_irreversible_block_time?: string; head_block_id: string; head_block_time: string; head_block_producer: string; @@ -202,6 +266,10 @@ export interface GetInfoResult { virtual_block_net_limit: number; block_cpu_limit: number; block_net_limit: number; + server_version_string?: string; + fork_db_head_block_num?: number; + fork_db_head_block_id?: string; + server_full_version_string?: string; } /** Return value of /v1/chain/get_producer_schedule */ @@ -235,7 +303,7 @@ export interface GetRawAbiResult { /** Return value of `/v1/chain/get_scheduled_transactions` */ export interface GetScheduledTransactionsResult { - transactions: any[]; + transactions: Transaction[]; more: string; } diff --git a/src/tests/eosjs-type-checks.test.ts b/src/tests/eosjs-type-checks.test.ts index 029e596f2..97e8c6db5 100644 --- a/src/tests/eosjs-type-checks.test.ts +++ b/src/tests/eosjs-type-checks.test.ts @@ -1,7 +1,23 @@ import { JsonRpc } from '../eosjs-jsonrpc'; import fetch from 'node-fetch'; -import { Abi, Asset, GetAbiResult, GetAccountResult, GetBlockHeaderStateResult, GetInfoResult } from '../eosjs-rpc-interfaces'; +import { + GetAbiResult, + GetAccountResult, + GetBlockHeaderStateResult, + GetBlockInfoResult, + GetBlockResult, + GetCodeResult, + GetCurrencyStatsResult, + GetInfoResult, + GetProducerScheduleResult, + GetProducersResult, + GetRawCodeAndAbiResult, + GetRawAbiResult, + GetScheduledTransactionsResult, + GetTableRowsResult, + GetTableByScopeResult, +} from '../eosjs-rpc-interfaces'; import 'jest-extended'; const rpc = new JsonRpc('http://localhost:8888', { fetch }); @@ -9,7 +25,7 @@ const rpc = new JsonRpc('http://localhost:8888', { fetch }); describe('Chain Plugin Endpoints', () => { it('validates return type of get_abi', async () => { const result: GetAbiResult = await rpc.get_abi('todo'); - const getAbiResultKeys: any = { + const getAbiResult: any = { account_name: 'string', abi: { version: 'string', @@ -73,12 +89,12 @@ describe('Chain Plugin Endpoints', () => { }, }, }; - verifyType(result, getAbiResultKeys); + verifyType(result, getAbiResult); }); it('validates return type of get_account', async () => { const result: GetAccountResult = await rpc.get_account('eosio'); - const getAccountResultKeys: any = { + const getAccountResult: any = { account_name: 'string', head_block_num: 'number', head_block_time: 'string', @@ -135,13 +151,13 @@ describe('Chain Plugin Endpoints', () => { voter_info: 'any', rex_info: 'any', }; - verifyType(result, getAccountResultKeys); + verifyType(result, getAccountResult); }); it('validates return type of get_block_header_state', async () => { const info: GetInfoResult = await rpc.get_info(); const result: GetBlockHeaderStateResult = await rpc.get_block_header_state(info.head_block_id); - const getBlockHeaderStateResultKeys: any = { + const getBlockHeaderStateResult: any = { id: 'string', header: { timestamp: 'string', @@ -151,23 +167,393 @@ describe('Chain Plugin Endpoints', () => { transaction_mroot: 'string', action_mroot: 'string', schedule_version: 'number', - new_producers: 'any', + 'new_producers?': { + version: 'number', + producers: { + producer_name: 'string', + block_signing_key: 'string', + }, + }, header_extensions: 'any', producer_signature: 'string', }, - pending_schedule: 'any', - activated_protocol_features: 'any', + pending_schedule: { + schedule_lib_num: 'number', + schedule_hash: 'string', + schedule: { + version: 'number', + producers: { + producer_name: 'string', + block_signing_key: 'string', + }, + }, + }, + activated_protocol_features: { + protocol_features: 'string', + }, + additional_signatures: 'string', block_num: 'number', dpos_proposed_irreversible_blocknum: 'number', dpos_irreversible_blocknum: 'number', - active_schedule: 'any', - blockroot_merkle: 'any', - producer_to_last_produced: 'any', - producer_to_last_implied_irb: 'any', - block_signing_key: 'string', - confirm_count: 'any', + active_schedule: { + version: 'number', + producers: { + producer_name: 'string', + // [ 0, { threshold: 1, keys: [ [Object] ] } ] + authority: 'any', + }, + }, + blockroot_merkle: { + _active_nodes: 'string', + _node_count: 'number', + }, + producer_to_last_produced: 'Map', + producer_to_last_implied_irb: 'Map', + valid_block_signing_authority: 'any', + confirm_count: 'number' + }; + verifyType(result, getBlockHeaderStateResult); + }); + + it('validates return type of get_block_info', async () => { + const info: GetInfoResult = await rpc.get_info(); + const result: GetBlockInfoResult = await rpc.get_block_info(info.last_irreversible_block_num); + const getBlockInfoResult: any = { + 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_num: 'number', + ref_block_prefix: 'number', + }; + verifyType(result, getBlockInfoResult); + }); + + it('validates return type of get_block', async () => { + const info: GetInfoResult = await rpc.get_info(); + const result: GetBlockResult = await rpc.get_block(info.last_irreversible_block_num); + const getBlockResult: any = { + timestamp: 'string', + producer: 'string', + confirmed: 'number', + previous: 'string', + transaction_mroot: 'string', + action_mroot: 'string', + schedule_version: 'number', + 'new_producers?': 'any', + producer_signature: 'string', + transactions: { + status: 'string', + cpu_usage_us: 'number', + net_usage_words: 'number', + trx: { + id: 'string', + signatures: 'string', + compression: 'number|string', + packed_context_free_data: 'string', + context_free_data: 'string', + packed_trx: 'string', + transaction: { + 'expiration?': 'string', + 'ref_block_num?': 'number', + 'ref_block_prefix?': 'number', + 'max_net_usage_words?': 'number', + 'max_cpu_usage_ms?': 'number', + 'delay_sec?': 'number', + 'context_free_actions?': { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', + }, + 'context_free_data?': 'number', + actions: { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', + }, + 'transaction_extensions?': { + type: 'number', + data: 'string', + }, + }, + }, + }, + id: 'string', + block_num: 'number', + ref_block_prefix: 'number', + }; + verifyType(result, getBlockResult); + }); + + it('validates return type of get_code', async () => { + const result: GetCodeResult = await rpc.get_code('todo'); + const getCodeResult: any = { + account_name: 'string', + code_hash: 'string', + wast: 'string', + wasm: 'string', + abi: { + version: 'string', + types: { + new_type_name: 'string', + type: 'string', + }, + structs: { + name: 'string', + base: 'string', + fields: { + name: 'string', + type: 'string', + }, + }, + actions: { + name: 'string', + type: 'string', + ricardian_contract: 'string', + }, + tables: { + name: 'string', + type: 'string', + index_type: 'string', + key_names: 'string', + key_types: 'string', + }, + ricardian_clauses: { + id: 'string', + body: 'string', + }, + error_messages: { + error_code: 'string', + error_msg: 'string', + }, + abi_extensions: { + tag: 'number', + value: 'string', + }, + 'variants?': { + name: 'string', + types: 'string', + }, + 'action_results?': { + name: 'string', + result_type: 'string', + }, + 'kv_tables?': { + todo: { // key is dynamic, using result from todo account + type: 'string', + primary_index: { + name: 'string', + type: 'string', + }, + secondary_indices: { + 'todo?': { // key is dynamic + type: 'string', + }, + }, + }, + }, + }, + }; + verifyType(result, getCodeResult); + }); + + it('validates return type of get_currency_balance', async () => { + const result: string[] = await rpc.get_currency_balance('eosio.token', 'bob', 'SYS'); + const getCurrencyBalanceResult: any = 'string'; + result.forEach((element: any) => { + expect(typeof element).toEqual('string'); + }); + }); + + it('validates return type of get_currency_stats', async () => { + const result: GetCurrencyStatsResult = await rpc.get_currency_stats('eosio.token', 'SYS'); + const getCurrencyStatsResult: any = { + SYS: { + supply: 'string', + max_supply: 'string', + issuer: 'string', + } + }; + verifyType(result, getCurrencyStatsResult); + }); + + it('validates return type of get_info', async () => { + const result: GetInfoResult = await rpc.get_info(); + const getInfoResult: any = { + server_version: 'string', + chain_id: 'string', + 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', + virtual_block_cpu_limit: 'number', + virtual_block_net_limit: 'number', + block_cpu_limit: 'number', + block_net_limit: 'number', + 'server_version_string?': 'string', + 'fork_db_head_block_num?': 'number', + 'fork_db_head_block_id?': 'string', + 'server_full_version_string?': 'string', + }; + verifyType(result, getInfoResult); + }); + + it('validates return type of get_producer_schedule', async () => { + const result: GetProducerScheduleResult = await rpc.get_producer_schedule(); + const getProducerScheduleResult: any = { + // nodeos has them listed as variant + active: 'any', + pending: 'any', + proposed: 'any', + }; + verifyType(result, getProducerScheduleResult); + }); + + it('validates return type of get_producer_schedule', async () => { + const result: GetProducerScheduleResult = await rpc.get_producer_schedule(); + const getProducerScheduleResult: any = { + // nodeos has them listed as variant + active: 'any', + pending: 'any', + proposed: 'any', + }; + verifyType(result, getProducerScheduleResult); + }); + + it('validates return type of get_producers', async () => { + const result: GetProducersResult = await rpc.get_producers(); + const getProducersResult: any = { + // nodeos has object listed as variant + rows: 'string|object', + total_producer_vote_weight: 'string', + more: 'string', + }; + verifyType(result, getProducersResult); + }); + + it('validates return type of get_raw_code_and_abi', async () => { + const result: GetRawCodeAndAbiResult = await rpc.get_raw_code_and_abi('todo'); + const getRawCodeAndAbiResult: any = { + account_name: 'string', + wasm: 'string', + abi: 'string', + }; + verifyType(result, getRawCodeAndAbiResult); + }); + + it('validates return type of get_raw_abi', async () => { + const result: GetRawAbiResult = await rpc.get_raw_abi('todo'); + const getRawAbiResult: any = { + account_name: 'string', + code_hash: 'string', + abi_hash: 'string', + abi: 'string', + }; + verifyType(result, getRawAbiResult); + }); + + it('validates return type of get_scheduled_transactions', async () => { + const result: GetScheduledTransactionsResult = await rpc.get_scheduled_transactions(); + const getScheduledTransactionsResult: any = { + transactions: { + 'expiration?': 'string', + 'ref_block_num?': 'number', + 'ref_block_prefix?': 'number', + 'max_net_usage_words?': 'number', + 'max_cpu_usage_ms?': 'number', + 'delay_sec?': 'number', + 'context_free_actions?': { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', + }, + 'context_free_data?': 'number', + 'actions': { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', + }, + 'transaction_extensions?': { + type: 'number', + data: 'string', + }, + }, + more: 'string', + }; + verifyType(result, getScheduledTransactionsResult); + }); + + it('validates return type of get_table_rows', async () => { + const result: GetTableRowsResult = await rpc.get_table_rows({ + code: 'eosio.token', + scope: 'eosio.token', + table: 'accounts', + }); + const getTableRowsResult: any = { + rows: 'any', + more: 'boolean', + next_key: 'string', + next_key_bytes: 'string', + }; + verifyType(result, getTableRowsResult); + }); + + it('validates return type of get_kv_table_rows', async () => { + const result: GetTableRowsResult = await rpc.get_kv_table_rows({ + code: 'todo', + table: 'todo', + index_name: 'map.index', + encode_type: 'string', + lower_bound: 'ac8acfe7-cd4e-4d22-8400-218b697a4517', + }); + const getTableRowsResult: any = { + rows: 'any', + more: 'boolean', + next_key: 'string', + next_key_bytes: 'string', + }; + verifyType(result, getTableRowsResult); + }); + + it('validates return type of get_table_by_scope', async () => { + const result: GetTableByScopeResult = await rpc.get_table_by_scope({ + code: 'eosio.token', + table: 'accounts', + }); + const getTableByScopeResult: any = { + rows: 'any', + more: 'string', }; - verifyType(result, getBlockHeaderStateResultKeys); + verifyType(result, getTableByScopeResult); }); }); @@ -195,6 +581,14 @@ const verifyType = (data: any, type: any): void => { const complexOrPrimative = (data: any, type: any): void => { if (typeof type === 'object') { verifyType(data, type); + } else if (type.includes('Map')) { + const types = type.replace('Map<', '').replace('>', '').split(', '); + data.forEach((value: any, index: number) => { + complexOrPrimative(value, types[index]); + }); + } else if (type.includes('|')) { + const types = type.split('|'); + expect(typeof data).toBeOneOf(types); } else if (type !== 'any') { expect(typeof data).toEqual(type); } From 1914b9c79ceeea3a0f03cac0b9a47e0cf1042a20 Mon Sep 17 00:00:00 2001 From: Bradley Hart Date: Fri, 12 Feb 2021 16:54:25 -0500 Subject: [PATCH 04/15] More accuracy and checking of these types --- package.json | 4 + src/eosjs-rpc-interfaces.ts | 87 +++++++++--- src/tests/eosjs-type-checks.test.ts | 184 +++++++++++++++++++------- yarn.lock | 198 +++++++++++++++++++++++++++- 4 files changed, 407 insertions(+), 66 deletions(-) diff --git a/package.json b/package.json index b8d5701e3..54a3f65d3 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "lint": "eslint --ext .js,.jsx,.ts,.tsx src", "test": "jest src/tests/*eosjs*", "test-node": "jest src/tests/*node*", + "test-types": "jest src/tests/eosjs-type-checks.test.ts", "test-all": "yarn test && yarn test-node && yarn cypress", "build": "rimraf dist && tsc -p ./tsconfig.json && node scripts/copy-ripe-md.js", "build-web": "webpack --config webpack.prod.js && webpack --config webpack.debug.js", @@ -36,12 +37,14 @@ "@types/elliptic": "^6.4.12", "@types/jest": "^26.0.20", "@types/node": "^14.14.25", + "@types/node-fetch": "^2.5.7", "@types/pako": "^1.0.1", "clean-webpack-plugin": "^3.0.0", "cypress": "^6.4.0", "eosjs-ecc": "^4.0.7", "eslint": "^6.8.0", "jest": "^26.6.3", + "jest-extended": "^0.11.5", "jest-fetch-mock": "^3.0.3", "rimraf": "^3.0.2", "ts-jest": "^26.5.1", @@ -55,6 +58,7 @@ "setupFiles": [ "./src/tests/setupJest.js" ], + "setupFilesAfterEnv": ["jest-extended"], "moduleFileExtensions": [ "ts", "tsx", diff --git a/src/eosjs-rpc-interfaces.ts b/src/eosjs-rpc-interfaces.ts index 8f3384f2a..de4eb04cd 100644 --- a/src/eosjs-rpc-interfaces.ts +++ b/src/eosjs-rpc-interfaces.ts @@ -3,7 +3,7 @@ * copyright defined in eosjs/LICENSE.txt */ -import { TransactionReceiptHeader, Transaction } from './eosjs-api-interfaces'; +import { TransactionReceiptHeader, Transaction, Extension } from './eosjs-api-interfaces'; /** Structured format for abis */ export interface Abi { @@ -13,7 +13,7 @@ export interface Abi { actions: { name: string, type: string, ricardian_contract: string }[]; tables: { name: string, type: string, index_type: string, key_names: string[], key_types: string[] }[]; ricardian_clauses: { id: string, body: string }[]; - error_messages: { error_code: string, error_msg: string }[]; + error_messages: { error_code: number, error_msg: string }[]; abi_extensions: { tag: number, value: string }[]; variants?: { name: string, types: string[] }[]; action_results?: { name: string, result_type: string }[], @@ -44,9 +44,47 @@ export interface AccountResourceInfo { current_used?: number; } -export interface Asset { - amount: number; - symbol: string; +export interface ResourceOverview { + owner: string; + ram_bytes: number; + net_weight: string; + cpu_weight: string; +} + +export interface ResourceDelegation { + from: string; + to: string; + net_weight: string; + cpu_weight: string; +} + +export interface RefundRequest { + owner: string; + request_time: string; + net_amount: string; + cpu_amount: string; +} + +export interface VoterInfo { + owner: string; + proxy: string; + producers: string[]; + staked: number; + last_vote_weight: string; + proxied_vote_weight: string; + is_proxy: number; + flags1: number; + reserved2: number; + reserved3: string; +} + +export interface RexBalance { + version: number; + owner: string; + vote_stake: string; + rex_balance: string; + matured_rex: number; + rex_maturities: any; } export interface Authority { @@ -85,7 +123,7 @@ export interface WaitWeight { /** Return value of `/v1/chain/get_abi` */ export interface GetAbiResult { account_name: string; - abi: Abi; + abi?: Abi; } /** Return value of `/v1/chain/get_account` */ @@ -96,7 +134,7 @@ export interface GetAccountResult { privileged: boolean; last_code_update: string; created: string; - core_liquid_balance?: Asset; + core_liquid_balance?: string; ram_quota: number; net_weight: number; cpu_weight: number; @@ -104,9 +142,9 @@ export interface GetAccountResult { cpu_limit: AccountResourceInfo; ram_usage: number; permissions: Permission[]; - total_resources: any; - self_delegated_bandwidth: any; - refund_request: any; + total_resources: ResourceOverview|null; + self_delegated_bandwidth: ResourceDelegation|null; + refund_request: RefundRequest|null; voter_info: any; rex_info: any; } @@ -150,7 +188,7 @@ export interface GetBlockResult { transaction_mroot: string; action_mroot: string; schedule_version: number; - new_producers?: ProducerScheduleType; + new_producers: ProducerScheduleType|null; producer_signature: string; transactions: any; id: string; @@ -178,8 +216,7 @@ export interface BlockSigningAuthority { export interface ProducerAuthority { producer_name: string; - // authority: BlockSigningAuthority; - authority: any; + authority: [ number|string, BlockSigningAuthority]; }; export interface ProducerAuthoritySchedule { @@ -239,7 +276,7 @@ export interface GetCodeResult { code_hash: string; wast: string; wasm: string; - abi: Abi; + abi?: Abi; } /** Return value of `/v1/chain/get_currency_stats` */ @@ -274,15 +311,27 @@ export interface GetInfoResult { /** Return value of /v1/chain/get_producer_schedule */ export interface GetProducerScheduleResult { - active: any; - pending: any; - proposed: any; + active: ProducerAuthoritySchedule|null; + pending: ProducerAuthoritySchedule|null; + proposed: ProducerAuthoritySchedule|null; +} + +export interface ProducerDetails { + owner: string; + producer_authority?: any[]; + url: string; + is_active?: number; + total_votes: string; + producer_key: string; + unpaid_blocks?: number; + last_claim_time?: string; + location?: number; } /** Return value of `/v1/chain/get_producers` */ export interface GetProducersResult { - rows: string[]|object[]; - total_producer_vote_weight: number; + rows: ProducerDetails[]; + total_producer_vote_weight: string; more: string; } diff --git a/src/tests/eosjs-type-checks.test.ts b/src/tests/eosjs-type-checks.test.ts index 97e8c6db5..00ea2ee56 100644 --- a/src/tests/eosjs-type-checks.test.ts +++ b/src/tests/eosjs-type-checks.test.ts @@ -27,7 +27,7 @@ describe('Chain Plugin Endpoints', () => { const result: GetAbiResult = await rpc.get_abi('todo'); const getAbiResult: any = { account_name: 'string', - abi: { + 'abi?': { version: 'string', types: { new_type_name: 'string', @@ -58,7 +58,7 @@ describe('Chain Plugin Endpoints', () => { body: 'string', }, error_messages: { - error_code: 'string', + error_code: 'number', error_msg: 'string', }, abi_extensions: { @@ -101,10 +101,7 @@ describe('Chain Plugin Endpoints', () => { privileged: 'boolean', last_code_update: 'string', created: 'string', - 'core_liquid_balance?': { - amount: 'number', - symbol: 'string', - }, + 'core_liquid_balance?': 'string', ram_quota: 'number', net_weight: 'number', cpu_weight: 'number', @@ -145,11 +142,44 @@ describe('Chain Plugin Endpoints', () => { } } }, - total_resources: 'any', - self_delegated_bandwidth: 'any', - refund_request: 'any', - voter_info: 'any', - rex_info: 'any', + 'total_resources&': { + owner: 'string', + ram_bytes: 'number', + net_weight: 'string', + cpu_weight: 'string', + }, + 'self_delegated_bandwidth&': { + from: 'string', + to: 'string', + net_weight: 'string', + cpu_weight: 'string', + }, + 'refund_request&': { + owner: 'string', + request_time: 'string', + net_amount: 'string', + cpu_amount: 'string', + }, + 'voter_info&': { + owner: 'string', + proxy: 'string', + producers: 'string', + staked: 'number', + last_vote_weight: 'string', + proxied_vote_weight: 'string', + is_proxy: 'number', + flags1: 'number', + reserved2: 'number', + reserved3: 'string', + }, + 'rex_info&': { + version: 'number', + owner: 'string', + vote_stake: 'string', + rex_balance: 'string', + matured_rex: 'number', + rex_maturities: 'any', + }, }; verifyType(result, getAccountResult); }); @@ -199,8 +229,13 @@ describe('Chain Plugin Endpoints', () => { version: 'number', producers: { producer_name: 'string', - // [ 0, { threshold: 1, keys: [ [Object] ] } ] - authority: 'any', + authority: [ 'number|string', { + threshold: 'number', + keys: { + key: 'string', + weight: 'number', + }, + }], }, }, blockroot_merkle: { @@ -209,7 +244,13 @@ describe('Chain Plugin Endpoints', () => { }, producer_to_last_produced: 'Map', producer_to_last_implied_irb: 'Map', - valid_block_signing_authority: 'any', + valid_block_signing_authority: [ 'number|string', { + threshold: 'number', + keys: { + key: 'string', + weight: 'number', + }, + }], confirm_count: 'number' }; verifyType(result, getBlockHeaderStateResult); @@ -246,7 +287,13 @@ describe('Chain Plugin Endpoints', () => { transaction_mroot: 'string', action_mroot: 'string', schedule_version: 'number', - 'new_producers?': 'any', + 'new_producers&': { + version: 'number', + producers: { + producer_name: 'string', + block_signing_key: 'string' + } + }, producer_signature: 'string', transactions: { status: 'string', @@ -308,7 +355,7 @@ describe('Chain Plugin Endpoints', () => { code_hash: 'string', wast: 'string', wasm: 'string', - abi: { + 'abi?': { version: 'string', types: { new_type_name: 'string', @@ -339,7 +386,7 @@ describe('Chain Plugin Endpoints', () => { body: 'string', }, error_messages: { - error_code: 'string', + error_code: 'number', error_msg: 'string', }, abi_extensions: { @@ -375,7 +422,6 @@ describe('Chain Plugin Endpoints', () => { it('validates return type of get_currency_balance', async () => { const result: string[] = await rpc.get_currency_balance('eosio.token', 'bob', 'SYS'); - const getCurrencyBalanceResult: any = 'string'; result.forEach((element: any) => { expect(typeof element).toEqual('string'); }); @@ -420,21 +466,45 @@ describe('Chain Plugin Endpoints', () => { it('validates return type of get_producer_schedule', async () => { const result: GetProducerScheduleResult = await rpc.get_producer_schedule(); const getProducerScheduleResult: any = { - // nodeos has them listed as variant - active: 'any', - pending: 'any', - proposed: 'any', - }; - verifyType(result, getProducerScheduleResult); - }); - - it('validates return type of get_producer_schedule', async () => { - const result: GetProducerScheduleResult = await rpc.get_producer_schedule(); - const getProducerScheduleResult: any = { - // nodeos has them listed as variant - active: 'any', - pending: 'any', - proposed: 'any', + 'active&': { + version: 'number', + producers: { + producer_name: 'string', + authority: [ 'number|string', { + threshold: 'number', + keys: { + key: 'string', + weight: 'number', + }, + }], + }, + }, + 'pending&': { + version: 'number', + producers: { + producer_name: 'string', + authority: [ 'number|string', { + threshold: 'number', + keys: { + key: 'string', + weight: 'number', + }, + }], + }, + }, + 'proposed&': { + version: 'number', + producers: { + producer_name: 'string', + authority: [ 'number|string', { + threshold: 'number', + keys: { + key: 'string', + weight: 'number', + }, + }], + }, + }, }; verifyType(result, getProducerScheduleResult); }); @@ -443,7 +513,23 @@ describe('Chain Plugin Endpoints', () => { const result: GetProducersResult = await rpc.get_producers(); const getProducersResult: any = { // nodeos has object listed as variant - rows: 'string|object', + rows: { + owner: 'string', + 'producer_authority?': [ 'number|string', { + threshold: 'number', + keys: { + key: 'string', + weight: 'number', + }, + }], + url: 'string', + 'is_active?': 'number', + total_votes: 'string', + producer_key: 'string', + 'unpaid_blocks?': 'number', + 'last_claim_time?': 'string', + 'location?': 'number', + }, total_producer_vote_weight: 'string', more: 'string', }; @@ -451,7 +537,7 @@ describe('Chain Plugin Endpoints', () => { }); it('validates return type of get_raw_code_and_abi', async () => { - const result: GetRawCodeAndAbiResult = await rpc.get_raw_code_and_abi('todo'); + const result: GetRawCodeAndAbiResult = await rpc.get_raw_code_and_abi('eosio'); const getRawCodeAndAbiResult: any = { account_name: 'string', wasm: 'string', @@ -461,7 +547,7 @@ describe('Chain Plugin Endpoints', () => { }); it('validates return type of get_raw_abi', async () => { - const result: GetRawAbiResult = await rpc.get_raw_abi('todo'); + const result: GetRawAbiResult = await rpc.get_raw_abi('eosio'); const getRawAbiResult: any = { account_name: 'string', code_hash: 'string', @@ -559,32 +645,42 @@ describe('Chain Plugin Endpoints', () => { const verifyType = (data: any, type: any): void => { const verifiedKeys: string[] = Object.keys(type).filter((key: string) => { - const formattedKey = key.replace('?', ''); + const formattedKey = key.replace('?', '').replace('&', ''); if (key.includes('?')) { if (!data.hasOwnProperty(formattedKey)) return false; } return true; }).map((key: string) => { - const formattedKey = key.replace('?', ''); + const formattedKey = key.replace('?', '').replace('&', ''); if (Array.isArray(data[formattedKey])) { - data[formattedKey].forEach((element: any) => { - complexOrPrimative(element, type[key]); - }); + if (Array.isArray(type[key])) { + data[formattedKey].forEach((element: any, index: number) => { + complexOrPrimitive(element, type[key][index], formattedKey); + }); + } else { + data[formattedKey].forEach((element: any) => { + complexOrPrimitive(element, type[key], formattedKey); + }); + } + } else if (key.includes('&')) { + if (data[formattedKey] !== null) { + complexOrPrimitive(data[formattedKey], type[key], formattedKey); + } } else { - complexOrPrimative(data[formattedKey], type[key]); + complexOrPrimitive(data[formattedKey], type[key], formattedKey); } return formattedKey; }); expect(data).toContainAllKeys(verifiedKeys); }; -const complexOrPrimative = (data: any, type: any): void => { +const complexOrPrimitive = (data: any, type: any, formattedKey: any): void => { if (typeof type === 'object') { verifyType(data, type); } else if (type.includes('Map')) { const types = type.replace('Map<', '').replace('>', '').split(', '); data.forEach((value: any, index: number) => { - complexOrPrimative(value, types[index]); + complexOrPrimitive(value, types[index], formattedKey); }); } else if (type.includes('|')) { const types = type.split('|'); diff --git a/yarn.lock b/yarn.lock index 51de003fa..388f813c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -357,6 +357,15 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== +"@jest/console@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" + integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== + dependencies: + "@jest/source-map" "^24.9.0" + chalk "^2.0.1" + slash "^2.0.0" + "@jest/console@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" @@ -466,6 +475,15 @@ optionalDependencies: node-notifier "^8.0.0" +"@jest/source-map@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" + integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.1.15" + source-map "^0.6.0" + "@jest/source-map@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" @@ -475,6 +493,15 @@ graceful-fs "^4.2.4" source-map "^0.6.0" +"@jest/test-result@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" + integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== + dependencies: + "@jest/console" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/istanbul-lib-coverage" "^2.0.0" + "@jest/test-result@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" @@ -517,6 +544,15 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" +"@jest/types@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" + integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^13.0.0" + "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -633,6 +669,14 @@ dependencies: "@types/istanbul-lib-coverage" "*" +"@types/istanbul-reports@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2" + integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw== + dependencies: + "@types/istanbul-lib-coverage" "*" + "@types/istanbul-lib-report" "*" + "@types/istanbul-reports@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" @@ -658,6 +702,14 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/node-fetch@^2.5.7": + version "2.5.8" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" + integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*", "@types/node@^14.14.25": version "14.14.25" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.25.tgz#15967a7b577ff81383f9b888aa6705d43fbbae93" @@ -693,6 +745,11 @@ resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== +"@types/stack-utils@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" + integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== + "@types/stack-utils@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" @@ -736,6 +793,13 @@ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA== +"@types/yargs@^13.0.0": + version "13.0.11" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.11.tgz#def2f0c93e4bdf2c61d7e34899b17e34be28d3b1" + integrity sha512-NRqD6T4gktUrDi1o1wLH3EKC1o2caCr7/wR87ODcbVITQF106OM3sFN92ysZ++wqelOd1CTzatnOBRDYYG6wGQ== + dependencies: + "@types/yargs-parser" "*" + "@types/yargs@^15.0.0": version "15.0.13" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.13.tgz#34f7fec8b389d7f3c1fd08026a5763e072d3c6dc" @@ -1016,7 +1080,7 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.1.0: +ansi-regex@^4.0.0, ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== @@ -1596,7 +1660,7 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1824,7 +1888,7 @@ colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -2209,6 +2273,11 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +diff-sequences@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" + integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== + diff-sequences@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" @@ -2612,6 +2681,18 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +expect@^24.1.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" + integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q== + dependencies: + "@jest/types" "^24.9.0" + ansi-styles "^3.2.0" + jest-get-type "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-regex-util "^24.9.0" + expect@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" @@ -2838,6 +2919,15 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -3683,6 +3773,16 @@ jest-config@^26.6.3: micromatch "^4.0.2" pretty-format "^26.6.2" +jest-diff@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" + integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== + dependencies: + chalk "^2.0.1" + diff-sequences "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + jest-diff@^26.0.0, jest-diff@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" @@ -3736,6 +3836,15 @@ jest-environment-node@^26.6.2: jest-mock "^26.6.2" jest-util "^26.6.2" +jest-extended@^0.11.5: + version "0.11.5" + resolved "https://registry.yarnpkg.com/jest-extended/-/jest-extended-0.11.5.tgz#f063b3f1eaadad8d7c13a01f0dfe0f538d498ccf" + integrity sha512-3RsdFpLWKScpsLD6hJuyr/tV5iFOrw7v6YjA3tPdda9sJwoHwcMROws5gwiIZfcwhHlJRwFJB2OUvGmF3evV/Q== + dependencies: + expect "^24.1.0" + jest-get-type "^22.4.3" + jest-matcher-utils "^22.0.0" + jest-fetch-mock@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz#31749c456ae27b8919d69824f1c2bd85fe0a1f3b" @@ -3744,6 +3853,16 @@ jest-fetch-mock@^3.0.3: cross-fetch "^3.0.4" promise-polyfill "^8.1.3" +jest-get-type@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" + integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w== + +jest-get-type@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" + integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== + jest-get-type@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" @@ -3802,6 +3921,25 @@ jest-leak-detector@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-matcher-utils@^22.0.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz#4632fe428ebc73ebc194d3c7b65d37b161f710ff" + integrity sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA== + dependencies: + chalk "^2.0.1" + jest-get-type "^22.4.3" + pretty-format "^22.4.3" + +jest-matcher-utils@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" + integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA== + dependencies: + chalk "^2.0.1" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + jest-matcher-utils@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" @@ -3812,6 +3950,20 @@ jest-matcher-utils@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-message-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" + integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/stack-utils" "^1.0.1" + chalk "^2.0.1" + micromatch "^3.1.10" + slash "^2.0.0" + stack-utils "^1.0.1" + jest-message-util@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" @@ -3840,6 +3992,11 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== +jest-regex-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" + integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== + jest-regex-util@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" @@ -5004,6 +5161,24 @@ pretty-bytes@^5.4.1: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.5.0.tgz#0cecda50a74a941589498011cf23275aa82b339e" integrity sha512-p+T744ZyjjiaFlMUZZv6YPC5JrkNj8maRmPaQCWFJFplUAzpIUTRaTcS+7wmZtUoFXHtESJb23ISliaWyz3SHA== +pretty-format@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.3.tgz#f873d780839a9c02e9664c8a082e9ee79eaac16f" + integrity sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ== + dependencies: + ansi-regex "^3.0.0" + ansi-styles "^3.2.0" + +pretty-format@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" + integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== + dependencies: + "@jest/types" "^24.9.0" + ansi-regex "^4.0.0" + ansi-styles "^3.2.0" + react-is "^16.8.4" + pretty-format@^26.0.0, pretty-format@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" @@ -5151,6 +5326,11 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" +react-is@^16.8.4: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + react-is@^17.0.1: version "17.0.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" @@ -5591,6 +5771,11 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -5744,6 +5929,13 @@ ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" +stack-utils@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.4.tgz#4b600971dcfc6aed0cbdf2a8268177cc916c87c8" + integrity sha512-IPDJfugEGbfizBwBZRZ3xpccMdRyP5lqsBWXGQWimVjua/ccLCeMOAVjlc1R7LxFjo5sEDhyNIXd8mo/AiDS9w== + dependencies: + escape-string-regexp "^2.0.0" + stack-utils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" From e99375f5ee4b060c0247a81468236854a586aff2 Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Thu, 28 Jan 2021 21:42:55 -0500 Subject: [PATCH 05/15] Finished existing transactions --- .eslintrc | 3 +- src/eosjs-api-interfaces.ts | 15 +- src/eosjs-api.ts | 4 +- src/eosjs-jsonrpc.ts | 1 - src/eosjs-rpc-interfaces.ts | 26 ++- src/tests/eosjs-type-checks.test.ts | 270 +++++++++++++++++++++++++++- 6 files changed, 295 insertions(+), 24 deletions(-) diff --git a/.eslintrc b/.eslintrc index 95fcd73ad..a0bb5c393 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,8 +13,7 @@ "@typescript-eslint/indent": ["error", 4], "@typescript-eslint/no-var-requires": "off", "semi": "off", - "@typescript-eslint/semi": ["error", "always"], - "@typescript-eslint/explicit-function-return-type": ["error"] + "@typescript-eslint/semi": ["error", "always"] } } ] diff --git a/src/eosjs-api-interfaces.ts b/src/eosjs-api-interfaces.ts index d2b05286b..2203e3510 100644 --- a/src/eosjs-api-interfaces.ts +++ b/src/eosjs-api-interfaces.ts @@ -72,11 +72,6 @@ export interface SignatureProvider { sign: (args: SignatureProviderArgs) => Promise; } -export interface Extension { - type: number; - data: string; -} - export interface Transaction { expiration?: string; ref_block_num?: number; @@ -87,7 +82,7 @@ export interface Transaction { context_free_actions?: Action[]; context_free_data?: Uint8Array[]; actions: Action[]; - transaction_extensions?: Extension[]; + transaction_extensions?: [number, string][]; } /** Optional transact configuration object */ @@ -122,7 +117,7 @@ export interface ActionReceipt { act_digest: string; global_sequence: number; recv_sequence: number; - auth_sequence: AuthSequence[]; + auth_sequence: [ string, number ][]; code_sequence: number; abi_sequence: number; } @@ -145,10 +140,10 @@ export interface ActionTrace { account_disk_deltas: AccountDelta[]; except: any; error_code: number|null; - return_value: any; - return_value_hex?: string; + return_value?: any; + return_value_hex_data?: string; return_value_data?: any; - inline_traces: ActionTrace[]; + inline_traces?: ActionTrace[]; } export interface TransactionReceiptHeader { diff --git a/src/eosjs-api.ts b/src/eosjs-api.ts index c6bba0113..c3aa8f096 100644 --- a/src/eosjs-api.ts +++ b/src/eosjs-api.ts @@ -446,7 +446,7 @@ export class Api { const taposBlockNumber: number = info.head_block_num - blocksBehind; - const refBlock: GetBlockHeaderStateResult | GetBlockResult = + const refBlock: GetBlockHeaderStateResult | GetBlockResult | GetBlockInfoResult = taposBlockNumber <= info.last_irreversible_block_num ? await this.tryGetBlockInfo(taposBlockNumber) : await this.tryGetBlockHeaderState(taposBlockNumber); @@ -459,7 +459,7 @@ export class Api { return !!(expiration && typeof(ref_block_num) === 'number' && typeof(ref_block_prefix) === 'number'); } - private async tryGetBlockHeaderState(taposBlockNumber: number): Promise + private async tryGetBlockHeaderState(taposBlockNumber: number): Promise { try { return await this.rpc.get_block_header_state(taposBlockNumber); diff --git a/src/eosjs-jsonrpc.ts b/src/eosjs-jsonrpc.ts index 4da5cf8e2..8f14a7516 100644 --- a/src/eosjs-jsonrpc.ts +++ b/src/eosjs-jsonrpc.ts @@ -6,7 +6,6 @@ import { AbiProvider, AuthorityProvider, AuthorityProviderArgs, BinaryAbi } from './eosjs-api-interfaces'; import { base64ToBinary, convertLegacyPublicKeys } from './eosjs-numeric'; import { - Asset, GetAbiResult, GetAccountResult, GetBlockInfoResult, diff --git a/src/eosjs-rpc-interfaces.ts b/src/eosjs-rpc-interfaces.ts index de4eb04cd..5400e030f 100644 --- a/src/eosjs-rpc-interfaces.ts +++ b/src/eosjs-rpc-interfaces.ts @@ -3,7 +3,7 @@ * copyright defined in eosjs/LICENSE.txt */ -import { TransactionReceiptHeader, Transaction, Extension } from './eosjs-api-interfaces'; +import { TransactionReceiptHeader, Transaction } from './eosjs-api-interfaces'; /** Structured format for abis */ export interface Abi { @@ -29,7 +29,7 @@ export interface BlockHeader { action_mroot: string; schedule_version: number; new_producers?: ProducerScheduleType; - header_extensions: any; + header_extensions: [number, string][]; } export interface SignedBlockHeader extends BlockHeader { @@ -350,9 +350,29 @@ export interface GetRawAbiResult { abi: string; } +export interface DeferredTransaction extends Transaction { + deferred_transaction_generation?: { + sender_trx_id: string; + sender_id: string; + sender: string; + } +} + +export interface GeneratedTransaction { + trx_id: string; + sender: string; + sender_id: string; + payer: string; + delay_until: string; + expiration: string; + published: string; + packed_trx?: string[]; + transaction?: DeferredTransaction[] +} + /** Return value of `/v1/chain/get_scheduled_transactions` */ export interface GetScheduledTransactionsResult { - transactions: Transaction[]; + transactions: GeneratedTransaction[]; more: string; } diff --git a/src/tests/eosjs-type-checks.test.ts b/src/tests/eosjs-type-checks.test.ts index 00ea2ee56..46762d620 100644 --- a/src/tests/eosjs-type-checks.test.ts +++ b/src/tests/eosjs-type-checks.test.ts @@ -1,6 +1,10 @@ import { JsonRpc } from '../eosjs-jsonrpc'; +import { JsSignatureProvider } from '../eosjs-jssig'; +import { Api } from '../eosjs-api'; +import * as ser from '../eosjs-serialize'; import fetch from 'node-fetch'; +const { TextEncoder, TextDecoder } = require('util'); import { GetAbiResult, GetAccountResult, @@ -17,10 +21,16 @@ import { GetScheduledTransactionsResult, GetTableRowsResult, GetTableByScopeResult, + PushTransactionArgs, } from '../eosjs-rpc-interfaces'; +import { TransactResult } from '../eosjs-api-interfaces'; import 'jest-extended'; +const privateKey = '5JuH9fCXmU3xbj8nRmhPZaVrxxXrdPaRmZLW1cznNTmTQR2Kg5Z'; + const rpc = new JsonRpc('http://localhost:8888', { fetch }); +const signatureProvider = new JsSignatureProvider([privateKey]); +const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() }); describe('Chain Plugin Endpoints', () => { it('validates return type of get_abi', async () => { @@ -561,9 +571,18 @@ describe('Chain Plugin Endpoints', () => { const result: GetScheduledTransactionsResult = await rpc.get_scheduled_transactions(); const getScheduledTransactionsResult: any = { transactions: { - 'expiration?': 'string', - 'ref_block_num?': 'number', - 'ref_block_prefix?': 'number', + trx_id: 'string', + sender: 'string', + sender_id: 'string', + payer: 'string', + delay_until: 'string', + expiration: 'string', + published: 'string', + 'packed_trx?': 'string', + 'transaction?': { + 'expiration?': 'string', + 'ref_block_num?': 'number', + 'ref_block_prefix?': 'number', 'max_net_usage_words?': 'number', 'max_cpu_usage_ms?': 'number', 'delay_sec?': 'number', @@ -589,8 +608,14 @@ describe('Chain Plugin Endpoints', () => { 'hex_data?': 'string', }, 'transaction_extensions?': { - type: 'number', - data: 'string', + type: 'number', + data: 'string', + }, + 'deferred_transaction_generation?': { + sender_trx_id: 'string', + sender_id: 'string', + sender: 'string', + }, }, }, more: 'string', @@ -641,6 +666,233 @@ describe('Chain Plugin Endpoints', () => { }; verifyType(result, getTableByScopeResult); }); + + it('validates return type of get_required_keys', async () => { + const info = await rpc.get_info(); + let transaction: any = { + actions: [{ + account: 'eosio.token', + name: 'transfer', + authorization: [{ + actor: 'bob', + permission: 'active', + }], + data: { + from: 'bob', + to: 'alice', + quantity: '0.0001 SYS', + memo: '', + }, + }], + context_free_actions: [] + }; + transaction = { + ...ser.transactionHeader({ + block_num: info.last_irreversible_block_num, + id: info.last_irreversible_block_id, + timestamp: info.last_irreversible_block_time, + }, 30), + context_free_actions: await api.serializeActions(transaction.context_free_actions || []), + actions: await api.serializeActions(transaction.actions), + ...transaction, + }; + + const availableKeys = await signatureProvider.getAvailableKeys(); + const result: string[] = await rpc.getRequiredKeys({ transaction, availableKeys }); + result.forEach((element: any) => { + expect(typeof element).toEqual('string'); + }); + }); + + it('validates return of push_transaction', async () => { + const transaction: PushTransactionArgs = await api.transact({ + actions: [{ + account: 'eosio.token', + name: 'transfer', + authorization: [{ + actor: 'bob', + permission: 'active', + }], + data: { + from: 'bob', + to: 'alice', + quantity: '0.0001 SYS', + memo: '', + }, + }], + }, { + sign: true, + broadcast: false, + useLastIrreversible: true, + expireSeconds: 30, + }) as PushTransactionArgs; + const result: TransactResult = await rpc.push_transaction(transaction); + const transactResult = { + transaction_id: 'string', + processed: { + id: 'string', + block_num: 'number', + block_time: 'string', + 'producer_block_id&': 'string', + 'receipt&': { + status: 'string', + cpu_usage_us: 'number', + net_usage_words: 'number', + }, + elapsed: 'number', + net_usage: 'number', + scheduled: 'boolean', + action_traces: { + action_ordinal: 'number', + creator_action_ordinal: 'number', + closest_unnotified_ancestor_action_ordinal: 'number', + receipt: { + receiver: 'string', + act_digest: 'string', + global_sequence: 'number', + recv_sequence: 'number', + auth_sequence: [ 'string', 'number' ], + code_sequence: 'number', + abi_sequence: 'number', + }, + receiver: 'string', + act: { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', + }, + context_free: 'boolean', + elapsed: 'number', + console: 'string', + trx_id: 'string', + block_num: 'number', + block_time: 'string', + 'producer_block_id&': 'string', + account_ram_deltas: { + account: 'string', + delta: 'number', + }, + account_disk_deltas: { + account: 'string', + delta: 'number', + }, + except: 'any', + 'error_code&': 'number', + 'return_value?': 'any', + 'return_value_hex_data?': 'string', + 'return_value_data?': 'any', + 'inline_traces?': 'any', // ActionTrace, recursive? + }, + 'account_ram_delta&': { + account: 'string', + delta: 'number', + }, + 'except&': 'string', + 'error_code&': 'number', + }, + }; + verifyType(result, transactResult); + }); + + it('validates return of send_transaction', async () => { + const transaction: PushTransactionArgs = await api.transact({ + actions: [{ + account: 'eosio.token', + name: 'transfer', + authorization: [{ + actor: 'alice', + permission: 'active', + }], + data: { + from: 'alice', + to: 'bob', + quantity: '0.0001 SYS', + memo: '', + }, + }], + }, { + sign: true, + broadcast: false, + useLastIrreversible: true, + expireSeconds: 30, + }) as PushTransactionArgs; + const result: TransactResult = await rpc.send_transaction(transaction); + const transactResult = { + transaction_id: 'string', + processed: { + id: 'string', + block_num: 'number', + block_time: 'string', + 'producer_block_id&': 'string', + 'receipt&': { + status: 'string', + cpu_usage_us: 'number', + net_usage_words: 'number', + }, + elapsed: 'number', + net_usage: 'number', + scheduled: 'boolean', + action_traces: { + action_ordinal: 'number', + creator_action_ordinal: 'number', + closest_unnotified_ancestor_action_ordinal: 'number', + receipt: { + receiver: 'string', + act_digest: 'string', + global_sequence: 'number', + recv_sequence: 'number', + auth_sequence: [ 'string', 'number' ], + code_sequence: 'number', + abi_sequence: 'number', + }, + receiver: 'string', + act: { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', + }, + context_free: 'boolean', + elapsed: 'number', + console: 'string', + trx_id: 'string', + block_num: 'number', + block_time: 'string', + 'producer_block_id&': 'string', + account_ram_deltas: { + account: 'string', + delta: 'number', + }, + account_disk_deltas: { + account: 'string', + delta: 'number', + }, + except: 'any', + 'error_code&': 'number', + 'return_value?': 'any', + 'return_value_hex_data?': 'string', + 'return_value_data?': 'any', + 'inline_traces?': 'any', // ActionTrace, recursive? + }, + 'account_ram_delta&': { + account: 'string', + delta: 'number', + }, + 'except&': 'string', + 'error_code&': 'number', + }, + }; + verifyType(result, transactResult); + }); }); const verifyType = (data: any, type: any): void => { @@ -655,7 +907,13 @@ const verifyType = (data: any, type: any): void => { if (Array.isArray(data[formattedKey])) { if (Array.isArray(type[key])) { data[formattedKey].forEach((element: any, index: number) => { - complexOrPrimitive(element, type[key][index], formattedKey); + if (Array.isArray(element)) { // auth_sequence [ [ string, number ] ] + element.forEach((secondElement: any, secondIndex: number) => { + complexOrPrimitive(secondElement, type[key][secondIndex], formattedKey); + }); + } else { + complexOrPrimitive(element, type[key][index], formattedKey); + } }); } else { data[formattedKey].forEach((element: any) => { From dd42eb318e02bf5fa7ba23df25145667056aa58b Mon Sep 17 00:00:00 2001 From: Bradley Hart Date: Fri, 12 Feb 2021 16:56:20 -0500 Subject: [PATCH 06/15] Fixing indent and adding test-types to test-all --- package.json | 2 +- src/tests/eosjs-type-checks.test.ts | 46 ++++++++++++++--------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 54a3f65d3..f71f6af19 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "test": "jest src/tests/*eosjs*", "test-node": "jest src/tests/*node*", "test-types": "jest src/tests/eosjs-type-checks.test.ts", - "test-all": "yarn test && yarn test-node && yarn cypress", + "test-all": "yarn test && yarn test-node && yarn test-types && yarn cypress", "build": "rimraf dist && tsc -p ./tsconfig.json && node scripts/copy-ripe-md.js", "build-web": "webpack --config webpack.prod.js && webpack --config webpack.debug.js", "build-production": "yarn build && yarn build-web && yarn test-all", diff --git a/src/tests/eosjs-type-checks.test.ts b/src/tests/eosjs-type-checks.test.ts index 46762d620..bf91b42b1 100644 --- a/src/tests/eosjs-type-checks.test.ts +++ b/src/tests/eosjs-type-checks.test.ts @@ -583,31 +583,31 @@ describe('Chain Plugin Endpoints', () => { 'expiration?': 'string', 'ref_block_num?': 'number', 'ref_block_prefix?': 'number', - 'max_net_usage_words?': 'number', - 'max_cpu_usage_ms?': 'number', - 'delay_sec?': 'number', - 'context_free_actions?': { - account: 'string', - name: 'string', - authorization: { - actor: 'string', - permission: 'string', + 'max_net_usage_words?': 'number', + 'max_cpu_usage_ms?': 'number', + 'delay_sec?': 'number', + 'context_free_actions?': { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', }, - data: 'any', - 'hex_data?': 'string', - }, - 'context_free_data?': 'number', - 'actions': { - account: 'string', - name: 'string', - authorization: { - actor: 'string', - permission: 'string', + 'context_free_data?': 'number', + 'actions': { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', }, - data: 'any', - 'hex_data?': 'string', - }, - 'transaction_extensions?': { + 'transaction_extensions?': { type: 'number', data: 'string', }, From 81827fc91b9fe8ea91fe1b6d997d604c110d9c6f Mon Sep 17 00:00:00 2001 From: Bradley Hart Date: Fri, 12 Feb 2021 17:05:04 -0500 Subject: [PATCH 07/15] Updating docker ci/cd to work with new tests --- .github/eosjs-ci/Dockerfile | 6 +- .github/eosjs-ci/scripts/deploy_contracts.sh | 65 +++++++++++++------- .github/workflows/ci.yml | 2 +- .github/workflows/publish-edge.yml | 2 +- .github/workflows/publish-release.yml | 4 +- 5 files changed, 51 insertions(+), 28 deletions(-) diff --git a/.github/eosjs-ci/Dockerfile b/.github/eosjs-ci/Dockerfile index ec86bedae..8aca16527 100644 --- a/.github/eosjs-ci/Dockerfile +++ b/.github/eosjs-ci/Dockerfile @@ -1,10 +1,10 @@ -### Current Version: v0.2.8 +### Current Version: v0.2.9 ### Test: #### docker build --tag eosjs-ci:test ./.github/eosjs-ci #### docker run --publish 8888:8888 eosjs-ci:test ### Deploy: -#### docker build --tag eosio/eosjs-ci:v0.2.8 ./.github/eosjs-ci -#### docker push eosio/eosjs-ci:v0.2.8 +#### docker build --tag eosio/eosjs-ci:v0.2.9 ./.github/eosjs-ci +#### docker push eosio/eosjs-ci:v0.2.9 FROM ubuntu:18.04 ENTRYPOINT ["nodeos", "--data-dir", "/root/.local/share", "-e", "-p", "eosio", "--replay-blockchain", "--plugin", "eosio::producer_plugin", "--plugin", "eosio::chain_api_plugin", "--plugin", "eosio::http_plugin", "--http-server-address=0.0.0.0:8888", "--access-control-allow-origin=*", "--contracts-console", "--http-validate-host=false", "--verbose-http-errors", "--max-transaction-time=100"] diff --git a/.github/eosjs-ci/scripts/deploy_contracts.sh b/.github/eosjs-ci/scripts/deploy_contracts.sh index 4975c74ae..94df274fc 100644 --- a/.github/eosjs-ci/scripts/deploy_contracts.sh +++ b/.github/eosjs-ci/scripts/deploy_contracts.sh @@ -147,6 +147,15 @@ cleos wallet import --private-key $EXAMPLE_ACCOUNT_PRIVATE_KEY cleos wallet import --private-key $R1_EXAMPLE_ACCOUNT_PRIVATE_KEY cleos wallet import --private-key $CFHELLO_PRIVATE_KEY cleos wallet import --private-key $CFACTOR_PRIVATE_KEY +cleos create account eosio eosio.bpay $SYSTEM_ACCOUNT_PUBLIC_KEY +cleos create account eosio eosio.msig $SYSTEM_ACCOUNT_PUBLIC_KEY +cleos create account eosio eosio.names $SYSTEM_ACCOUNT_PUBLIC_KEY +cleos create account eosio eosio.ram $SYSTEM_ACCOUNT_PUBLIC_KEY +cleos create account eosio eosio.ramfee $SYSTEM_ACCOUNT_PUBLIC_KEY +cleos create account eosio eosio.saving $SYSTEM_ACCOUNT_PUBLIC_KEY +cleos create account eosio eosio.stake $SYSTEM_ACCOUNT_PUBLIC_KEY +cleos create account eosio eosio.vpay $SYSTEM_ACCOUNT_PUBLIC_KEY +cleos create account eosio eosio.rex $SYSTEM_ACCOUNT_PUBLIC_KEY cleos create account eosio eosio.token $SYSTEM_ACCOUNT_PUBLIC_KEY cleos create account eosio returnvalue $SYSTEM_ACCOUNT_PUBLIC_KEY cleos create account eosio todo $SYSTEM_ACCOUNT_PUBLIC_KEY @@ -165,21 +174,21 @@ setabi eosio $CONTRACTS_DIR/eosio.boot/eosio.boot.abi setcode eosio $CONTRACTS_DIR/eosio.boot/eosio.boot.wasm sleep 1s -activate_feature "299dcb6af692324b899b39f16d5a530a33062804e41f09dc97e9f156b4476707" -activate_feature "825ee6288fb1373eab1b5187ec2f04f6eacb39cb3a97f356a07c91622dd61d16" -activate_feature "c3a6138c5061cf291310887c0b5c71fcaffeab90d5deb50d3b9e687cead45071" -activate_feature "4e7bf348da00a945489b2a681749eb56f5de00b900014e137ddae39f48f69d67" -activate_feature "f0af56d2c5a48d60a4a5b5c903edfb7db3a736a94ed589d0b797df33ff9d3e1d" -activate_feature "2652f5f96006294109b3dd0bbde63693f55324af452b799ee137a81a905eed25" -activate_feature "8ba52fe7a3956c5cd3a656a3174b931d3bb2abb45578befc59f283ecd816a405" -activate_feature "ad9e3d8f650687709fd68f4b90b41f7d825a365b02c23a636cef88ac2ac00c43" -activate_feature "68dcaa34c0517d19666e6b33add67351d8c5f69e999ca1e37931bc410a297428" -activate_feature "e0fb64b1085cc5538970158d05a009c24e276fb94e1a0bf6a528b48fbc4ff526" -activate_feature "ef43112c6543b88db2283a2e077278c315ae2c84719a8b25f25cc88565fbea99" -activate_feature "4a90c00d55454dc5b059055ca213579c6ea856967712a56017487886a4d4cc0f" -activate_feature "1a99a59d87e06e09ec5b028a9cbb7749b4a5ad8819004365d02dc4379a8b7241" -activate_feature "bf61537fd21c61a60e542a5d66c3f6a78da0589336868307f94a82bccea84e88" -activate_feature "5443fcf88330c586bc0e5f3dee10e7f63c76c00249c87fe4fbf7f38c082006b4" +cleos push action eosio activate '["299dcb6af692324b899b39f16d5a530a33062804e41f09dc97e9f156b4476707"]' -p eosio@active +cleos push action eosio activate '["825ee6288fb1373eab1b5187ec2f04f6eacb39cb3a97f356a07c91622dd61d16"]' -p eosio@active +cleos push action eosio activate '["c3a6138c5061cf291310887c0b5c71fcaffeab90d5deb50d3b9e687cead45071"]' -p eosio@active +cleos push action eosio activate '["4e7bf348da00a945489b2a681749eb56f5de00b900014e137ddae39f48f69d67"]' -p eosio@active +cleos push action eosio activate '["f0af56d2c5a48d60a4a5b5c903edfb7db3a736a94ed589d0b797df33ff9d3e1d"]' -p eosio@active +cleos push action eosio activate '["2652f5f96006294109b3dd0bbde63693f55324af452b799ee137a81a905eed25"]' -p eosio@active +cleos push action eosio activate '["8ba52fe7a3956c5cd3a656a3174b931d3bb2abb45578befc59f283ecd816a405"]' -p eosio@active +cleos push action eosio activate '["ad9e3d8f650687709fd68f4b90b41f7d825a365b02c23a636cef88ac2ac00c43"]' -p eosio@active +cleos push action eosio activate '["68dcaa34c0517d19666e6b33add67351d8c5f69e999ca1e37931bc410a297428"]' -p eosio@active +cleos push action eosio activate '["e0fb64b1085cc5538970158d05a009c24e276fb94e1a0bf6a528b48fbc4ff526"]' -p eosio@active +cleos push action eosio activate '["ef43112c6543b88db2283a2e077278c315ae2c84719a8b25f25cc88565fbea99"]' -p eosio@active +cleos push action eosio activate '["4a90c00d55454dc5b059055ca213579c6ea856967712a56017487886a4d4cc0f"]' -p eosio@active +cleos push action eosio activate '["1a99a59d87e06e09ec5b028a9cbb7749b4a5ad8819004365d02dc4379a8b7241"]' -p eosio@active +cleos push action eosio activate '["bf61537fd21c61a60e542a5d66c3f6a78da0589336868307f94a82bccea84e88"]' -p eosio@active +cleos push action eosio activate '["5443fcf88330c586bc0e5f3dee10e7f63c76c00249c87fe4fbf7f38c082006b4"]' -p eosio@active sleep 1s setabi eosio $CONTRACTS_DIR/eosio.bios/eosio.bios.abi @@ -190,21 +199,33 @@ cleos push action eosio setkvparams '[{"max_key_size":1024, "max_value_size":409 cleos push action eosio setpparams '["01110000400100000000"]' -p eosio@active sleep 1s -setabi cfhello $CONTRACTS_DIR/cfhello/cfhello.abi -setcode cfhello $CONTRACTS_DIR/cfhello/cfhello.wasm +setabi eosio $CONTRACTS_DIR/eosio.bios/eosio.bios.abi +setcode eosio $CONTRACTS_DIR/eosio.bios/eosio.bios.wasm +cleos set abi eosio $CONTRACTS_DIR/eosio.system/eosio.system.abi -p eosio@active +cleos set code eosio $CONTRACTS_DIR/eosio.system/eosio.system.wasm -p eosio@active sleep 1s -setabi todo $CONTRACTS_DIR/kv_todo/kv_todo.abi -setcode todo $CONTRACTS_DIR/kv_todo/kv_todo.wasm +cleos push action eosio setkvparams '[{"max_key_size":1024, "max_value_size":4096, "max_iterators":1024}]' -p eosio@active +cleos push action eosio setpparams '["01110000400100000000"]' -p eosio@active +cleos set abi eosio.msig $CONTRACTS_DIR/eosio.msig/eosio.msig.abi -p eosio.msig@active +cleos set code eosio.msig $CONTRACTS_DIR/eosio.msig/eosio.msig.wasm -p eosio.msig@active sleep 1s -setabi returnvalue $CONTRACTS_DIR/action_return_value/action_return_value.abi -setcode returnvalue $CONTRACTS_DIR/action_return_value/action_return_value.wasm +cleos set abi cfhello $CONTRACTS_DIR/cfhello/cfhello.abi -p cfhello@active -p eosio@active +cleos set code cfhello $CONTRACTS_DIR/cfhello/cfhello.wasm -p cfhello@active -p eosio@active sleep 1s setabi eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.abi setcode eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.wasm +sleep 1s +cleos set abi returnvalue $CONTRACTS_DIR/action_return_value/action_return_value.abi -p returnvalue@active +cleos set code returnvalue $CONTRACTS_DIR/action_return_value/action_return_value.wasm -p returnvalue@active + +sleep 1s +cleos set abi eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.abi -p eosio.token@active -p eosio@active +cleos set code eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.wasm -p eosio.token@active -p eosio@active + sleep 1s cleos push action eosio.token create '["bob", "10000000000.0000 SYS"]' -p eosio.token cleos push action eosio.token issue '["bob", "5000000000.0000 SYS", "Half of available supply"]' -p bob @@ -216,6 +237,8 @@ cleos push action todo upsert '["bf581bee-9f2c-447b-94ad-78e4984b6f51", "todo", cleos push action todo upsert '["b7b0d09d-a82b-44d9-b067-3bae2d02917e", "todo", "Start Blockchain", false]' -p todo@active cleos push action todo upsert '["ac8acfe7-cd4e-4d22-8400-218b697a4517", "todo", "Deploy Hello World Contract", false]' -p todo@active +cleos push action eosio init '[0, "4,SYS"]' -p eosio@active + echo "All done initializing the blockchain" if [[ -z $NODEOS_RUNNING ]]; then diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94e3a1bee..9d30bccf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,7 +73,7 @@ jobs: git push origin ${GITHUB_REF#refs/*/} services: nodeos: - image: eosio/eosjs-ci:v0.2.8 + image: eosio/eosjs-ci:v0.2.9 ports: - 8888:8888 diff --git a/.github/workflows/publish-edge.yml b/.github/workflows/publish-edge.yml index 4c1fa4210..1730d046e 100644 --- a/.github/workflows/publish-edge.yml +++ b/.github/workflows/publish-edge.yml @@ -58,7 +58,7 @@ jobs: services: nodeos: - image: eosio/eosjs-ci:v0.2.8 + image: eosio/eosjs-ci:v0.2.9 ports: - 8888:8888 diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 8b50a6bc3..a655b4c78 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -57,7 +57,7 @@ jobs: services: nodeos: - image: eosio/eosjs-ci:v0.2.8 + image: eosio/eosjs-ci:v0.2.9 ports: - 8888:8888 @@ -117,7 +117,7 @@ jobs: services: nodeos: - image: eosio/eosjs-ci:v0.2.8 + image: eosio/eosjs-ci:v0.2.9 ports: - 8888:8888 From 9d761fcdb85c3a62ec5699772250d273f8fe81d3 Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Fri, 29 Jan 2021 00:04:43 -0500 Subject: [PATCH 08/15] Adding test-types to ci/cd --- .github/workflows/ci.yml | 3 +++ .github/workflows/publish-edge.yml | 3 +++ .github/workflows/publish-release.yml | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d30bccf9..85db35228 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,6 +51,9 @@ jobs: - name: Test Node run: | yarn test-node + - name: Test Types + run: | + yarn test-types - name: Build run: | yarn build-web diff --git a/.github/workflows/publish-edge.yml b/.github/workflows/publish-edge.yml index 1730d046e..ab3dbb4a1 100644 --- a/.github/workflows/publish-edge.yml +++ b/.github/workflows/publish-edge.yml @@ -38,6 +38,9 @@ jobs: - name: Test Node run: | yarn test-node + - name: Test Types + run: | + yarn test-types - name: Build run: | yarn build-web diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index a655b4c78..9111514c7 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -38,6 +38,9 @@ jobs: - name: Test Node run: | yarn test-node + - name: Test Types + run: | + yarn test-types - name: Build run: | yarn build-web @@ -98,6 +101,9 @@ jobs: - name: Test Node run: | yarn test-node + - name: Test Types + run: | + yarn test-types - name: Build run: | yarn build-web From cea63bb9f9934adc13f14eef16e6566ec24395a1 Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Mon, 1 Feb 2021 15:12:44 -0500 Subject: [PATCH 09/15] Documentation --- src/tests/eosjs-type-checks.test.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/tests/eosjs-type-checks.test.ts b/src/tests/eosjs-type-checks.test.ts index bf91b42b1..2ddc76d85 100644 --- a/src/tests/eosjs-type-checks.test.ts +++ b/src/tests/eosjs-type-checks.test.ts @@ -32,6 +32,17 @@ const rpc = new JsonRpc('http://localhost:8888', { fetch }); const signatureProvider = new JsSignatureProvider([privateKey]); const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() }); +/** Checking types with verifyType/complexOrPrimitive + * To ensure that the data structure coming from eos matches the declared types in eosjs for developers and documentation + * Since typescript is not a runtime language, it's required to test with javascript format + * Create an object matching the typescript type with some requirements: + * nullable: make the key a string and add a `&` character to the end + * optional: make the key a string and add a `?` character to the end (same as typescript) + * []: remove array symbols from simple/complex types, use arrays for std::pair + * Map<>: use Map<> in the value field + * |: operates the same as typescript but does not work for complex types + */ + describe('Chain Plugin Endpoints', () => { it('validates return type of get_abi', async () => { const result: GetAbiResult = await rpc.get_abi('todo'); @@ -522,7 +533,6 @@ describe('Chain Plugin Endpoints', () => { it('validates return type of get_producers', async () => { const result: GetProducersResult = await rpc.get_producers(); const getProducersResult: any = { - // nodeos has object listed as variant rows: { owner: 'string', 'producer_authority?': [ 'number|string', { @@ -907,7 +917,7 @@ const verifyType = (data: any, type: any): void => { if (Array.isArray(data[formattedKey])) { if (Array.isArray(type[key])) { data[formattedKey].forEach((element: any, index: number) => { - if (Array.isArray(element)) { // auth_sequence [ [ string, number ] ] + if (Array.isArray(element)) { element.forEach((secondElement: any, secondIndex: number) => { complexOrPrimitive(secondElement, type[key][secondIndex], formattedKey); }); From c2d796b1b0864582b1e54b2aac1255057ce01c31 Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Mon, 8 Feb 2021 13:36:45 -0500 Subject: [PATCH 10/15] Remaining endpoints and tests --- .github/eosjs-ci/scripts/deploy_contracts.sh | 1 + src/eosjs-api.ts | 2 +- src/eosjs-jsonrpc.ts | 77 +++++- src/eosjs-rpc-interfaces.ts | 110 +++++++- src/tests/eosjs-type-checks.test.ts | 254 ++++++++++++++++++- 5 files changed, 427 insertions(+), 17 deletions(-) diff --git a/.github/eosjs-ci/scripts/deploy_contracts.sh b/.github/eosjs-ci/scripts/deploy_contracts.sh index 94df274fc..3f620b106 100644 --- a/.github/eosjs-ci/scripts/deploy_contracts.sh +++ b/.github/eosjs-ci/scripts/deploy_contracts.sh @@ -121,6 +121,7 @@ if [ -z "$NODEOS_RUNNING" ]; then --http-server-address=0.0.0.0:8888 \ --access-control-allow-origin=* \ --contracts-console \ + --enable-account-queries=true \ --max-transaction-time=100000 \ --verbose-http-errors & fi diff --git a/src/eosjs-api.ts b/src/eosjs-api.ts index c3aa8f096..c1399901d 100644 --- a/src/eosjs-api.ts +++ b/src/eosjs-api.ts @@ -389,7 +389,7 @@ export class Api { signatures, compression: 0, serializedTransaction - }); + }) as any; const returnBuffer = new ser.SerialBuffer({ textEncoder: this.textEncoder, diff --git a/src/eosjs-jsonrpc.ts b/src/eosjs-jsonrpc.ts index 8f14a7516..374a8a613 100644 --- a/src/eosjs-jsonrpc.ts +++ b/src/eosjs-jsonrpc.ts @@ -3,14 +3,20 @@ */ // copyright defined in eosjs/LICENSE.txt -import { AbiProvider, AuthorityProvider, AuthorityProviderArgs, BinaryAbi } from './eosjs-api-interfaces'; +import { AbiProvider, AuthorityProvider, AuthorityProviderArgs, BinaryAbi, TransactResult } from './eosjs-api-interfaces'; import { base64ToBinary, convertLegacyPublicKeys } from './eosjs-numeric'; import { + AbiBinToJsonResult, + AbiJsonToBinResult, GetAbiResult, GetAccountResult, + GetAccountsByAuthorizersResult, + GetActivatedProtocolFeaturesParams, + GetActivatedProtocolFeaturesResult, GetBlockInfoResult, GetBlockResult, GetCodeResult, + GetCodeHashResult, GetCurrencyStatsResult, GetInfoResult, GetProducerScheduleResult, @@ -20,14 +26,17 @@ import { GetScheduledTransactionsResult, GetTableRowsResult, PushTransactionArgs, + PackedTrx, GetBlockHeaderStateResult, GetTableByScopeResult, DBSizeGetResult, + TraceApiGetBlockResult, GetActionsResult, GetTransactionResult, GetKeyAccountsResult, - GetControlledAccountsResult + GetControlledAccountsResult, } from './eosjs-rpc-interfaces'; +import { Authorization } from './eosjs-serialize'; import { RpcError } from './eosjs-rpcerror'; const arrayToHex = (data: Uint8Array): string => { @@ -87,6 +96,22 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { return json; } + public async abi_bin_to_json( + code: string, + action: string, + binargs: string, + ): Promise { + return await this.fetch('/v1/chain/abi_bin_to_json', { code, action, binargs }); + } + + public async abi_json_to_bin( + code: string, + action: string, + args: any[], + ): Promise { + return await this.fetch('/v1/chain/abi_json_to_bin', { code, action, args }); + } + /** Raw call to `/v1/chain/get_abi` */ public async get_abi(accountName: string): Promise { return await this.fetch('/v1/chain/get_abi', { account_name: accountName }); @@ -97,6 +122,22 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { return await this.fetch('/v1/chain/get_account', { account_name: accountName }); } + /** Raw call to `/v1/chain/get_accounts_by_authorizers` */ + public async get_accounts_by_authorizers(accounts: Authorization[], keys: string[]): Promise { + return await this.fetch('/v1/chain/get_accounts_by_authorizers', { accounts, keys }); + } + + /** Raw call to `get_activated_protocol_features` */ + public async get_activated_protocol_features({ + limit = 10, + search_by_block_num = false, + reverse = false, + lower_bound = null, + upper_bound = null, + }: GetActivatedProtocolFeaturesParams): Promise { + return await this.fetch('/v1/chain/get_activated_protocol_features', { lower_bound, upper_bound, limit, search_by_block_num, reverse }); + } + /** Raw call to `/v1/chain/get_block_header_state` */ public async get_block_header_state(blockNumOrId: number | string): Promise { return await this.fetch('/v1/chain/get_block_header_state', { block_num_or_id: blockNumOrId }); @@ -120,6 +161,11 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { }); } + /** Raw call to `/v1/chain/get_code_hash` */ + public async get_code_hash(accountName: string): Promise { + return await this.fetch('/v1/chain/get_code_hash', { account_name: accountName }); + } + /** Raw call to `/v1/chain/get_currency_balance` */ public async get_currency_balance(code: string, account: string, symbol: string = null): Promise { return await this.fetch('/v1/chain/get_currency_balance', { code, account, symbol }); @@ -204,9 +250,9 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { table, index_name, encode_type = 'bytes', - index_value = '', - lower_bound = '', - upper_bound = '', + index_value, + lower_bound, + upper_bound, limit = 10, reverse = false, show_payer = false, @@ -256,7 +302,7 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { /** Push a serialized transaction (replaced by send_transaction, but returned format has changed) */ public async push_transaction( { signatures, compression = 0, serializedTransaction, serializedContextFreeData }: PushTransactionArgs - ): Promise { + ): Promise { return await this.fetch('/v1/chain/push_transaction', { signatures, compression, @@ -265,10 +311,22 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { }); } + public async push_transactions(transactions: PushTransactionArgs[]): Promise { + const packedTrxs: PackedTrx[] = transactions.map(({signatures, compression = 0, serializedTransaction, serializedContextFreeData }: PushTransactionArgs) => { + return { + signatures, + compression, + packed_context_free_data: arrayToHex(serializedContextFreeData || new Uint8Array(0)), + packed_trx: arrayToHex(serializedTransaction), + }; + }); + return await this.fetch('/v1/chain/push_transactions', packedTrxs ); + } + /** Send a serialized transaction */ public async send_transaction( { signatures, compression = 0, serializedTransaction, serializedContextFreeData }: PushTransactionArgs - ): Promise { + ): Promise { return await this.fetch('/v1/chain/send_transaction', { signatures, compression, @@ -280,6 +338,11 @@ export class JsonRpc implements AuthorityProvider, AbiProvider { /** Raw call to `/v1/db_size/get` */ public async db_size_get(): Promise { return await this.fetch('/v1/db_size/get', {}); } + /** Raw call to `/v1/trace_api/get_block` */ + public async trace_get_block(block_num: number): Promise { + return await this.fetch('/v1/trace_api/get_block', { block_num }); + } + /** Raw call to `/v1/history/get_actions` */ public async history_get_actions(accountName: string, pos: number = null, offset: number = null): Promise { return await this.fetch('/v1/history/get_actions', { account_name: accountName, pos, offset }); diff --git a/src/eosjs-rpc-interfaces.ts b/src/eosjs-rpc-interfaces.ts index 5400e030f..22ea64e78 100644 --- a/src/eosjs-rpc-interfaces.ts +++ b/src/eosjs-rpc-interfaces.ts @@ -4,6 +4,7 @@ */ import { TransactionReceiptHeader, Transaction } from './eosjs-api-interfaces'; +import { Authorization } from './eosjs-serialize'; /** Structured format for abis */ export interface Abi { @@ -120,6 +121,16 @@ export interface WaitWeight { weight: number; } +/** Return value of `/v1/chain/abi_bin_to_json` */ +export interface AbiBinToJsonResult { + args: 'any' +} + +/** Return value of `/v1/chain/abi_json_to_bin` */ +export interface AbiJsonToBinResult { + binargs: 'string' +} + /** Return value of `/v1/chain/get_abi` */ export interface GetAbiResult { account_name: string; @@ -149,6 +160,44 @@ export interface GetAccountResult { rex_info: any; } +export interface AccountResult { + account_name: string; + permission_name: string; + authorizing_account?: Authorization; + authorizing_key?: string; + weight: number; + threshold: number; +} + +/** Return value of `/v1/chain/get_accounts_by_authorizers` */ +export interface GetAccountsByAuthorizersResult { + accounts: AccountResult[]; +} + +export interface GetActivatedProtocolFeaturesParams { + limit?: number; + search_by_block_num?: boolean; + reverse?: boolean; + lower_bound?: number; + upper_bound?: number; +} + +export interface ActivatedProtocolFeature { + feature_digest: string; + activation_ordinal: number; + activation_block_num: number; + description_digest: string; + dependencies: string[]; + protocol_feature_type: string; + specification: { name: string, value: string, }; +} + +/** Return value of `/v1/chain/get_activated_protocol_features` */ +export interface GetActivatedProtocolFeaturesResult { + activated_protocol_features: ActivatedProtocolFeature[]; + more?: number; +} + /** Return value of `/v1/chain/get_block_info` */ export interface GetBlockInfoResult { timestamp: string; @@ -175,6 +224,13 @@ export interface PackedTransaction { transaction: Transaction; } +export interface PackedTrx { + signatures: string[]; + compression: number; + packed_trx: string; + packed_context_free_data: string; +} + export interface TransactionReceipt extends TransactionReceiptHeader { trx: PackedTransaction; } @@ -279,6 +335,12 @@ export interface GetCodeResult { abi?: Abi; } +/** Return value of `/v1/chain/get_code_hash` */ +export interface GetCodeHashResult { + account_name: string; + code_hash: string; +} + /** Return value of `/v1/chain/get_currency_stats` */ export interface GetCurrencyStatsResult { [key: string]: { @@ -406,11 +468,6 @@ export interface PushTransactionArgs { serializedContextFreeData?: Uint8Array; } -/** Return value of `/v1/chain/push_transaction` */ -export interface PushTransactionResult { - -} - export interface DBSizeIndexCount { index: string; row_count: number; @@ -424,6 +481,49 @@ export interface DBSizeGetResult { indices: DBSizeIndexCount[]; } +export interface TraceApiAction { + global_sequence: number; + receiver: string; + account: string; + action: string; + authorization: Authorization[]; + data: any; + return_value: any; +} + +export interface TraceApiTransactionHeader { + expiration: string; + ref_block_num: number; + ref_block_prefix: number; + max_net_usage_words: number; + max_cpu_usage_ms: number; + delay_sec: number; +} + +export interface TraceApiTransaction { + id: string; + actions: TraceApiAction[]; + status?: string; + cpu_usage_us?: number; + net_usage_words?: number; + signatures?: string[]; + transaction_header?: TraceApiTransactionHeader +} + +/** Return value of `/v1/trace_api/get_block` */ +export interface TraceApiGetBlockResult { + id: string; + number: number; + previous_id: string; + status: string; + timestamp: string; + producer: string; + transaction_mroot?: string; + action_mroot?: string; + schedule_version: number; + transactions: TraceApiTransaction; +} + export interface OrderedActionResult { global_action_seq: number; account_action_seq: number; diff --git a/src/tests/eosjs-type-checks.test.ts b/src/tests/eosjs-type-checks.test.ts index 2ddc76d85..6df878f6a 100644 --- a/src/tests/eosjs-type-checks.test.ts +++ b/src/tests/eosjs-type-checks.test.ts @@ -6,12 +6,16 @@ import * as ser from '../eosjs-serialize'; import fetch from 'node-fetch'; const { TextEncoder, TextDecoder } = require('util'); import { + AbiJsonToBinResult, GetAbiResult, GetAccountResult, + GetAccountsByAuthorizersResult, + GetActivatedProtocolFeaturesResult, GetBlockHeaderStateResult, GetBlockInfoResult, GetBlockResult, GetCodeResult, + GetCodeHashResult, GetCurrencyStatsResult, GetInfoResult, GetProducerScheduleResult, @@ -22,6 +26,9 @@ import { GetTableRowsResult, GetTableByScopeResult, PushTransactionArgs, + AbiBinToJsonResult, + TraceApiGetBlockResult, + DBSizeGetResult, } from '../eosjs-rpc-interfaces'; import { TransactResult } from '../eosjs-api-interfaces'; import 'jest-extended'; @@ -43,7 +50,23 @@ const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), te * |: operates the same as typescript but does not work for complex types */ -describe('Chain Plugin Endpoints', () => { +describe('Chain API Plugin Endpoints', () => { + it('validates return type of abi_bin_to_json', async () => { + const result: AbiBinToJsonResult = await rpc.abi_bin_to_json('returnvalue', 'sum', '0500000005000000'); + const abiBinToJsonResult: any = { + args: 'any' + }; + verifyType(result, abiBinToJsonResult); + }); + + it('validates return type of abi_json_to_bin', async () => { + const result: AbiJsonToBinResult = await rpc.abi_json_to_bin('returnvalue', 'sum', [5, 5]); + const abiJsonToBinResult: any = { + binargs: 'string' + }; + verifyType(result, abiJsonToBinResult); + }); + it('validates return type of get_abi', async () => { const result: GetAbiResult = await rpc.get_abi('todo'); const getAbiResult: any = { @@ -205,6 +228,47 @@ describe('Chain Plugin Endpoints', () => { verifyType(result, getAccountResult); }); + it('validates return type of get_accounts_by_authorizers', async () => { + const result: GetAccountsByAuthorizersResult = await rpc.get_accounts_by_authorizers([ + { actor: 'bob', permission: 'active' }, + { actor: 'cfhello', permission: 'active' } + ], ['EOS7bxrQUTbQ4mqcoefhWPz1aFieN4fA9RQAiozRz7FrUChHZ7Rb8', 'EOS6nVrBASwwviMy3CntKsb1cD5Ai2gRZnyrxJDqypL3JLL7KCKrK']); + const getAccountsByAuthorizersResult: any = { + accounts: { + account_name: 'string', + permission_name: 'string', + 'authorizing_key?': 'string', + 'authorizing_account?': { + actor: 'string', + permission: 'string', + }, + weight: 'number', + threshold: 'number', + } + }; + verifyType(result, getAccountsByAuthorizersResult); + }); + + it('validates return type of get_activated_protocol_features', async () => { + const result: GetActivatedProtocolFeaturesResult = await rpc.get_activated_protocol_features({}); + const getActivatedProtocolFeaturesResult: any = { + activated_protocol_features: { + feature_digest: 'string', + activation_ordinal: 'number', + activation_block_num: 'number', + description_digest: 'string', + dependencies: 'string', + protocol_feature_type: 'string', + specification: { + name: 'string', + value: 'string', + }, + }, + 'more?': 'number', + }; + verifyType(result, getActivatedProtocolFeaturesResult); + }); + it('validates return type of get_block_header_state', async () => { const info: GetInfoResult = await rpc.get_info(); const result: GetBlockHeaderStateResult = await rpc.get_block_header_state(info.head_block_id); @@ -441,6 +505,15 @@ describe('Chain Plugin Endpoints', () => { verifyType(result, getCodeResult); }); + it('validates return type of get_code_hash', async () => { + const result: GetCodeHashResult = await rpc.get_code_hash('todo'); + const getCodeHashResult: any = { + account_name: 'string', + code_hash: 'string', + }; + verifyType(result, getCodeHashResult); + }); + it('validates return type of get_currency_balance', async () => { const result: string[] = await rpc.get_currency_balance('eosio.token', 'bob', 'SYS'); result.forEach((element: any) => { @@ -654,7 +727,6 @@ describe('Chain Plugin Endpoints', () => { table: 'todo', index_name: 'map.index', encode_type: 'string', - lower_bound: 'ac8acfe7-cd4e-4d22-8400-218b697a4517', }); const getTableRowsResult: any = { rows: 'any', @@ -714,7 +786,7 @@ describe('Chain Plugin Endpoints', () => { }); }); - it('validates return of push_transaction', async () => { + it('validates return type of push_transaction', async () => { const transaction: PushTransactionArgs = await api.transact({ actions: [{ account: 'eosio.token', @@ -809,7 +881,125 @@ describe('Chain Plugin Endpoints', () => { verifyType(result, transactResult); }); - it('validates return of send_transaction', async () => { + it('validates return type of push_transactions', async () => { + const transactionA: PushTransactionArgs = await api.transact({ + actions: [{ + account: 'eosio.token', + name: 'transfer', + authorization: [{ + actor: 'bob', + permission: 'active', + }], + data: { + from: 'bob', + to: 'alice', + quantity: '0.0001 SYS', + memo: 'A', + }, + }], + }, { + sign: true, + broadcast: false, + useLastIrreversible: true, + expireSeconds: 30, + }) as PushTransactionArgs; + const transactionB: PushTransactionArgs = await api.transact({ + actions: [{ + account: 'eosio.token', + name: 'transfer', + authorization: [{ + actor: 'bob', + permission: 'active', + }], + data: { + from: 'bob', + to: 'alice', + quantity: '0.0001 SYS', + memo: 'B', + }, + }], + }, { + sign: true, + broadcast: false, + useLastIrreversible: true, + expireSeconds: 30, + }) as PushTransactionArgs; + const result: TransactResult[] = await rpc.push_transactions([ transactionA, transactionB ]); + const transactResult = { + transaction_id: 'string', + processed: { + id: 'string', + block_num: 'number', + block_time: 'string', + 'producer_block_id&': 'string', + 'receipt&': { + status: 'string', + cpu_usage_us: 'number', + net_usage_words: 'number', + }, + elapsed: 'number', + net_usage: 'number', + scheduled: 'boolean', + action_traces: { + action_ordinal: 'number', + creator_action_ordinal: 'number', + closest_unnotified_ancestor_action_ordinal: 'number', + receipt: { + receiver: 'string', + act_digest: 'string', + global_sequence: 'number', + recv_sequence: 'number', + auth_sequence: [ 'string', 'number' ], + code_sequence: 'number', + abi_sequence: 'number', + }, + receiver: 'string', + act: { + account: 'string', + name: 'string', + authorization: { + actor: 'string', + permission: 'string', + }, + data: 'any', + 'hex_data?': 'string', + }, + context_free: 'boolean', + elapsed: 'number', + console: 'string', + trx_id: 'string', + block_num: 'number', + block_time: 'string', + 'producer_block_id&': 'string', + account_ram_deltas: { + account: 'string', + delta: 'number', + }, + account_disk_deltas: { + account: 'string', + delta: 'number', + }, + except: 'any', + 'error_code&': 'number', + 'return_value?': 'any', + 'return_value_hex_data?': 'string', + 'return_value_data?': 'any', + 'inline_traces?': 'any', // ActionTrace, recursive? + }, + 'account_ram_delta&': { + account: 'string', + delta: 'number', + }, + 'except&': 'string', + 'error_code&': 'number', + }, + }; + result.forEach((transaction: TransactResult) => { + verifyType(transaction, transactResult); + }); + }); + + it('validates return type of send_transaction', async () => { const transaction: PushTransactionArgs = await api.transact({ actions: [{ account: 'eosio.token', @@ -905,6 +1095,62 @@ describe('Chain Plugin Endpoints', () => { }); }); +describe('DB Size API Plugin Endpoints', () => { + it('validates return type of get', async () => { + const result: DBSizeGetResult = await rpc.db_size_get(); + const dbSizeGetResult: any = { + free_bytes: 'number', + used_bytes: 'number', + size: 'number', + indices: { + index: 'string', + row_count: 'number', + }, + }; + verifyType(result, dbSizeGetResult); + }); +}); + +describe('Trace API Plugin Endpoints', () => { + it('validates return type of get_block', async () => { + const info: GetInfoResult = await rpc.get_info(); + const result: any = await rpc.trace_get_block(info.last_irreversible_block_num); + const traceApiGetBlockResult: any = { + id: 'string', + number: 'number', + previous_id: 'string', + status: 'string', + timestamp: 'string', + producer: 'string', + transaction_mroot: 'string', + action_mroot: 'string', + schedule_version: 'number', + transactions: { + id: 'string', + actions: { + global_sequence: 'number', + receiver: 'string', + account: 'string', + action: 'string', + authorization: { + account: 'string', + permission: 'string' + }, + data: 'string', + return_value: 'string', + }, + status: 'string', + cpu_usage_us: 'number', + net_usage_words: 'number', + signatures: 'string', + transaction_header: 'any' + }, + }; + verifyType(result, traceApiGetBlockResult); + }); +}); + + const verifyType = (data: any, type: any): void => { const verifiedKeys: string[] = Object.keys(type).filter((key: string) => { const formattedKey = key.replace('?', '').replace('&', ''); From d4ff75ce77014908c03a3c751d163bcfb09c4d4c Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Tue, 9 Feb 2021 14:53:36 -0500 Subject: [PATCH 11/15] Adding changes to ci/cd and fixing a test --- .github/eosjs-ci/Dockerfile | 2 +- .github/eosjs-ci/scripts/deploy_contracts.sh | 3 +++ src/tests/eosjs-jsonrpc.test.ts | 6 ------ 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/eosjs-ci/Dockerfile b/.github/eosjs-ci/Dockerfile index 8aca16527..edfaf9105 100644 --- a/.github/eosjs-ci/Dockerfile +++ b/.github/eosjs-ci/Dockerfile @@ -7,7 +7,7 @@ #### docker push eosio/eosjs-ci:v0.2.9 FROM ubuntu:18.04 -ENTRYPOINT ["nodeos", "--data-dir", "/root/.local/share", "-e", "-p", "eosio", "--replay-blockchain", "--plugin", "eosio::producer_plugin", "--plugin", "eosio::chain_api_plugin", "--plugin", "eosio::http_plugin", "--http-server-address=0.0.0.0:8888", "--access-control-allow-origin=*", "--contracts-console", "--http-validate-host=false", "--verbose-http-errors", "--max-transaction-time=100"] +ENTRYPOINT ["nodeos", "--data-dir", "/root/.local/share", "-e", "-p", "eosio", "--replay-blockchain", "--plugin", "eosio::producer_plugin", "--plugin", "eosio::chain_api_plugin", "--plugin eosio::trace_api_plugin", "--trace-no-abis", "--plugin", "eosio::db_size_api_plugin", "--plugin", "eosio::http_plugin", "--http-server-address=0.0.0.0:8888", "--access-control-allow-origin=*", "--contracts-console", "--http-validate-host=false", "--enable-account-queries=true", "--verbose-http-errors", "--max-transaction-time=100"] ### base RUN yes | unminimize \ diff --git a/.github/eosjs-ci/scripts/deploy_contracts.sh b/.github/eosjs-ci/scripts/deploy_contracts.sh index 3f620b106..cbc90c9fe 100644 --- a/.github/eosjs-ci/scripts/deploy_contracts.sh +++ b/.github/eosjs-ci/scripts/deploy_contracts.sh @@ -117,6 +117,9 @@ if [ -z "$NODEOS_RUNNING" ]; then --http-validate-host=false \ --plugin eosio::producer_api_plugin \ --plugin eosio::chain_api_plugin \ + --plugin eosio::trace_api_plugin \ + --trace-no-abis \ + --plugin eosio::db_size_api_plugin \ --plugin eosio::http_plugin \ --http-server-address=0.0.0.0:8888 \ --access-control-allow-origin=* \ diff --git a/src/tests/eosjs-jsonrpc.test.ts b/src/tests/eosjs-jsonrpc.test.ts index 3b02645e7..53e315350 100644 --- a/src/tests/eosjs-jsonrpc.test.ts +++ b/src/tests/eosjs-jsonrpc.test.ts @@ -517,9 +517,6 @@ describe('JSON RPC', () => { const table = 'coffee'; const indexName = 'type'; const encodeType = 'bytes'; - const indexValue = ''; - const lowerBound = ''; - const upperBound = ''; const limit = 10; const reverse = false; const showPayer = false; @@ -536,9 +533,6 @@ describe('JSON RPC', () => { table, index_name: indexName, encode_type: encodeType, - index_value: indexValue, - lower_bound: lowerBound, - upper_bound: upperBound, limit, reverse, show_payer: showPayer, From dddf01c5b299528652dad4fa9a6768695672373d Mon Sep 17 00:00:00 2001 From: Bradley Hart Date: Fri, 12 Feb 2021 17:07:37 -0500 Subject: [PATCH 12/15] Cherry pick into additional_types_endpoints --- .github/eosjs-ci/scripts/deploy_contracts.sh | 58 +++++++++----------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/.github/eosjs-ci/scripts/deploy_contracts.sh b/.github/eosjs-ci/scripts/deploy_contracts.sh index cbc90c9fe..00f990f6c 100644 --- a/.github/eosjs-ci/scripts/deploy_contracts.sh +++ b/.github/eosjs-ci/scripts/deploy_contracts.sh @@ -178,21 +178,21 @@ setabi eosio $CONTRACTS_DIR/eosio.boot/eosio.boot.abi setcode eosio $CONTRACTS_DIR/eosio.boot/eosio.boot.wasm sleep 1s -cleos push action eosio activate '["299dcb6af692324b899b39f16d5a530a33062804e41f09dc97e9f156b4476707"]' -p eosio@active -cleos push action eosio activate '["825ee6288fb1373eab1b5187ec2f04f6eacb39cb3a97f356a07c91622dd61d16"]' -p eosio@active -cleos push action eosio activate '["c3a6138c5061cf291310887c0b5c71fcaffeab90d5deb50d3b9e687cead45071"]' -p eosio@active -cleos push action eosio activate '["4e7bf348da00a945489b2a681749eb56f5de00b900014e137ddae39f48f69d67"]' -p eosio@active -cleos push action eosio activate '["f0af56d2c5a48d60a4a5b5c903edfb7db3a736a94ed589d0b797df33ff9d3e1d"]' -p eosio@active -cleos push action eosio activate '["2652f5f96006294109b3dd0bbde63693f55324af452b799ee137a81a905eed25"]' -p eosio@active -cleos push action eosio activate '["8ba52fe7a3956c5cd3a656a3174b931d3bb2abb45578befc59f283ecd816a405"]' -p eosio@active -cleos push action eosio activate '["ad9e3d8f650687709fd68f4b90b41f7d825a365b02c23a636cef88ac2ac00c43"]' -p eosio@active -cleos push action eosio activate '["68dcaa34c0517d19666e6b33add67351d8c5f69e999ca1e37931bc410a297428"]' -p eosio@active -cleos push action eosio activate '["e0fb64b1085cc5538970158d05a009c24e276fb94e1a0bf6a528b48fbc4ff526"]' -p eosio@active -cleos push action eosio activate '["ef43112c6543b88db2283a2e077278c315ae2c84719a8b25f25cc88565fbea99"]' -p eosio@active -cleos push action eosio activate '["4a90c00d55454dc5b059055ca213579c6ea856967712a56017487886a4d4cc0f"]' -p eosio@active -cleos push action eosio activate '["1a99a59d87e06e09ec5b028a9cbb7749b4a5ad8819004365d02dc4379a8b7241"]' -p eosio@active -cleos push action eosio activate '["bf61537fd21c61a60e542a5d66c3f6a78da0589336868307f94a82bccea84e88"]' -p eosio@active -cleos push action eosio activate '["5443fcf88330c586bc0e5f3dee10e7f63c76c00249c87fe4fbf7f38c082006b4"]' -p eosio@active +activate_feature "299dcb6af692324b899b39f16d5a530a33062804e41f09dc97e9f156b4476707" +activate_feature "825ee6288fb1373eab1b5187ec2f04f6eacb39cb3a97f356a07c91622dd61d16" +activate_feature "c3a6138c5061cf291310887c0b5c71fcaffeab90d5deb50d3b9e687cead45071" +activate_feature "4e7bf348da00a945489b2a681749eb56f5de00b900014e137ddae39f48f69d67" +activate_feature "f0af56d2c5a48d60a4a5b5c903edfb7db3a736a94ed589d0b797df33ff9d3e1d" +activate_feature "2652f5f96006294109b3dd0bbde63693f55324af452b799ee137a81a905eed25" +activate_feature "8ba52fe7a3956c5cd3a656a3174b931d3bb2abb45578befc59f283ecd816a405" +activate_feature "ad9e3d8f650687709fd68f4b90b41f7d825a365b02c23a636cef88ac2ac00c43" +activate_feature "68dcaa34c0517d19666e6b33add67351d8c5f69e999ca1e37931bc410a297428" +activate_feature "e0fb64b1085cc5538970158d05a009c24e276fb94e1a0bf6a528b48fbc4ff526" +activate_feature "ef43112c6543b88db2283a2e077278c315ae2c84719a8b25f25cc88565fbea99" +activate_feature "4a90c00d55454dc5b059055ca213579c6ea856967712a56017487886a4d4cc0f" +activate_feature "1a99a59d87e06e09ec5b028a9cbb7749b4a5ad8819004365d02dc4379a8b7241" +activate_feature "bf61537fd21c61a60e542a5d66c3f6a78da0589336868307f94a82bccea84e88" +activate_feature "5443fcf88330c586bc0e5f3dee10e7f63c76c00249c87fe4fbf7f38c082006b4" sleep 1s setabi eosio $CONTRACTS_DIR/eosio.bios/eosio.bios.abi @@ -203,32 +203,28 @@ cleos push action eosio setkvparams '[{"max_key_size":1024, "max_value_size":409 cleos push action eosio setpparams '["01110000400100000000"]' -p eosio@active sleep 1s -setabi eosio $CONTRACTS_DIR/eosio.bios/eosio.bios.abi -setcode eosio $CONTRACTS_DIR/eosio.bios/eosio.bios.wasm -cleos set abi eosio $CONTRACTS_DIR/eosio.system/eosio.system.abi -p eosio@active -cleos set code eosio $CONTRACTS_DIR/eosio.system/eosio.system.wasm -p eosio@active +setabi eosio $CONTRACTS_DIR/eosio.system/eosio.system.abi +setcode eosio $CONTRACTS_DIR/eosio.system/eosio.system.wasm sleep 1s -cleos push action eosio setkvparams '[{"max_key_size":1024, "max_value_size":4096, "max_iterators":1024}]' -p eosio@active -cleos push action eosio setpparams '["01110000400100000000"]' -p eosio@active -cleos set abi eosio.msig $CONTRACTS_DIR/eosio.msig/eosio.msig.abi -p eosio.msig@active -cleos set code eosio.msig $CONTRACTS_DIR/eosio.msig/eosio.msig.wasm -p eosio.msig@active +setabi eosio.msig $CONTRACTS_DIR/eosio.msig/eosio.msig.abi +setcode eosio.msig $CONTRACTS_DIR/eosio.msig/eosio.msig.wasm sleep 1s -cleos set abi cfhello $CONTRACTS_DIR/cfhello/cfhello.abi -p cfhello@active -p eosio@active -cleos set code cfhello $CONTRACTS_DIR/cfhello/cfhello.wasm -p cfhello@active -p eosio@active +setabi cfhello $CONTRACTS_DIR/cfhello/cfhello.abi +setcode cfhello $CONTRACTS_DIR/cfhello/cfhello.wasm sleep 1s -setabi eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.abi -setcode eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.wasm +setabi todo $CONTRACTS_DIR/kv_todo/kv_todo.abi +setcode todo $CONTRACTS_DIR/kv_todo/kv_todo.wasm sleep 1s -cleos set abi returnvalue $CONTRACTS_DIR/action_return_value/action_return_value.abi -p returnvalue@active -cleos set code returnvalue $CONTRACTS_DIR/action_return_value/action_return_value.wasm -p returnvalue@active +setabi returnvalue $CONTRACTS_DIR/action_return_value/action_return_value.abi +setcode returnvalue $CONTRACTS_DIR/action_return_value/action_return_value.wasm sleep 1s -cleos set abi eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.abi -p eosio.token@active -p eosio@active -cleos set code eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.wasm -p eosio.token@active -p eosio@active +setabi eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.abi +setcode eosio.token $CONTRACTS_DIR/eosio.token/eosio.token.wasm sleep 1s cleos push action eosio.token create '["bob", "10000000000.0000 SYS"]' -p eosio.token From 8a609368bdc32363c9c45947a92f98870e006827 Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Tue, 9 Feb 2021 16:59:33 -0500 Subject: [PATCH 13/15] Adjusting entrypoint for dockerfile --- .github/eosjs-ci/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/eosjs-ci/Dockerfile b/.github/eosjs-ci/Dockerfile index edfaf9105..33229e1b3 100644 --- a/.github/eosjs-ci/Dockerfile +++ b/.github/eosjs-ci/Dockerfile @@ -7,7 +7,7 @@ #### docker push eosio/eosjs-ci:v0.2.9 FROM ubuntu:18.04 -ENTRYPOINT ["nodeos", "--data-dir", "/root/.local/share", "-e", "-p", "eosio", "--replay-blockchain", "--plugin", "eosio::producer_plugin", "--plugin", "eosio::chain_api_plugin", "--plugin eosio::trace_api_plugin", "--trace-no-abis", "--plugin", "eosio::db_size_api_plugin", "--plugin", "eosio::http_plugin", "--http-server-address=0.0.0.0:8888", "--access-control-allow-origin=*", "--contracts-console", "--http-validate-host=false", "--enable-account-queries=true", "--verbose-http-errors", "--max-transaction-time=100"] +ENTRYPOINT ["nodeos", "--data-dir", "/root/.local/share", "-e", "-p", "eosio", "--replay-blockchain", "--plugin", "eosio::producer_plugin", "--plugin", "eosio::chain_api_plugin", "--plugin", "eosio::trace_api_plugin", "--trace-no-abis", "--plugin", "eosio::db_size_api_plugin", "--plugin", "eosio::http_plugin", "--http-server-address=0.0.0.0:8888", "--access-control-allow-origin=*", "--contracts-console", "--http-validate-host=false", "--enable-account-queries=true", "--verbose-http-errors", "--max-transaction-time=100"] ### base RUN yes | unminimize \ From 882a4cda3f7decce595309534903b4d81602a7cf Mon Sep 17 00:00:00 2001 From: Brad Hart Date: Tue, 9 Feb 2021 17:24:14 -0500 Subject: [PATCH 14/15] Adjusting so yarn test can continue to not need a running nodeos process --- package.json | 2 +- src/tests/{eosjs-type-checks.test.ts => type-checks.test.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/tests/{eosjs-type-checks.test.ts => type-checks.test.ts} (100%) diff --git a/package.json b/package.json index f71f6af19..6f538cdbe 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "eslint --ext .js,.jsx,.ts,.tsx src", "test": "jest src/tests/*eosjs*", "test-node": "jest src/tests/*node*", - "test-types": "jest src/tests/eosjs-type-checks.test.ts", + "test-types": "jest src/tests/type-checks.test.ts", "test-all": "yarn test && yarn test-node && yarn test-types && yarn cypress", "build": "rimraf dist && tsc -p ./tsconfig.json && node scripts/copy-ripe-md.js", "build-web": "webpack --config webpack.prod.js && webpack --config webpack.debug.js", diff --git a/src/tests/eosjs-type-checks.test.ts b/src/tests/type-checks.test.ts similarity index 100% rename from src/tests/eosjs-type-checks.test.ts rename to src/tests/type-checks.test.ts From 167d35e777c520a3027aa147ff11fbf5c839cf1a Mon Sep 17 00:00:00 2001 From: "Block.one DevOps" Date: Fri, 12 Feb 2021 22:17:21 +0000 Subject: [PATCH 15/15] Updating package.json and yarn.lock --- package.json | 8 +++++--- yarn.lock | 42 +++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 6f538cdbe..6fb655e6c 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "@blockone/eslint-config-blockone": "^3.0.0", "@types/elliptic": "^6.4.12", "@types/jest": "^26.0.20", - "@types/node": "^14.14.25", - "@types/node-fetch": "^2.5.7", + "@types/node": "^14.14.27", + "@types/node-fetch": "^2.5.8", "@types/pako": "^1.0.1", "clean-webpack-plugin": "^3.0.0", "cypress": "^6.4.0", @@ -58,7 +58,9 @@ "setupFiles": [ "./src/tests/setupJest.js" ], - "setupFilesAfterEnv": ["jest-extended"], + "setupFilesAfterEnv": [ + "jest-extended" + ], "moduleFileExtensions": [ "ts", "tsx", diff --git a/yarn.lock b/yarn.lock index 388f813c1..1a4065934 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,15 +10,15 @@ "@babel/highlight" "^7.12.13" "@babel/core@^7.1.0", "@babel/core@^7.7.5": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.13.tgz#b73a87a3a3e7d142a66248bf6ad88b9ceb093425" - integrity sha512-BQKE9kXkPlXHPeqissfxo0lySWJcYdEP0hdtJOH/iJfDdhOCcgtNCjftCJg3qqauB4h+lz2N6ixM++b9DN1Tcw== + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.16.tgz#8c6ba456b23b680a6493ddcfcd9d3c3ad51cab7c" + integrity sha512-t/hHIB504wWceOeaOoONOhu+gX+hpjfeN6YRBT209X/4sibZQfSF1I0HFRRlBe97UZZosGx5XwUg1ZgNbelmNw== dependencies: "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.12.13" + "@babel/generator" "^7.12.15" "@babel/helper-module-transforms" "^7.12.13" "@babel/helpers" "^7.12.13" - "@babel/parser" "^7.12.13" + "@babel/parser" "^7.12.16" "@babel/template" "^7.12.13" "@babel/traverse" "^7.12.13" "@babel/types" "^7.12.13" @@ -30,7 +30,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.12.13": +"@babel/generator@^7.12.13", "@babel/generator@^7.12.15": version "7.12.15" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" integrity sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ== @@ -56,9 +56,9 @@ "@babel/types" "^7.12.13" "@babel/helper-member-expression-to-functions@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.13.tgz#c5715695b4f8bab32660dbdcdc2341dec7e3df40" - integrity sha512-B+7nN0gIL8FZ8SvMcF+EPyB21KnCcZHQZFczCxbiNGV/O0rsrSBlWGLzmtBJ3GMjSVMIm4lpFhR+VdVBuIsUcQ== + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.16.tgz#41e0916b99f8d5f43da4f05d85f4930fa3d62b22" + integrity sha512-zYoZC1uvebBFmj1wFAlXwt35JLEgecefATtKp20xalwEK8vHAixLBXTGxNrVGEmTT+gzOThUgr8UEdgtalc1BQ== dependencies: "@babel/types" "^7.12.13" @@ -143,10 +143,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.7.0": - version "7.12.15" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.15.tgz#2b20de7f0b4b332d9b119dd9c33409c538b8aacf" - integrity sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.16", "@babel/parser@^7.7.0": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4" + integrity sha512-c/+u9cqV6F0+4Hpq01jnJO+GLp2DdT63ppz9Xa+6cHaajM9VFzK/iDXiKK65YtpeVwu+ctfS6iqlMqRgQRzeCw== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -651,9 +651,9 @@ "@types/node" "*" "@types/graceful-fs@^4.1.2": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.4.tgz#4ff9f641a7c6d1a3508ff88bc3141b152772e753" - integrity sha512-mWA/4zFQhfvOA8zWkXobwJvBD7vzcxgrOQ0J5CH1votGqdq9m7+FwtGaqyCZqC3NyyBkc9z4m+iry4LlqcMWJg== + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== dependencies: "@types/node" "*" @@ -702,7 +702,7 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/node-fetch@^2.5.7": +"@types/node-fetch@^2.5.8": version "2.5.8" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== @@ -710,10 +710,10 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@^14.14.25": - version "14.14.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.25.tgz#15967a7b577ff81383f9b888aa6705d43fbbae93" - integrity sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ== +"@types/node@*", "@types/node@^14.14.27": + version "14.14.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.27.tgz#c7127f8da0498993e13b1a42faf1303d3110d2f2" + integrity sha512-Ecfmo4YDQPwuqTCl1yBxLV5ihKfRlkBmzUEDcfIRvDxOTGQEeikr317Ln7Gcv0tjA8dVgKI3rniqW2G1OyKDng== "@types/normalize-package-data@^2.4.0": version "2.4.0"