From 719dda5f33a2bed353bd1bf311a2baf3110d1654 Mon Sep 17 00:00:00 2001 From: Janek Rahrt Date: Fri, 1 Apr 2022 12:48:35 +0200 Subject: [PATCH] feat: default estimateFee to pending block --- src/account/default.ts | 30 +++++++++++++++++++++--------- src/contract/default.ts | 38 ++++++++++++++++++++------------------ src/provider/default.ts | 1 - src/provider/utils.ts | 15 +++++++-------- src/types/api.ts | 4 +++- 5 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/account/default.ts b/src/account/default.ts index 0269e3892..f901e3fd3 100644 --- a/src/account/default.ts +++ b/src/account/default.ts @@ -1,6 +1,7 @@ import assert from 'minimalistic-assert'; import { Provider } from '../provider'; +import { BlockIdentifier } from '../provider/utils'; import { Signer, SignerInterface } from '../signer'; import { Abi, @@ -46,9 +47,15 @@ export class Account extends Provider implements AccountInterface { return toHex(toBN(result[0])); } - public async estimateFee(calls: Call | Call[]): Promise { + public async estimateFee( + calls: Call | Call[], + { + nonce: providedNonce, + blockIdentifier = 'pending', + }: { nonce?: BigNumberish; blockIdentifier?: BlockIdentifier } = {} + ): Promise { const transactions = Array.isArray(calls) ? calls : [calls]; - const nonce = await this.getNonce(); + const nonce = providedNonce ?? (await this.getNonce()); const signerDetails = { walletAddress: this.address, nonce: toBN(nonce), @@ -57,12 +64,16 @@ export class Account extends Provider implements AccountInterface { const signature = await this.signer.signTransaction(transactions, signerDetails); const calldata = [...fromCallsToExecuteCalldata(transactions), signerDetails.nonce.toString()]; - return this.fetchEndpoint('estimate_fee', undefined, { - contract_address: this.address, - entry_point_selector: getSelectorFromName('__execute__'), - calldata, - signature: bigNumberishArrayToDecimalStringArray(signature), - }); + return this.fetchEndpoint( + 'estimate_fee', + { blockIdentifier }, + { + contract_address: this.address, + entry_point_selector: getSelectorFromName('__execute__'), + calldata, + signature: bigNumberishArrayToDecimalStringArray(signature), + } + ); } /** @@ -80,7 +91,8 @@ export class Account extends Provider implements AccountInterface { ): Promise { const transactions = Array.isArray(calls) ? calls : [calls]; const nonce = toBN(transactionsDetail.nonce ?? (await this.getNonce())); - const maxFee = transactionsDetail.maxFee ?? (await this.estimateFee(transactions)).amount; + const maxFee = + transactionsDetail.maxFee ?? (await this.estimateFee(transactions, { nonce })).amount; const signerDetails = { walletAddress: this.address, nonce, diff --git a/src/contract/default.ts b/src/contract/default.ts index 489555ae6..613bae715 100644 --- a/src/contract/default.ts +++ b/src/contract/default.ts @@ -3,6 +3,7 @@ import assert from 'minimalistic-assert'; import { AccountInterface } from '../account'; import { ProviderInterface, defaultProvider } from '../provider'; +import { BlockIdentifier } from '../provider/utils'; import { Abi, AbiEntry, @@ -528,7 +529,11 @@ export class Contract implements ContractInterface { }, [] as Result); } - public invoke(method: string, args: Array = []): Promise { + public invoke( + method: string, + args: Array = [], + options: Overrides = {} + ): Promise { // ensure contract is connected assert(this.address !== null, 'contract isnt connected to an address'); // validate method and args @@ -542,11 +547,6 @@ export class Contract implements ContractInterface { return acc; }, 0); - const overrides: Overrides = {}; - if (args.length === inputsLength + 1 && Array.isArray(args[args.length - 1])) { - Object.assign(overrides, args.pop()); - } - if (args.length !== inputsLength) { throw Error( `Invalid number of arguments, expected ${inputsLength} arguments, but got ${args.length}` @@ -562,31 +562,33 @@ export class Contract implements ContractInterface { }; if ('execute' in this.providerOrAccount) { return this.providerOrAccount.execute(invocation, undefined, { - maxFee: overrides.maxFee, - nonce: overrides.nonce, + maxFee: options.maxFee, + nonce: options.nonce, }); } return this.providerOrAccount.invokeFunction({ ...invocation, - signature: overrides.signature || [], + signature: options.signature || [], }); } - public async call(method: string, args: Array = []): Promise { + public async call( + method: string, + args: Array = [], + { + blockIdentifier = 'pending', + }: { + blockIdentifier?: BlockIdentifier; + } = {} + ): Promise { // ensure contract is connected assert(this.address !== null, 'contract isnt connected to an address'); // validate method and args this.validateMethodAndArgs('CALL', method, args); const { inputs } = this.abi.find((abi) => abi.name === method) as FunctionAbi; - const inputsLength = inputs.length; - const options = { - blockIdentifier: null, - }; - if (args.length === inputsLength + 1 && typeof args[args.length - 1] === 'object') { - Object.assign(options, args.pop()); - } + // compile calldata const calldata = this.compileCalldata(args, inputs); return this.providerOrAccount @@ -596,7 +598,7 @@ export class Contract implements ContractInterface { calldata, entrypoint: method, }, - options + { blockIdentifier } ) .then((x) => this.parseResponse(method, x.result)); } diff --git a/src/provider/default.ts b/src/provider/default.ts index 293c17db3..f00cb7dee 100644 --- a/src/provider/default.ts +++ b/src/provider/default.ts @@ -344,7 +344,6 @@ export class Provider implements ProviderInterface { public async waitForTransaction(txHash: BigNumberish, retryInterval: number = 8000) { let onchain = false; - await wait(retryInterval); while (!onchain) { // eslint-disable-next-line no-await-in-loop diff --git a/src/provider/utils.ts b/src/provider/utils.ts index 392ed08b1..103158470 100644 --- a/src/provider/utils.ts +++ b/src/provider/utils.ts @@ -43,6 +43,12 @@ type BlockIdentifierObject = * @returns block identifier object */ export function getBlockIdentifier(blockIdentifier: BlockIdentifier): BlockIdentifierObject { + if (blockIdentifier === null) { + return { type: 'BLOCK_NUMBER', data: null }; + } + if (blockIdentifier === 'pending') { + return { type: 'BLOCK_NUMBER', data: 'pending' }; + } if (typeof blockIdentifier === 'number') { return { type: 'BLOCK_NUMBER', data: blockIdentifier }; } @@ -52,12 +58,6 @@ export function getBlockIdentifier(blockIdentifier: BlockIdentifier): BlockIdent if (typeof blockIdentifier === 'string' && !Number.isNaN(parseInt(blockIdentifier, 10))) { return { type: 'BLOCK_NUMBER', data: parseInt(blockIdentifier, 10) }; } - if (blockIdentifier === null) { - return { type: 'BLOCK_NUMBER', data: null }; - } - if (blockIdentifier === 'pending') { - return { type: 'BLOCK_NUMBER', data: 'pending' }; - } if (typeof blockIdentifier === 'string') { throw new Error(`Invalid block identifier: ${blockIdentifier}`); } @@ -69,8 +69,7 @@ export function getBlockIdentifier(blockIdentifier: BlockIdentifier): BlockIdent * * [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L164-L173) * - * @param blockNumber - * @param blockHash + * @param blockIdentifier * @returns block identifier for API request */ export function getFormattedBlockIdentifier(blockIdentifier: BlockIdentifier = null): string { diff --git a/src/types/api.ts b/src/types/api.ts index 619e32c13..66e627bfc 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -75,7 +75,9 @@ export type Endpoints = { RESPONSE: CallContractResponse; }; estimate_fee: { - QUERY: never; + QUERY: { + blockIdentifier: BlockIdentifier; + }; REQUEST: CallContractTransaction; RESPONSE: EstimateFeeResponse; };