near-safe 0.2.0 → 0.3.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/README.md +5 -4
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/lib/bundler.d.ts +31 -9
- package/dist/cjs/lib/bundler.js +46 -27
- package/dist/cjs/lib/multisend.d.ts +3 -0
- package/dist/cjs/lib/multisend.js +40 -0
- package/dist/cjs/lib/safe.d.ts +20 -18
- package/dist/cjs/lib/safe.js +117 -71
- package/dist/cjs/tx-manager.d.ts +13 -7
- package/dist/cjs/tx-manager.js +44 -22
- package/dist/cjs/types.d.ts +10 -0
- package/dist/cjs/types.js +6 -0
- package/dist/cjs/util.d.ts +4 -3
- package/dist/cjs/util.js +9 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/lib/bundler.d.ts +31 -9
- package/dist/esm/lib/bundler.js +48 -29
- package/dist/esm/lib/multisend.d.ts +3 -0
- package/dist/esm/lib/multisend.js +36 -0
- package/dist/esm/lib/safe.d.ts +20 -18
- package/dist/esm/lib/safe.js +120 -73
- package/dist/esm/tx-manager.d.ts +13 -7
- package/dist/esm/tx-manager.js +44 -23
- package/dist/esm/types.d.ts +10 -0
- package/dist/esm/types.js +5 -1
- package/dist/esm/util.d.ts +4 -3
- package/dist/esm/util.js +8 -1
- package/package.json +9 -6
package/README.md
CHANGED
@@ -27,15 +27,16 @@ yarn install
|
|
27
27
|
Create a `.env` (or use our `.env.sample`) file in the root of the project and add the following environment variables:
|
28
28
|
|
29
29
|
```sh
|
30
|
-
ETH_RPC=https://rpc2.sepolia.org
|
31
|
-
|
32
30
|
NEAR_ACCOUNT_ID=
|
33
|
-
NEAR_ACCOUNT_PRIVATE_KEY=
|
34
|
-
|
35
31
|
# Head to https://www.pimlico.io/ for an API key
|
36
32
|
PIMLICO_KEY=
|
37
33
|
```
|
38
34
|
|
35
|
+
To use the CLI tool provided here in `examples/*` you will also need to provide a privateKey for your Near account.
|
36
|
+
|
37
|
+
```sh
|
38
|
+
NEAR_ACCOUNT_PRIVATE_KEY=
|
39
|
+
```
|
39
40
|
|
40
41
|
## Usage
|
41
42
|
|
package/dist/cjs/index.d.ts
CHANGED
package/dist/cjs/index.js
CHANGED
@@ -14,6 +14,10 @@ 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.populateTx = exports.Network = void 0;
|
17
18
|
__exportStar(require("./tx-manager"), exports);
|
18
19
|
__exportStar(require("./types"), exports);
|
19
20
|
__exportStar(require("./util"), exports);
|
21
|
+
var near_ca_1 = require("near-ca");
|
22
|
+
Object.defineProperty(exports, "Network", { enumerable: true, get: function () { return near_ca_1.Network; } });
|
23
|
+
Object.defineProperty(exports, "populateTx", { enumerable: true, get: function () { return near_ca_1.populateTx; } });
|
@@ -1,15 +1,37 @@
|
|
1
|
-
import {
|
2
|
-
import { GasPrices, PaymasterData, UnsignedUserOperation, UserOperation, UserOperationReceipt } from "../types
|
1
|
+
import { Address, Hash, PublicClient, Transport } from "viem";
|
2
|
+
import { GasPrices, PaymasterData, UnsignedUserOperation, UserOperation, UserOperationReceipt } from "../types";
|
3
|
+
type BundlerRpcSchema = [
|
4
|
+
{
|
5
|
+
Method: "pm_sponsorUserOperation";
|
6
|
+
Parameters: [UnsignedUserOperation, Address];
|
7
|
+
ReturnType: PaymasterData;
|
8
|
+
},
|
9
|
+
{
|
10
|
+
Method: "eth_sendUserOperation";
|
11
|
+
Parameters: [UserOperation, Address];
|
12
|
+
ReturnType: Hash;
|
13
|
+
},
|
14
|
+
{
|
15
|
+
Method: "pimlico_getUserOperationGasPrice";
|
16
|
+
Parameters: [];
|
17
|
+
ReturnType: GasPrices;
|
18
|
+
},
|
19
|
+
{
|
20
|
+
Method: "eth_getUserOperationReceipt";
|
21
|
+
Parameters: [Hash];
|
22
|
+
ReturnType: UserOperationReceipt | null;
|
23
|
+
}
|
24
|
+
];
|
3
25
|
export declare class Erc4337Bundler {
|
4
|
-
|
5
|
-
entryPointAddress:
|
26
|
+
client: PublicClient<Transport, undefined, undefined, BundlerRpcSchema>;
|
27
|
+
entryPointAddress: Address;
|
6
28
|
apiKey: string;
|
7
29
|
chainId: number;
|
8
|
-
constructor(entryPointAddress:
|
9
|
-
client(chainId: number): ethers.JsonRpcProvider;
|
30
|
+
constructor(entryPointAddress: Address, apiKey: string, chainId: number);
|
10
31
|
getPaymasterData(rawUserOp: UnsignedUserOperation, usePaymaster: boolean, safeNotDeployed: boolean): Promise<PaymasterData>;
|
11
|
-
sendUserOperation(userOp: UserOperation): Promise<
|
32
|
+
sendUserOperation(userOp: UserOperation): Promise<Hash>;
|
12
33
|
getGasPrice(): Promise<GasPrices>;
|
13
|
-
|
14
|
-
|
34
|
+
getUserOpReceipt(userOpHash: Hash): Promise<UserOperationReceipt>;
|
35
|
+
private _getUserOpReceiptInner;
|
15
36
|
}
|
37
|
+
export {};
|
package/dist/cjs/lib/bundler.js
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.Erc4337Bundler = void 0;
|
4
|
-
// TODO: Ethers dependency is only for Generic HTTP Provider
|
5
|
-
const ethers_1 = require("ethers");
|
6
|
-
const util_js_1 = require("../util.js");
|
7
4
|
const viem_1 = require("viem");
|
5
|
+
const util_1 = require("../util");
|
8
6
|
function bundlerUrl(chainId, apikey) {
|
9
7
|
return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${apikey}`;
|
10
8
|
}
|
@@ -13,41 +11,37 @@ class Erc4337Bundler {
|
|
13
11
|
this.entryPointAddress = entryPointAddress;
|
14
12
|
this.apiKey = apiKey;
|
15
13
|
this.chainId = chainId;
|
16
|
-
this.
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
this.client = (0, viem_1.createPublicClient)({
|
15
|
+
transport: (0, viem_1.http)(bundlerUrl(chainId, this.apiKey)),
|
16
|
+
rpcSchema: (0, viem_1.rpcSchema)(),
|
17
|
+
});
|
20
18
|
}
|
21
19
|
async getPaymasterData(rawUserOp, usePaymaster, safeNotDeployed) {
|
22
20
|
// TODO: Keep this option out of the bundler
|
23
21
|
if (usePaymaster) {
|
24
22
|
console.log("Requesting paymaster data...");
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
return handleRequest(() => this.client.request({
|
24
|
+
method: "pm_sponsorUserOperation",
|
25
|
+
params: [
|
26
|
+
{ ...rawUserOp, signature: util_1.PLACEHOLDER_SIG },
|
27
|
+
this.entryPointAddress,
|
28
|
+
],
|
29
|
+
}));
|
30
30
|
}
|
31
31
|
return defaultPaymasterData(safeNotDeployed);
|
32
32
|
}
|
33
33
|
async sendUserOperation(userOp) {
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
return userOpHash;
|
40
|
-
}
|
41
|
-
catch (err) {
|
42
|
-
const error = err.error;
|
43
|
-
throw new Error(`Failed to send user op with: ${error.message}`);
|
44
|
-
}
|
34
|
+
return handleRequest(() => this.client.request({
|
35
|
+
method: "eth_sendUserOperation",
|
36
|
+
params: [userOp, this.entryPointAddress],
|
37
|
+
}));
|
38
|
+
// throw new Error(`Failed to send user op with: ${error.message}`);
|
45
39
|
}
|
46
40
|
async getGasPrice() {
|
47
|
-
return this.
|
48
|
-
|
49
|
-
|
50
|
-
|
41
|
+
return handleRequest(() => this.client.request({
|
42
|
+
method: "pimlico_getUserOperationGasPrice",
|
43
|
+
params: [],
|
44
|
+
}));
|
51
45
|
}
|
52
46
|
async getUserOpReceipt(userOpHash) {
|
53
47
|
let userOpReceipt = null;
|
@@ -58,8 +52,33 @@ class Erc4337Bundler {
|
|
58
52
|
}
|
59
53
|
return userOpReceipt;
|
60
54
|
}
|
55
|
+
async _getUserOpReceiptInner(userOpHash) {
|
56
|
+
return handleRequest(() => this.client.request({
|
57
|
+
method: "eth_getUserOperationReceipt",
|
58
|
+
params: [userOpHash],
|
59
|
+
}));
|
60
|
+
}
|
61
61
|
}
|
62
62
|
exports.Erc4337Bundler = Erc4337Bundler;
|
63
|
+
async function handleRequest(clientMethod) {
|
64
|
+
try {
|
65
|
+
return await clientMethod();
|
66
|
+
}
|
67
|
+
catch (error) {
|
68
|
+
if (error instanceof viem_1.HttpRequestError) {
|
69
|
+
if (error.status === 401) {
|
70
|
+
throw new Error("Unauthorized request. Please check your API key.");
|
71
|
+
}
|
72
|
+
else {
|
73
|
+
console.error(`Request failed with status ${error.status}: ${error.message}`);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
else if (error instanceof viem_1.RpcError) {
|
77
|
+
throw new Error(`Failed to send user op with: ${error.message}`);
|
78
|
+
}
|
79
|
+
throw new Error(`Unexpected error ${error instanceof Error ? error.message : String(error)}`);
|
80
|
+
}
|
81
|
+
}
|
63
82
|
// TODO(bh2smith) Should probably get reasonable estimates here:
|
64
83
|
const defaultPaymasterData = (safeNotDeployed) => {
|
65
84
|
return {
|
@@ -0,0 +1,40 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.MULTI_SEND_ABI = void 0;
|
4
|
+
exports.encodeMulti = encodeMulti;
|
5
|
+
const viem_1 = require("viem");
|
6
|
+
const types_1 = require("../types");
|
7
|
+
exports.MULTI_SEND_ABI = ["function multiSend(bytes memory transactions)"];
|
8
|
+
const MULTISEND_141 = "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526";
|
9
|
+
const MULTISEND_CALLONLY_141 = "0x9641d764fc13c8B624c04430C7356C1C7C8102e2";
|
10
|
+
/// Encodes the transaction as packed bytes of:
|
11
|
+
/// - `operation` as a `uint8` with `0` for a `call` or `1` for a `delegatecall` (=> 1 byte),
|
12
|
+
/// - `to` as an `address` (=> 20 bytes),
|
13
|
+
/// - `value` as a `uint256` (=> 32 bytes),
|
14
|
+
/// - length of `data` as a `uint256` (=> 32 bytes),
|
15
|
+
/// - `data` as `bytes`.
|
16
|
+
const encodeMetaTx = (tx) => (0, viem_1.encodePacked)(["uint8", "address", "uint256", "uint256", "bytes"], [
|
17
|
+
tx.operation || types_1.OperationType.Call,
|
18
|
+
tx.to,
|
19
|
+
BigInt(tx.value),
|
20
|
+
BigInt((0, viem_1.size)(tx.data)),
|
21
|
+
tx.data,
|
22
|
+
]);
|
23
|
+
const remove0x = (hexString) => hexString.slice(2);
|
24
|
+
// Encodes a batch of module transactions into a single multiSend module transaction.
|
25
|
+
// A module transaction is an object with fields corresponding to a Gnosis Safe's (i.e., Zodiac IAvatar's) `execTransactionFromModule` method parameters.
|
26
|
+
function encodeMulti(transactions, multiSendContractAddress = transactions.some((t) => t.operation === types_1.OperationType.DelegateCall)
|
27
|
+
? MULTISEND_141
|
28
|
+
: MULTISEND_CALLONLY_141) {
|
29
|
+
const encodedTransactions = "0x" + transactions.map(encodeMetaTx).map(remove0x).join("");
|
30
|
+
return {
|
31
|
+
operation: types_1.OperationType.DelegateCall,
|
32
|
+
to: multiSendContractAddress,
|
33
|
+
value: "0x00",
|
34
|
+
data: (0, viem_1.encodeFunctionData)({
|
35
|
+
abi: (0, viem_1.parseAbi)(exports.MULTI_SEND_ABI),
|
36
|
+
functionName: "multiSend",
|
37
|
+
args: [encodedTransactions],
|
38
|
+
}),
|
39
|
+
};
|
40
|
+
}
|
package/dist/cjs/lib/safe.d.ts
CHANGED
@@ -1,25 +1,27 @@
|
|
1
|
-
import {
|
2
|
-
import { GasPrice, UnsignedUserOperation, UserOperation } from "../types";
|
3
|
-
|
4
|
-
|
1
|
+
import { Address, Hash, Hex, ParseAbi, PublicClient } from "viem";
|
2
|
+
import { GasPrice, MetaTransaction, UnsignedUserOperation, UserOperation } from "../types";
|
3
|
+
interface DeploymentData {
|
4
|
+
abi: unknown[] | ParseAbi<readonly string[]>;
|
5
|
+
address: `0x${string}`;
|
6
|
+
}
|
5
7
|
/**
|
6
8
|
* All contracts used in account creation & execution
|
7
9
|
*/
|
8
10
|
export declare class ContractSuite {
|
9
|
-
|
10
|
-
singleton:
|
11
|
-
proxyFactory:
|
12
|
-
m4337:
|
13
|
-
moduleSetup:
|
14
|
-
entryPoint:
|
15
|
-
constructor(
|
11
|
+
dummyClient: PublicClient;
|
12
|
+
singleton: DeploymentData;
|
13
|
+
proxyFactory: DeploymentData;
|
14
|
+
m4337: DeploymentData;
|
15
|
+
moduleSetup: DeploymentData;
|
16
|
+
entryPoint: DeploymentData;
|
17
|
+
constructor(client: PublicClient, singleton: DeploymentData, proxyFactory: DeploymentData, m4337: DeploymentData, moduleSetup: DeploymentData, entryPoint: DeploymentData);
|
16
18
|
static init(): Promise<ContractSuite>;
|
17
|
-
addressForSetup(setup:
|
18
|
-
getSetup(owners: string[]):
|
19
|
+
addressForSetup(setup: Hex, saltNonce?: string): Promise<Address>;
|
20
|
+
getSetup(owners: string[]): Hex;
|
21
|
+
addOwnerData(newOwner: Address): Hex;
|
19
22
|
getOpHash(unsignedUserOp: UserOperation): Promise<Hash>;
|
20
|
-
factoryDataForSetup
|
21
|
-
|
22
|
-
|
23
|
-
};
|
24
|
-
buildUserOp(txData: MetaTransaction, safeAddress: Address, feeData: GasPrice, setup: string, safeNotDeployed: boolean, safeSaltNonce: string): Promise<UnsignedUserOperation>;
|
23
|
+
private factoryDataForSetup;
|
24
|
+
buildUserOp(nonce: bigint, txData: MetaTransaction, safeAddress: Address, feeData: GasPrice, setup: string, safeNotDeployed: boolean, safeSaltNonce: string): Promise<UnsignedUserOperation>;
|
25
|
+
getNonce(address: Address, chainId: number): Promise<bigint>;
|
25
26
|
}
|
27
|
+
export {};
|
package/dist/cjs/lib/safe.js
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.ContractSuite = void 0;
|
4
|
-
const ethers_1 = require("ethers");
|
5
4
|
const safe_deployments_1 = require("@safe-global/safe-deployments");
|
6
5
|
const safe_modules_deployments_1 = require("@safe-global/safe-modules-deployments");
|
6
|
+
const viem_1 = require("viem");
|
7
7
|
const util_1 = require("../util");
|
8
8
|
/**
|
9
9
|
* All contracts used in account creation & execution
|
10
10
|
*/
|
11
11
|
class ContractSuite {
|
12
|
-
constructor(
|
13
|
-
this.
|
12
|
+
constructor(client, singleton, proxyFactory, m4337, moduleSetup, entryPoint) {
|
13
|
+
this.dummyClient = client;
|
14
14
|
this.singleton = singleton;
|
15
15
|
this.proxyFactory = proxyFactory;
|
16
16
|
this.m4337 = m4337;
|
@@ -19,109 +19,155 @@ class ContractSuite {
|
|
19
19
|
}
|
20
20
|
static async init() {
|
21
21
|
// TODO - this is a cheeky hack.
|
22
|
-
const
|
23
|
-
const safeDeployment = (fn) => getDeployment(fn, {
|
22
|
+
const client = (0, util_1.getClient)(11155111);
|
23
|
+
const safeDeployment = (fn) => getDeployment(fn, { version: "1.4.1" });
|
24
24
|
const m4337Deployment = async (fn) => {
|
25
|
-
return getDeployment(fn, {
|
25
|
+
return getDeployment(fn, { version: "0.3.0" });
|
26
26
|
};
|
27
|
-
|
28
|
-
const m4337 = await m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment);
|
29
|
-
const [singleton, proxyFactory, moduleSetup, supportedEntryPoint] = await Promise.all([
|
27
|
+
const [singleton, proxyFactory, moduleSetup, m4337] = await Promise.all([
|
30
28
|
safeDeployment(safe_deployments_1.getSafeL2SingletonDeployment),
|
31
29
|
safeDeployment(safe_deployments_1.getProxyFactoryDeployment),
|
32
30
|
m4337Deployment(safe_modules_deployments_1.getSafeModuleSetupDeployment),
|
33
|
-
|
31
|
+
m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment),
|
34
32
|
]);
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
// console.log("Initialized ERC4337 & Safe Module Contracts:", {
|
34
|
+
// singleton: await singleton.getAddress(),
|
35
|
+
// proxyFactory: await proxyFactory.getAddress(),
|
36
|
+
// m4337: await m4337.getAddress(),
|
37
|
+
// moduleSetup: await moduleSetup.getAddress(),
|
38
|
+
// entryPoint: await entryPoint.getAddress(),
|
39
|
+
// });
|
40
|
+
return new ContractSuite(client, singleton, proxyFactory, m4337, moduleSetup,
|
41
|
+
// EntryPoint:
|
42
|
+
{
|
43
|
+
address: (await client.readContract({
|
44
|
+
address: m4337.address,
|
45
|
+
abi: m4337.abi,
|
46
|
+
functionName: "SUPPORTED_ENTRYPOINT",
|
47
|
+
})),
|
48
|
+
abi: (0, viem_1.parseAbi)([
|
49
|
+
"function getNonce(address, uint192 key) view returns (uint256 nonce)",
|
50
|
+
]),
|
42
51
|
});
|
43
|
-
return new ContractSuite(provider, singleton, proxyFactory, m4337, moduleSetup, entryPoint);
|
44
52
|
}
|
45
53
|
async addressForSetup(setup, saltNonce) {
|
46
54
|
// bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
|
47
55
|
// cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L58
|
48
|
-
const salt =
|
56
|
+
const salt = (0, viem_1.keccak256)((0, viem_1.encodePacked)(["bytes32", "uint256"], [(0, viem_1.keccak256)(setup), BigInt(saltNonce || "0")]));
|
49
57
|
// abi.encodePacked(type(SafeProxy).creationCode, uint256(uint160(_singleton)));
|
50
58
|
// cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L29
|
51
|
-
const initCode =
|
52
|
-
await this.
|
53
|
-
|
59
|
+
const initCode = (0, viem_1.encodePacked)(["bytes", "uint256"], [
|
60
|
+
(await this.dummyClient.readContract({
|
61
|
+
address: this.proxyFactory.address,
|
62
|
+
abi: this.proxyFactory.abi,
|
63
|
+
functionName: "proxyCreationCode",
|
64
|
+
})),
|
65
|
+
BigInt(this.singleton.address),
|
54
66
|
]);
|
55
|
-
return
|
67
|
+
return (0, viem_1.getCreate2Address)({
|
68
|
+
from: this.proxyFactory.address,
|
69
|
+
salt,
|
70
|
+
bytecodeHash: (0, viem_1.keccak256)(initCode),
|
71
|
+
});
|
56
72
|
}
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
getSetup(owners) {
|
74
|
+
return (0, viem_1.encodeFunctionData)({
|
75
|
+
abi: this.singleton.abi,
|
76
|
+
functionName: "setup",
|
77
|
+
args: [
|
78
|
+
owners,
|
79
|
+
1, // We use sign threshold of 1.
|
80
|
+
this.moduleSetup.address,
|
81
|
+
(0, viem_1.encodeFunctionData)({
|
82
|
+
abi: this.moduleSetup.abi,
|
83
|
+
functionName: "enableModules",
|
84
|
+
args: [[this.m4337.address]],
|
85
|
+
}),
|
86
|
+
this.m4337.address,
|
87
|
+
viem_1.zeroAddress,
|
88
|
+
0,
|
89
|
+
viem_1.zeroAddress,
|
90
|
+
],
|
91
|
+
});
|
92
|
+
}
|
93
|
+
addOwnerData(newOwner) {
|
94
|
+
return (0, viem_1.encodeFunctionData)({
|
95
|
+
abi: this.singleton.abi,
|
96
|
+
functionName: "addOwnerWithThreshold",
|
97
|
+
args: [newOwner, 1],
|
98
|
+
});
|
71
99
|
}
|
72
100
|
async getOpHash(unsignedUserOp) {
|
73
101
|
const { factory, factoryData, verificationGasLimit, callGasLimit, maxPriorityFeePerGas, maxFeePerGas, } = unsignedUserOp;
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
102
|
+
const opHash = await this.dummyClient.readContract({
|
103
|
+
address: this.m4337.address,
|
104
|
+
abi: this.m4337.abi,
|
105
|
+
functionName: "getOperationHash",
|
106
|
+
args: [
|
107
|
+
{
|
108
|
+
...unsignedUserOp,
|
109
|
+
initCode: factory
|
110
|
+
? (0, viem_1.encodePacked)(["address", "bytes"], [factory, factoryData])
|
111
|
+
: "0x",
|
112
|
+
accountGasLimits: (0, util_1.packGas)(verificationGasLimit, callGasLimit),
|
113
|
+
gasFees: (0, util_1.packGas)(maxPriorityFeePerGas, maxFeePerGas),
|
114
|
+
paymasterAndData: (0, util_1.packPaymasterData)(unsignedUserOp),
|
115
|
+
signature: util_1.PLACEHOLDER_SIG,
|
116
|
+
},
|
117
|
+
],
|
83
118
|
});
|
119
|
+
return opHash;
|
84
120
|
}
|
85
121
|
factoryDataForSetup(safeNotDeployed, setup, safeSaltNonce) {
|
86
122
|
return safeNotDeployed
|
87
123
|
? {
|
88
|
-
factory: this.proxyFactory.
|
89
|
-
factoryData:
|
124
|
+
factory: this.proxyFactory.address,
|
125
|
+
factoryData: (0, viem_1.encodeFunctionData)({
|
126
|
+
abi: this.proxyFactory.abi,
|
127
|
+
functionName: "createProxyWithNonce",
|
128
|
+
args: [this.singleton.address, setup, safeSaltNonce],
|
129
|
+
}),
|
90
130
|
}
|
91
131
|
: {};
|
92
132
|
}
|
93
|
-
async buildUserOp(txData, safeAddress, feeData, setup, safeNotDeployed, safeSaltNonce) {
|
94
|
-
|
133
|
+
async buildUserOp(nonce, txData, safeAddress, feeData, setup, safeNotDeployed, safeSaltNonce) {
|
134
|
+
return {
|
95
135
|
sender: safeAddress,
|
96
|
-
nonce:
|
136
|
+
nonce: (0, viem_1.toHex)(nonce),
|
97
137
|
...this.factoryDataForSetup(safeNotDeployed, setup, safeSaltNonce),
|
98
138
|
// <https://github.com/safe-global/safe-modules/blob/9a18245f546bf2a8ed9bdc2b04aae44f949ec7a0/modules/4337/contracts/Safe4337Module.sol#L172>
|
99
|
-
callData:
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
139
|
+
callData: (0, viem_1.encodeFunctionData)({
|
140
|
+
abi: this.m4337.abi,
|
141
|
+
functionName: "executeUserOp",
|
142
|
+
args: [
|
143
|
+
txData.to,
|
144
|
+
BigInt(txData.value),
|
145
|
+
txData.data,
|
146
|
+
txData.operation || 0,
|
147
|
+
],
|
148
|
+
}),
|
105
149
|
...feeData,
|
106
150
|
};
|
107
|
-
|
151
|
+
}
|
152
|
+
async getNonce(address, chainId) {
|
153
|
+
const nonce = (await (0, util_1.getClient)(chainId).readContract({
|
154
|
+
abi: this.entryPoint.abi,
|
155
|
+
address: this.entryPoint.address,
|
156
|
+
functionName: "getNonce",
|
157
|
+
args: [address, 0],
|
158
|
+
}));
|
159
|
+
return nonce;
|
108
160
|
}
|
109
161
|
}
|
110
162
|
exports.ContractSuite = ContractSuite;
|
111
|
-
async function getDeployment(fn, {
|
112
|
-
const { chainId } = await provider.getNetwork();
|
163
|
+
async function getDeployment(fn, { version }) {
|
113
164
|
const deployment = fn({ version });
|
114
165
|
if (!deployment) {
|
115
|
-
throw new Error(`Deployment not found for ${fn.name} version ${version}
|
116
|
-
}
|
117
|
-
let address = deployment.networkAddresses[`${chainId}`];
|
118
|
-
if (!address) {
|
119
|
-
// console.warn(
|
120
|
-
// `Deployment asset ${fn.name} not listed on chainId ${chainId}, using likely fallback. For more info visit https://github.com/safe-global/safe-modules-deployments`
|
121
|
-
// );
|
122
|
-
// TODO: This is a cheeky hack. Real solution proposed in
|
123
|
-
// https://github.com/Mintbase/near-safe/issues/42
|
124
|
-
address = deployment.networkAddresses["11155111"];
|
166
|
+
throw new Error(`Deployment not found for ${fn.name} version ${version}`);
|
125
167
|
}
|
126
|
-
|
168
|
+
// TODO: maybe call parseAbi on deployment.abi here.
|
169
|
+
return {
|
170
|
+
address: deployment.networkAddresses["11155111"],
|
171
|
+
abi: deployment.abi,
|
172
|
+
};
|
127
173
|
}
|
package/dist/cjs/tx-manager.d.ts
CHANGED
@@ -1,25 +1,27 @@
|
|
1
|
+
import { FinalExecutionOutcome } from "near-api-js/lib/providers";
|
1
2
|
import { NearEthAdapter, NearEthTxData, BaseTx } from "near-ca";
|
3
|
+
import { Address, Hash, Hex } from "viem";
|
2
4
|
import { Erc4337Bundler } from "./lib/bundler";
|
3
|
-
import { UserOperation, UserOperationReceipt } from "./types";
|
4
|
-
import { MetaTransaction } from "ethers-multisend";
|
5
5
|
import { ContractSuite } from "./lib/safe";
|
6
|
-
import {
|
6
|
+
import { MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
|
7
7
|
export declare class TransactionManager {
|
8
8
|
readonly nearAdapter: NearEthAdapter;
|
9
9
|
readonly address: Address;
|
10
|
-
readonly entryPointAddress: Address;
|
11
10
|
private safePack;
|
12
11
|
private setup;
|
13
12
|
private pimlicoKey;
|
14
13
|
private safeSaltNonce;
|
15
14
|
private deployedChains;
|
16
|
-
constructor(nearAdapter: NearEthAdapter, safePack: ContractSuite, pimlicoKey: string, setup: string, safeAddress: Address,
|
15
|
+
constructor(nearAdapter: NearEthAdapter, safePack: ContractSuite, pimlicoKey: string, setup: string, safeAddress: Address, safeSaltNonce: string);
|
17
16
|
static create(config: {
|
17
|
+
accountId: string;
|
18
|
+
mpcContractId: string;
|
18
19
|
pimlicoKey: string;
|
19
|
-
|
20
|
+
privateKey?: string;
|
20
21
|
safeSaltNonce?: string;
|
21
22
|
}): Promise<TransactionManager>;
|
22
23
|
get mpcAddress(): Address;
|
24
|
+
get mpcContractId(): string;
|
23
25
|
getBalance(chainId: number): Promise<bigint>;
|
24
26
|
bundlerForChainId(chainId: number): Erc4337Bundler;
|
25
27
|
buildTransaction(args: {
|
@@ -32,6 +34,10 @@ export declare class TransactionManager {
|
|
32
34
|
encodeSignRequest(tx: BaseTx): Promise<NearEthTxData>;
|
33
35
|
executeTransaction(chainId: number, userOp: UserOperation): Promise<UserOperationReceipt>;
|
34
36
|
safeDeployed(chainId: number): Promise<boolean>;
|
35
|
-
addOwnerTx(address:
|
37
|
+
addOwnerTx(address: Address): MetaTransaction;
|
36
38
|
safeSufficientlyFunded(chainId: number, transactions: MetaTransaction[], gasCost: bigint): Promise<boolean>;
|
39
|
+
broadcastEvm(chainId: number, outcome: FinalExecutionOutcome, unsignedUserOp: UserOperation): Promise<{
|
40
|
+
signature: Hex;
|
41
|
+
receipt: UserOperationReceipt;
|
42
|
+
}>;
|
37
43
|
}
|