updates: UserOp example + receipt retrieval function (#3712)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user