Skip to content

Commit

Permalink
cleanup smart wallet options
Browse files Browse the repository at this point in the history
  • Loading branch information
joaquim-verges committed Feb 14, 2024
1 parent bd08212 commit b7a618e
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 53 deletions.
9 changes: 3 additions & 6 deletions packages/thirdweb/src/wallets/smart/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import type {
import type { SmartWalletOptions } from "./types.js";
import { createUnsignedUserOp, signUserOp } from "./lib/userop.js";
import { bundleUserOp } from "./lib/bundler.js";
import { getContract, type ThirdwebContract } from "../../contract/contract.js";
import { toHex } from "viem";
import { readContract } from "../../transaction/read-contract.js";
import { getContract } from "../../contract/contract.js";
import { predictAddress } from "./lib/calls.js";

/**
* Creates a smart wallet.
Expand Down Expand Up @@ -55,9 +54,7 @@ async function smartAccount(
address: options.factoryAddress,
chain: options.chain,
});
const accountAddress = options.predictAddressOverride
? await options.predictAddressOverride()
: await predictAddress(factoryContract, options);
const accountAddress = await predictAddress(factoryContract, options);
const accountContract = getContract({
client: options.client,
address: accountAddress,
Expand Down
15 changes: 8 additions & 7 deletions packages/thirdweb/src/wallets/smart/lib/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getClientFetch } from "../../../utils/fetch.js";
import type {
EstimationResult,
SmartWalletOptions,
UserOperationStruct,
UserOperation,
} from "../types.js";
import {
DEBUG,
Expand All @@ -16,7 +16,7 @@ import { hexlifyUserOp } from "./utils.js";
* @internal
*/
export async function bundleUserOp(args: {
userOp: UserOperationStruct;
userOp: UserOperation;
options: SmartWalletOptions;
}): Promise<Hex> {
return sendBundlerRequest({
Expand All @@ -29,7 +29,7 @@ export async function bundleUserOp(args: {
* @internal
*/
export async function estimateUserOpGas(args: {
userOp: UserOperationStruct;
userOp: UserOperation;
options: SmartWalletOptions;
}): Promise<EstimationResult> {
const res = await sendBundlerRequest({
Expand All @@ -46,17 +46,18 @@ export async function estimateUserOpGas(args: {
}

async function sendBundlerRequest(args: {
userOp: UserOperationStruct;
userOp: UserOperation;
options: SmartWalletOptions;
operation: "eth_estimateUserOperationGas" | "eth_sendUserOperation";
}) {
const { userOp, options, operation } = args;
const hexifiedUserOp = await hexlifyUserOp(userOp);
const jsonRequestData: [UserOperationStruct, string] = [
const jsonRequestData: [UserOperation, string] = [
hexifiedUserOp,
options.entrypointAddress ?? ENTRYPOINT_ADDRESS,
options.overrides?.entrypointAddress ?? ENTRYPOINT_ADDRESS,
];
const bundlerUrl = options.bundlerUrl ?? getDefaultBundlerUrl(options.chain);
const bundlerUrl =
options.overrides?.bundlerUrl ?? getDefaultBundlerUrl(options.chain);
const fetchWithHeaders = getClientFetch(options.client);
const response = await fetchWithHeaders(bundlerUrl, {
method: "POST",
Expand Down
20 changes: 10 additions & 10 deletions packages/thirdweb/src/wallets/smart/lib/calls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ export async function predictAddress(
factoryContract: ThirdwebContract,
options: SmartWalletOptions,
): Promise<string> {
if (options.predictAddressOverride) {
return options.predictAddressOverride();
if (options.overrides?.predictAddress) {
return options.overrides.predictAddress(factoryContract);
}
const accountAddress =
options.accountAddress || options.personalAccount.address;
const extraData = toHex(options.accountExtraData || "");
options.overrides?.accountAddress || options.personalAccount.address;
const extraData = toHex(options.overrides?.accountSalt ?? "");
return readContract({
contract: factoryContract,
method: "function getAddress(address, bytes) returns (address)",
Expand All @@ -35,15 +35,15 @@ export function prepareCreateAccount(args: {
options: SmartWalletOptions;
}): PreparedTransaction {
const { factoryContract, options } = args;
if (options.createAccountOverride) {
return options.createAccountOverride();
if (options.overrides?.createAccount) {
return options.overrides.createAccount(factoryContract);
}
return prepareContractCall({
contract: factoryContract,
method: "function createAccount(address, bytes) public returns (address)",
params: [
options.accountAddress || options.personalAccount.address,
toHex(options.accountExtraData || ""),
options.overrides?.accountAddress || options.personalAccount.address,
toHex(options.overrides?.accountSalt ?? ""),
],
});
}
Expand All @@ -59,8 +59,8 @@ export function prepareExecute(args: {
data: Hex;
}): PreparedTransaction {
const { accountContract, options, target, value, data } = args;
if (options.executeOverride) {
return options.executeOverride(target, value, data);
if (options.overrides?.execute) {
return options.overrides.execute(accountContract, target, value, data);
}
return prepareContractCall({
contract: accountContract,
Expand Down
11 changes: 8 additions & 3 deletions packages/thirdweb/src/wallets/smart/lib/paymaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getClientFetch } from "../../../utils/fetch.js";
import type {
PaymasterResult,
SmartWalletOptions,
UserOperationStruct,
UserOperation,
} from "../types.js";
import {
DEBUG,
Expand All @@ -17,17 +17,22 @@ import { hexlifyUserOp } from "./utils.js";
* @internal
*/
export async function getPaymasterAndData(args: {
userOp: UserOperationStruct;
userOp: UserOperation;
options: SmartWalletOptions;
}): Promise<PaymasterResult> {
const { userOp, options } = args;

if (options.overrides?.paymaster) {
return options.overrides?.paymaster(userOp);
}

const headers: Record<string, string> = {
"Content-Type": "application/json",
};

const client = options.client;
const paymasterUrl = getDefaultPaymasterUrl(options.chain);
const entrypoint = options.entrypointAddress ?? ENTRYPOINT_ADDRESS;
const entrypoint = options.overrides?.entrypointAddress ?? ENTRYPOINT_ADDRESS;

// Ask the paymaster to sign the transaction and return a valid paymasterAndData value.
const fetchWithHeaders = getClientFetch(client);
Expand Down
22 changes: 11 additions & 11 deletions packages/thirdweb/src/wallets/smart/lib/userop.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { keccak256, concat, type Hex, toHex, encodeAbiParameters } from "viem";
import type { SmartWalletOptions, UserOperationStruct } from "../types.js";
import { keccak256, concat, type Hex, encodeAbiParameters } from "viem";
import type { SmartWalletOptions, UserOperation } from "../types.js";
import type { SendTransactionOption } from "../../interfaces/wallet.js";
import { isContractDeployed } from "../../../utils/bytecode/is-contract-deployed.js";
import type { ThirdwebContract } from "../../../contract/contract.js";
import { encode } from "../../../transaction/actions/encode.js";
import { getDefaultGasOverrides } from "../../../gas/fee-data.js";
import { getChainIdFromChain, prepareContractCall } from "../../../index.js";
import { getChainIdFromChain } from "../../../index.js";
import { DUMMY_SIGNATURE, ENTRYPOINT_ADDRESS } from "./constants.js";
import { getPaymasterAndData } from "./paymaster.js";
import { estimateUserOpGas } from "./bundler.js";
Expand All @@ -25,7 +25,7 @@ export async function createUnsignedUserOp(args: {
accountContract: ThirdwebContract;
transaction: SendTransactionOption;
options: SmartWalletOptions;
}): Promise<UserOperationStruct> {
}): Promise<UserOperation> {
const { factoryContract, accountContract, transaction, options } = args;
const isDeployed = await isContractDeployed(accountContract);
const initCode = isDeployed
Expand Down Expand Up @@ -59,7 +59,7 @@ export async function createUnsignedUserOp(args: {
//const nonce = BigInt(transaction.nonce || randomNonce());
const nonce = randomNonce(); // FIXME getNonce should be overrideable by the wallet

const partialOp: UserOperationStruct = {
const partialOp: UserOperation = {
sender: accountContract.address,
nonce,
initCode,
Expand All @@ -82,7 +82,7 @@ export async function createUnsignedUserOp(args: {
console.log("PM", paymasterResult);
const paymasterAndData = paymasterResult.paymasterAndData;
if (paymasterAndData && paymasterAndData !== "0x") {
partialOp.paymasterAndData = paymasterAndData;
partialOp.paymasterAndData = paymasterAndData as Hex;
}
// paymaster can have the gas limits in the response
if (
Expand Down Expand Up @@ -112,7 +112,7 @@ export async function createUnsignedUserOp(args: {
paymasterResult2.paymasterAndData &&
paymasterResult2.paymasterAndData !== "0x"
) {
partialOp.paymasterAndData = paymasterResult2.paymasterAndData;
partialOp.paymasterAndData = paymasterResult2.paymasterAndData as Hex;
}
}
}
Expand All @@ -139,13 +139,13 @@ export async function createUnsignedUserOp(args: {
* @internal
*/
export async function signUserOp(args: {
userOp: UserOperationStruct;
userOp: UserOperation;
options: SmartWalletOptions;
}): Promise<UserOperationStruct> {
}): Promise<UserOperation> {
const { userOp, options } = args;
const userOpHash = getUserOpHash({
userOp,
entryPoint: options.entrypointAddress || ENTRYPOINT_ADDRESS,
entryPoint: options.overrides?.entrypointAddress || ENTRYPOINT_ADDRESS,
chainId: getChainIdFromChain(options.chain),
});
if (options.personalAccount.signMessage) {
Expand Down Expand Up @@ -179,7 +179,7 @@ async function getAccountInitCode(args: {
* @internal
*/
export function getUserOpHash(args: {
userOp: UserOperationStruct;
userOp: UserOperation;
entryPoint: string;
chainId: bigint;
}): Hex {
Expand Down
4 changes: 2 additions & 2 deletions packages/thirdweb/src/wallets/smart/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { concat, toHex } from "viem";
import type { UserOperationStruct } from "../types.js";
import type { UserOperation } from "../types.js";

const generateRandomUint192 = (): bigint => {
const rand1 = BigInt(Math.floor(Math.random() * 0x100000000));
Expand Down Expand Up @@ -28,7 +28,7 @@ export const randomNonce = () => {
/**
* @internal
*/
export async function hexlifyUserOp(userOp: UserOperationStruct): Promise<any> {
export async function hexlifyUserOp(userOp: UserOperation): Promise<any> {
return Object.keys(userOp)
.map((key) => {
let val = (userOp as any)[key];
Expand Down
32 changes: 18 additions & 14 deletions packages/thirdweb/src/wallets/smart/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Chain } from "../../chain/index.js";
import type { ThirdwebClient } from "../../client/client.js";
import type { PreparedTransaction } from "../../index.js";
import type { PreparedTransaction, ThirdwebContract } from "../../index.js";
import type { Account } from "../interfaces/wallet.js";
import type { Address, Hex } from "viem";

Expand All @@ -10,20 +10,24 @@ export type SmartWalletOptions = {
chain: Chain;
gasless: boolean;
factoryAddress: string; // TODO make this optional
accountExtraData?: string;
accountAddress?: string;
entrypointAddress?: string;
bundlerUrl?: string;
predictAddressOverride?: () => Promise<string>;
createAccountOverride?: () => PreparedTransaction;
executeOverride?: (
target: string,
value: bigint,
data: string,
) => PreparedTransaction;
overrides?: {
bundlerUrl?: string;
accountAddress?: string;
accountSalt?: string;
entrypointAddress?: string;
paymaster?: (userOp: UserOperation) => Promise<PaymasterResult>;
predictAddress?: (factoryContract: ThirdwebContract) => Promise<string>;
createAccount?: (factoryContract: ThirdwebContract) => PreparedTransaction;
execute?: (
accountContract: ThirdwebContract,
target: string,
value: bigint,
data: string,
) => PreparedTransaction;
};
};

export type UserOperationStruct = {
export type UserOperation = {
sender: Address;
nonce: bigint;
initCode: Hex | Uint8Array;
Expand All @@ -38,7 +42,7 @@ export type UserOperationStruct = {
};

export type PaymasterResult = {
paymasterAndData: Hex;
paymasterAndData: string;
preVerificationGas?: bigint;
verificationGasLimit?: bigint;
callGasLimit?: bigint;
Expand Down

0 comments on commit b7a618e

Please sign in to comment.