near-safe 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/lib/multisend.d.ts +1 -0
- package/dist/cjs/lib/multisend.js +6 -0
- package/dist/cjs/near-safe.d.ts +129 -3
- package/dist/cjs/near-safe.js +153 -9
- package/dist/cjs/types.d.ts +7 -6
- package/dist/esm/lib/multisend.d.ts +1 -0
- package/dist/esm/lib/multisend.js +5 -0
- package/dist/esm/near-safe.d.ts +129 -3
- package/dist/esm/near-safe.js +155 -11
- package/dist/esm/types.d.ts +7 -6
- package/package.json +3 -3
@@ -1,3 +1,4 @@
|
|
1
1
|
import { MetaTransaction } from "../types";
|
2
2
|
export declare const MULTI_SEND_ABI: string[];
|
3
3
|
export declare function encodeMulti(transactions: readonly MetaTransaction[], multiSendContractAddress?: string): MetaTransaction;
|
4
|
+
export declare function isMultisendTx(args: readonly unknown[]): boolean;
|
@@ -2,6 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.MULTI_SEND_ABI = void 0;
|
4
4
|
exports.encodeMulti = encodeMulti;
|
5
|
+
exports.isMultisendTx = isMultisendTx;
|
5
6
|
const viem_1 = require("viem");
|
6
7
|
const types_1 = require("../types");
|
7
8
|
exports.MULTI_SEND_ABI = ["function multiSend(bytes memory transactions)"];
|
@@ -38,3 +39,8 @@ function encodeMulti(transactions, multiSendContractAddress = transactions.some(
|
|
38
39
|
}),
|
39
40
|
};
|
40
41
|
}
|
42
|
+
function isMultisendTx(args) {
|
43
|
+
const to = args[0].toLowerCase();
|
44
|
+
return (to === MULTISEND_141.toLowerCase() ||
|
45
|
+
to === MULTISEND_CALLONLY_141.toLowerCase());
|
46
|
+
}
|
package/dist/cjs/near-safe.d.ts
CHANGED
@@ -3,7 +3,7 @@ import { FinalExecutionOutcome } from "near-api-js/lib/providers";
|
|
3
3
|
import { NearEthAdapter, SignRequestData } from "near-ca";
|
4
4
|
import { Address, Hash, Hex } from "viem";
|
5
5
|
import { SafeContractSuite } from "./lib/safe";
|
6
|
-
import { EncodedTxData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
|
6
|
+
import { EncodedTxData, EvmTransactionData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
|
7
7
|
export interface NearSafeConfig {
|
8
8
|
accountId: string;
|
9
9
|
mpcContractId: string;
|
@@ -19,28 +19,154 @@ export declare class NearSafe {
|
|
19
19
|
private setup;
|
20
20
|
private pimlicoKey;
|
21
21
|
private safeSaltNonce;
|
22
|
+
/**
|
23
|
+
* Creates a new instance of the `NearSafe` class using the provided configuration.
|
24
|
+
*
|
25
|
+
* @param {NearSafeConfig} config - The configuration object required to initialize the `NearSafe` instance, including the Pimlico key and safe salt nonce.
|
26
|
+
* @returns {Promise<NearSafe>} - A promise that resolves to a new `NearSafe` instance.
|
27
|
+
*/
|
22
28
|
static create(config: NearSafeConfig): Promise<NearSafe>;
|
29
|
+
/**
|
30
|
+
* Constructs a new `NearSafe` object with the provided parameters.
|
31
|
+
*
|
32
|
+
* @param {NearEthAdapter} nearAdapter - The NEAR adapter used for interacting with the NEAR blockchain.
|
33
|
+
* @param {SafeContractSuite} safePack - A suite of contracts and utilities for managing the Safe contract.
|
34
|
+
* @param {string} pimlicoKey - A key required for authenticating with the Pimlico service.
|
35
|
+
* @param {string} setup - The setup string generated for the Safe contract.
|
36
|
+
* @param {Address} safeAddress - The address of the deployed Safe contract.
|
37
|
+
* @param {string} safeSaltNonce - A unique nonce used to differentiate the Safe setup.
|
38
|
+
*/
|
23
39
|
constructor(nearAdapter: NearEthAdapter, safePack: SafeContractSuite, pimlicoKey: string, setup: string, safeAddress: Address, safeSaltNonce: string);
|
40
|
+
/**
|
41
|
+
* Retrieves the MPC (Multi-Party Computation) address associated with the NEAR adapter.
|
42
|
+
*
|
43
|
+
* @returns {Address} - The MPC address of the NEAR adapter.
|
44
|
+
*/
|
24
45
|
get mpcAddress(): Address;
|
46
|
+
/**
|
47
|
+
* Retrieves the contract ID of the MPC contract associated with the NEAR adapter.
|
48
|
+
*
|
49
|
+
* @returns {string} - The contract ID of the MPC contract.
|
50
|
+
*/
|
25
51
|
get mpcContractId(): string;
|
52
|
+
/**
|
53
|
+
* Retrieves the balance of the Safe account on the specified EVM chain.
|
54
|
+
*
|
55
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe account is located.
|
56
|
+
* @returns {Promise<bigint>} - A promise that resolves to the balance of the Safe account in wei.
|
57
|
+
*/
|
26
58
|
getBalance(chainId: number): Promise<bigint>;
|
59
|
+
/**
|
60
|
+
* Constructs a user operation for the specified chain, including necessary gas fees, nonce, and paymaster data.
|
61
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
62
|
+
*
|
63
|
+
* @param {Object} args - The arguments for building the transaction.
|
64
|
+
* @param {number} args.chainId - The ID of the blockchain network where the transaction will be executed.
|
65
|
+
* @param {MetaTransaction[]} args.transactions - A list of meta-transactions to be included in the user operation.
|
66
|
+
* @param {boolean} args.usePaymaster - Flag indicating whether to use a paymaster for gas fees. If true, the transaction will be sponsored by the paymaster.
|
67
|
+
* @returns {Promise<UserOperation>} - A promise that resolves to a complete `UserOperation` object, including gas fees, nonce, and paymaster data.
|
68
|
+
* @throws {Error} - Throws an error if the transaction set is empty or if any operation fails during the building process.
|
69
|
+
*/
|
27
70
|
buildTransaction(args: {
|
28
71
|
chainId: number;
|
29
72
|
transactions: MetaTransaction[];
|
30
73
|
usePaymaster: boolean;
|
31
74
|
}): Promise<UserOperation>;
|
75
|
+
/**
|
76
|
+
* Signs a transaction with the NEAR adapter using the provided operation hash.
|
77
|
+
*
|
78
|
+
* @param {Hex} safeOpHash - The hash of the user operation that needs to be signed.
|
79
|
+
* @returns {Promise<Hex>} - A promise that resolves to the packed signature in hexadecimal format.
|
80
|
+
*/
|
32
81
|
signTransaction(safeOpHash: Hex): Promise<Hex>;
|
82
|
+
/**
|
83
|
+
* Computes the operation hash for a given user operation.
|
84
|
+
*
|
85
|
+
* @param {UserOperation} userOp - The user operation for which the hash needs to be computed.
|
86
|
+
* @returns {Promise<Hash>} - A promise that resolves to the hash of the provided user operation.
|
87
|
+
*/
|
33
88
|
opHash(userOp: UserOperation): Promise<Hash>;
|
89
|
+
/**
|
90
|
+
* Encodes a request to sign a transaction using either a paymaster or the user's own funds.
|
91
|
+
*
|
92
|
+
* @param {SignRequestData} signRequest - The data required to create the signature request. This includes information such as the chain ID and other necessary fields for the transaction.
|
93
|
+
* @param {boolean} usePaymaster - Flag indicating whether to use a paymaster for gas fees. If true, the transaction will be sponsored by the paymaster.
|
94
|
+
* @returns {Promise<EncodedTxData>} - A promise that resolves to the encoded transaction data for the NEAR and EVM networks.
|
95
|
+
*/
|
34
96
|
encodeSignRequest(signRequest: SignRequestData, usePaymaster: boolean): Promise<EncodedTxData>;
|
97
|
+
/**
|
98
|
+
* Broadcasts a user operation to the EVM network with a provided signature.
|
99
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
100
|
+
*
|
101
|
+
* @param {number} chainId - The ID of the EVM network to which the transaction should be broadcasted.
|
102
|
+
* @param {FinalExecutionOutcome} outcome - The result of the NEAR transaction execution, which contains the necessary data to construct an EVM signature.
|
103
|
+
* @param {UserOperation} unsignedUserOp - The unsigned user operation to be broadcasted. This includes transaction data such as the destination address and data payload.
|
104
|
+
* @returns {Promise<{ signature: Hex; opHash: Hash }>} - A promise that resolves to an object containing the signature used and the hash of the executed user operation.
|
105
|
+
* @throws {Error} - Throws an error if the EVM broadcast fails, including the error message for debugging.
|
106
|
+
*/
|
35
107
|
broadcastEvm(chainId: number, outcome: FinalExecutionOutcome, unsignedUserOp: UserOperation): Promise<{
|
36
108
|
signature: Hex;
|
37
|
-
|
109
|
+
opHash: Hash;
|
38
110
|
}>;
|
39
|
-
|
111
|
+
/**
|
112
|
+
* Executes a user operation on the specified blockchain network.
|
113
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
114
|
+
*
|
115
|
+
* @param {number} chainId - The ID of the blockchain network on which to execute the transaction.
|
116
|
+
* @param {UserOperation} userOp - The user operation to be executed, typically includes the data and signatures necessary for the transaction.
|
117
|
+
* @returns {Promise<Hash>} - A promise that resolves to the hash of the executed transaction.
|
118
|
+
*/
|
119
|
+
executeTransaction(chainId: number, userOp: UserOperation): Promise<Hash>;
|
120
|
+
/**
|
121
|
+
* Retrieves the receipt of a previously executed user operation.
|
122
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
123
|
+
*
|
124
|
+
* @param {number} chainId - The ID of the blockchain network where the operation was executed.
|
125
|
+
* @param {Hash} userOpHash - The hash of the user operation for which to retrieve the receipt.
|
126
|
+
* @returns {Promise<UserOperationReceipt>} - A promise that resolves to the receipt of the user operation, which includes status and logs.
|
127
|
+
*/
|
128
|
+
getOpReceipt(chainId: number, userOpHash: Hash): Promise<UserOperationReceipt>;
|
129
|
+
/**
|
130
|
+
* Checks if the Safe contract is deployed on the specified chain.
|
131
|
+
*
|
132
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe contract should be checked.
|
133
|
+
* @returns {Promise<boolean>} - A promise that resolves to `true` if the Safe contract is deployed, otherwise `false`.
|
134
|
+
*/
|
40
135
|
safeDeployed(chainId: number): Promise<boolean>;
|
136
|
+
/**
|
137
|
+
* Determines if the Safe account has sufficient funds to cover the transaction costs.
|
138
|
+
*
|
139
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe account is located.
|
140
|
+
* @param {MetaTransaction[]} transactions - A list of meta-transactions to be evaluated for funding.
|
141
|
+
* @param {bigint} gasCost - The estimated gas cost of executing the transactions.
|
142
|
+
* @returns {Promise<boolean>} - A promise that resolves to `true` if the Safe account has sufficient funds, otherwise `false`.
|
143
|
+
*/
|
41
144
|
sufficientlyFunded(chainId: number, transactions: MetaTransaction[], gasCost: bigint): Promise<boolean>;
|
145
|
+
/**
|
146
|
+
* Creates a meta-transaction for adding a new owner to the Safe contract.
|
147
|
+
*
|
148
|
+
* @param {Address} address - The address of the new owner to be added.
|
149
|
+
* @returns {MetaTransaction} - A meta-transaction object for adding the new owner.
|
150
|
+
*/
|
42
151
|
addOwnerTx(address: Address): MetaTransaction;
|
152
|
+
/**
|
153
|
+
* Creates and returns a new `Erc4337Bundler` instance for the specified chain.
|
154
|
+
*
|
155
|
+
* @param {number} chainId - The ID of the blockchain network for which the bundler is to be created.
|
156
|
+
* @returns {Erc4337Bundler} - A new instance of the `Erc4337Bundler` class configured for the specified chain.
|
157
|
+
*/
|
43
158
|
private bundlerForChainId;
|
159
|
+
/**
|
160
|
+
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
161
|
+
*
|
162
|
+
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
163
|
+
* @returns {{ chainId: number; costEstimate: string; transactions: MetaTransaction[] }} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
164
|
+
*/
|
165
|
+
decodeTxData(data: EvmTransactionData): {
|
166
|
+
chainId: number;
|
167
|
+
costEstimate: string;
|
168
|
+
transactions: MetaTransaction[];
|
169
|
+
};
|
44
170
|
/**
|
45
171
|
* Handles routing of signature requests based on the provided method, chain ID, and parameters.
|
46
172
|
*
|
package/dist/cjs/near-safe.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.NearSafe = void 0;
|
4
|
+
const ethers_multisend_1 = require("ethers-multisend");
|
4
5
|
const near_ca_1 = require("near-ca");
|
5
6
|
const viem_1 = require("viem");
|
6
7
|
const bundler_1 = require("./lib/bundler");
|
@@ -9,6 +10,12 @@ const safe_1 = require("./lib/safe");
|
|
9
10
|
const safe_message_1 = require("./lib/safe-message");
|
10
11
|
const util_1 = require("./util");
|
11
12
|
class NearSafe {
|
13
|
+
/**
|
14
|
+
* Creates a new instance of the `NearSafe` class using the provided configuration.
|
15
|
+
*
|
16
|
+
* @param {NearSafeConfig} config - The configuration object required to initialize the `NearSafe` instance, including the Pimlico key and safe salt nonce.
|
17
|
+
* @returns {Promise<NearSafe>} - A promise that resolves to a new `NearSafe` instance.
|
18
|
+
*/
|
12
19
|
static async create(config) {
|
13
20
|
const { pimlicoKey, safeSaltNonce } = config;
|
14
21
|
const nearAdapter = await (0, near_ca_1.setupAdapter)({ ...config });
|
@@ -23,6 +30,16 @@ class NearSafe {
|
|
23
30
|
`);
|
24
31
|
return new NearSafe(nearAdapter, safePack, pimlicoKey, setup, safeAddress, safeSaltNonce || "0");
|
25
32
|
}
|
33
|
+
/**
|
34
|
+
* Constructs a new `NearSafe` object with the provided parameters.
|
35
|
+
*
|
36
|
+
* @param {NearEthAdapter} nearAdapter - The NEAR adapter used for interacting with the NEAR blockchain.
|
37
|
+
* @param {SafeContractSuite} safePack - A suite of contracts and utilities for managing the Safe contract.
|
38
|
+
* @param {string} pimlicoKey - A key required for authenticating with the Pimlico service.
|
39
|
+
* @param {string} setup - The setup string generated for the Safe contract.
|
40
|
+
* @param {Address} safeAddress - The address of the deployed Safe contract.
|
41
|
+
* @param {string} safeSaltNonce - A unique nonce used to differentiate the Safe setup.
|
42
|
+
*/
|
26
43
|
constructor(nearAdapter, safePack, pimlicoKey, setup, safeAddress, safeSaltNonce) {
|
27
44
|
this.nearAdapter = nearAdapter;
|
28
45
|
this.address = safeAddress;
|
@@ -31,15 +48,42 @@ class NearSafe {
|
|
31
48
|
this.pimlicoKey = pimlicoKey;
|
32
49
|
this.safeSaltNonce = safeSaltNonce;
|
33
50
|
}
|
51
|
+
/**
|
52
|
+
* Retrieves the MPC (Multi-Party Computation) address associated with the NEAR adapter.
|
53
|
+
*
|
54
|
+
* @returns {Address} - The MPC address of the NEAR adapter.
|
55
|
+
*/
|
34
56
|
get mpcAddress() {
|
35
57
|
return this.nearAdapter.address;
|
36
58
|
}
|
59
|
+
/**
|
60
|
+
* Retrieves the contract ID of the MPC contract associated with the NEAR adapter.
|
61
|
+
*
|
62
|
+
* @returns {string} - The contract ID of the MPC contract.
|
63
|
+
*/
|
37
64
|
get mpcContractId() {
|
38
65
|
return this.nearAdapter.mpcContract.contract.contractId;
|
39
66
|
}
|
67
|
+
/**
|
68
|
+
* Retrieves the balance of the Safe account on the specified EVM chain.
|
69
|
+
*
|
70
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe account is located.
|
71
|
+
* @returns {Promise<bigint>} - A promise that resolves to the balance of the Safe account in wei.
|
72
|
+
*/
|
40
73
|
async getBalance(chainId) {
|
41
74
|
return await (0, util_1.getClient)(chainId).getBalance({ address: this.address });
|
42
75
|
}
|
76
|
+
/**
|
77
|
+
* Constructs a user operation for the specified chain, including necessary gas fees, nonce, and paymaster data.
|
78
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
79
|
+
*
|
80
|
+
* @param {Object} args - The arguments for building the transaction.
|
81
|
+
* @param {number} args.chainId - The ID of the blockchain network where the transaction will be executed.
|
82
|
+
* @param {MetaTransaction[]} args.transactions - A list of meta-transactions to be included in the user operation.
|
83
|
+
* @param {boolean} args.usePaymaster - Flag indicating whether to use a paymaster for gas fees. If true, the transaction will be sponsored by the paymaster.
|
84
|
+
* @returns {Promise<UserOperation>} - A promise that resolves to a complete `UserOperation` object, including gas fees, nonce, and paymaster data.
|
85
|
+
* @throws {Error} - Throws an error if the transaction set is empty or if any operation fails during the building process.
|
86
|
+
*/
|
43
87
|
async buildTransaction(args) {
|
44
88
|
const { transactions, usePaymaster, chainId } = args;
|
45
89
|
if (transactions.length === 0) {
|
@@ -58,13 +102,32 @@ class NearSafe {
|
|
58
102
|
const unsignedUserOp = { ...rawUserOp, ...paymasterData };
|
59
103
|
return unsignedUserOp;
|
60
104
|
}
|
105
|
+
/**
|
106
|
+
* Signs a transaction with the NEAR adapter using the provided operation hash.
|
107
|
+
*
|
108
|
+
* @param {Hex} safeOpHash - The hash of the user operation that needs to be signed.
|
109
|
+
* @returns {Promise<Hex>} - A promise that resolves to the packed signature in hexadecimal format.
|
110
|
+
*/
|
61
111
|
async signTransaction(safeOpHash) {
|
62
112
|
const signature = await this.nearAdapter.sign(safeOpHash);
|
63
113
|
return (0, util_1.packSignature)(signature);
|
64
114
|
}
|
115
|
+
/**
|
116
|
+
* Computes the operation hash for a given user operation.
|
117
|
+
*
|
118
|
+
* @param {UserOperation} userOp - The user operation for which the hash needs to be computed.
|
119
|
+
* @returns {Promise<Hash>} - A promise that resolves to the hash of the provided user operation.
|
120
|
+
*/
|
65
121
|
async opHash(userOp) {
|
66
122
|
return this.safePack.getOpHash(userOp);
|
67
123
|
}
|
124
|
+
/**
|
125
|
+
* Encodes a request to sign a transaction using either a paymaster or the user's own funds.
|
126
|
+
*
|
127
|
+
* @param {SignRequestData} signRequest - The data required to create the signature request. This includes information such as the chain ID and other necessary fields for the transaction.
|
128
|
+
* @param {boolean} usePaymaster - Flag indicating whether to use a paymaster for gas fees. If true, the transaction will be sponsored by the paymaster.
|
129
|
+
* @returns {Promise<EncodedTxData>} - A promise that resolves to the encoded transaction data for the NEAR and EVM networks.
|
130
|
+
*/
|
68
131
|
async encodeSignRequest(signRequest, usePaymaster) {
|
69
132
|
const { payload, evmMessage, hash } = await this.requestRouter(signRequest, usePaymaster);
|
70
133
|
return {
|
@@ -80,12 +143,22 @@ class NearSafe {
|
|
80
143
|
},
|
81
144
|
};
|
82
145
|
}
|
146
|
+
/**
|
147
|
+
* Broadcasts a user operation to the EVM network with a provided signature.
|
148
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
149
|
+
*
|
150
|
+
* @param {number} chainId - The ID of the EVM network to which the transaction should be broadcasted.
|
151
|
+
* @param {FinalExecutionOutcome} outcome - The result of the NEAR transaction execution, which contains the necessary data to construct an EVM signature.
|
152
|
+
* @param {UserOperation} unsignedUserOp - The unsigned user operation to be broadcasted. This includes transaction data such as the destination address and data payload.
|
153
|
+
* @returns {Promise<{ signature: Hex; opHash: Hash }>} - A promise that resolves to an object containing the signature used and the hash of the executed user operation.
|
154
|
+
* @throws {Error} - Throws an error if the EVM broadcast fails, including the error message for debugging.
|
155
|
+
*/
|
83
156
|
async broadcastEvm(chainId, outcome, unsignedUserOp) {
|
84
157
|
const signature = (0, util_1.packSignature)((0, viem_1.serializeSignature)((0, near_ca_1.signatureFromOutcome)(outcome)));
|
85
158
|
try {
|
86
159
|
return {
|
87
160
|
signature,
|
88
|
-
|
161
|
+
opHash: await this.executeTransaction(chainId, {
|
89
162
|
...unsignedUserOp,
|
90
163
|
signature,
|
91
164
|
}),
|
@@ -95,19 +168,45 @@ class NearSafe {
|
|
95
168
|
throw new Error(`Failed EVM broadcast: ${error instanceof Error ? error.message : String(error)}`);
|
96
169
|
}
|
97
170
|
}
|
171
|
+
/**
|
172
|
+
* Executes a user operation on the specified blockchain network.
|
173
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
174
|
+
*
|
175
|
+
* @param {number} chainId - The ID of the blockchain network on which to execute the transaction.
|
176
|
+
* @param {UserOperation} userOp - The user operation to be executed, typically includes the data and signatures necessary for the transaction.
|
177
|
+
* @returns {Promise<Hash>} - A promise that resolves to the hash of the executed transaction.
|
178
|
+
*/
|
98
179
|
async executeTransaction(chainId, userOp) {
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
180
|
+
return this.bundlerForChainId(chainId).sendUserOperation(userOp);
|
181
|
+
}
|
182
|
+
/**
|
183
|
+
* Retrieves the receipt of a previously executed user operation.
|
184
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
185
|
+
*
|
186
|
+
* @param {number} chainId - The ID of the blockchain network where the operation was executed.
|
187
|
+
* @param {Hash} userOpHash - The hash of the user operation for which to retrieve the receipt.
|
188
|
+
* @returns {Promise<UserOperationReceipt>} - A promise that resolves to the receipt of the user operation, which includes status and logs.
|
189
|
+
*/
|
190
|
+
async getOpReceipt(chainId, userOpHash) {
|
191
|
+
return this.bundlerForChainId(chainId).getUserOpReceipt(userOpHash);
|
107
192
|
}
|
193
|
+
/**
|
194
|
+
* Checks if the Safe contract is deployed on the specified chain.
|
195
|
+
*
|
196
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe contract should be checked.
|
197
|
+
* @returns {Promise<boolean>} - A promise that resolves to `true` if the Safe contract is deployed, otherwise `false`.
|
198
|
+
*/
|
108
199
|
async safeDeployed(chainId) {
|
109
200
|
return (0, util_1.isContract)(this.address, chainId);
|
110
201
|
}
|
202
|
+
/**
|
203
|
+
* Determines if the Safe account has sufficient funds to cover the transaction costs.
|
204
|
+
*
|
205
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe account is located.
|
206
|
+
* @param {MetaTransaction[]} transactions - A list of meta-transactions to be evaluated for funding.
|
207
|
+
* @param {bigint} gasCost - The estimated gas cost of executing the transactions.
|
208
|
+
* @returns {Promise<boolean>} - A promise that resolves to `true` if the Safe account has sufficient funds, otherwise `false`.
|
209
|
+
*/
|
111
210
|
async sufficientlyFunded(chainId, transactions, gasCost) {
|
112
211
|
const txValue = transactions.reduce((acc, tx) => acc + BigInt(tx.value), 0n);
|
113
212
|
if (txValue + gasCost === 0n) {
|
@@ -116,6 +215,12 @@ class NearSafe {
|
|
116
215
|
const safeBalance = await this.getBalance(chainId);
|
117
216
|
return txValue + gasCost < safeBalance;
|
118
217
|
}
|
218
|
+
/**
|
219
|
+
* Creates a meta-transaction for adding a new owner to the Safe contract.
|
220
|
+
*
|
221
|
+
* @param {Address} address - The address of the new owner to be added.
|
222
|
+
* @returns {MetaTransaction} - A meta-transaction object for adding the new owner.
|
223
|
+
*/
|
119
224
|
addOwnerTx(address) {
|
120
225
|
return {
|
121
226
|
to: this.address,
|
@@ -123,9 +228,48 @@ class NearSafe {
|
|
123
228
|
data: this.safePack.addOwnerData(address),
|
124
229
|
};
|
125
230
|
}
|
231
|
+
/**
|
232
|
+
* Creates and returns a new `Erc4337Bundler` instance for the specified chain.
|
233
|
+
*
|
234
|
+
* @param {number} chainId - The ID of the blockchain network for which the bundler is to be created.
|
235
|
+
* @returns {Erc4337Bundler} - A new instance of the `Erc4337Bundler` class configured for the specified chain.
|
236
|
+
*/
|
126
237
|
bundlerForChainId(chainId) {
|
127
238
|
return new bundler_1.Erc4337Bundler(this.safePack.entryPoint.address, this.pimlicoKey, chainId);
|
128
239
|
}
|
240
|
+
/**
|
241
|
+
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
242
|
+
*
|
243
|
+
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
244
|
+
* @returns {{ chainId: number; costEstimate: string; transactions: MetaTransaction[] }} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
245
|
+
*/
|
246
|
+
decodeTxData(data) {
|
247
|
+
// TODO: data.data may not always parse to UserOperation. We will have to handle the other cases.
|
248
|
+
const userOp = JSON.parse(data.data);
|
249
|
+
const { callGasLimit, maxFeePerGas, maxPriorityFeePerGas } = userOp;
|
250
|
+
const maxGasPrice = BigInt(maxFeePerGas) + BigInt(maxPriorityFeePerGas);
|
251
|
+
const { args } = (0, viem_1.decodeFunctionData)({
|
252
|
+
abi: this.safePack.m4337.abi,
|
253
|
+
data: userOp.callData,
|
254
|
+
});
|
255
|
+
// Determine if singular or double!
|
256
|
+
const transactions = (0, multisend_1.isMultisendTx)(args)
|
257
|
+
? (0, ethers_multisend_1.decodeMulti)(args[2])
|
258
|
+
: [
|
259
|
+
{
|
260
|
+
to: args[0],
|
261
|
+
value: args[1],
|
262
|
+
data: args[2],
|
263
|
+
operation: args[3],
|
264
|
+
},
|
265
|
+
];
|
266
|
+
return {
|
267
|
+
chainId: data.chainId,
|
268
|
+
// This is an upper bound on the gas fees (could be lower)
|
269
|
+
costEstimate: (0, viem_1.formatEther)(BigInt(callGasLimit) * maxGasPrice),
|
270
|
+
transactions,
|
271
|
+
};
|
272
|
+
}
|
129
273
|
/**
|
130
274
|
* Handles routing of signature requests based on the provided method, chain ID, and parameters.
|
131
275
|
*
|
package/dist/cjs/types.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { FunctionCallTransaction, SignArgs } from "near-ca";
|
2
|
-
import { Address,
|
2
|
+
import { Address, Hex, ParseAbi } from "viem";
|
3
3
|
export type SafeDeployments = {
|
4
4
|
singleton: Deployment;
|
5
5
|
proxyFactory: Deployment;
|
@@ -101,12 +101,13 @@ export interface MetaTransaction {
|
|
101
101
|
readonly data: string;
|
102
102
|
readonly operation?: OperationType;
|
103
103
|
}
|
104
|
+
export interface EvmTransactionData {
|
105
|
+
chainId: number;
|
106
|
+
data: string;
|
107
|
+
hash: string;
|
108
|
+
}
|
104
109
|
export interface EncodedTxData {
|
105
|
-
evmData:
|
106
|
-
chainId: number;
|
107
|
-
data: string | TransactionSerializable;
|
108
|
-
hash: Hash;
|
109
|
-
};
|
110
|
+
evmData: EvmTransactionData;
|
110
111
|
nearPayload: FunctionCallTransaction<{
|
111
112
|
request: SignArgs;
|
112
113
|
}>;
|
@@ -1,3 +1,4 @@
|
|
1
1
|
import { MetaTransaction } from "../types";
|
2
2
|
export declare const MULTI_SEND_ABI: string[];
|
3
3
|
export declare function encodeMulti(transactions: readonly MetaTransaction[], multiSendContractAddress?: string): MetaTransaction;
|
4
|
+
export declare function isMultisendTx(args: readonly unknown[]): boolean;
|
@@ -34,3 +34,8 @@ export function encodeMulti(transactions, multiSendContractAddress = transaction
|
|
34
34
|
}),
|
35
35
|
};
|
36
36
|
}
|
37
|
+
export function isMultisendTx(args) {
|
38
|
+
const to = args[0].toLowerCase();
|
39
|
+
return (to === MULTISEND_141.toLowerCase() ||
|
40
|
+
to === MULTISEND_CALLONLY_141.toLowerCase());
|
41
|
+
}
|
package/dist/esm/near-safe.d.ts
CHANGED
@@ -3,7 +3,7 @@ import { FinalExecutionOutcome } from "near-api-js/lib/providers";
|
|
3
3
|
import { NearEthAdapter, SignRequestData } from "near-ca";
|
4
4
|
import { Address, Hash, Hex } from "viem";
|
5
5
|
import { SafeContractSuite } from "./lib/safe";
|
6
|
-
import { EncodedTxData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
|
6
|
+
import { EncodedTxData, EvmTransactionData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
|
7
7
|
export interface NearSafeConfig {
|
8
8
|
accountId: string;
|
9
9
|
mpcContractId: string;
|
@@ -19,28 +19,154 @@ export declare class NearSafe {
|
|
19
19
|
private setup;
|
20
20
|
private pimlicoKey;
|
21
21
|
private safeSaltNonce;
|
22
|
+
/**
|
23
|
+
* Creates a new instance of the `NearSafe` class using the provided configuration.
|
24
|
+
*
|
25
|
+
* @param {NearSafeConfig} config - The configuration object required to initialize the `NearSafe` instance, including the Pimlico key and safe salt nonce.
|
26
|
+
* @returns {Promise<NearSafe>} - A promise that resolves to a new `NearSafe` instance.
|
27
|
+
*/
|
22
28
|
static create(config: NearSafeConfig): Promise<NearSafe>;
|
29
|
+
/**
|
30
|
+
* Constructs a new `NearSafe` object with the provided parameters.
|
31
|
+
*
|
32
|
+
* @param {NearEthAdapter} nearAdapter - The NEAR adapter used for interacting with the NEAR blockchain.
|
33
|
+
* @param {SafeContractSuite} safePack - A suite of contracts and utilities for managing the Safe contract.
|
34
|
+
* @param {string} pimlicoKey - A key required for authenticating with the Pimlico service.
|
35
|
+
* @param {string} setup - The setup string generated for the Safe contract.
|
36
|
+
* @param {Address} safeAddress - The address of the deployed Safe contract.
|
37
|
+
* @param {string} safeSaltNonce - A unique nonce used to differentiate the Safe setup.
|
38
|
+
*/
|
23
39
|
constructor(nearAdapter: NearEthAdapter, safePack: SafeContractSuite, pimlicoKey: string, setup: string, safeAddress: Address, safeSaltNonce: string);
|
40
|
+
/**
|
41
|
+
* Retrieves the MPC (Multi-Party Computation) address associated with the NEAR adapter.
|
42
|
+
*
|
43
|
+
* @returns {Address} - The MPC address of the NEAR adapter.
|
44
|
+
*/
|
24
45
|
get mpcAddress(): Address;
|
46
|
+
/**
|
47
|
+
* Retrieves the contract ID of the MPC contract associated with the NEAR adapter.
|
48
|
+
*
|
49
|
+
* @returns {string} - The contract ID of the MPC contract.
|
50
|
+
*/
|
25
51
|
get mpcContractId(): string;
|
52
|
+
/**
|
53
|
+
* Retrieves the balance of the Safe account on the specified EVM chain.
|
54
|
+
*
|
55
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe account is located.
|
56
|
+
* @returns {Promise<bigint>} - A promise that resolves to the balance of the Safe account in wei.
|
57
|
+
*/
|
26
58
|
getBalance(chainId: number): Promise<bigint>;
|
59
|
+
/**
|
60
|
+
* Constructs a user operation for the specified chain, including necessary gas fees, nonce, and paymaster data.
|
61
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
62
|
+
*
|
63
|
+
* @param {Object} args - The arguments for building the transaction.
|
64
|
+
* @param {number} args.chainId - The ID of the blockchain network where the transaction will be executed.
|
65
|
+
* @param {MetaTransaction[]} args.transactions - A list of meta-transactions to be included in the user operation.
|
66
|
+
* @param {boolean} args.usePaymaster - Flag indicating whether to use a paymaster for gas fees. If true, the transaction will be sponsored by the paymaster.
|
67
|
+
* @returns {Promise<UserOperation>} - A promise that resolves to a complete `UserOperation` object, including gas fees, nonce, and paymaster data.
|
68
|
+
* @throws {Error} - Throws an error if the transaction set is empty or if any operation fails during the building process.
|
69
|
+
*/
|
27
70
|
buildTransaction(args: {
|
28
71
|
chainId: number;
|
29
72
|
transactions: MetaTransaction[];
|
30
73
|
usePaymaster: boolean;
|
31
74
|
}): Promise<UserOperation>;
|
75
|
+
/**
|
76
|
+
* Signs a transaction with the NEAR adapter using the provided operation hash.
|
77
|
+
*
|
78
|
+
* @param {Hex} safeOpHash - The hash of the user operation that needs to be signed.
|
79
|
+
* @returns {Promise<Hex>} - A promise that resolves to the packed signature in hexadecimal format.
|
80
|
+
*/
|
32
81
|
signTransaction(safeOpHash: Hex): Promise<Hex>;
|
82
|
+
/**
|
83
|
+
* Computes the operation hash for a given user operation.
|
84
|
+
*
|
85
|
+
* @param {UserOperation} userOp - The user operation for which the hash needs to be computed.
|
86
|
+
* @returns {Promise<Hash>} - A promise that resolves to the hash of the provided user operation.
|
87
|
+
*/
|
33
88
|
opHash(userOp: UserOperation): Promise<Hash>;
|
89
|
+
/**
|
90
|
+
* Encodes a request to sign a transaction using either a paymaster or the user's own funds.
|
91
|
+
*
|
92
|
+
* @param {SignRequestData} signRequest - The data required to create the signature request. This includes information such as the chain ID and other necessary fields for the transaction.
|
93
|
+
* @param {boolean} usePaymaster - Flag indicating whether to use a paymaster for gas fees. If true, the transaction will be sponsored by the paymaster.
|
94
|
+
* @returns {Promise<EncodedTxData>} - A promise that resolves to the encoded transaction data for the NEAR and EVM networks.
|
95
|
+
*/
|
34
96
|
encodeSignRequest(signRequest: SignRequestData, usePaymaster: boolean): Promise<EncodedTxData>;
|
97
|
+
/**
|
98
|
+
* Broadcasts a user operation to the EVM network with a provided signature.
|
99
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
100
|
+
*
|
101
|
+
* @param {number} chainId - The ID of the EVM network to which the transaction should be broadcasted.
|
102
|
+
* @param {FinalExecutionOutcome} outcome - The result of the NEAR transaction execution, which contains the necessary data to construct an EVM signature.
|
103
|
+
* @param {UserOperation} unsignedUserOp - The unsigned user operation to be broadcasted. This includes transaction data such as the destination address and data payload.
|
104
|
+
* @returns {Promise<{ signature: Hex; opHash: Hash }>} - A promise that resolves to an object containing the signature used and the hash of the executed user operation.
|
105
|
+
* @throws {Error} - Throws an error if the EVM broadcast fails, including the error message for debugging.
|
106
|
+
*/
|
35
107
|
broadcastEvm(chainId: number, outcome: FinalExecutionOutcome, unsignedUserOp: UserOperation): Promise<{
|
36
108
|
signature: Hex;
|
37
|
-
|
109
|
+
opHash: Hash;
|
38
110
|
}>;
|
39
|
-
|
111
|
+
/**
|
112
|
+
* Executes a user operation on the specified blockchain network.
|
113
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
114
|
+
*
|
115
|
+
* @param {number} chainId - The ID of the blockchain network on which to execute the transaction.
|
116
|
+
* @param {UserOperation} userOp - The user operation to be executed, typically includes the data and signatures necessary for the transaction.
|
117
|
+
* @returns {Promise<Hash>} - A promise that resolves to the hash of the executed transaction.
|
118
|
+
*/
|
119
|
+
executeTransaction(chainId: number, userOp: UserOperation): Promise<Hash>;
|
120
|
+
/**
|
121
|
+
* Retrieves the receipt of a previously executed user operation.
|
122
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
123
|
+
*
|
124
|
+
* @param {number} chainId - The ID of the blockchain network where the operation was executed.
|
125
|
+
* @param {Hash} userOpHash - The hash of the user operation for which to retrieve the receipt.
|
126
|
+
* @returns {Promise<UserOperationReceipt>} - A promise that resolves to the receipt of the user operation, which includes status and logs.
|
127
|
+
*/
|
128
|
+
getOpReceipt(chainId: number, userOpHash: Hash): Promise<UserOperationReceipt>;
|
129
|
+
/**
|
130
|
+
* Checks if the Safe contract is deployed on the specified chain.
|
131
|
+
*
|
132
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe contract should be checked.
|
133
|
+
* @returns {Promise<boolean>} - A promise that resolves to `true` if the Safe contract is deployed, otherwise `false`.
|
134
|
+
*/
|
40
135
|
safeDeployed(chainId: number): Promise<boolean>;
|
136
|
+
/**
|
137
|
+
* Determines if the Safe account has sufficient funds to cover the transaction costs.
|
138
|
+
*
|
139
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe account is located.
|
140
|
+
* @param {MetaTransaction[]} transactions - A list of meta-transactions to be evaluated for funding.
|
141
|
+
* @param {bigint} gasCost - The estimated gas cost of executing the transactions.
|
142
|
+
* @returns {Promise<boolean>} - A promise that resolves to `true` if the Safe account has sufficient funds, otherwise `false`.
|
143
|
+
*/
|
41
144
|
sufficientlyFunded(chainId: number, transactions: MetaTransaction[], gasCost: bigint): Promise<boolean>;
|
145
|
+
/**
|
146
|
+
* Creates a meta-transaction for adding a new owner to the Safe contract.
|
147
|
+
*
|
148
|
+
* @param {Address} address - The address of the new owner to be added.
|
149
|
+
* @returns {MetaTransaction} - A meta-transaction object for adding the new owner.
|
150
|
+
*/
|
42
151
|
addOwnerTx(address: Address): MetaTransaction;
|
152
|
+
/**
|
153
|
+
* Creates and returns a new `Erc4337Bundler` instance for the specified chain.
|
154
|
+
*
|
155
|
+
* @param {number} chainId - The ID of the blockchain network for which the bundler is to be created.
|
156
|
+
* @returns {Erc4337Bundler} - A new instance of the `Erc4337Bundler` class configured for the specified chain.
|
157
|
+
*/
|
43
158
|
private bundlerForChainId;
|
159
|
+
/**
|
160
|
+
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
161
|
+
*
|
162
|
+
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
163
|
+
* @returns {{ chainId: number; costEstimate: string; transactions: MetaTransaction[] }} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
164
|
+
*/
|
165
|
+
decodeTxData(data: EvmTransactionData): {
|
166
|
+
chainId: number;
|
167
|
+
costEstimate: string;
|
168
|
+
transactions: MetaTransaction[];
|
169
|
+
};
|
44
170
|
/**
|
45
171
|
* Handles routing of signature requests based on the provided method, chain ID, and parameters.
|
46
172
|
*
|
package/dist/esm/near-safe.js
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
import { decodeMulti } from "ethers-multisend";
|
1
2
|
import { setupAdapter, signatureFromOutcome, toPayload, } from "near-ca";
|
2
|
-
import { serializeSignature } from "viem";
|
3
|
+
import { decodeFunctionData, formatEther, serializeSignature, } from "viem";
|
3
4
|
import { Erc4337Bundler } from "./lib/bundler";
|
4
|
-
import { encodeMulti } from "./lib/multisend";
|
5
|
+
import { encodeMulti, isMultisendTx } from "./lib/multisend";
|
5
6
|
import { SafeContractSuite } from "./lib/safe";
|
6
7
|
import { decodeSafeMessage } from "./lib/safe-message";
|
7
8
|
import { getClient, isContract, metaTransactionsFromRequest, packSignature, } from "./util";
|
@@ -12,6 +13,12 @@ export class NearSafe {
|
|
12
13
|
setup;
|
13
14
|
pimlicoKey;
|
14
15
|
safeSaltNonce;
|
16
|
+
/**
|
17
|
+
* Creates a new instance of the `NearSafe` class using the provided configuration.
|
18
|
+
*
|
19
|
+
* @param {NearSafeConfig} config - The configuration object required to initialize the `NearSafe` instance, including the Pimlico key and safe salt nonce.
|
20
|
+
* @returns {Promise<NearSafe>} - A promise that resolves to a new `NearSafe` instance.
|
21
|
+
*/
|
15
22
|
static async create(config) {
|
16
23
|
const { pimlicoKey, safeSaltNonce } = config;
|
17
24
|
const nearAdapter = await setupAdapter({ ...config });
|
@@ -26,6 +33,16 @@ export class NearSafe {
|
|
26
33
|
`);
|
27
34
|
return new NearSafe(nearAdapter, safePack, pimlicoKey, setup, safeAddress, safeSaltNonce || "0");
|
28
35
|
}
|
36
|
+
/**
|
37
|
+
* Constructs a new `NearSafe` object with the provided parameters.
|
38
|
+
*
|
39
|
+
* @param {NearEthAdapter} nearAdapter - The NEAR adapter used for interacting with the NEAR blockchain.
|
40
|
+
* @param {SafeContractSuite} safePack - A suite of contracts and utilities for managing the Safe contract.
|
41
|
+
* @param {string} pimlicoKey - A key required for authenticating with the Pimlico service.
|
42
|
+
* @param {string} setup - The setup string generated for the Safe contract.
|
43
|
+
* @param {Address} safeAddress - The address of the deployed Safe contract.
|
44
|
+
* @param {string} safeSaltNonce - A unique nonce used to differentiate the Safe setup.
|
45
|
+
*/
|
29
46
|
constructor(nearAdapter, safePack, pimlicoKey, setup, safeAddress, safeSaltNonce) {
|
30
47
|
this.nearAdapter = nearAdapter;
|
31
48
|
this.address = safeAddress;
|
@@ -34,15 +51,42 @@ export class NearSafe {
|
|
34
51
|
this.pimlicoKey = pimlicoKey;
|
35
52
|
this.safeSaltNonce = safeSaltNonce;
|
36
53
|
}
|
54
|
+
/**
|
55
|
+
* Retrieves the MPC (Multi-Party Computation) address associated with the NEAR adapter.
|
56
|
+
*
|
57
|
+
* @returns {Address} - The MPC address of the NEAR adapter.
|
58
|
+
*/
|
37
59
|
get mpcAddress() {
|
38
60
|
return this.nearAdapter.address;
|
39
61
|
}
|
62
|
+
/**
|
63
|
+
* Retrieves the contract ID of the MPC contract associated with the NEAR adapter.
|
64
|
+
*
|
65
|
+
* @returns {string} - The contract ID of the MPC contract.
|
66
|
+
*/
|
40
67
|
get mpcContractId() {
|
41
68
|
return this.nearAdapter.mpcContract.contract.contractId;
|
42
69
|
}
|
70
|
+
/**
|
71
|
+
* Retrieves the balance of the Safe account on the specified EVM chain.
|
72
|
+
*
|
73
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe account is located.
|
74
|
+
* @returns {Promise<bigint>} - A promise that resolves to the balance of the Safe account in wei.
|
75
|
+
*/
|
43
76
|
async getBalance(chainId) {
|
44
77
|
return await getClient(chainId).getBalance({ address: this.address });
|
45
78
|
}
|
79
|
+
/**
|
80
|
+
* Constructs a user operation for the specified chain, including necessary gas fees, nonce, and paymaster data.
|
81
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
82
|
+
*
|
83
|
+
* @param {Object} args - The arguments for building the transaction.
|
84
|
+
* @param {number} args.chainId - The ID of the blockchain network where the transaction will be executed.
|
85
|
+
* @param {MetaTransaction[]} args.transactions - A list of meta-transactions to be included in the user operation.
|
86
|
+
* @param {boolean} args.usePaymaster - Flag indicating whether to use a paymaster for gas fees. If true, the transaction will be sponsored by the paymaster.
|
87
|
+
* @returns {Promise<UserOperation>} - A promise that resolves to a complete `UserOperation` object, including gas fees, nonce, and paymaster data.
|
88
|
+
* @throws {Error} - Throws an error if the transaction set is empty or if any operation fails during the building process.
|
89
|
+
*/
|
46
90
|
async buildTransaction(args) {
|
47
91
|
const { transactions, usePaymaster, chainId } = args;
|
48
92
|
if (transactions.length === 0) {
|
@@ -61,13 +105,32 @@ export class NearSafe {
|
|
61
105
|
const unsignedUserOp = { ...rawUserOp, ...paymasterData };
|
62
106
|
return unsignedUserOp;
|
63
107
|
}
|
108
|
+
/**
|
109
|
+
* Signs a transaction with the NEAR adapter using the provided operation hash.
|
110
|
+
*
|
111
|
+
* @param {Hex} safeOpHash - The hash of the user operation that needs to be signed.
|
112
|
+
* @returns {Promise<Hex>} - A promise that resolves to the packed signature in hexadecimal format.
|
113
|
+
*/
|
64
114
|
async signTransaction(safeOpHash) {
|
65
115
|
const signature = await this.nearAdapter.sign(safeOpHash);
|
66
116
|
return packSignature(signature);
|
67
117
|
}
|
118
|
+
/**
|
119
|
+
* Computes the operation hash for a given user operation.
|
120
|
+
*
|
121
|
+
* @param {UserOperation} userOp - The user operation for which the hash needs to be computed.
|
122
|
+
* @returns {Promise<Hash>} - A promise that resolves to the hash of the provided user operation.
|
123
|
+
*/
|
68
124
|
async opHash(userOp) {
|
69
125
|
return this.safePack.getOpHash(userOp);
|
70
126
|
}
|
127
|
+
/**
|
128
|
+
* Encodes a request to sign a transaction using either a paymaster or the user's own funds.
|
129
|
+
*
|
130
|
+
* @param {SignRequestData} signRequest - The data required to create the signature request. This includes information such as the chain ID and other necessary fields for the transaction.
|
131
|
+
* @param {boolean} usePaymaster - Flag indicating whether to use a paymaster for gas fees. If true, the transaction will be sponsored by the paymaster.
|
132
|
+
* @returns {Promise<EncodedTxData>} - A promise that resolves to the encoded transaction data for the NEAR and EVM networks.
|
133
|
+
*/
|
71
134
|
async encodeSignRequest(signRequest, usePaymaster) {
|
72
135
|
const { payload, evmMessage, hash } = await this.requestRouter(signRequest, usePaymaster);
|
73
136
|
return {
|
@@ -83,12 +146,22 @@ export class NearSafe {
|
|
83
146
|
},
|
84
147
|
};
|
85
148
|
}
|
149
|
+
/**
|
150
|
+
* Broadcasts a user operation to the EVM network with a provided signature.
|
151
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
152
|
+
*
|
153
|
+
* @param {number} chainId - The ID of the EVM network to which the transaction should be broadcasted.
|
154
|
+
* @param {FinalExecutionOutcome} outcome - The result of the NEAR transaction execution, which contains the necessary data to construct an EVM signature.
|
155
|
+
* @param {UserOperation} unsignedUserOp - The unsigned user operation to be broadcasted. This includes transaction data such as the destination address and data payload.
|
156
|
+
* @returns {Promise<{ signature: Hex; opHash: Hash }>} - A promise that resolves to an object containing the signature used and the hash of the executed user operation.
|
157
|
+
* @throws {Error} - Throws an error if the EVM broadcast fails, including the error message for debugging.
|
158
|
+
*/
|
86
159
|
async broadcastEvm(chainId, outcome, unsignedUserOp) {
|
87
160
|
const signature = packSignature(serializeSignature(signatureFromOutcome(outcome)));
|
88
161
|
try {
|
89
162
|
return {
|
90
163
|
signature,
|
91
|
-
|
164
|
+
opHash: await this.executeTransaction(chainId, {
|
92
165
|
...unsignedUserOp,
|
93
166
|
signature,
|
94
167
|
}),
|
@@ -98,19 +171,45 @@ export class NearSafe {
|
|
98
171
|
throw new Error(`Failed EVM broadcast: ${error instanceof Error ? error.message : String(error)}`);
|
99
172
|
}
|
100
173
|
}
|
174
|
+
/**
|
175
|
+
* Executes a user operation on the specified blockchain network.
|
176
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
177
|
+
*
|
178
|
+
* @param {number} chainId - The ID of the blockchain network on which to execute the transaction.
|
179
|
+
* @param {UserOperation} userOp - The user operation to be executed, typically includes the data and signatures necessary for the transaction.
|
180
|
+
* @returns {Promise<Hash>} - A promise that resolves to the hash of the executed transaction.
|
181
|
+
*/
|
101
182
|
async executeTransaction(chainId, userOp) {
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
183
|
+
return this.bundlerForChainId(chainId).sendUserOperation(userOp);
|
184
|
+
}
|
185
|
+
/**
|
186
|
+
* Retrieves the receipt of a previously executed user operation.
|
187
|
+
* Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
|
188
|
+
*
|
189
|
+
* @param {number} chainId - The ID of the blockchain network where the operation was executed.
|
190
|
+
* @param {Hash} userOpHash - The hash of the user operation for which to retrieve the receipt.
|
191
|
+
* @returns {Promise<UserOperationReceipt>} - A promise that resolves to the receipt of the user operation, which includes status and logs.
|
192
|
+
*/
|
193
|
+
async getOpReceipt(chainId, userOpHash) {
|
194
|
+
return this.bundlerForChainId(chainId).getUserOpReceipt(userOpHash);
|
110
195
|
}
|
196
|
+
/**
|
197
|
+
* Checks if the Safe contract is deployed on the specified chain.
|
198
|
+
*
|
199
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe contract should be checked.
|
200
|
+
* @returns {Promise<boolean>} - A promise that resolves to `true` if the Safe contract is deployed, otherwise `false`.
|
201
|
+
*/
|
111
202
|
async safeDeployed(chainId) {
|
112
203
|
return isContract(this.address, chainId);
|
113
204
|
}
|
205
|
+
/**
|
206
|
+
* Determines if the Safe account has sufficient funds to cover the transaction costs.
|
207
|
+
*
|
208
|
+
* @param {number} chainId - The ID of the blockchain network where the Safe account is located.
|
209
|
+
* @param {MetaTransaction[]} transactions - A list of meta-transactions to be evaluated for funding.
|
210
|
+
* @param {bigint} gasCost - The estimated gas cost of executing the transactions.
|
211
|
+
* @returns {Promise<boolean>} - A promise that resolves to `true` if the Safe account has sufficient funds, otherwise `false`.
|
212
|
+
*/
|
114
213
|
async sufficientlyFunded(chainId, transactions, gasCost) {
|
115
214
|
const txValue = transactions.reduce((acc, tx) => acc + BigInt(tx.value), 0n);
|
116
215
|
if (txValue + gasCost === 0n) {
|
@@ -119,6 +218,12 @@ export class NearSafe {
|
|
119
218
|
const safeBalance = await this.getBalance(chainId);
|
120
219
|
return txValue + gasCost < safeBalance;
|
121
220
|
}
|
221
|
+
/**
|
222
|
+
* Creates a meta-transaction for adding a new owner to the Safe contract.
|
223
|
+
*
|
224
|
+
* @param {Address} address - The address of the new owner to be added.
|
225
|
+
* @returns {MetaTransaction} - A meta-transaction object for adding the new owner.
|
226
|
+
*/
|
122
227
|
addOwnerTx(address) {
|
123
228
|
return {
|
124
229
|
to: this.address,
|
@@ -126,9 +231,48 @@ export class NearSafe {
|
|
126
231
|
data: this.safePack.addOwnerData(address),
|
127
232
|
};
|
128
233
|
}
|
234
|
+
/**
|
235
|
+
* Creates and returns a new `Erc4337Bundler` instance for the specified chain.
|
236
|
+
*
|
237
|
+
* @param {number} chainId - The ID of the blockchain network for which the bundler is to be created.
|
238
|
+
* @returns {Erc4337Bundler} - A new instance of the `Erc4337Bundler` class configured for the specified chain.
|
239
|
+
*/
|
129
240
|
bundlerForChainId(chainId) {
|
130
241
|
return new Erc4337Bundler(this.safePack.entryPoint.address, this.pimlicoKey, chainId);
|
131
242
|
}
|
243
|
+
/**
|
244
|
+
* Decodes transaction data for a given EVM transaction and extracts relevant details.
|
245
|
+
*
|
246
|
+
* @param {EvmTransactionData} data - The raw transaction data to be decoded.
|
247
|
+
* @returns {{ chainId: number; costEstimate: string; transactions: MetaTransaction[] }} - An object containing the chain ID, estimated cost, and a list of decoded meta-transactions.
|
248
|
+
*/
|
249
|
+
decodeTxData(data) {
|
250
|
+
// TODO: data.data may not always parse to UserOperation. We will have to handle the other cases.
|
251
|
+
const userOp = JSON.parse(data.data);
|
252
|
+
const { callGasLimit, maxFeePerGas, maxPriorityFeePerGas } = userOp;
|
253
|
+
const maxGasPrice = BigInt(maxFeePerGas) + BigInt(maxPriorityFeePerGas);
|
254
|
+
const { args } = decodeFunctionData({
|
255
|
+
abi: this.safePack.m4337.abi,
|
256
|
+
data: userOp.callData,
|
257
|
+
});
|
258
|
+
// Determine if singular or double!
|
259
|
+
const transactions = isMultisendTx(args)
|
260
|
+
? decodeMulti(args[2])
|
261
|
+
: [
|
262
|
+
{
|
263
|
+
to: args[0],
|
264
|
+
value: args[1],
|
265
|
+
data: args[2],
|
266
|
+
operation: args[3],
|
267
|
+
},
|
268
|
+
];
|
269
|
+
return {
|
270
|
+
chainId: data.chainId,
|
271
|
+
// This is an upper bound on the gas fees (could be lower)
|
272
|
+
costEstimate: formatEther(BigInt(callGasLimit) * maxGasPrice),
|
273
|
+
transactions,
|
274
|
+
};
|
275
|
+
}
|
132
276
|
/**
|
133
277
|
* Handles routing of signature requests based on the provided method, chain ID, and parameters.
|
134
278
|
*
|
package/dist/esm/types.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { FunctionCallTransaction, SignArgs } from "near-ca";
|
2
|
-
import { Address,
|
2
|
+
import { Address, Hex, ParseAbi } from "viem";
|
3
3
|
export type SafeDeployments = {
|
4
4
|
singleton: Deployment;
|
5
5
|
proxyFactory: Deployment;
|
@@ -101,12 +101,13 @@ export interface MetaTransaction {
|
|
101
101
|
readonly data: string;
|
102
102
|
readonly operation?: OperationType;
|
103
103
|
}
|
104
|
+
export interface EvmTransactionData {
|
105
|
+
chainId: number;
|
106
|
+
data: string;
|
107
|
+
hash: string;
|
108
|
+
}
|
104
109
|
export interface EncodedTxData {
|
105
|
-
evmData:
|
106
|
-
chainId: number;
|
107
|
-
data: string | TransactionSerializable;
|
108
|
-
hash: Hash;
|
109
|
-
};
|
110
|
+
evmData: EvmTransactionData;
|
110
111
|
nearPayload: FunctionCallTransaction<{
|
111
112
|
request: SignArgs;
|
112
113
|
}>;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "near-safe",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.5.0",
|
4
4
|
"license": "MIT",
|
5
5
|
"description": "An SDK for controlling Ethereum Smart Accounts via ERC4337 from a Near Account.",
|
6
6
|
"author": "bh2smith",
|
@@ -42,6 +42,7 @@
|
|
42
42
|
},
|
43
43
|
"dependencies": {
|
44
44
|
"@safe-global/safe-gateway-typescript-sdk": "^3.22.2",
|
45
|
+
"ethers-multisend": "^3.1.0",
|
45
46
|
"near-api-js": "^5.0.0",
|
46
47
|
"near-ca": "^0.5.6",
|
47
48
|
"semver": "^7.6.3",
|
@@ -68,7 +69,6 @@
|
|
68
69
|
"yargs": "^17.7.2"
|
69
70
|
},
|
70
71
|
"resolutions": {
|
71
|
-
"glob": "^
|
72
|
-
"base-x": "^3.0.0"
|
72
|
+
"glob": "^11.0.0"
|
73
73
|
}
|
74
74
|
}
|