Skip to content

Commit

Permalink
feat: support overrides for all user operation methods on smart accon…
Browse files Browse the repository at this point in the history
…t 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 <[email protected]>

* Update site/packages/aa-core/provider/sendTransactions.md

Co-authored-by: Ajay Vasisht <[email protected]>

* Update site/packages/aa-core/provider/sendTransaction.md

Co-authored-by: Ajay Vasisht <[email protected]>

* Update site/packages/aa-core/provider/buildUserOperation.md

Co-authored-by: Ajay Vasisht <[email protected]>

* Update site/packages/aa-core/provider/buildUserOperationFromTx.md

Co-authored-by: Ajay Vasisht <[email protected]>

* Update site/packages/aa-core/provider/dropAndReplaceUserOperation.md

Co-authored-by: Ajay Vasisht <[email protected]>

---------

Co-authored-by: Ajay Vasisht <[email protected]>
  • Loading branch information
denniswon and avasisht23 committed Nov 13, 2023
1 parent 32bfe92 commit c30760b
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 20 deletions.
28 changes: 28 additions & 0 deletions packages/alchemy/e2e-tests/simple-account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
52 changes: 32 additions & 20 deletions packages/core/src/provider/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,40 +202,49 @@ export class SmartAccountProvider<
return this.account.signTypedDataWith6492(params);
};

sendTransaction = async (request: RpcTransactionRequest): Promise<Hash> => {
const uoStruct = await this.buildUserOperationFromTx(request);
sendTransaction = async (
request: RpcTransactionRequest,
overrides?: UserOperationOverrides
): Promise<Hash> => {
const uoStruct = await this.buildUserOperationFromTx(request, overrides);

const { hash } = await this._sendUserOperation(uoStruct);

return await this.waitForUserOperationTransaction(hash as Hash);
};

buildUserOperationFromTx = async (
request: RpcTransactionRequest
request: RpcTransactionRequest,
overrides?: UserOperationOverrides
): Promise<UserOperationStruct> => {
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(
{
target: request.to,
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(
Expand All @@ -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);
};
Expand Down Expand Up @@ -353,7 +363,8 @@ export class SmartAccountProvider<
};

dropAndReplaceUserOperation = async (
uoToDrop: UserOperationRequest
uoToDrop: UserOperationRequest,
overrides?: UserOperationOverrides
): Promise<SendUserOperationResult> => {
const uoToSubmit = {
initCode: uoToDrop.initCode,
Expand All @@ -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)
Expand All @@ -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);
};

Expand Down
4 changes: 4 additions & 0 deletions site/packages/aa-core/provider/buildUserOperation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions site/packages/aa-core/provider/buildUserOperationFromTx.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions site/packages/aa-core/provider/dropAndReplaceUserOperation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions site/packages/aa-core/provider/sendTransaction.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions site/packages/aa-core/provider/sendTransactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions site/packages/aa-core/provider/sendUserOperation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit c30760b

Please sign in to comment.