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 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
 
@@ -1,3 +1,4 @@
1
1
  export * from "./tx-manager";
2
2
  export * from "./types";
3
3
  export * from "./util";
4
+ export { Network, BaseTx, SignRequestData, populateTx } from "near-ca";
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 { ethers } from "ethers";
2
- import { GasPrices, PaymasterData, UnsignedUserOperation, UserOperation, UserOperationReceipt } from "../types.js";
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
- provider: ethers.JsonRpcProvider;
5
- entryPointAddress: string;
26
+ client: PublicClient<Transport, undefined, undefined, BundlerRpcSchema>;
27
+ entryPointAddress: Address;
6
28
  apiKey: string;
7
29
  chainId: number;
8
- constructor(entryPointAddress: string, apiKey: string, chainId: number);
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<string>;
32
+ sendUserOperation(userOp: UserOperation): Promise<Hash>;
12
33
  getGasPrice(): Promise<GasPrices>;
13
- _getUserOpReceiptInner(userOpHash: string): Promise<UserOperationReceipt | null>;
14
- getUserOpReceipt(userOpHash: string): Promise<UserOperationReceipt>;
34
+ getUserOpReceipt(userOpHash: Hash): Promise<UserOperationReceipt>;
35
+ private _getUserOpReceiptInner;
15
36
  }
37
+ export {};
@@ -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.provider = new ethers_1.ethers.JsonRpcProvider(bundlerUrl(chainId, apiKey));
17
- }
18
- client(chainId) {
19
- return new ethers_1.ethers.JsonRpcProvider(bundlerUrl(chainId, this.apiKey));
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
- const data = this.provider.send("pm_sponsorUserOperation", [
26
- { ...rawUserOp, signature: util_js_1.PLACEHOLDER_SIG },
27
- this.entryPointAddress,
28
- ]);
29
- return data;
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
- try {
35
- const userOpHash = await this.provider.send("eth_sendUserOperation", [
36
- userOp,
37
- this.entryPointAddress,
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.provider.send("pimlico_getUserOperationGasPrice", []);
48
- }
49
- async _getUserOpReceiptInner(userOpHash) {
50
- return this.provider.send("eth_getUserOperationReceipt", [userOpHash]);
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,3 @@
1
+ import { MetaTransaction } from "../types";
2
+ export declare const MULTI_SEND_ABI: string[];
3
+ export declare function encodeMulti(transactions: readonly MetaTransaction[], multiSendContractAddress?: string): MetaTransaction;
@@ -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
+ }
@@ -1,25 +1,27 @@
1
- import { ethers } from "ethers";
2
- import { GasPrice, UnsignedUserOperation, UserOperation } from "../types";
3
- import { MetaTransaction } from "ethers-multisend";
4
- import { Address, Hash, Hex } from "viem";
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
- provider: ethers.JsonRpcProvider;
10
- singleton: ethers.Contract;
11
- proxyFactory: ethers.Contract;
12
- m4337: ethers.Contract;
13
- moduleSetup: ethers.Contract;
14
- entryPoint: ethers.Contract;
15
- constructor(provider: ethers.JsonRpcProvider, singleton: ethers.Contract, proxyFactory: ethers.Contract, m4337: ethers.Contract, moduleSetup: ethers.Contract, entryPoint: ethers.Contract);
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: ethers.BytesLike, saltNonce?: string): Promise<Address>;
18
- getSetup(owners: string[]): Promise<Hex>;
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(safeNotDeployed: boolean, setup: string, safeSaltNonce: string): {
21
- factory?: Address;
22
- factoryData?: Hex;
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 {};
@@ -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(provider, singleton, proxyFactory, m4337, moduleSetup, entryPoint) {
13
- this.provider = provider;
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 provider = new ethers_1.ethers.JsonRpcProvider("https://rpc2.sepolia.org");
23
- const safeDeployment = (fn) => getDeployment(fn, { provider, version: "1.4.1" });
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, { provider, version: "0.3.0" });
25
+ return getDeployment(fn, { version: "0.3.0" });
26
26
  };
27
- // Need this first to get entryPoint address
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
- m4337.SUPPORTED_ENTRYPOINT(),
31
+ m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment),
34
32
  ]);
