Skip to content

Commit 08b27ba

Browse files
committed
refactor: optimize gas estimates with overrides
1 parent b31947d commit 08b27ba

File tree

120 files changed

+286
-327
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+286
-327
lines changed

aa-sdk/core/src/index.ts

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export { sendTransactions } from "./actions/smartAccount/sendTransactions.js";
2323
export { sendUserOperation } from "./actions/smartAccount/sendUserOperation.js";
2424
export type * from "./actions/smartAccount/types.js";
2525
export { waitForUserOperationTransaction } from "./actions/smartAccount/waitForUserOperationTransacation.js";
26+
export * from "./client/addBreadcrumb.js";
2627
export type * from "./client/bundlerClient.js";
2728
export {
2829
createBundlerClient,
@@ -65,19 +66,19 @@ export {
6566
IncorrectAccountType,
6667
SignTransactionNotSupportedError,
6768
SmartAccountWithSignerRequiredError,
68-
UpgradeToAndCallNotSupportedError,
6969
UpgradesNotSupportedError,
70+
UpgradeToAndCallNotSupportedError,
7071
} from "./errors/account.js";
7172
export { BaseError } from "./errors/base.js";
7273
export {
7374
ChainNotFoundError,
75+
EntityIdOverrideError,
7476
IncompatibleClientError,
75-
InvalidRpcUrlError,
77+
InvalidDeferredActionNonce,
7678
InvalidEntityIdError,
77-
InvalidNonceKeyError,
78-
EntityIdOverrideError,
7979
InvalidModularAccountV2Mode,
80-
InvalidDeferredActionNonce,
80+
InvalidNonceKeyError,
81+
InvalidRpcUrlError,
8182
} from "./errors/client.js";
8283
export {
8384
EntryPointNotFoundError,
@@ -92,11 +93,10 @@ export {
9293
InvalidUserOperationError,
9394
WaitForUserOperationError,
9495
} from "./errors/useroperation.js";
95-
export * from "./client/addBreadcrumb.js";
96-
export { LogLevel, Logger } from "./logger.js";
96+
export { Logger, LogLevel } from "./logger.js";
9797
export { middlewareActions } from "./middleware/actions.js";
98-
export { default7702UserOpSigner } from "./middleware/defaults/7702signer.js";
9998
export { default7702GasEstimator } from "./middleware/defaults/7702gasEstimator.js";
99+
export { default7702UserOpSigner } from "./middleware/defaults/7702signer.js";
100100
export { defaultFeeEstimator } from "./middleware/defaults/feeEstimator.js";
101101
export { defaultGasEstimator } from "./middleware/defaults/gasEstimator.js";
102102
export { defaultPaymasterAndData } from "./middleware/defaults/paymasterAndData.js";
@@ -106,7 +106,7 @@ export { erc7677Middleware } from "./middleware/erc7677middleware.js";
106106
export { noopMiddleware } from "./middleware/noopMiddleware.js";
107107
export type * from "./middleware/types.js";
108108
export { LocalAccountSigner } from "./signer/local-account.js";
109-
export { SignerSchema, isSigner } from "./signer/schema.js";
109+
export { isSigner, SignerSchema } from "./signer/schema.js";
110110
export type {
111111
SmartAccountAuthenticator,
112112
SmartAccountSigner,
@@ -117,35 +117,36 @@ export { split, type SplitTransportParams } from "./transport/split.js";
117117
export type * from "./types.js";
118118
export type * from "./utils/index.js";
119119
export {
120-
TraceHeader,
121-
TRACE_HEADER_NAME,
122-
TRACE_HEADER_STATE,
123-
} from "./utils/traceHeader.js";
124-
export {
125-
BigNumberishRangeSchema,
126-
BigNumberishSchema,
127-
ChainSchema,
128-
HexSchema,
129-
MultiplierSchema,
130120
allEqual,
121+
applyGasAndFeeOverrides,
131122
applyUserOpFeeOption,
132123
applyUserOpOverride,
133124
applyUserOpOverrideOrFeeOption,
134125
asyncPipe,
135126
bigIntMax,
136127
bigIntMultiply,
128+
BigNumberishRangeSchema,
129+
BigNumberishSchema,
137130
bypassPaymasterAndData,
138131
bypassPaymasterAndDataEmptyHex,
132+
ChainSchema,
139133
concatPaymasterAndData,
140134
deepHexlify,
141135
filterUndefined,
142136
getDefaultUserOperationFeeOptions,
137+
HexSchema,
143138
isBigNumberish,
144139
isMultiplier,
145140
isValidRequest,
141+
MultiplierSchema,
146142
parsePaymasterAndData,
147143
pick,
148144
resolveProperties,
149145
takeBytes,
150146
toRecord,
151147
} from "./utils/index.js";
148+
export {
149+
TRACE_HEADER_NAME,
150+
TRACE_HEADER_STATE,
151+
TraceHeader,
152+
} from "./utils/traceHeader.js";

aa-sdk/core/src/middleware/defaults/gasEstimator.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import type {
44
UserOperationStruct,
55
} from "../../types.js";
66
import { deepHexlify, resolveProperties } from "../../utils/index.js";
7-
import { applyUserOpOverrideOrFeeOption } from "../../utils/userop.js";
7+
import {
8+
applyGasAndFeeOverrides,
9+
applyUserOpOverrideOrFeeOption,
10+
} from "../../utils/userop.js";
811
import type { MiddlewareClient } from "../actions.js";
912
import type { ClientMiddlewareFn } from "../types.js";
1013

@@ -21,7 +24,9 @@ export const defaultGasEstimator: <C extends MiddlewareClient>(
2124
) => ClientMiddlewareFn =
2225
(client: MiddlewareClient): ClientMiddlewareFn =>
2326
async (struct, { account, overrides, feeOptions }) => {
24-
const request = deepHexlify(await resolveProperties(struct));
27+
const request = deepHexlify(
28+
await resolveProperties(await applyGasAndFeeOverrides(struct, overrides))
29+
);
2530

2631
const estimates = await client.estimateUserOperationGas(
2732
request,

aa-sdk/core/src/utils/userop.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { concat, type Address, type Hex } from "viem";
1+
import { concat, type Address, type Hex, type IsUndefined } from "viem";
22
import type { EntryPointVersion } from "../entrypoint/types";
33
import type {
44
BigNumberish,
@@ -11,7 +11,12 @@ import type {
1111
UserOperationStruct_v7,
1212
} from "../types";
1313
import { bigIntClamp, bigIntMultiply } from "./bigint.js";
14-
import { allEqual, isBigNumberish } from "./index.js";
14+
import {
15+
allEqual,
16+
isBigNumberish,
17+
resolveProperties,
18+
type Deferrable,
19+
} from "./index.js";
1520

1621
/**
1722
* Utility method for asserting a UserOperationStruct has valid fields for the given entry point version
@@ -105,6 +110,52 @@ export function applyUserOpOverride<TValue extends BigNumberish | undefined>(
105110
}
106111
}
107112

113+
function keysOf<
114+
T extends Record<string, unknown>,
115+
Filter extends (keyof T)[] | undefined = undefined
116+
>(
117+
obj?: T,
118+
filterBy?: Filter
119+
): IsUndefined<Filter> extends true ? (keyof T)[] : NonNullable<Filter> {
120+
if (obj == null) {
121+
return [] as any;
122+
}
123+
124+
const keys = Object.keys(obj);
125+
if (filterBy == null) {
126+
return keys as any;
127+
}
128+
129+
return keys.filter((key) => filterBy.includes(key)) as any;
130+
}
131+
132+
export async function applyGasAndFeeOverrides<
133+
TEntryPointVersion extends EntryPointVersion
134+
>(
135+
uo: Deferrable<UserOperationStruct<TEntryPointVersion>>,
136+
overrides?: UserOperationOverrides<TEntryPointVersion>
137+
): Promise<Deferrable<UserOperationStruct<TEntryPointVersion>>> {
138+
const awaitedUo = await resolveProperties(uo);
139+
140+
for (const override of keysOf(overrides, [
141+
"callGasLimit",
142+
"maxFeePerGas",
143+
"maxPriorityFeePerGas",
144+
"preVerificationGas",
145+
"verificationGasLimit",
146+
])) {
147+
const overrideValue = applyUserOpOverride(
148+
awaitedUo[override],
149+
overrides?.[override]
150+
);
151+
if (overrideValue != null) {
152+
awaitedUo[override] = overrideValue;
153+
}
154+
}
155+
156+
return awaitedUo;
157+
}
158+
108159
/**
109160
* Utility method for applying a UserOperationFeeOptionsField value
110161
* over the current value set for the field

account-kit/infra/src/middleware/gasManager.ts

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
UserOperationRequest,
1212
} from "@aa-sdk/core";
1313
import {
14+
applyGasAndFeeOverrides,
1415
bypassPaymasterAndData,
1516
ChainNotFoundError,
1617
clientHeaderTrack,
@@ -24,23 +25,23 @@ import {
2425
resolveProperties,
2526
} from "@aa-sdk/core";
2627
import {
27-
fromHex,
28-
isHex,
29-
toHex,
30-
type Hex,
3128
encodeAbiParameters,
3229
encodeFunctionData,
33-
parseAbi,
30+
fromHex,
31+
isHex,
3432
maxUint256,
33+
parseAbi,
3534
sliceHex,
35+
toHex,
36+
type Hex,
3637
} from "viem";
37-
import type { AlchemySmartAccountClient } from "../client/smartAccountClient.js";
38+
import type { MiddlewareClient } from "../../../../aa-sdk/core/dist/types/middleware/actions.js";
39+
import type { RequestGasAndPaymasterAndDataRequest } from "../actions/types.js";
3840
import type { AlchemyTransport } from "../alchemyTransport.js";
41+
import type { AlchemySmartAccountClient } from "../client/smartAccountClient.js";
42+
import type { PermitDomain, PermitMessage } from "../gas-manager.js";
43+
import { EIP712NoncesAbi, PermitTypes } from "../gas-manager.js";
3944
import { alchemyFeeEstimator } from "./feeEstimator.js";
40-
import type { RequestGasAndPaymasterAndDataRequest } from "../actions/types.js";
41-
import { PermitTypes, EIP712NoncesAbi } from "../gas-manager.js";
42-
import type { PermitMessage, PermitDomain } from "../gas-manager.js";
43-
import type { MiddlewareClient } from "../../../../aa-sdk/core/dist/types/middleware/actions.js";
4445

4546
type Context = {
4647
policyId: string | string[];
@@ -119,6 +120,7 @@ export function alchemyGasManagerMiddleware(
119120
paymasterAndData: async (uo, args) => {
120121
const context = await buildContext(uo, args);
121122
const baseMiddleware = erc7677Middleware({ context });
123+
uo = await applyGasAndFeeOverrides(uo, args.overrides);
122124
return baseMiddleware.paymasterAndData(uo, args);
123125
},
124126
};
@@ -223,39 +225,11 @@ export function alchemyGasAndPaymasterAndDataMiddleware(
223225
throw new ChainNotFoundError();
224226
}
225227

226-
const userOp = deepHexlify(await resolveProperties(uo));
228+
const userOp = deepHexlify(
229+
await resolveProperties(await applyGasAndFeeOverrides(uo, overrides_))
230+
);
227231

228232
const overrides: UserOperationOverrides = filterUndefined({
229-
maxFeePerGas: overrideField(
230-
"maxFeePerGas",
231-
overrides_ as UserOperationOverrides,
232-
feeOptions,
233-
userOp
234-
),
235-
maxPriorityFeePerGas: overrideField(
236-
"maxPriorityFeePerGas",
237-
overrides_ as UserOperationOverrides,
238-
feeOptions,
239-
userOp
240-
),
241-
callGasLimit: overrideField(
242-
"callGasLimit",
243-
overrides_ as UserOperationOverrides,
244-
feeOptions,
245-
userOp
246-
),
247-
verificationGasLimit: overrideField(
248-
"verificationGasLimit",
249-
overrides_ as UserOperationOverrides,
250-
feeOptions,
251-
userOp
252-
),
253-
preVerificationGas: overrideField(
254-
"preVerificationGas",
255-
overrides_ as UserOperationOverrides,
256-
feeOptions,
257-
userOp
258-
),
259233
...(account.getEntryPoint().version === "0.7.0"
260234
? {
261235
paymasterVerificationGasLimit: overrideField<"0.7.0">(

0 commit comments

Comments
 (0)