updates: UserOp example + receipt retrieval function (#3712)

This commit is contained in:
Farhan Khwaja
2024-07-16 22:32:35 -07:00
committed by GitHub
parent 39b329a56e
commit c5b97407b0
6 changed files with 135 additions and 16 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---
updated getUserOpReceipt & waitForUserOpReceipt to use a decodeRevertReason flag. Updated example for createUnsignedUserOp & signUserOp. Exposed getPaymasterAndData for Paymaster
@@ -8,6 +8,7 @@ export {
export {
getUserOpReceipt,
getUserOpReceiptRaw,
bundleUserOp,
getUserOpGasFees,
estimateUserOpGas,
@@ -15,6 +16,8 @@ export {
export { predictAddress } from "../../wallets/smart/lib/calls.js";
export { getPaymasterAndData } from "../../wallets/smart/lib/paymaster.js";
export type {
SmartWalletConnectionOptions,
SmartWalletOptions,
@@ -5,12 +5,14 @@ import type { TransactionReceipt } from "../../../transaction/types.js";
import { type Hex, hexToBigInt } from "../../../utils/encoding/hex.js";
import { getClientFetch } from "../../../utils/fetch.js";
import { stringify } from "../../../utils/json.js";
import type {
BundlerOptions,
EstimationResult,
GasPriceResult,
PmTransactionData,
UserOperation,
import {
type BundlerOptions,
type EstimationResult,
type GasPriceResult,
type PmTransactionData,
type UserOperation,
type UserOperationReceipt,
formatUserOperationReceipt,
} from "../types.js";
import {
DEBUG,
@@ -136,14 +138,12 @@ export async function getUserOpReceipt(
userOpHash: Hex;
},
): Promise<TransactionReceipt | undefined> {
const res = await sendBundlerRequest({
options: args,
operation: "eth_getUserOperationReceipt",
params: [args.userOpHash],
});
const res = await getUserOpReceiptRaw(args);
if (!res) {
return undefined;
}
if (res.success === false) {
// parse revert reason
const logs = parseEventLogs({
@@ -152,20 +152,54 @@ export async function getUserOpReceipt(
});
const revertReason = logs[0]?.args?.revertReason;
if (!revertReason) {
throw new Error(`UserOp failed at txHash: ${res.transactionHash}`);
throw new Error(
`UserOp failed at txHash: ${res.receipt.transactionHash}`,
);
}
const revertMsg = decodeErrorResult({
data: revertReason,
});
throw new Error(
`UserOp failed with reason: '${revertMsg.args.join(",")}' at txHash: ${
res.transactionHash
res.receipt.transactionHash
}`,
);
}
return res.receipt;
}
/**
* Get the receipt of a user operation.
* @param args - The options for getting the receipt of a user operation.
* @returns The raw receipt of the user operation.
* @example
* ```ts
* import { getUserOpReceiptRaw } from "thirdweb/wallets/smart";
*
* const receipt = await getUserOpReceiptRaw({
* client,
* chain,
* userOpHash,
* });
* ```
* @walletUtils
*/
export async function getUserOpReceiptRaw(
args: BundlerOptions & {
userOpHash: Hex;
},
): Promise<UserOperationReceipt | undefined> {
const res = await sendBundlerRequest({
options: args,
operation: "eth_getUserOperationReceipt",
params: [args.userOpHash],
});
if (!res) {
return undefined;
}
return formatUserOperationReceipt(res as UserOperationReceipt);
}
/**
* @internal
*/
@@ -11,8 +11,22 @@ import {
import { hexlifyUserOp } from "./utils.js";
/**
* TODO Docs
* @internal
* Get paymaster and data details for a user operation.
* @param args - The userOp and options
* @returns - The paymaster and data details for the user operation.
* @example
* ```ts
* import { getPaymasterAndData } from "thirdweb/wallets/smart";
*
* const userOp = createUnsignedUserOp(...);
*
* const paymasterAndData = await getPaymasterAndData({
* userOp,
* client,
* chain,
* });
* ```
* @walletUtils
*/
export async function getPaymasterAndData(args: {
userOp: UserOperation;
@@ -81,7 +81,9 @@ export async function waitForUserOpReceipt(
*
* const userOp = await createUnsignedUserOp({
* transaction,
* factoryContract,
* accountContract,
* adminAddress,
* sponsorGas,
* overrides,
* });
@@ -246,7 +248,8 @@ export async function createUnsignedUserOp(args: {
*
* const signedUserOp = await signUserOp({
* userOp,
* options,
* chain,
* adminAccount,
* });
* ```
* @walletUtils
@@ -3,6 +3,7 @@ import type { Chain } from "../../chains/types.js";
import type { ThirdwebClient } from "../../client/client.js";
import type { ThirdwebContract } from "../../contract/contract.js";
import type { PreparedTransaction } from "../../transaction/prepare-transaction.js";
import type { TransactionReceipt } from "../../transaction/types.js";
import type { Hex } from "../../utils/encoding/hex.js";
import type { Prettify } from "../../utils/type-utils.js";
import type { Account, SendTransactionOption } from "../interfaces/wallet.js";
@@ -119,3 +120,62 @@ export type PmTransactionData = {
paymaster: Address;
paymasterInput: Hex;
};
export type UserOperationReceipt = {
receipt: TransactionReceipt;
logs: TransactionReceipt["logs"];
userOpHash: Hex;
entryPoint: Address;
sender: Address;
nonce: bigint;
paymaster: Address;
actualGasUsed: bigint;
actualGasCost: bigint;
success: boolean;
};
export function formatUserOperationReceipt(
userOpReceiptRaw: UserOperationReceipt,
) {
const { receipt: transactionReceipt } = userOpReceiptRaw;
const receipt = {
...transactionReceipt,
transactionHash: transactionReceipt.transactionHash,
blockNumber: transactionReceipt.blockNumber
? BigInt(transactionReceipt.blockNumber)
: null,
contractAddress: transactionReceipt.contractAddress
? transactionReceipt.contractAddress
: null,
cumulativeGasUsed: transactionReceipt.cumulativeGasUsed
? BigInt(transactionReceipt.cumulativeGasUsed)
: null,
effectiveGasPrice: transactionReceipt.effectiveGasPrice
? BigInt(transactionReceipt.effectiveGasPrice)
: null,
gasUsed: transactionReceipt.gasUsed
? BigInt(transactionReceipt.gasUsed)
: null,
logs: transactionReceipt.logs,
to: transactionReceipt.to ? transactionReceipt.to : null,
transactionIndex: transactionReceipt.transactionIndex,
status: transactionReceipt.status,
type: transactionReceipt.type,
} as TransactionReceipt;
if (transactionReceipt.blobGasPrice)
receipt.blobGasPrice = BigInt(transactionReceipt.blobGasPrice);
if (transactionReceipt.blobGasUsed)
receipt.blobGasUsed = BigInt(transactionReceipt.blobGasUsed);
const userOpReceipt = {
...userOpReceiptRaw,
receipt,
userOpHash: userOpReceiptRaw.userOpHash,
actualGasCost: BigInt(userOpReceiptRaw.actualGasCost),
actualGasUsed: BigInt(userOpReceiptRaw.actualGasUsed),
nonce: BigInt(userOpReceiptRaw.nonce),
} as UserOperationReceipt;
return userOpReceipt;
}