35
- const entryPoint = new ethers_1.ethers.Contract(supportedEntryPoint, ["function getNonce(address, uint192 key) view returns (uint256 nonce)"], provider);
36
- console.log("Initialized ERC4337 & Safe Module Contracts:", {
37
- singleton: await singleton.getAddress(),
38
- proxyFactory: await proxyFactory.getAddress(),
39
- m4337: await m4337.getAddress(),
40
- moduleSetup: await moduleSetup.getAddress(),
41
- entryPoint: await entryPoint.getAddress(),
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 = ethers_1.ethers.keccak256(ethers_1.ethers.solidityPacked(["bytes32", "uint256"], [ethers_1.ethers.keccak256(setup), saltNonce || 0]));
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 = ethers_1.ethers.solidityPacked(["bytes", "uint256"], [
52
- await this.proxyFactory.proxyCreationCode(),
53
- await this.singleton.getAddress(),
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 ethers_1.ethers.getCreate2Address(await this.proxyFactory.getAddress(), salt, ethers_1.ethers.keccak256(initCode));
67
+ return (0, viem_1.getCreate2Address)({
68
+ from: this.proxyFactory.address,
69
+ salt,
70
+ bytecodeHash: (0, viem_1.keccak256)(initCode),
71
+ });
56
72
  }
57
- async getSetup(owners) {
58
- const setup = await this.singleton.interface.encodeFunctionData("setup", [
59
- owners,
60
- 1, // We use sign threshold of 1.
61
- this.moduleSetup.target,
62
- this.moduleSetup.interface.encodeFunctionData("enableModules", [
63
- [this.m4337.target],
64
- ]),
65
- this.m4337.target,
66
- ethers_1.ethers.ZeroAddress,
67
- 0,
68
- ethers_1.ethers.ZeroAddress,
69
- ]);
70
- return setup;
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
- return this.m4337.getOperationHash({
75
- ...unsignedUserOp,
76
- initCode: factory
77
- ? ethers_1.ethers.solidityPacked(["address", "bytes"], [factory, factoryData])
78
- : "0x",
79
- accountGasLimits: (0, util_1.packGas)(verificationGasLimit, callGasLimit),
80
- gasFees: (0, util_1.packGas)(maxPriorityFeePerGas, maxFeePerGas),
81
- paymasterAndData: (0, util_1.packPaymasterData)(unsignedUserOp),
82
- signature: util_1.PLACEHOLDER_SIG,
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.target,
89
- factoryData: this.proxyFactory.interface.encodeFunctionData("createProxyWithNonce", [this.singleton.target, setup, safeSaltNonce]),
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
- const rawUserOp = {
133
+ async buildUserOp(nonce, txData, safeAddress, feeData, setup, safeNotDeployed, safeSaltNonce) {
134
+ return {
95
135
  sender: safeAddress,
96
- nonce: ethers_1.ethers.toBeHex(await this.entryPoint.getNonce(safeAddress, 0)),
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: this.m4337.interface.encodeFunctionData("executeUserOp", [
100
- txData.to,
101
- BigInt(txData.value),
102
- txData.data,
103
- txData.operation || 0,
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
- return rawUserOp;
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, { provider, version }) {
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} on chainId ${chainId}`);
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
- return new ethers_1.ethers.Contract(address, deployment.abi, provider);
168
+ // TODO: maybe call parseAbi on deployment.abi here.
169
+ return {
170
+ address: deployment.networkAddresses["11155111"],
171
+ abi: deployment.abi,
172
+ };
127
173
  }
@@ -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 { Address, Hash, Hex } from "viem";
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, entryPointAddress: Address, safeSaltNonce: string);
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
- nearAdapter: NearEthAdapter;
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: string): MetaTransaction;
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
  }