From c30760bcd91b56b8ce46c7ecd34dbb39369f2ea0 Mon Sep 17 00:00:00 2001 From: Dennis Won Date: Mon, 13 Nov 2023 10:55:13 -0800 Subject: [PATCH] feat: support overrides for all user operation methods on smart accont provider (#238) * feat: support overrides for all user operation methods on smart account provider * Update site/packages/aa-core/provider/sendUserOperation.md Co-authored-by: Ajay Vasisht <43521356+avasisht23@users.noreply.github.com> * Update site/packages/aa-core/provider/sendTransactions.md Co-authored-by: Ajay Vasisht <43521356+avasisht23@users.noreply.github.com> * Update site/packages/aa-core/provider/sendTransaction.md Co-authored-by: Ajay Vasisht <43521356+avasisht23@users.noreply.github.com> * Update site/packages/aa-core/provider/buildUserOperation.md Co-authored-by: Ajay Vasisht <43521356+avasisht23@users.noreply.github.com> * Update site/packages/aa-core/provider/buildUserOperationFromTx.md Co-authored-by: Ajay Vasisht <43521356+avasisht23@users.noreply.github.com> * Update site/packages/aa-core/provider/dropAndReplaceUserOperation.md Co-authored-by: Ajay Vasisht <43521356+avasisht23@users.noreply.github.com> --------- Co-authored-by: Ajay Vasisht <43521356+avasisht23@users.noreply.github.com> --- .../alchemy/e2e-tests/simple-account.test.ts | 28 ++++++++++ packages/core/src/provider/base.ts | 52 ++++++++++++------- .../aa-core/provider/buildUserOperation.md | 4 ++ .../provider/buildUserOperationFromTx.md | 4 ++ .../provider/dropAndReplaceUserOperation.md | 4 ++ .../aa-core/provider/sendTransaction.md | 4 ++ .../aa-core/provider/sendTransactions.md | 4 ++ .../aa-core/provider/sendUserOperation.md | 4 ++ 8 files changed, 84 insertions(+), 20 deletions(-) diff --git a/packages/alchemy/e2e-tests/simple-account.test.ts b/packages/alchemy/e2e-tests/simple-account.test.ts index 2e299c0fb..466918429 100644 --- a/packages/alchemy/e2e-tests/simple-account.test.ts +++ b/packages/alchemy/e2e-tests/simple-account.test.ts @@ -99,6 +99,34 @@ describe("Simple Account Tests", () => { ).rejects.toThrow(); }, 50000); + it("should support overrides for buildUserOperation", async () => { + const signer = givenConnectedProvider({ + owner, + chain, + }).withAlchemyGasManager({ + policyId: PAYMASTER_POLICY_ID, + }); + + const overrides = { + maxFeePerGas: 100000000n, + maxPriorityFeePerGas: 100000000n, + paymasterAndData: "0x", + }; + const uoStruct = await signer.buildUserOperation( + { + target: await signer.getAddress(), + data: "0x", + }, + overrides + ); + + expect(uoStruct.maxFeePerGas).toEqual(overrides.maxFeePerGas); + expect(uoStruct.maxPriorityFeePerGas).toEqual( + overrides.maxPriorityFeePerGas + ); + expect(uoStruct.paymasterAndData).toEqual(overrides.paymasterAndData); + }, 50000); + it("should successfully use paymaster with fee opts", async () => { const signer = givenConnectedProvider({ owner, diff --git a/packages/core/src/provider/base.ts b/packages/core/src/provider/base.ts index 86fe77739..a0cd18a74 100644 --- a/packages/core/src/provider/base.ts +++ b/packages/core/src/provider/base.ts @@ -202,8 +202,11 @@ export class SmartAccountProvider< return this.account.signTypedDataWith6492(params); }; - sendTransaction = async (request: RpcTransactionRequest): Promise => { - const uoStruct = await this.buildUserOperationFromTx(request); + sendTransaction = async ( + request: RpcTransactionRequest, + overrides?: UserOperationOverrides + ): Promise => { + const uoStruct = await this.buildUserOperationFromTx(request, overrides); const { hash } = await this._sendUserOperation(uoStruct); @@ -211,19 +214,22 @@ export class SmartAccountProvider< }; buildUserOperationFromTx = async ( - request: RpcTransactionRequest + request: RpcTransactionRequest, + overrides?: UserOperationOverrides ): Promise => { if (!request.to) { throw new Error("transaction is missing to address"); } - const overrides: UserOperationOverrides = {}; - if (request.maxFeePerGas) { - overrides.maxFeePerGas = request.maxFeePerGas; + const _overrides: UserOperationOverrides = {}; + if (overrides?.maxFeePerGas || request.maxFeePerGas) { + _overrides.maxFeePerGas = overrides?.maxFeePerGas ?? request.maxFeePerGas; } - if (request.maxPriorityFeePerGas) { - overrides.maxPriorityFeePerGas = request.maxPriorityFeePerGas; + if (overrides?.maxPriorityFeePerGas || request.maxPriorityFeePerGas) { + _overrides.maxPriorityFeePerGas = + overrides?.maxPriorityFeePerGas ?? request.maxPriorityFeePerGas; } + _overrides.paymasterAndData = overrides?.paymasterAndData; return this.buildUserOperation( { @@ -231,11 +237,14 @@ export class SmartAccountProvider< data: request.data ?? "0x", value: request.value ? fromHex(request.value, "bigint") : 0n, }, - overrides + _overrides ); }; - sendTransactions = async (requests: RpcTransactionRequest[]) => { + sendTransactions = async ( + requests: RpcTransactionRequest[], + overrides?: UserOperationOverrides + ) => { const batch = requests.map((request) => { if (!request.to) { throw new Error( @@ -261,16 +270,17 @@ export class SmartAccountProvider< .filter((x) => x.maxPriorityFeePerGas != null) .map((x) => fromHex(x.maxPriorityFeePerGas!, "bigint")) ); - const overrides: UserOperationOverrides = {}; - if (maxFeePerGas != null) { - overrides.maxFeePerGas = maxFeePerGas; + const _overrides: UserOperationOverrides = {}; + if (overrides?.maxFeePerGas || maxFeePerGas != null) { + _overrides.maxFeePerGas = overrides?.maxFeePerGas ?? maxFeePerGas; } - if (maxPriorityFeePerGas != null) { - overrides.maxPriorityFeePerGas = maxPriorityFeePerGas; + if (overrides?.maxPriorityFeePerGas || maxPriorityFeePerGas != null) { + _overrides.maxPriorityFeePerGas = + overrides?.maxPriorityFeePerGas ?? maxPriorityFeePerGas; } - const { hash } = await this.sendUserOperation(batch, overrides); + const { hash } = await this.sendUserOperation(batch, _overrides); return await this.waitForUserOperationTransaction(hash as Hash); }; @@ -353,7 +363,8 @@ export class SmartAccountProvider< }; dropAndReplaceUserOperation = async ( - uoToDrop: UserOperationRequest + uoToDrop: UserOperationRequest, + overrides?: UserOperationOverrides ): Promise => { const uoToSubmit = { initCode: uoToDrop.initCode, @@ -366,9 +377,9 @@ export class SmartAccountProvider< // Run once to get the fee estimates // This can happen at any part of the middleware stack, so we want to run it all const { maxFeePerGas, maxPriorityFeePerGas } = - await this._runMiddlewareStack(uoToSubmit); + await this._runMiddlewareStack(uoToSubmit, overrides); - const overrides: UserOperationOverrides = { + const _overrides: UserOperationOverrides = { maxFeePerGas: bigIntMax( BigInt(maxFeePerGas ?? 0n), bigIntPercent(uoToDrop.maxFeePerGas, 110n) @@ -377,9 +388,10 @@ export class SmartAccountProvider< BigInt(maxPriorityFeePerGas ?? 0n), bigIntPercent(uoToDrop.maxPriorityFeePerGas, 110n) ), + paymasterAndData: uoToDrop.paymasterAndData, }; - const uoToSend = await this._runMiddlewareStack(uoToSubmit, overrides); + const uoToSend = await this._runMiddlewareStack(uoToSubmit, _overrides); return this._sendUserOperation(uoToSend); }; diff --git a/site/packages/aa-core/provider/buildUserOperation.md b/site/packages/aa-core/provider/buildUserOperation.md index a9426c206..29f4443e4 100644 --- a/site/packages/aa-core/provider/buildUserOperation.md +++ b/site/packages/aa-core/provider/buildUserOperation.md @@ -74,3 +74,7 @@ A Promise containing the _unsigned_ UserOperation struct resulting from the midd - `target: Address` - the target of the call (equivalent to `to` in a transaction) - `data: Hex` - can be either `0x` or a call data string - `value?: bigint` - optionally, set the value in wei you want to send to the target + +### `overrides?: UserOperationOverrides` + +Optional parameter where you can specify override values for `maxFeePerGas`, `maxPriorityFeePerGas` or `paymasterAndData` on the user operation request diff --git a/site/packages/aa-core/provider/buildUserOperationFromTx.md b/site/packages/aa-core/provider/buildUserOperationFromTx.md index a65472b69..9d14bc18a 100644 --- a/site/packages/aa-core/provider/buildUserOperationFromTx.md +++ b/site/packages/aa-core/provider/buildUserOperationFromTx.md @@ -59,3 +59,7 @@ A Promise containing the _unsigned_ UserOperation struct converted from the inpu ### `tx: RpcTransactionRequest` The `RpcTransactionRequest` object representing a traditional ethereum transaction + +### `overrides?: UserOperationOverrides` + +Optional parameter where you can specify override values for `maxFeePerGas`, `maxPriorityFeePerGas` or `paymasterAndData` on the user operation request diff --git a/site/packages/aa-core/provider/dropAndReplaceUserOperation.md b/site/packages/aa-core/provider/dropAndReplaceUserOperation.md index 0029062a0..907d7b0c1 100644 --- a/site/packages/aa-core/provider/dropAndReplaceUserOperation.md +++ b/site/packages/aa-core/provider/dropAndReplaceUserOperation.md @@ -50,3 +50,7 @@ A Promise containing the hash of the user operation and the request that was sen ### `UserOperationRequest` A previously submitted UserOperation. + +### `overrides?: UserOperationOverrides` + +Optional parameter where you can specify override values for `maxFeePerGas`, `maxPriorityFeePerGas` or `paymasterAndData` on the user operation request diff --git a/site/packages/aa-core/provider/sendTransaction.md b/site/packages/aa-core/provider/sendTransaction.md index 9a31e2c23..f85dbd67c 100644 --- a/site/packages/aa-core/provider/sendTransaction.md +++ b/site/packages/aa-core/provider/sendTransaction.md @@ -53,3 +53,7 @@ A Promise containing the transaction hash ### `request: RpcTransactionRequest` The `RpcTransactionRequest` object representing a traditional ethereum transaction + +### `overrides?: UserOperationOverrides` + +Optional parameter where you can specify override values for `maxFeePerGas`, `maxPriorityFeePerGas` or `paymasterAndData` on the user operation request diff --git a/site/packages/aa-core/provider/sendTransactions.md b/site/packages/aa-core/provider/sendTransactions.md index 10e8d893f..4ad5c4d56 100644 --- a/site/packages/aa-core/provider/sendTransactions.md +++ b/site/packages/aa-core/provider/sendTransactions.md @@ -74,3 +74,7 @@ A Promise containing the transaction hash ### `request: RpcTransactionRequest[]` An `RpcTransactionRequest` array representing a traditional ethereum transaction + +### `overrides?: UserOperationOverrides` + +Optional parameter where you can specify override values for `maxFeePerGas`, `maxPriorityFeePerGas` or `paymasterAndData` on the user operation request diff --git a/site/packages/aa-core/provider/sendUserOperation.md b/site/packages/aa-core/provider/sendUserOperation.md index bed9d948f..0a8c6e13b 100644 --- a/site/packages/aa-core/provider/sendUserOperation.md +++ b/site/packages/aa-core/provider/sendUserOperation.md @@ -70,3 +70,7 @@ A Promise containing the hash of the user operation and the request that was sen - `target: Address` - the target of the call (equivalent to `to` in a transaction) - `data: Hex` - can be either `0x` or a call data string - `value?: bigint` - optionally, set the value in wei you want to send to the target + +### `overrides?: UserOperationOverrides` + +Optional parameter where you can specify override values for `maxFeePerGas`, `maxPriorityFeePerGas` or `paymasterAndData` on the user operation request