From e942a9d88479d88b82a3dbc05ec2f60ab9ad1f19 Mon Sep 17 00:00:00 2001 From: Antun Badurina Date: Thu, 7 Jul 2022 16:23:59 +0200 Subject: [PATCH] feat: implement new interface on contract class --- src/account/default.ts | 9 ++-- src/account/interface.ts | 26 +++++++++++- src/contract/default.ts | 10 ++--- src/provider/default.ts | 12 +++--- src/provider/gateway.ts | 15 +++---- src/provider/interface.ts | 12 +++--- src/provider/rpc.ts | 22 +++++----- src/types/api/gateway.ts | 88 +++++++++++++++++++-------------------- src/types/provider.ts | 8 +--- 9 files changed, 114 insertions(+), 88 deletions(-) diff --git a/src/account/default.ts b/src/account/default.ts index e20f537b7..e02e22779 100644 --- a/src/account/default.ts +++ b/src/account/default.ts @@ -38,7 +38,7 @@ export class Account extends Provider implements AccountInterface { public async getNonce(): Promise { const { result } = await this.callContract({ contractAddress: this.address, - entryPointSelector: 'get_nonce', + entrypoint: 'get_nonce', calldata: [], }); return toHex(toBN(result[0])); @@ -64,8 +64,9 @@ export class Account extends Provider implements AccountInterface { const calldata = fromCallsToExecuteCalldataWithNonce(transactions, nonce); const fetchedEstimate = await super.getEstimateFee( - { contractAddress: this.address, entryPointSelector: '__execute__', calldata, signature }, - blockIdentifier + { contractAddress: this.address, entrypoint: '__execute__', calldata }, + blockIdentifier, + signature ); const suggestedMaxFee = estimatedFeeToMaxFee(fetchedEstimate.overallFee); @@ -159,7 +160,7 @@ export class Account extends Provider implements AccountInterface { try { await this.callContract({ contractAddress: this.address, - entryPointSelector: 'is_valid_signature', + entrypoint: 'is_valid_signature', calldata: compileCalldata({ hash: toBN(hash).toString(), signature: signature.map((x) => toBN(x).toString()), diff --git a/src/account/interface.ts b/src/account/interface.ts index af82da469..160ac507c 100644 --- a/src/account/interface.ts +++ b/src/account/interface.ts @@ -1,6 +1,14 @@ import { ProviderInterface } from '../provider'; import { SignerInterface } from '../signer'; -import { Abi, Call, InvocationsDetails, InvokeFunctionResponse, Signature } from '../types'; +import { + Abi, + Call, + EstimateFee, + EstimateFeeDetails, + InvocationsDetails, + InvokeFunctionResponse, + Signature, +} from '../types'; import { BigNumberish } from '../utils/number'; import { TypedData } from '../utils/typedData/types'; @@ -9,6 +17,22 @@ export abstract class AccountInterface extends ProviderInterface { public abstract signer: SignerInterface; + /** + * Estimate Fee for a method on starknet + * + * @param invocation the invocation object containing: + * - contractAddress - the address of the contract + * - entrypoint - the entrypoint of the contract + * - calldata - (defaults to []) the calldata + * - signature - (defaults to []) the signature + * + * @returns response from addTransaction + */ + public abstract estimateFee( + calls: Call | Call[], + estimateFeeDetails?: EstimateFeeDetails + ): Promise; + /** * Invoke execute function in account contract * diff --git a/src/contract/default.ts b/src/contract/default.ts index e079e7501..b934a1f7c 100644 --- a/src/contract/default.ts +++ b/src/contract/default.ts @@ -7,13 +7,13 @@ import { BlockIdentifier } from '../provider/utils'; import { Abi, AbiEntry, - AddTransactionResponse, Args, AsyncContractFunction, Calldata, ContractFunction, FunctionAbi, Invocation, + InvokeFunctionResponse, Overrides, ParsedStruct, Result, @@ -97,7 +97,7 @@ export class Contract implements ContractInterface { address: string; - providerOrAccount: ProviderInterface | AccountInterface; + providerOrAccount!: ProviderInterface | AccountInterface; deployTransactionHash?: string; @@ -544,7 +544,7 @@ export class Contract implements ContractInterface { method: string, args: Array = [], options: Overrides = {} - ): Promise { + ): Promise { // ensure contract is connected assert(this.address !== null, 'contract isnt connected to an address'); // validate method and args @@ -578,6 +578,7 @@ export class Contract implements ContractInterface { }); } + // TODO: throw warning return this.providerOrAccount.invokeFunction({ ...invocation, signature: options.signature || [], @@ -609,13 +610,12 @@ export class Contract implements ContractInterface { calldata, entrypoint: method, }, - { blockIdentifier } + blockIdentifier ) .then((x) => this.parseResponse(method, x.result)); } public async estimate(method: string, args: Array = []) { - // TODO; remove error as soon as estimate fees are supported // ensure contract is connected assert(this.address !== null, 'contract isnt connected to an address'); diff --git a/src/provider/default.ts b/src/provider/default.ts index 25248cc1f..f675d08b0 100644 --- a/src/provider/default.ts +++ b/src/provider/default.ts @@ -1,18 +1,19 @@ import { StarknetChainId } from '../constants'; import { + Call, CallContractResponse, DeclareContractPayload, DeclareContractResponse, DeployContractPayload, DeployContractResponse, EstimateFeeResponse, - FunctionCall, GetBlockResponse, GetTransactionReceiptResponse, GetTransactionResponse, Invocation, InvocationsDetails, InvokeFunctionResponse, + Signature, } from '../types'; import { BigNumberish } from '../utils/number'; import { GatewayProvider, GatewayProviderOptions } from './gateway'; @@ -52,10 +53,11 @@ export class Provider implements ProviderInterface { } public async getEstimateFee( - request: FunctionCall, - blockIdentifier: BlockIdentifier + request: Call, + blockIdentifier: BlockIdentifier, + signature?: Signature ): Promise { - return this.provider.getEstimateFee(request, blockIdentifier); + return this.provider.getEstimateFee(request, blockIdentifier, signature); } public async getStorageAt( @@ -75,7 +77,7 @@ export class Provider implements ProviderInterface { } public async callContract( - request: FunctionCall, + request: Call, blockIdentifier: BlockIdentifier = 'pending' ): Promise { return this.provider.callContract(request, blockIdentifier); diff --git a/src/provider/gateway.ts b/src/provider/gateway.ts index 88f93334a..371bae436 100644 --- a/src/provider/gateway.ts +++ b/src/provider/gateway.ts @@ -2,6 +2,7 @@ import urljoin from 'url-join'; import { ONE, StarknetChainId, ZERO } from '../constants'; import { + Call, CallContractResponse, CompiledContract, DeclareContractPayload, @@ -9,7 +10,6 @@ import { DeployContractPayload, DeployContractResponse, EstimateFeeResponse, - FunctionCall, Gateway, GetBlockResponse, GetContractAddressesResponse, @@ -20,6 +20,7 @@ import { Invocation, InvocationsDetails, InvokeFunctionResponse, + Signature, } from '../types'; import { getSelectorFromName } from '../utils/hash'; import { parse, parseAlwaysAsBig, stringify } from '../utils/json'; @@ -205,7 +206,7 @@ export class GatewayProvider implements ProviderInterface { } public async callContract( - { contractAddress, entryPointSelector, calldata = [] }: FunctionCall, + { contractAddress, entrypoint: entryPointSelector, calldata = [] }: Call, blockIdentifier: BlockIdentifier = 'pending' ): Promise { return this.fetchEndpoint( @@ -322,17 +323,17 @@ export class GatewayProvider implements ProviderInterface { } public async getEstimateFee( - request: FunctionCall, + call: Call, blockIdentifier: BlockIdentifier = 'pending', - signature?: Array + signature?: Signature ): Promise { return this.fetchEndpoint( 'estimate_fee', { blockIdentifier }, { - contract_address: request.contractAddress, - entry_point_selector: getSelectorFromName(request.entryPointSelector), - calldata: bigNumberishArrayToDecimalStringArray(request.calldata ?? []), + contract_address: call.contractAddress, + entry_point_selector: getSelectorFromName(call.entrypoint), + calldata: bigNumberishArrayToDecimalStringArray(call.calldata ?? []), signature: bigNumberishArrayToDecimalStringArray(signature || []), } ).then(this.responseParser.parseFeeEstimateResponse); diff --git a/src/provider/interface.ts b/src/provider/interface.ts index 746b77f46..8fc7f423f 100644 --- a/src/provider/interface.ts +++ b/src/provider/interface.ts @@ -1,18 +1,19 @@ import { StarknetChainId } from '../constants'; import type { + Call, CallContractResponse, DeclareContractPayload, DeclareContractResponse, DeployContractPayload, DeployContractResponse, EstimateFeeResponse, - FunctionCall, GetBlockResponse, GetTransactionReceiptResponse, GetTransactionResponse, Invocation, InvocationsDetails, InvokeFunctionResponse, + Signature, } from '../types'; import type { BigNumberish } from '../utils/number'; import { BlockIdentifier } from './utils'; @@ -28,7 +29,7 @@ export abstract class ProviderInterface { * @returns the result of the function on the smart contract. */ public abstract callContract( - request: FunctionCall, + request: Call, blockIdentifier?: BlockIdentifier ): Promise; @@ -122,12 +123,13 @@ export abstract class ProviderInterface { */ public abstract invokeFunction( invocation: Invocation, - details: InvocationsDetails + details?: InvocationsDetails ): Promise; public abstract getEstimateFee( - request: FunctionCall, - blockIdentifier: BlockIdentifier + request: Call, + blockIdentifier: BlockIdentifier, + signature?: Signature ): Promise; public abstract waitForTransaction(txHash: BigNumberish, retryInterval?: number): Promise; diff --git a/src/provider/rpc.ts b/src/provider/rpc.ts index 9ed80892a..31802019b 100644 --- a/src/provider/rpc.ts +++ b/src/provider/rpc.ts @@ -2,6 +2,7 @@ import fetch from 'cross-fetch'; import { StarknetChainId } from '../constants'; import { + Call, CallContractResponse, CompiledContract, DeclareContractPayload, @@ -9,7 +10,6 @@ import { DeployContractPayload, DeployContractResponse, EstimateFeeResponse, - FunctionCall, GetBlockResponse, GetTransactionReceiptResponse, GetTransactionResponse, @@ -17,6 +17,7 @@ import { InvocationsDetails, InvokeFunctionResponse, RPC, + Signature, } from '../types'; import { getSelectorFromName } from '../utils/hash'; import { parse, stringify } from '../utils/json'; @@ -135,10 +136,11 @@ export class RPCProvider implements ProviderInterface { } public async getEstimateFee( - request: FunctionCall, - blockIdentifier: BlockIdentifier = 'pending' + call: Call, + blockIdentifier: BlockIdentifier = 'pending', + _signature: Signature = [] ): Promise { - const parsedCalldata = request.calldata.map((data) => { + const parsedCalldata = call.calldata?.map((data) => { if (typeof data === 'string' && isHex(data as string)) { return data; } @@ -147,8 +149,8 @@ export class RPCProvider implements ProviderInterface { return this.fetchEndpoint('starknet_estimateFee', [ { - contract_address: request.contractAddress, - entry_point_selector: getSelectorFromName(request.entryPointSelector), + contract_address: call.contractAddress, + entry_point_selector: getSelectorFromName(call.entrypoint), calldata: parsedCalldata, }, blockIdentifier, @@ -223,10 +225,10 @@ export class RPCProvider implements ProviderInterface { } public async callContract( - request: FunctionCall, + call: Call, blockIdentifier: BlockIdentifier = 'pending' ): Promise { - const parsedCalldata = request.calldata.map((data) => { + const parsedCalldata = call.calldata?.map((data) => { if (typeof data === 'string' && isHex(data as string)) { return data; } @@ -235,8 +237,8 @@ export class RPCProvider implements ProviderInterface { const result = await this.fetchEndpoint('starknet_call', [ { - contract_address: request.contractAddress, - entry_point_selector: getSelectorFromName(request.entryPointSelector), + contract_address: call.contractAddress, + entry_point_selector: getSelectorFromName(call.entrypoint), calldata: parsedCalldata, }, blockIdentifier, diff --git a/src/types/api/gateway.ts b/src/types/api/gateway.ts index fbc8bc797..771470e48 100644 --- a/src/types/api/gateway.ts +++ b/src/types/api/gateway.ts @@ -22,43 +22,63 @@ export type GetTransactionStatusResponse = { }; }; -export namespace Gateway { - export type GetContractAddressesResponse = { - Starknet: string; - GpsStatementVerifier: string; +export type GetContractAddressesResponse = { + Starknet: string; + GpsStatementVerifier: string; +}; + +export type InvokeFunctionTrace = { + caller_address: string; + contract_address: string; + code_address: string; + selector: string; + calldata: RawCalldata; + result: Array; + execution_resources: ExecutionResources; + internal_call: Array; + events: Array; + messages: Array; +}; + +export type ExecutionResources = { + n_steps: number; + builtin_instance_counter: { + pedersen_builtin: number; + range_check_builtin: number; + bitwise_builtin: number; + output_builtin: number; + ecdsa_builtin: number; + ec_op_builtin?: number; }; + n_memory_holes: number; +}; - export type InvokeFunctionTrace = { +export type GetCodeResponse = { + bytecode: string[]; + abi: Abi; +}; + +export type GetTransactionTraceResponse = { + function_invocation: { caller_address: string; contract_address: string; code_address: string; selector: string; - calldata: RawCalldata; + calldata: RawArgs; result: Array; execution_resources: ExecutionResources; - internal_call: Array; + internal_call: Array; events: Array; messages: Array; }; + signature: Signature; +}; - export type ExecutionResources = { - n_steps: number; - builtin_instance_counter: { - pedersen_builtin: number; - range_check_builtin: number; - bitwise_builtin: number; - output_builtin: number; - ecdsa_builtin: number; - ec_op_builtin?: number; - }; - n_memory_holes: number; - }; - - export type GetCodeResponse = { - bytecode: string[]; - abi: Abi; - }; +export type RawArgs = { + [inputName: string]: string | string[] | { type: 'struct'; [k: string]: BigNumberish }; +}; +export namespace Gateway { export type DeclareTransaction = { type: 'DECLARE'; contract_class: CompressedCompiledContract; @@ -124,26 +144,6 @@ export namespace Gateway { export type GetTransactionResponse = SuccessfulTransactionResponse | FailedTransactionResponse; - export type RawArgs = { - [inputName: string]: string | string[] | { type: 'struct'; [k: string]: BigNumberish }; - }; - - export type GetTransactionTraceResponse = { - function_invocation: { - caller_address: string; - contract_address: string; - code_address: string; - selector: string; - calldata: RawArgs; - result: Array; - execution_resources: ExecutionResources; - internal_call: Array; - events: Array; - messages: Array; - }; - signature: Signature; - }; - export type TransactionReceiptResponse = | SuccessfulTransactionReceiptResponse | FailedTransactionReceiptResponse; diff --git a/src/types/provider.ts b/src/types/provider.ts index 8583434ec..2e4103f64 100644 --- a/src/types/provider.ts +++ b/src/types/provider.ts @@ -88,12 +88,6 @@ export interface EstimateFeeResponse { overallFee: BigNumberish; } -export interface FunctionCall { - contractAddress: string; - entryPointSelector: string; - calldata: Array; -} - export interface InvokeFunctionResponse { transactionHash: string; } @@ -109,5 +103,5 @@ export interface DeclareContractResponse { } export type CallContractResponse = { - result: Array; + result: Array; };