Skip to content

Commit

Permalink
feat: update simulate tx
Browse files Browse the repository at this point in the history
  • Loading branch information
irisdv committed Dec 20, 2022
1 parent 21efcb1 commit 8f3ea55
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 2 deletions.
10 changes: 10 additions & 0 deletions __tests__/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ describe('deploy and test Wallet', () => {
innerInvokeEstFeeSpy.mockClear();
});

test('simulate transaction', async () => {
const res = await account.simulateTransaction({
contractAddress: erc20Address,
entrypoint: 'transfer',
calldata: [erc20.address, '10', '0'],
});
expect(res).toHaveProperty('fee_estimation');
expect(res).toHaveProperty('trace');
});

test('read balance of wallet', async () => {
const x = await erc20.balanceOf(account.address);

Expand Down
33 changes: 33 additions & 0 deletions src/account/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
InvokeFunctionResponse,
KeyPair,
MultiDeployContractResponse,
Sequencer,
Signature,
UniversalDeployerContractPayload,
} from '../types';
Expand Down Expand Up @@ -498,4 +499,36 @@ export class Account extends Provider implements AccountInterface {

return feeEstimate.suggestedMaxFee.toString();
}

public async simulateTransaction(
calls: AllowArray<Call>,
{ nonce: providedNonce, blockIdentifier }: EstimateFeeDetails = {}
): Promise<Sequencer.TransactionSimulationResponse> {
const transactions = Array.isArray(calls) ? calls : [calls];
const nonce = toBN(providedNonce ?? (await this.getNonce()));
const version = toBN(feeTransactionVersion);
const chainId = await this.getChainId();

const signerDetails: InvocationsSignerDetails = {
walletAddress: this.address,
nonce,
maxFee: ZERO,
version,
chainId,
};

const signature = await this.signer.signTransaction(transactions, signerDetails);

const calldata = fromCallsToExecuteCalldata(transactions);
const response: any = await super.getSimulateTransaction(
{ contractAddress: this.address, calldata, signature },
{ version, nonce },
blockIdentifier
);

const suggestedMaxFee = estimatedFeeToMaxFee(response.fee_estimation.overall_fee);
response.fee_estimation.suggestedMaxFee = suggestedMaxFee;

return response;
}
}
16 changes: 16 additions & 0 deletions src/account/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
InvocationsDetails,
InvokeFunctionResponse,
MultiDeployContractResponse,
Sequencer,
Signature,
UniversalDeployerContractPayload,
} from '../types';
Expand Down Expand Up @@ -308,4 +309,19 @@ export abstract class AccountInterface extends ProviderInterface {
estimateFeeAction: EstimateFeeAction,
details: EstimateFeeDetails
): Promise<BigNumberish>;

/**
* Estimate Fee for executing an INVOKE transaction on starknet
*
* @param calls the invocation object containing:
* - contractAddress - the address of the contract
* - entrypoint - the entrypoint of the contract
* - calldata - (defaults to []) the calldata
*
* @returns response from estimate_fee
*/
public abstract simulateTransaction(
calls: AllowArray<Call>,
estimateFeeDetails?: EstimateFeeDetails
): Promise<Sequencer.TransactionSimulationResponse>;
}
9 changes: 9 additions & 0 deletions src/provider/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Invocation,
InvocationsDetailsWithNonce,
InvokeFunctionResponse,
Sequencer,
Status,
} from '../types';
import { BigNumberish } from '../utils/number';
Expand Down Expand Up @@ -184,4 +185,12 @@ export class Provider implements ProviderInterface {
): Promise<GetTransactionReceiptResponse> {
return this.provider.waitForTransaction(txHash, retryInterval, successStates);
}

public async getSimulateTransaction(
invocation: Invocation,
invocationDetails: InvocationsDetailsWithNonce,
blockIdentifier?: BlockIdentifier
): Promise<Sequencer.TransactionSimulationResponse> {
return this.provider.getSimulateTransaction(invocation, invocationDetails, blockIdentifier);
}
}
8 changes: 8 additions & 0 deletions src/provider/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
Invocation,
InvocationsDetailsWithNonce,
InvokeFunctionResponse,
Sequencer,
Status,
} from '../types';
import type { BigNumberish } from '../utils/number';
Expand Down Expand Up @@ -278,4 +279,11 @@ export abstract class ProviderInterface {
retryInterval?: number,
successStates?: Array<Status>
): Promise<GetTransactionReceiptResponse>;

// todo documentation
public abstract getSimulateTransaction(
invocation: Invocation,
invocationDetails: InvocationsDetailsWithNonce,
blockIdentifier?: BlockIdentifier
): Promise<Sequencer.TransactionSimulationResponse>;
}
9 changes: 9 additions & 0 deletions src/provider/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
InvocationsDetailsWithNonce,
InvokeFunctionResponse,
RPC,
Sequencer,
} from '../types';
import fetch from '../utils/fetchPonyfill';
import { getSelectorFromName } from '../utils/hash';
Expand Down Expand Up @@ -481,4 +482,12 @@ export class RpcProvider implements ProviderInterface {
public async getEvents(eventFilter: RPC.EventFilter): Promise<RPC.GetEventsResponse> {
return this.fetchEndpoint('starknet_getEvents', { filter: eventFilter });
}

public async getSimulateTransaction(
_invocation: Invocation,
_invocationDetails: InvocationsDetailsWithNonce,
_blockIdentifier?: BlockIdentifier
): Promise<Sequencer.TransactionSimulationResponse> {
throw new Error('RPC does not implement simulateTransaction function');
}
}
4 changes: 2 additions & 2 deletions src/provider/sequencer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,10 +522,10 @@ export class SequencerProvider implements ProviderInterface {
return this.fetchEndpoint('estimate_message_fee', { blockIdentifier }, validCallL1Handler);
}

public async simulateTransaction(
public async getSimulateTransaction(
invocation: Invocation,
invocationDetails: InvocationsDetailsWithNonce,
blockIdentifier: BlockIdentifier = 'pending'
blockIdentifier: BlockIdentifier = this.blockIdentifier
): Promise<Sequencer.TransactionSimulationResponse> {
return this.fetchEndpoint(
'simulate_transaction',
Expand Down

0 comments on commit 8f3ea55

Please sign in to comment.