From 6f784ea4e4edd298f1950dac956fd1c81b953497 Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Tue, 12 Mar 2024 10:32:17 +0000 Subject: [PATCH] feat: skip signatures when skipValidate is true * feat: don't sign when skipValidate is true * test: adjust tests for skipValidate change --------- Co-authored-by: Petar Penovic --- __tests__/account.test.ts | 15 ++++++++-- src/account/default.ts | 61 +++++++++++++++++++++++++-------------- src/types/account.ts | 1 + src/types/signer.ts | 1 + 4 files changed, 54 insertions(+), 24 deletions(-) diff --git a/__tests__/account.test.ts b/__tests__/account.test.ts index 3e012d684..0a15b05ca 100644 --- a/__tests__/account.test.ts +++ b/__tests__/account.test.ts @@ -1,6 +1,8 @@ import typedDataExample from '../__mocks__/typedData/baseExample.json'; import { Account, + AllowArray, + Call, Contract, DeclareDeployUDCResponse, Provider, @@ -87,17 +89,24 @@ describe('deploy and test Wallet', () => { test('estimateInvokeFee Cairo 0', async () => { const innerInvokeEstFeeSpy = jest.spyOn(account.signer, 'signTransaction'); - const result = await account.estimateInvokeFee({ + + const calls: AllowArray = { contractAddress: erc20Address, entrypoint: 'transfer', calldata: [erc20.address, '10', '0'], - }); + }; + + let result = await account.estimateInvokeFee(calls, { skipValidate: true }); + expect(result).toMatchSchemaRef('EstimateFee'); + expect(innerInvokeEstFeeSpy).not.toHaveBeenCalled(); + innerInvokeEstFeeSpy.mockClear(); + result = await account.estimateInvokeFee(calls, { skipValidate: false }); expect(result).toMatchSchemaRef('EstimateFee'); expect([constants.TRANSACTION_VERSION.F1, constants.TRANSACTION_VERSION.F3]).toContain( innerInvokeEstFeeSpy.mock.calls[0][1].version ); - innerInvokeEstFeeSpy.mockClear(); + innerInvokeEstFeeSpy.mockRestore(); }); xtest('estimateDeclareFee Cairo 0 & Cairo 1', async () => { diff --git a/src/account/default.ts b/src/account/default.ts index 47620bc72..763ed88e6 100644 --- a/src/account/default.ts +++ b/src/account/default.ts @@ -134,7 +134,12 @@ export class Account extends Provider implements AccountInterface { calls: AllowArray, details: UniversalDetails = {} ): Promise { - const { nonce: providedNonce, blockIdentifier, version: providedVersion } = details; + const { + nonce: providedNonce, + blockIdentifier, + version: providedVersion, + skipValidate = true, + } = details; const transactions = Array.isArray(calls) ? calls : [calls]; const nonce = toBigInt(providedNonce ?? (await this.getNonce())); @@ -152,6 +157,7 @@ export class Account extends Provider implements AccountInterface { version, chainId, cairoVersion: await this.getCairoVersion(), + skipValidate, }; const invocation = await this.buildInvocation(transactions, signerDetails); @@ -167,7 +173,12 @@ export class Account extends Provider implements AccountInterface { payload: DeclareContractPayload, details: UniversalDetails = {} ): Promise { - const { blockIdentifier, nonce: providedNonce, version: providedVersion } = details; + const { + blockIdentifier, + nonce: providedNonce, + version: providedVersion, + skipValidate = true, + } = details; const nonce = toBigInt(providedNonce ?? (await this.getNonce())); const version = toTransactionVersion( !isSierra(payload.contract) @@ -185,6 +196,7 @@ export class Account extends Provider implements AccountInterface { walletAddress: this.address, maxFee: ZERO, cairoVersion: undefined, // unused parameter + skipValidate, }); return super.getDeclareEstimateFee( @@ -204,7 +216,7 @@ export class Account extends Provider implements AccountInterface { }: DeployAccountContractPayload, details: UniversalDetails = {} ): Promise { - const { blockIdentifier, version: providedVersion } = details; + const { blockIdentifier, version: providedVersion, skipValidate = true } = details; const version = toTransactionVersion( this.getPreferredVersion(ETransactionVersion.F1, ETransactionVersion.F3), toFeeVersion(providedVersion) @@ -222,6 +234,7 @@ export class Account extends Provider implements AccountInterface { walletAddress: this.address, // unused parameter maxFee: ZERO, cairoVersion: undefined, // unused parameter, + skipValidate, } ); @@ -269,7 +282,7 @@ export class Account extends Provider implements AccountInterface { invocations: Invocations, details: SimulateTransactionDetails = {} ): Promise { - const { nonce, blockIdentifier, skipValidate, skipExecute, version } = details; + const { nonce, blockIdentifier, skipValidate = true, skipExecute, version } = details; const accountInvocations = await this.accountInvocationsFactory(invocations, { ...v3Details(details), versions: [ @@ -281,6 +294,7 @@ export class Account extends Provider implements AccountInterface { ], nonce, blockIdentifier, + skipValidate, }); return super.getSimulateTransaction(accountInvocations, { @@ -649,7 +663,7 @@ export class Account extends Provider implements AccountInterface { details: InvocationsSignerDetails ): Promise { const calldata = getExecuteCalldata(call, await this.getCairoVersion()); - const signature = await this.signer.signTransaction(call, details); + const signature = !details.skipValidate ? await this.signer.signTransaction(call, details) : []; return { ...v3Details(details), @@ -673,13 +687,15 @@ export class Account extends Provider implements AccountInterface { throw Error('V3 Transaction work with Cairo1 Contracts and require compiledClassHash'); } - const signature = await this.signer.signDeclareTransaction({ - ...details, - ...v3Details(details), - classHash, - compiledClassHash: compiledClassHash as string, // TODO: TS Nekuzi da v2 nemora imat a v3 mora i da je throvano ako nije definiran - senderAddress: details.walletAddress, - }); + const signature = !details.skipValidate + ? await this.signer.signDeclareTransaction({ + ...details, + ...v3Details(details), + classHash, + compiledClassHash: compiledClassHash as string, // TODO: TS Nekuzi da v2 nemora imat a v3 mora i da je throvano ako nije definiran + senderAddress: details.walletAddress, + }) + : []; return { senderAddress: details.walletAddress, @@ -703,14 +719,16 @@ export class Account extends Provider implements AccountInterface { providedContractAddress ?? calculateContractAddressFromHash(addressSalt, classHash, compiledCalldata, 0); - const signature = await this.signer.signDeployAccountTransaction({ - ...details, - ...v3Details(details), - classHash, - contractAddress, - addressSalt, - constructorCalldata: compiledCalldata, - }); + const signature = !details.skipValidate + ? await this.signer.signDeployAccountTransaction({ + ...details, + ...v3Details(details), + classHash, + contractAddress, + addressSalt, + constructorCalldata: compiledCalldata, + }) + : []; return { ...v3Details(details), @@ -752,7 +770,7 @@ export class Account extends Provider implements AccountInterface { invocations: Invocations, details: AccountInvocationsFactoryDetails ) { - const { nonce, blockIdentifier } = details; + const { nonce, blockIdentifier, skipValidate = true } = details; const safeNonce = await this.getNonceSafe(nonce); const chainId = await this.getChainId(); const versions = details.versions.map((it) => toTransactionVersion(it)); @@ -775,6 +793,7 @@ export class Account extends Provider implements AccountInterface { chainId, cairoVersion, version: '' as ETransactionVersion, + skipValidate, }; const common = { type: transaction.type, diff --git a/src/types/account.ts b/src/types/account.ts index f90008114..9572cfeb8 100644 --- a/src/types/account.ts +++ b/src/types/account.ts @@ -21,6 +21,7 @@ export type AccountInvocationsFactoryDetails = { versions: Array<`${ETransactionVersion}`>; nonce?: BigNumberish; blockIdentifier?: BlockIdentifier; + skipValidate?: boolean; } & Partial; export interface UniversalDetails { diff --git a/src/types/signer.ts b/src/types/signer.ts index 6696e3005..80d98a8d6 100644 --- a/src/types/signer.ts +++ b/src/types/signer.ts @@ -10,6 +10,7 @@ import { export type InvocationsSignerDetails = (V2InvocationsSignerDetails | V3InvocationsSignerDetails) & { version: `${ETransactionVersion}`; + skipValidate?: boolean; }; export type V2InvocationsSignerDetails = {