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
@@ -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,97 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.formatEvmData = void 0;
|
4
|
+
exports.explainSignRequest = explainSignRequest;
|
5
|
+
exports.safeDecodeTx = safeDecodeTx;
|
6
|
+
const near_ca_1 = require("near-ca");
|
7
|
+
const _1 = require(".");
|
8
|
+
/**
|
9
|
+
* Explain a Safe Signature Request.
|
10
|
+
* @param signRequest - The Safe Signature Request to explain.
|
11
|
+
* @returns The decoded transaction data as stringified JSON or null if there was an error.
|
12
|
+
*/
|
13
|
+
async function explainSignRequest(signRequest) {
|
14
|
+
// Decode the Signature Request
|
15
|
+
const decodedEvmData = (0, _1.decodeTxData)(signRequest);
|
16
|
+
// Decode the function signatures
|
17
|
+
const functionSignatures = await Promise.all(decodedEvmData.transactions.map((tx) => safeDecodeTx(tx.data, tx.to, decodedEvmData.chainId)));
|
18
|
+
// Format the decoded data
|
19
|
+
return (0, exports.formatEvmData)(decodedEvmData, functionSignatures);
|
20
|
+
}
|
21
|
+
const SAFE_NETWORKS = {
|
22
|
+
1: "mainnet", // Ethereum Mainnet
|
23
|
+
10: "optimism", // Optimism Mainnet
|
24
|
+
56: "binance", // Binance Smart Chain Mainnet
|
25
|
+
97: "bsc-testnet", // Binance Smart Chain Testnet
|
26
|
+
100: "gnosis-chain", // Gnosis Chain (formerly xDAI)
|
27
|
+
137: "polygon", // Polygon Mainnet
|
28
|
+
250: "fantom", // Fantom Mainnet
|
29
|
+
288: "boba", // Boba Network Mainnet
|
30
|
+
1284: "moonbeam", // Moonbeam (Polkadot)
|
31
|
+
1285: "moonriver", // Moonriver (Kusama)
|
32
|
+
4002: "fantom-testnet", // Fantom Testnet
|
33
|
+
42161: "arbitrum", // Arbitrum One Mainnet
|
34
|
+
43113: "avalanche-fuji", // Avalanche Fuji Testnet
|
35
|
+
43114: "avalanche", // Avalanche Mainnet
|
36
|
+
80001: "polygon-mumbai", // Polygon Mumbai Testnet
|
37
|
+
8453: "base", // Base Mainnet
|
38
|
+
11155111: "sepolia", // Sepolia Testnet
|
39
|
+
1666600000: "harmony", // Harmony Mainnet
|
40
|
+
1666700000: "harmony-testnet", // Harmony Testnet
|
41
|
+
1313161554: "aurora", // Aurora Mainnet (NEAR)
|
42
|
+
1313161555: "aurora-testnet", // Aurora Testnet (NEAR)
|
43
|
+
};
|
44
|
+
/**
|
45
|
+
* Decode a transaction using the Safe Decoder API. According to this spec:
|
46
|
+
* https://safe-transaction-sepolia.safe.global/#/data-decoder/data_decoder_create
|
47
|
+
* @param data - The transaction data to decode.
|
48
|
+
* @param to - The address of the contract that was called.
|
49
|
+
* @param chainId - The chain ID of the transaction.
|
50
|
+
* @returns The decoded transaction data or null if there was an error.
|
51
|
+
*/
|
52
|
+
async function safeDecodeTx(data, to, chainId) {
|
53
|
+
try {
|
54
|
+
const network = SAFE_NETWORKS[chainId] || SAFE_NETWORKS[1];
|
55
|
+
const response = await fetch(`https://safe-transaction-${network}.safe.global/api/v1/data-decoder/`, {
|
56
|
+
method: "POST",
|
57
|
+
headers: {
|
58
|
+
"Content-Type": "application/json",
|
59
|
+
accept: "application/json",
|
60
|
+
},
|
61
|
+
body: JSON.stringify({ data, to }),
|
62
|
+
});
|
63
|
+
// Handle different response status codes
|
64
|
+
if (response.status === 404) {
|
65
|
+
console.warn("Cannot find function selector to decode data");
|
66
|
+
return null;
|
67
|
+
}
|
68
|
+
if (response.status === 422) {
|
69
|
+
const errorData = (await response.json());
|
70
|
+
console.error("Invalid data:", errorData.message, errorData.arguments);
|
71
|
+
return null;
|
72
|
+
}
|
73
|
+
if (!response.ok) {
|
74
|
+
console.error(`Unexpected response status: ${response.status}`);
|
75
|
+
return null;
|
76
|
+
}
|
77
|
+
return (await response.json());
|
78
|
+
}
|
79
|
+
catch (error) {
|
80
|
+
const message = error instanceof Error ? error.message : String(error);
|
81
|
+
console.error("Error decoding transaction:", message);
|
82
|
+
return null;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
const formatEvmData = (decodedEvmData, functionSignatures = []) => {
|
86
|
+
const formatted = {
|
87
|
+
...decodedEvmData,
|
88
|
+
network: near_ca_1.Network.fromChainId(decodedEvmData.chainId).name,
|
89
|
+
functionSignatures,
|
90
|
+
};
|
91
|
+
return JSON.stringify(formatted, bigIntReplacer, 2);
|
92
|
+
};
|
93
|
+
exports.formatEvmData = formatEvmData;
|
94
|
+
/**
|
95
|
+
* Replaces bigint values with their string representation.
|
96
|
+
*/
|
97
|
+
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/cjs/decode/index.js
CHANGED
@@ -1,52 +1,18 @@
|
|
1
1
|
"use strict";
|
2
|
-
Object.
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
8
|
-
*
|
9
|
-
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
10
|
-
* @returns {DecodedTxData} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
11
|
-
*/
|
12
|
-
function decodeTxData({ evmMessage, chainId, }) {
|
13
|
-
const data = evmMessage;
|
14
|
-
if ((0, safe_message_1.isRlpHex)(evmMessage)) {
|
15
|
-
return (0, util_1.decodeRlpHex)(chainId, evmMessage);
|
16
|
-
}
|
17
|
-
if ((0, safe_message_1.isTransactionSerializable)(data)) {
|
18
|
-
return (0, util_1.decodeTransactionSerializable)(chainId, data);
|
19
|
-
}
|
20
|
-
if (typeof data !== "string") {
|
21
|
-
return (0, util_1.decodeTypedData)(chainId, data);
|
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]; } };
|
22
7
|
}
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
transactions: [],
|
35
|
-
message: data,
|
36
|
-
};
|
37
|
-
}
|
38
|
-
else {
|
39
|
-
// TODO: This shouldn't happen anymore and can probably be reverted.
|
40
|
-
// We keep it here now, because near-ca might not have adapted its router.
|
41
|
-
console.warn("Failed UserOp Parsing, try TypedData Parsing", error);
|
42
|
-
try {
|
43
|
-
const typedData = JSON.parse(data);
|
44
|
-
return (0, util_1.decodeTypedData)(chainId, typedData);
|
45
|
-
}
|
46
|
-
catch (error) {
|
47
|
-
const message = error instanceof Error ? error.message : String(error);
|
48
|
-
throw new Error(`decodeTxData: Unexpected error - ${message}`);
|
49
|
-
}
|
50
|
-
}
|
51
|
-
}
|
52
|
-
}
|
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
|
+
__exportStar(require("./explain"), exports);
|
18
|
+
__exportStar(require("./sign-request"), exports);
|
@@ -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,83 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.decodeTxData = decodeTxData;
|
4
|
+
exports.determineBroadcastTarget = determineBroadcastTarget;
|
5
|
+
const near_ca_1 = require("near-ca");
|
6
|
+
const viem_1 = require("viem");
|
7
|
+
const types_1 = require("../types");
|
8
|
+
const util_1 = require("./util");
|
9
|
+
/**
|
10
|
+
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
11
|
+
*
|
12
|
+
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
13
|
+
* @returns {DecodedTxData} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
14
|
+
*/
|
15
|
+
function decodeTxData({ evmMessage, chainId, }) {
|
16
|
+
const data = evmMessage;
|
17
|
+
if ((0, near_ca_1.isRlpHex)(evmMessage)) {
|
18
|
+
return (0, util_1.decodeRlpHex)(chainId, evmMessage);
|
19
|
+
}
|
20
|
+
if ((0, near_ca_1.isTransactionSerializable)(data)) {
|
21
|
+
return (0, util_1.decodeTransactionSerializable)(chainId, data);
|
22
|
+
}
|
23
|
+
const parsedTypedData = (0, types_1.parseEip712TypedData)(data);
|
24
|
+
if (parsedTypedData) {
|
25
|
+
return (0, util_1.decodeTypedData)(chainId, parsedTypedData);
|
26
|
+
}
|
27
|
+
const userOp = (0, types_1.parseUserOperation)(data);
|
28
|
+
if (userOp) {
|
29
|
+
return (0, util_1.decodeUserOperation)(chainId, userOp);
|
30
|
+
}
|
31
|
+
// At this point we are certain that the data is a string.
|
32
|
+
// Typescript would disagree here because of the EIP712TypedData possibility that remains.
|
33
|
+
// However this is captured (indirectly) by parseEip712TypedData above.
|
34
|
+
// We check now if its a string and return a reasonable default (for the case of a raw message).
|
35
|
+
if (typeof data === "string") {
|
36
|
+
return {
|
37
|
+
chainId,
|
38
|
+
costEstimate: "0",
|
39
|
+
transactions: [],
|
40
|
+
message: data,
|
41
|
+
};
|
42
|
+
}
|
43
|
+
// Otherwise we have no idea what the data is and we throw.
|
44
|
+
console.warn("Unrecognized txData format,", chainId, data);
|
45
|
+
throw new Error(`decodeTxData: Invalid or unsupported message format ${data}`);
|
46
|
+
}
|
47
|
+
/**
|
48
|
+
* Determines where and how an EVM message should be broadcast
|
49
|
+
* @param evmMessage - The message to be analyzed
|
50
|
+
* @returns Information about how to broadcast the message, or null if invalid
|
51
|
+
*/
|
52
|
+
function determineBroadcastTarget(evmMessage) {
|
53
|
+
// Case 1: User Operation
|
54
|
+
if (typeof evmMessage === "string") {
|
55
|
+
try {
|
56
|
+
const parsed = (0, types_1.parseUserOperation)(evmMessage);
|
57
|
+
if (parsed) {
|
58
|
+
return {
|
59
|
+
type: "bundler",
|
60
|
+
userOp: parsed,
|
61
|
+
};
|
62
|
+
}
|
63
|
+
}
|
64
|
+
catch (error) {
|
65
|
+
console.warn("Failed to parse potential UserOperation:", error);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
// Case 2: RLP Encoded EVM transaction
|
69
|
+
if ((0, near_ca_1.isRlpHex)(evmMessage)) {
|
70
|
+
return {
|
71
|
+
type: "evm",
|
72
|
+
transaction: (0, viem_1.parseTransaction)(evmMessage),
|
73
|
+
};
|
74
|
+
}
|
75
|
+
// Case 3: Serializable Transaction
|
76
|
+
if ((0, near_ca_1.isTransactionSerializable)(evmMessage)) {
|
77
|
+
return {
|
78
|
+
type: "evm",
|
79
|
+
transaction: evmMessage,
|
80
|
+
};
|
81
|
+
}
|
82
|
+
return null;
|
83
|
+
}
|
@@ -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/cjs/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/cjs/index.js
CHANGED
@@ -14,17 +14,18 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
15
|
};
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
|
-
exports.mpcRequestRouter = exports.signatureFromTxHash = exports.signatureFromOutcome = exports.populateTx = exports.Network =
|
17
|
+
exports.isRlpHex = exports.mpcRequestRouter = exports.signatureFromTxHash = exports.signatureFromOutcome = exports.populateTx = exports.Network = void 0;
|
18
18
|
__exportStar(require("./near-safe"), exports);
|
19
19
|
__exportStar(require("./types"), exports);
|
20
20
|
__exportStar(require("./util"), exports);
|
21
21
|
__exportStar(require("./constants"), exports);
|
22
|
-
|
23
|
-
Object.defineProperty(exports, "decodeTxData", { enumerable: true, get: function () { return decode_1.decodeTxData; } });
|
22
|
+
__exportStar(require("./decode"), exports);
|
24
23
|
__exportStar(require("./lib/safe-message"), exports);
|
24
|
+
// TODO: Improve re-exports...
|
25
25
|
var near_ca_1 = require("near-ca");
|
26
26
|
Object.defineProperty(exports, "Network", { enumerable: true, get: function () { return near_ca_1.Network; } });
|
27
27
|
Object.defineProperty(exports, "populateTx", { enumerable: true, get: function () { return near_ca_1.populateTx; } });
|
28
28
|
Object.defineProperty(exports, "signatureFromOutcome", { enumerable: true, get: function () { return near_ca_1.signatureFromOutcome; } });
|
29
29
|
Object.defineProperty(exports, "signatureFromTxHash", { enumerable: true, get: function () { return near_ca_1.signatureFromTxHash; } });
|
30
30
|
Object.defineProperty(exports, "mpcRequestRouter", { enumerable: true, get: function () { return near_ca_1.requestRouter; } });
|
31
|
+
Object.defineProperty(exports, "isRlpHex", { enumerable: true, get: function () { return near_ca_1.isRlpHex; } });
|
@@ -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/cjs/lib/bundler.js
CHANGED
@@ -17,20 +17,24 @@ class Erc4337Bundler {
|
|
17
17
|
rpcSchema: (0, viem_1.rpcSchema)(),
|
18
18
|
});
|
19
19
|
}
|
20
|
-
async getPaymasterData(rawUserOp,
|
21
|
-
|
20
|
+
async getPaymasterData(rawUserOp, sponsorshipPolicy) {
|
21
|
+
const userOp = { ...rawUserOp, signature: util_1.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({
|
@@ -94,14 +98,6 @@ async function handleRequest(clientMethod) {
|
|
94
98
|
throw new Error(`Bundler Request: ${message}`);
|
95
99
|
}
|
96
100
|
}
|
97
|
-
// TODO(bh2smith) Should probably get reasonable estimates here:
|
98
|
-
const defaultPaymasterData = (safeNotDeployed) => {
|
99
|
-
return {
|
100
|
-
verificationGasLimit: (0, viem_1.toHex)(safeNotDeployed ? 500000 : 100000),
|
101
|
-
callGasLimit: (0, viem_1.toHex)(100000),
|
102
|
-
preVerificationGas: (0, viem_1.toHex)(100000),
|
103
|
-
};
|
104
|
-
};
|
105
101
|
function stripApiKey(error) {
|
106
102
|
const message = error instanceof Error ? error.message : String(error);
|
107
103
|
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,8 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.decodeSafeMessage = decodeSafeMessage;
|
4
|
-
exports.isTransactionSerializable = isTransactionSerializable;
|
5
|
-
exports.isRlpHex = isRlpHex;
|
6
4
|
const semver_1 = require("semver");
|
7
5
|
const viem_1 = require("viem");
|
8
6
|
/*
|
@@ -84,33 +82,5 @@ function decodeSafeMessage(message, safe) {
|
|
84
82
|
safeMessageHash: generateSafeMessageHash(safe, decodedMessage),
|
85
83
|
};
|
86
84
|
}
|
87
|
-
// const isEIP712TypedData = (obj: any): obj is EIP712TypedData => {
|
88
|
-
// return (
|
89
|
-
// typeof obj === "object" &&
|
90
|
-
// obj != null &&
|
91
|
-
// "domain" in obj &&
|
92
|
-
// "types" in obj &&
|
93
|
-
// "message" in obj
|
94
|
-
// );
|
95
|
-
// };
|
96
85
|
// export const isBlindSigningPayload = (obj: EIP712TypedData | string): boolean =>
|
97
86
|
// !isEIP712TypedData(obj) && isHash(obj);
|
98
|
-
// Cheeky attempt to serialize. return true if successful!
|
99
|
-
function isTransactionSerializable(data) {
|
100
|
-
try {
|
101
|
-
(0, viem_1.serializeTransaction)(data);
|
102
|
-
return true;
|
103
|
-
}
|
104
|
-
catch (error) {
|
105
|
-
return false;
|
106
|
-
}
|
107
|
-
}
|
108
|
-
function isRlpHex(data) {
|
109
|
-
try {
|
110
|
-
(0, viem_1.parseTransaction)(data);
|
111
|
-
return true;
|
112
|
-
}
|
113
|
-
catch (error) {
|
114
|
-
return false;
|
115
|
-
}
|
116
|
-
}
|
package/dist/cjs/near-safe.js
CHANGED
@@ -100,7 +100,7 @@ class NearSafe {
|
|
100
100
|
// Build Singular MetaTransaction for Multisend from transaction list.
|
101
101
|
const tx = transactions.length > 1 ? (0, multisend_1.encodeMulti)(transactions) : transactions[0];
|
102
102
|
const rawUserOp = await this.safePack.buildUserOp(nonce, tx, this.address, gasFees.fast, this.setup, !safeDeployed, this.safeSaltNonce);
|
103
|
-
const paymasterData = await bundler.getPaymasterData(rawUserOp,
|
103
|
+
const paymasterData = await bundler.getPaymasterData(rawUserOp, sponsorshipPolicy);
|
104
104
|
const unsignedUserOp = { ...rawUserOp, ...paymasterData };
|
105
105
|
return unsignedUserOp;
|
106
106
|
}
|
@@ -236,7 +236,7 @@ class NearSafe {
|
|
236
236
|
async removeOwnerTx(chainId, address) {
|
237
237
|
return {
|
238
238
|
to: this.address,
|
239
|
-
value: "
|
239
|
+
value: "0x00",
|
240
240
|
data: await this.safePack.removeOwnerData(chainId, this.address, address),
|
241
241
|
};
|
242
242
|
}
|
@@ -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;
|
@@ -0,0 +1,90 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.parseEip712TypedData = exports.parseUserOperation = exports.parseWithTypeGuard = exports.isUserOperation = void 0;
|
4
|
+
const near_ca_1 = require("near-ca");
|
5
|
+
const viem_1 = require("viem");
|
6
|
+
const isUserOperation = (data) => {
|
7
|
+
if (typeof data !== "object" || data === null)
|
8
|
+
return false;
|
9
|
+
const candidate = data;
|
10
|
+
// Required fields
|
11
|
+
const hasRequiredFields = "sender" in candidate &&
|
12
|
+
"nonce" in candidate &&
|
13
|
+
"callData" in candidate &&
|
14
|
+
"maxPriorityFeePerGas" in candidate &&
|
15
|
+
"maxFeePerGas" in candidate &&
|
16
|
+
"verificationGasLimit" in candidate &&
|
17
|
+
"callGasLimit" in candidate &&
|
18
|
+
"preVerificationGas" in candidate;
|
19
|
+
if (!hasRequiredFields)
|
20
|
+
return false;
|
21
|
+
// Type checks for required fields
|
22
|
+
const hasValidRequiredTypes = typeof candidate.sender === "string" &&
|
23
|
+
(0, viem_1.isAddress)(candidate.sender) &&
|
24
|
+
typeof candidate.nonce === "string" &&
|
25
|
+
(0, viem_1.isHex)(candidate.callData) &&
|
26
|
+
(0, viem_1.isHex)(candidate.maxPriorityFeePerGas) &&
|
27
|
+
(0, viem_1.isHex)(candidate.maxFeePerGas) &&
|
28
|
+
(0, viem_1.isHex)(candidate.verificationGasLimit) &&
|
29
|
+
(0, viem_1.isHex)(candidate.callGasLimit) &&
|
30
|
+
(0, viem_1.isHex)(candidate.preVerificationGas);
|
31
|
+
if (!hasValidRequiredTypes)
|
32
|
+
return false;
|
33
|
+
// Optional fields type checks
|
34
|
+
if ("factory" in candidate && candidate.factory !== undefined) {
|
35
|
+
if (typeof candidate.factory !== "string" || !(0, viem_1.isAddress)(candidate.factory))
|
36
|
+
return false;
|
37
|
+
}
|
38
|
+
if ("factoryData" in candidate && candidate.factoryData !== undefined) {
|
39
|
+
if (!(0, viem_1.isHex)(candidate.factoryData))
|
40
|
+
return false;
|
41
|
+
}
|
42
|
+
if ("signature" in candidate && candidate.signature !== undefined) {
|
43
|
+
if (!(0, viem_1.isHex)(candidate.signature))
|
44
|
+
return false;
|
45
|
+
}
|
46
|
+
if ("paymaster" in candidate && candidate.paymaster !== undefined) {
|
47
|
+
if (typeof candidate.paymaster !== "string" ||
|
48
|
+
!(0, viem_1.isAddress)(candidate.paymaster))
|
49
|
+
return false;
|
50
|
+
}
|
51
|
+
if ("paymasterData" in candidate && candidate.paymasterData !== undefined) {
|
52
|
+
if (!(0, viem_1.isHex)(candidate.paymasterData))
|
53
|
+
return false;
|
54
|
+
}
|
55
|
+
if ("paymasterVerificationGasLimit" in candidate &&
|
56
|
+
candidate.paymasterVerificationGasLimit !== undefined) {
|
57
|
+
if (!(0, viem_1.isHex)(candidate.paymasterVerificationGasLimit))
|
58
|
+
return false;
|
59
|
+
}
|
60
|
+
if ("paymasterPostOpGasLimit" in candidate &&
|
61
|
+
candidate.paymasterPostOpGasLimit !== undefined) {
|
62
|
+
if (!(0, viem_1.isHex)(candidate.paymasterPostOpGasLimit))
|
63
|
+
return false;
|
64
|
+
}
|
65
|
+
return true;
|
66
|
+
};
|
67
|
+
exports.isUserOperation = isUserOperation;
|
68
|
+
const parseWithTypeGuard = (data, typeGuard) => {
|
69
|
+
// Case 1: Already the correct type
|
70
|
+
if (typeGuard(data)) {
|
71
|
+
return data;
|
72
|
+
}
|
73
|
+
// Case 2: Stringified data
|
74
|
+
if (typeof data === "string") {
|
75
|
+
try {
|
76
|
+
const parsed = JSON.parse(data);
|
77
|
+
return typeGuard(parsed) ? parsed : null;
|
78
|
+
}
|
79
|
+
catch (error) {
|
80
|
+
return null;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
// Neither valid type nor valid stringified type
|
84
|
+
return null;
|
85
|
+
};
|
86
|
+
exports.parseWithTypeGuard = parseWithTypeGuard;
|
87
|
+
const parseUserOperation = (data) => (0, exports.parseWithTypeGuard)(data, exports.isUserOperation);
|
88
|
+
exports.parseUserOperation = parseUserOperation;
|
89
|
+
const parseEip712TypedData = (data) => (0, exports.parseWithTypeGuard)(data, near_ca_1.isEIP712TypedData);
|
90
|
+
exports.parseEip712TypedData = parseEip712TypedData;
|