near-safe 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }