near-safe 0.8.8 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/cjs/decode/explain.d.ts +38 -0
- package/dist/cjs/decode/explain.js +97 -0
- package/dist/cjs/decode/index.d.ts +2 -8
- package/dist/cjs/decode/index.js +16 -50
- package/dist/cjs/decode/sign-request.d.ts +26 -0
- package/dist/cjs/decode/sign-request.js +83 -0
- package/dist/cjs/decode/util.d.ts +0 -10
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +4 -3
- package/dist/cjs/lib/bundler.d.ts +7 -2
- package/dist/cjs/lib/bundler.js +8 -12
- package/dist/cjs/lib/safe-message.d.ts +1 -3
- package/dist/cjs/lib/safe-message.js +0 -30
- package/dist/cjs/near-safe.js +2 -2
- package/dist/cjs/types/guards.d.ts +6 -0
- package/dist/cjs/types/guards.js +90 -0
- package/dist/cjs/{types.d.ts → types/index.d.ts} +5 -9
- package/dist/cjs/types/index.js +28 -0
- package/dist/cjs/util.d.ts +2 -1
- package/dist/cjs/util.js +23 -2
- package/dist/esm/decode/explain.d.ts +38 -0
- package/dist/esm/decode/explain.js +91 -0
- package/dist/esm/decode/index.d.ts +2 -8
- package/dist/esm/decode/index.js +2 -49
- package/dist/esm/decode/sign-request.d.ts +26 -0
- package/dist/esm/decode/sign-request.js +79 -0
- package/dist/esm/decode/util.d.ts +0 -10
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +3 -2
- package/dist/esm/lib/bundler.d.ts +7 -2
- package/dist/esm/lib/bundler.js +9 -13
- package/dist/esm/lib/safe-message.d.ts +1 -3
- package/dist/esm/lib/safe-message.js +1 -29
- package/dist/esm/near-safe.js +2 -2
- package/dist/esm/types/guards.d.ts +6 -0
- package/dist/esm/types/guards.js +83 -0
- package/dist/esm/{types.d.ts → types/index.d.ts} +5 -9
- package/dist/esm/{types.js → types/index.js} +1 -0
- package/dist/esm/util.d.ts +2 -1
- package/dist/esm/util.js +22 -2
- package/package.json +2 -2
- package/dist/cjs/types.js +0 -13
@@ -1,5 +1,6 @@
|
|
1
1
|
import { EIP712TypedData, EncodedSignRequest, FunctionCallTransaction, SignArgs } from "near-ca";
|
2
2
|
import { Address, Hex, ParseAbi } from "viem";
|
3
|
+
export * from "./guards";
|
3
4
|
/**
|
4
5
|
* Represents a collection of Safe contract deployments, each with its own address and ABI.
|
5
6
|
*/
|
@@ -46,24 +47,20 @@ export interface UnsignedUserOperation {
|
|
46
47
|
/**
|
47
48
|
* Supported representation of a user operation for EntryPoint version 0.7, including gas limits and signature.
|
48
49
|
*/
|
49
|
-
export interface UserOperation extends UnsignedUserOperation {
|
50
|
-
/** The gas limit for verification of the operation. */
|
51
|
-
verificationGasLimit: Hex;
|
52
|
-
/** The gas limit for the execution of the operation call. */
|
53
|
-
callGasLimit: Hex;
|
54
|
-
/** The gas used before verification begins. */
|
55
|
-
preVerificationGas: Hex;
|
50
|
+
export interface UserOperation extends UnsignedUserOperation, PaymasterData {
|
56
51
|
/** Optional signature for the user operation. */
|
57
52
|
signature?: Hex;
|
58
53
|
}
|
59
54
|
/**
|
60
55
|
* Represents additional paymaster-related data for a user operation.
|
61
56
|
*/
|
62
|
-
export interface PaymasterData {
|
57
|
+
export interface PaymasterData extends UserOperationGas {
|
63
58
|
/** Optional paymaster address responsible for covering gas costs. */
|
64
59
|
paymaster?: Address;
|
65
60
|
/** Optional additional data required by the paymaster. */
|
66
61
|
paymasterData?: Hex;
|
62
|
+
}
|
63
|
+
export interface UserOperationGas {
|
67
64
|
/** The gas limit for paymaster verification. */
|
68
65
|
paymasterVerificationGasLimit?: Hex;
|
69
66
|
/** The gas limit for paymaster post-operation execution. */
|
@@ -270,4 +267,3 @@ export interface SpendingLimit {
|
|
270
267
|
export interface ChainIds {
|
271
268
|
allowlist: number[];
|
272
269
|
}
|
273
|
-
export {};
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
|
+
};
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
17
|
+
exports.OperationType = void 0;
|
18
|
+
__exportStar(require("./guards"), exports);
|
19
|
+
/**
|
20
|
+
* Enum representing the type of operation in a meta-transaction.
|
21
|
+
*/
|
22
|
+
var OperationType;
|
23
|
+
(function (OperationType) {
|
24
|
+
/** Standard call operation (0). */
|
25
|
+
OperationType[OperationType["Call"] = 0] = "Call";
|
26
|
+
/** Delegate call operation (1). */
|
27
|
+
OperationType[OperationType["DelegateCall"] = 1] = "DelegateCall";
|
28
|
+
})(OperationType || (exports.OperationType = OperationType = {}));
|
package/dist/cjs/util.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { SessionRequestParams } from "near-ca";
|
2
2
|
import { Address, Hex, PublicClient } from "viem";
|
3
|
-
import { PaymasterData, MetaTransaction } from "./types";
|
3
|
+
import { PaymasterData, MetaTransaction, UserOperation } from "./types";
|
4
4
|
export declare const PLACEHOLDER_SIG: `0x${string}`;
|
5
5
|
type IntLike = Hex | bigint | string | number;
|
6
6
|
export declare const packGas: (hi: IntLike, lo: IntLike) => string;
|
@@ -38,4 +38,5 @@ export declare function signatureFromTxHash(txHash: string, accountId?: string):
|
|
38
38
|
*/
|
39
39
|
export declare function raceToFirstResolve<T>(promises: Promise<T>[]): Promise<T>;
|
40
40
|
export declare function assertUnique<T>(iterable: Iterable<T>, errorMessage?: string): void;
|
41
|
+
export declare function userOpTransactionCost(userOp: UserOperation): bigint;
|
41
42
|
export {};
|
package/dist/cjs/util.js
CHANGED
@@ -11,6 +11,7 @@ exports.saltNonceFromMessage = saltNonceFromMessage;
|
|
11
11
|
exports.signatureFromTxHash = signatureFromTxHash;
|
12
12
|
exports.raceToFirstResolve = raceToFirstResolve;
|
13
13
|
exports.assertUnique = assertUnique;
|
14
|
+
exports.userOpTransactionCost = userOpTransactionCost;
|
14
15
|
const near_ca_1 = require("near-ca");
|
15
16
|
const viem_1 = require("viem");
|
16
17
|
const constants_1 = require("./constants");
|
@@ -31,13 +32,13 @@ function packPaymasterData(data) {
|
|
31
32
|
: "0x");
|
32
33
|
}
|
33
34
|
function containsValue(transactions) {
|
34
|
-
return transactions.some((tx) => tx.value !==
|
35
|
+
return transactions.some((tx) => BigInt(tx.value) !== 0n);
|
35
36
|
}
|
36
37
|
async function isContract(address, chainId) {
|
37
38
|
return (await getClient(chainId).getCode({ address })) !== undefined;
|
38
39
|
}
|
39
40
|
function getClient(chainId) {
|
40
|
-
// TODO(bh2smith)
|
41
|
+
// TODO(bh2smith): Update defailt client URL in viem for sepolia.
|
41
42
|
if (chainId === 11155111) {
|
42
43
|
return (0, viem_1.createPublicClient)({ transport: (0, viem_1.http)(constants_1.DEFAULT_SETUP_RPC) });
|
43
44
|
}
|
@@ -144,3 +145,23 @@ function assertUnique(iterable, errorMessage = "The collection contains more tha
|
|
144
145
|
throw new Error(errorMessage);
|
145
146
|
}
|
146
147
|
}
|
148
|
+
function userOpTransactionCost(userOp) {
|
149
|
+
// Convert values from hex to decimal
|
150
|
+
const preVerificationGas = BigInt(userOp.preVerificationGas);
|
151
|
+
const verificationGasLimit = BigInt(userOp.verificationGasLimit);
|
152
|
+
const callGasLimit = BigInt(userOp.callGasLimit);
|
153
|
+
const paymasterVerificationGasLimit = BigInt(userOp.paymasterVerificationGasLimit || "0x0");
|
154
|
+
const paymasterPostOpGasLimit = BigInt(userOp.paymasterPostOpGasLimit || "0x0");
|
155
|
+
// Sum total gas
|
156
|
+
const totalGasUsed = preVerificationGas +
|
157
|
+
verificationGasLimit +
|
158
|
+
callGasLimit +
|
159
|
+
paymasterVerificationGasLimit +
|
160
|
+
paymasterPostOpGasLimit;
|
161
|
+
// Convert maxFeePerGas from hex to decimal
|
162
|
+
const maxFeePerGas = BigInt(userOp.maxFeePerGas);
|
163
|
+
// Calculate total cost in wei
|
164
|
+
const totalCostInWei = totalGasUsed * maxFeePerGas;
|
165
|
+
// Convert to Ether for a human-readable value
|
166
|
+
return totalCostInWei;
|
167
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { DecodedTxData, SafeEncodedSignRequest } from "../types";
|
2
|
+
/**
|
3
|
+
* Explain a Safe Signature Request.
|
4
|
+
* @param signRequest - The Safe Signature Request to explain.
|
5
|
+
* @returns The decoded transaction data as stringified JSON or null if there was an error.
|
6
|
+
*/
|
7
|
+
export declare function explainSignRequest(signRequest: SafeEncodedSignRequest): Promise<string>;
|
8
|
+
/**
|
9
|
+
* Represents a parameter in a decoded contract call.
|
10
|
+
*/
|
11
|
+
interface DecodedParameter {
|
12
|
+
/** The parameter name from the contract ABI */
|
13
|
+
name: string;
|
14
|
+
/** The parameter type (e.g., 'address', 'uint256') */
|
15
|
+
type: string;
|
16
|
+
/** The actual value of the parameter */
|
17
|
+
value: string;
|
18
|
+
}
|
19
|
+
/**
|
20
|
+
* Represents a successful response from the Safe transaction decoder.
|
21
|
+
*/
|
22
|
+
interface FunctionSignature {
|
23
|
+
/** The name of the contract method that was called */
|
24
|
+
method: string;
|
25
|
+
/** Array of decoded parameters from the function call */
|
26
|
+
parameters: DecodedParameter[];
|
27
|
+
}
|
28
|
+
/**
|
29
|
+
* Decode a transaction using the Safe Decoder API. According to this spec:
|
30
|
+
* https://safe-transaction-sepolia.safe.global/#/data-decoder/data_decoder_create
|
31
|
+
* @param data - The transaction data to decode.
|
32
|
+
* @param to - The address of the contract that was called.
|
33
|
+
* @param chainId - The chain ID of the transaction.
|
34
|
+
* @returns The decoded transaction data or null if there was an error.
|
35
|
+
*/
|
36
|
+
export declare function safeDecodeTx(data: string, to: string, chainId: number): Promise<FunctionSignature | null>;
|
37
|
+
export declare const formatEvmData: (decodedEvmData: DecodedTxData, functionSignatures?: (FunctionSignature | null)[]) => string;
|
38
|
+
export {};
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import { Network } from "near-ca";
|
2
|
+
import { decodeTxData } from ".";
|
3
|
+
/**
|
4
|
+
* Explain a Safe Signature Request.
|
5
|
+
* @param signRequest - The Safe Signature Request to explain.
|
6
|
+
* @returns The decoded transaction data as stringified JSON or null if there was an error.
|
7
|
+
*/
|
8
|
+
export async function explainSignRequest(signRequest) {
|
9
|
+
// Decode the Signature Request
|
10
|
+
const decodedEvmData = decodeTxData(signRequest);
|
11
|
+
// Decode the function signatures
|
12
|
+
const functionSignatures = await Promise.all(decodedEvmData.transactions.map((tx) => safeDecodeTx(tx.data, tx.to, decodedEvmData.chainId)));
|
13
|
+
// Format the decoded data
|
14
|
+
return formatEvmData(decodedEvmData, functionSignatures);
|
15
|
+
}
|
16
|
+
const SAFE_NETWORKS = {
|
17
|
+
1: "mainnet", // Ethereum Mainnet
|
18
|
+
10: "optimism", // Optimism Mainnet
|
19
|
+
56: "binance", // Binance Smart Chain Mainnet
|
20
|
+
97: "bsc-testnet", // Binance Smart Chain Testnet
|
21
|
+
100: "gnosis-chain", // Gnosis Chain (formerly xDAI)
|
22
|
+
137: "polygon", // Polygon Mainnet
|
23
|
+
250: "fantom", // Fantom Mainnet
|
24
|
+
288: "boba", // Boba Network Mainnet
|
25
|
+
1284: "moonbeam", // Moonbeam (Polkadot)
|
26
|
+
1285: "moonriver", // Moonriver (Kusama)
|
27
|
+
4002: "fantom-testnet", // Fantom Testnet
|
28
|
+
42161: "arbitrum", // Arbitrum One Mainnet
|
29
|
+
43113: "avalanche-fuji", // Avalanche Fuji Testnet
|
30
|
+
43114: "avalanche", // Avalanche Mainnet
|
31
|
+
80001: "polygon-mumbai", // Polygon Mumbai Testnet
|
32
|
+
8453: "base", // Base Mainnet
|
33
|
+
11155111: "sepolia", // Sepolia Testnet
|
34
|
+
1666600000: "harmony", // Harmony Mainnet
|
35
|
+
1666700000: "harmony-testnet", // Harmony Testnet
|
36
|
+
1313161554: "aurora", // Aurora Mainnet (NEAR)
|
37
|
+
1313161555: "aurora-testnet", // Aurora Testnet (NEAR)
|
38
|
+
};
|
39
|
+
/**
|
40
|
+
* Decode a transaction using the Safe Decoder API. According to this spec:
|
41
|
+
* https://safe-transaction-sepolia.safe.global/#/data-decoder/data_decoder_create
|
42
|
+
* @param data - The transaction data to decode.
|
43
|
+
* @param to - The address of the contract that was called.
|
44
|
+
* @param chainId - The chain ID of the transaction.
|
45
|
+
* @returns The decoded transaction data or null if there was an error.
|
46
|
+
*/
|
47
|
+
export async function safeDecodeTx(data, to, chainId) {
|
48
|
+
try {
|
49
|
+
const network = SAFE_NETWORKS[chainId] || SAFE_NETWORKS[1];
|
50
|
+
const response = await fetch(`https://safe-transaction-${network}.safe.global/api/v1/data-decoder/`, {
|
51
|
+
method: "POST",
|
52
|
+
headers: {
|
53
|
+
"Content-Type": "application/json",
|
54
|
+
accept: "application/json",
|
55
|
+
},
|
56
|
+
body: JSON.stringify({ data, to }),
|
57
|
+
});
|
58
|
+
// Handle different response status codes
|
59
|
+
if (response.status === 404) {
|
60
|
+
console.warn("Cannot find function selector to decode data");
|
61
|
+
return null;
|
62
|
+
}
|
63
|
+
if (response.status === 422) {
|
64
|
+
const errorData = (await response.json());
|
65
|
+
console.error("Invalid data:", errorData.message, errorData.arguments);
|
66
|
+
return null;
|
67
|
+
}
|
68
|
+
if (!response.ok) {
|
69
|
+
console.error(`Unexpected response status: ${response.status}`);
|
70
|
+
return null;
|
71
|
+
}
|
72
|
+
return (await response.json());
|
73
|
+
}
|
74
|
+
catch (error) {
|
75
|
+
const message = error instanceof Error ? error.message : String(error);
|
76
|
+
console.error("Error decoding transaction:", message);
|
77
|
+
return null;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
export const formatEvmData = (decodedEvmData, functionSignatures = []) => {
|
81
|
+
const formatted = {
|
82
|
+
...decodedEvmData,
|
83
|
+
network: Network.fromChainId(decodedEvmData.chainId).name,
|
84
|
+
functionSignatures,
|
85
|
+
};
|
86
|
+
return JSON.stringify(formatted, bigIntReplacer, 2);
|
87
|
+
};
|
88
|
+
/**
|
89
|
+
* Replaces bigint values with their string representation.
|
90
|
+
*/
|
91
|
+
const bigIntReplacer = (_, value) => typeof value === "bigint" ? value.toString() : value;
|
@@ -1,8 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
4
|
-
*
|
5
|
-
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
6
|
-
* @returns {DecodedTxData} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
7
|
-
*/
|
8
|
-
export declare function decodeTxData({ evmMessage, chainId, }: Omit<SafeEncodedSignRequest, "hashToSign">): DecodedTxData;
|
1
|
+
export * from "./explain";
|
2
|
+
export * from "./sign-request";
|
package/dist/esm/decode/index.js
CHANGED
@@ -1,49 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
/**
|
4
|
-
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
5
|
-
*
|
6
|
-
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
7
|
-
* @returns {DecodedTxData} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
8
|
-
*/
|
9
|
-
export function decodeTxData({ evmMessage, chainId, }) {
|
10
|
-
const data = evmMessage;
|
11
|
-
if (isRlpHex(evmMessage)) {
|
12
|
-
return decodeRlpHex(chainId, evmMessage);
|
13
|
-
}
|
14
|
-
if (isTransactionSerializable(data)) {
|
15
|
-
return decodeTransactionSerializable(chainId, data);
|
16
|
-
}
|
17
|
-
if (typeof data !== "string") {
|
18
|
-
return decodeTypedData(chainId, data);
|
19
|
-
}
|
20
|
-
try {
|
21
|
-
// Stringified UserOperation.
|
22
|
-
const userOp = JSON.parse(data);
|
23
|
-
return decodeUserOperation(chainId, userOp);
|
24
|
-
}
|
25
|
-
catch (error) {
|
26
|
-
if (error instanceof SyntaxError) {
|
27
|
-
// Raw message string.
|
28
|
-
return {
|
29
|
-
chainId,
|
30
|
-
costEstimate: "0",
|
31
|
-
transactions: [],
|
32
|
-
message: data,
|
33
|
-
};
|
34
|
-
}
|
35
|
-
else {
|
36
|
-
// TODO: This shouldn't happen anymore and can probably be reverted.
|
37
|
-
// We keep it here now, because near-ca might not have adapted its router.
|
38
|
-
console.warn("Failed UserOp Parsing, try TypedData Parsing", error);
|
39
|
-
try {
|
40
|
-
const typedData = JSON.parse(data);
|
41
|
-
return decodeTypedData(chainId, typedData);
|
42
|
-
}
|
43
|
-
catch (error) {
|
44
|
-
const message = error instanceof Error ? error.message : String(error);
|
45
|
-
throw new Error(`decodeTxData: Unexpected error - ${message}`);
|
46
|
-
}
|
47
|
-
}
|
48
|
-
}
|
49
|
-
}
|
1
|
+
export * from "./explain";
|
2
|
+
export * from "./sign-request";
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { EvmMessage } from "near-ca";
|
2
|
+
import { TransactionSerializable } from "viem";
|
3
|
+
import { DecodedTxData, SafeEncodedSignRequest, UserOperation } from "../types";
|
4
|
+
/**
|
5
|
+
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
6
|
+
*
|
7
|
+
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
8
|
+
* @returns {DecodedTxData} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
9
|
+
*/
|
10
|
+
export declare function decodeTxData({ evmMessage, chainId, }: Omit<SafeEncodedSignRequest, "hashToSign">): DecodedTxData;
|
11
|
+
/**
|
12
|
+
* Represents different types of broadcastable messages
|
13
|
+
*/
|
14
|
+
export type BroadcastTarget = {
|
15
|
+
type: "evm";
|
16
|
+
transaction: TransactionSerializable;
|
17
|
+
} | {
|
18
|
+
type: "bundler";
|
19
|
+
userOp: UserOperation;
|
20
|
+
};
|
21
|
+
/**
|
22
|
+
* Determines where and how an EVM message should be broadcast
|
23
|
+
* @param evmMessage - The message to be analyzed
|
24
|
+
* @returns Information about how to broadcast the message, or null if invalid
|
25
|
+
*/
|
26
|
+
export declare function determineBroadcastTarget(evmMessage: EvmMessage): BroadcastTarget | null;
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import { isRlpHex, isTransactionSerializable } from "near-ca";
|
2
|
+
import { parseTransaction } from "viem";
|
3
|
+
import { parseEip712TypedData, parseUserOperation, } from "../types";
|
4
|
+
import { decodeRlpHex, decodeTransactionSerializable, decodeTypedData, decodeUserOperation, } from "./util";
|
5
|
+
/**
|
6
|
+
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
7
|
+
*
|
8
|
+
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
9
|
+
* @returns {DecodedTxData} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
10
|
+
*/
|
11
|
+
export function decodeTxData({ evmMessage, chainId, }) {
|
12
|
+
const data = evmMessage;
|
13
|
+
if (isRlpHex(evmMessage)) {
|
14
|
+
return decodeRlpHex(chainId, evmMessage);
|
15
|
+
}
|
16
|
+
if (isTransactionSerializable(data)) {
|
17
|
+
return decodeTransactionSerializable(chainId, data);
|
18
|
+
}
|
19
|
+
const parsedTypedData = parseEip712TypedData(data);
|
20
|
+
if (parsedTypedData) {
|
21
|
+
return decodeTypedData(chainId, parsedTypedData);
|
22
|
+
}
|
23
|
+
const userOp = parseUserOperation(data);
|
24
|
+
if (userOp) {
|
25
|
+
return decodeUserOperation(chainId, userOp);
|
26
|
+
}
|
27
|
+
// At this point we are certain that the data is a string.
|
28
|
+
// Typescript would disagree here because of the EIP712TypedData possibility that remains.
|
29
|
+
// However this is captured (indirectly) by parseEip712TypedData above.
|
30
|
+
// We check now if its a string and return a reasonable default (for the case of a raw message).
|
31
|
+
if (typeof data === "string") {
|
32
|
+
return {
|
33
|
+
chainId,
|
34
|
+
costEstimate: "0",
|
35
|
+
transactions: [],
|
36
|
+
message: data,
|
37
|
+
};
|
38
|
+
}
|
39
|
+
// Otherwise we have no idea what the data is and we throw.
|
40
|
+
console.warn("Unrecognized txData format,", chainId, data);
|
41
|
+
throw new Error(`decodeTxData: Invalid or unsupported message format ${data}`);
|
42
|
+
}
|
43
|
+
/**
|
44
|
+
* Determines where and how an EVM message should be broadcast
|
45
|
+
* @param evmMessage - The message to be analyzed
|
46
|
+
* @returns Information about how to broadcast the message, or null if invalid
|
47
|
+
*/
|
48
|
+
export function determineBroadcastTarget(evmMessage) {
|
49
|
+
// Case 1: User Operation
|
50
|
+
if (typeof evmMessage === "string") {
|
51
|
+
try {
|
52
|
+
const parsed = parseUserOperation(evmMessage);
|
53
|
+
if (parsed) {
|
54
|
+
return {
|
55
|
+
type: "bundler",
|
56
|
+
userOp: parsed,
|
57
|
+
};
|
58
|
+
}
|
59
|
+
}
|
60
|
+
catch (error) {
|
61
|
+
console.warn("Failed to parse potential UserOperation:", error);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
// Case 2: RLP Encoded EVM transaction
|
65
|
+
if (isRlpHex(evmMessage)) {
|
66
|
+
return {
|
67
|
+
type: "evm",
|
68
|
+
transaction: parseTransaction(evmMessage),
|
69
|
+
};
|
70
|
+
}
|
71
|
+
// Case 3: Serializable Transaction
|
72
|
+
if (isTransactionSerializable(evmMessage)) {
|
73
|
+
return {
|
74
|
+
type: "evm",
|
75
|
+
transaction: evmMessage,
|
76
|
+
};
|
77
|
+
}
|
78
|
+
return null;
|
79
|
+
}
|
@@ -5,13 +5,3 @@ export declare function decodeTransactionSerializable(chainId: number, tx: Trans
|
|
5
5
|
export declare function decodeRlpHex(chainId: number, tx: Hex): DecodedTxData;
|
6
6
|
export declare function decodeTypedData(chainId: number, data: EIP712TypedData): DecodedTxData;
|
7
7
|
export declare function decodeUserOperation(chainId: number, userOp: UserOperation): DecodedTxData;
|
8
|
-
export declare enum OperationType {
|
9
|
-
Call = 0,
|
10
|
-
DelegateCall = 1
|
11
|
-
}
|
12
|
-
export interface MetaTransaction {
|
13
|
-
readonly to: string;
|
14
|
-
readonly value: string;
|
15
|
-
readonly data: string;
|
16
|
-
readonly operation?: OperationType;
|
17
|
-
}
|
package/dist/esm/index.d.ts
CHANGED
@@ -2,6 +2,6 @@ export * from "./near-safe";
|
|
2
2
|
export * from "./types";
|
3
3
|
export * from "./util";
|
4
4
|
export * from "./constants";
|
5
|
-
export
|
5
|
+
export * from "./decode";
|
6
6
|
export * from "./lib/safe-message";
|
7
|
-
export { Network, BaseTx, SignRequestData, populateTx, NetworkFields, signatureFromOutcome, signatureFromTxHash, requestRouter as mpcRequestRouter, EthTransactionParams, } from "near-ca";
|
7
|
+
export { Network, BaseTx, SignRequestData, populateTx, NetworkFields, signatureFromOutcome, signatureFromTxHash, requestRouter as mpcRequestRouter, EthTransactionParams, isRlpHex, } from "near-ca";
|
package/dist/esm/index.js
CHANGED
@@ -2,6 +2,7 @@ export * from "./near-safe";
|
|
2
2
|
export * from "./types";
|
3
3
|
export * from "./util";
|
4
4
|
export * from "./constants";
|
5
|
-
export
|
5
|
+
export * from "./decode";
|
6
6
|
export * from "./lib/safe-message";
|
7
|
-
|
7
|
+
// TODO: Improve re-exports...
|
8
|
+
export { Network, populateTx, signatureFromOutcome, signatureFromTxHash, requestRouter as mpcRequestRouter, isRlpHex, } from "near-ca";
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Address, Hash, PublicClient, Transport } from "viem";
|
2
|
-
import { GasPrices, PaymasterData, SponsorshipPolicyData, UnsignedUserOperation, UserOperation, UserOperationReceipt } from "../types";
|
2
|
+
import { GasPrices, PaymasterData, SponsorshipPolicyData, UnsignedUserOperation, UserOperation, UserOperationGas, UserOperationReceipt } from "../types";
|
3
3
|
type SponsorshipPolicy = {
|
4
4
|
sponsorshipPolicyId: string;
|
5
5
|
};
|
@@ -9,6 +9,11 @@ type BundlerRpcSchema = [
|
|
9
9
|
Parameters: [UnsignedUserOperation, Address, SponsorshipPolicy];
|
10
10
|
ReturnType: PaymasterData;
|
11
11
|
},
|
12
|
+
{
|
13
|
+
Method: "eth_estimateUserOperationGas";
|
14
|
+
Parameters: [UnsignedUserOperation, Address];
|
15
|
+
ReturnType: UserOperationGas;
|
16
|
+
},
|
12
17
|
{
|
13
18
|
Method: "eth_sendUserOperation";
|
14
19
|
Parameters: [UserOperation, Address];
|
@@ -31,7 +36,7 @@ export declare class Erc4337Bundler {
|
|
31
36
|
apiKey: string;
|
32
37
|
chainId: number;
|
33
38
|
constructor(entryPointAddress: Address, apiKey: string, chainId: number);
|
34
|
-
getPaymasterData(rawUserOp: UnsignedUserOperation,
|
39
|
+
getPaymasterData(rawUserOp: UnsignedUserOperation, sponsorshipPolicy?: string): Promise<PaymasterData>;
|
35
40
|
sendUserOperation(userOp: UserOperation): Promise<Hash>;
|
36
41
|
getGasPrice(): Promise<GasPrices>;
|
37
42
|
getUserOpReceipt(userOpHash: Hash): Promise<UserOperationReceipt>;
|
package/dist/esm/lib/bundler.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { createPublicClient, http, rpcSchema,
|
1
|
+
import { createPublicClient, http, rpcSchema, RpcError, HttpRequestError, } from "viem";
|
2
2
|
import { PLACEHOLDER_SIG } from "../util";
|
3
3
|
function bundlerUrl(chainId, apikey) {
|
4
4
|
return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${apikey}`;
|
@@ -17,20 +17,24 @@ export class Erc4337Bundler {
|
|
17
17
|
rpcSchema: rpcSchema(),
|
18
18
|
});
|
19
19
|
}
|
20
|
-
async getPaymasterData(rawUserOp,
|
21
|
-
|
20
|
+
async getPaymasterData(rawUserOp, sponsorshipPolicy) {
|
21
|
+
const userOp = { ...rawUserOp, signature: PLACEHOLDER_SIG };
|
22
22
|
if (sponsorshipPolicy) {
|
23
23
|
console.log("Requesting paymaster data...");
|
24
24
|
return handleRequest(() => this.client.request({
|
25
25
|
method: "pm_sponsorUserOperation",
|
26
26
|
params: [
|
27
|
-
|
27
|
+
userOp,
|
28
28
|
this.entryPointAddress,
|
29
29
|
{ sponsorshipPolicyId: sponsorshipPolicy },
|
30
30
|
],
|
31
31
|
}));
|
32
32
|
}
|
33
|
-
|
33
|
+
console.log("Estimating user operation gas...");
|
34
|
+
return handleRequest(() => this.client.request({
|
35
|
+
method: "eth_estimateUserOperationGas",
|
36
|
+
params: [userOp, this.entryPointAddress],
|
37
|
+
}));
|
34
38
|
}
|
35
39
|
async sendUserOperation(userOp) {
|
36
40
|
return handleRequest(() => this.client.request({
|
@@ -93,14 +97,6 @@ async function handleRequest(clientMethod) {
|
|
93
97
|
throw new Error(`Bundler Request: ${message}`);
|
94
98
|
}
|
95
99
|
}
|
96
|
-
// TODO(bh2smith) Should probably get reasonable estimates here:
|
97
|
-
const defaultPaymasterData = (safeNotDeployed) => {
|
98
|
-
return {
|
99
|
-
verificationGasLimit: toHex(safeNotDeployed ? 500000 : 100000),
|
100
|
-
callGasLimit: toHex(100000),
|
101
|
-
preVerificationGas: toHex(100000),
|
102
|
-
};
|
103
|
-
};
|
104
100
|
export function stripApiKey(error) {
|
105
101
|
const message = error instanceof Error ? error.message : String(error);
|
106
102
|
return message.replace(/(apikey=)[^\s&]+/, "$1***");
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { type SafeInfo } from "@safe-global/safe-gateway-typescript-sdk";
|
2
2
|
import { EIP712TypedData } from "near-ca";
|
3
|
-
import { Hash
|
3
|
+
import { Hash } from "viem";
|
4
4
|
export type DecodedSafeMessage = {
|
5
5
|
decodedMessage: string | EIP712TypedData;
|
6
6
|
safeMessageMessage: string;
|
@@ -20,5 +20,3 @@ export type MinimalSafeInfo = Pick<SafeInfo, "address" | "version" | "chainId">;
|
|
20
20
|
* }`
|
21
21
|
*/
|
22
22
|
export declare function decodeSafeMessage(message: string | EIP712TypedData, safe: MinimalSafeInfo): DecodedSafeMessage;
|
23
|
-
export declare function isTransactionSerializable(data: unknown): data is TransactionSerializable;
|
24
|
-
export declare function isRlpHex(data: unknown): data is Hex;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { gte } from "semver";
|
2
|
-
import { fromHex, hashMessage, hashTypedData, isHex,
|
2
|
+
import { fromHex, hashMessage, hashTypedData, isHex, } from "viem";
|
3
3
|
/*
|
4
4
|
* From v1.3.0, EIP-1271 support was moved to the CompatibilityFallbackHandler.
|
5
5
|
* Also 1.3.0 introduces the chainId in the domain part of the SafeMessage
|
@@ -79,33 +79,5 @@ export function decodeSafeMessage(message, safe) {
|
|
79
79
|
safeMessageHash: generateSafeMessageHash(safe, decodedMessage),
|
80
80
|
};
|
81
81
|
}
|
82
|
-
// const isEIP712TypedData = (obj: any): obj is EIP712TypedData => {
|
83
|
-
// return (
|
84
|
-
// typeof obj === "object" &&
|
85
|
-
// obj != null &&
|
86
|
-
// "domain" in obj &&
|
87
|
-
// "types" in obj &&
|
88
|
-
// "message" in obj
|
89
|
-
// );
|
90
|
-
// };
|
91
82
|
// export const isBlindSigningPayload = (obj: EIP712TypedData | string): boolean =>
|
92
83
|
// !isEIP712TypedData(obj) && isHash(obj);
|
93
|
-
// Cheeky attempt to serialize. return true if successful!
|
94
|
-
export function isTransactionSerializable(data) {
|
95
|
-
try {
|
96
|
-
serializeTransaction(data);
|
97
|
-
return true;
|
98
|
-
}
|
99
|
-
catch (error) {
|
100
|
-
return false;
|
101
|
-
}
|
102
|
-
}
|
103
|
-
export function isRlpHex(data) {
|
104
|
-
try {
|
105
|
-
parseTransaction(data);
|
106
|
-
return true;
|
107
|
-
}
|
108
|
-
catch (error) {
|
109
|
-
return false;
|
110
|
-
}
|
111
|
-
}
|
package/dist/esm/near-safe.js
CHANGED
@@ -103,7 +103,7 @@ export class NearSafe {
|
|
103
103
|
// Build Singular MetaTransaction for Multisend from transaction list.
|
104
104
|
const tx = transactions.length > 1 ? encodeMulti(transactions) : transactions[0];
|
105
105
|
const rawUserOp = await this.safePack.buildUserOp(nonce, tx, this.address, gasFees.fast, this.setup, !safeDeployed, this.safeSaltNonce);
|
106
|
-
const paymasterData = await bundler.getPaymasterData(rawUserOp,
|
106
|
+
const paymasterData = await bundler.getPaymasterData(rawUserOp, sponsorshipPolicy);
|
107
107
|
const unsignedUserOp = { ...rawUserOp, ...paymasterData };
|
108
108
|
return unsignedUserOp;
|
109
109
|
}
|
@@ -239,7 +239,7 @@ export class NearSafe {
|
|
239
239
|
async removeOwnerTx(chainId, address) {
|
240
240
|
return {
|
241
241
|
to: this.address,
|
242
|
-
value: "
|
242
|
+
value: "0x00",
|
243
243
|
data: await this.safePack.removeOwnerData(chainId, this.address, address),
|
244
244
|
};
|
245
245
|
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { EIP712TypedData } from "near-ca";
|
2
|
+
import { UserOperation } from ".";
|
3
|
+
export declare const isUserOperation: (data: unknown) => data is UserOperation;
|
4
|
+
export declare const parseWithTypeGuard: <T>(data: unknown, typeGuard: (value: unknown) => value is T) => T | null;
|
5
|
+
export declare const parseUserOperation: (data: unknown) => UserOperation | null;
|
6
|
+
export declare const parseEip712TypedData: (data: unknown) => EIP712TypedData | null;
|