near-safe 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. package/dist/cjs/scripts/fetch-deployments.d.ts +17 -0
  2. package/dist/cjs/scripts/fetch-deployments.js +59 -0
  3. package/dist/cjs/src/_gen/deployments.d.ts +2 -0
  4. package/dist/cjs/src/_gen/deployments.js +1889 -0
  5. package/dist/cjs/{index.d.ts → src/index.d.ts} +1 -1
  6. package/dist/cjs/{index.js → src/index.js} +1 -1
  7. package/dist/{esm → cjs/src}/lib/bundler.d.ts +1 -0
  8. package/dist/cjs/{lib → src/lib}/bundler.js +15 -4
  9. package/dist/cjs/{lib → src/lib}/safe-message.d.ts +2 -7
  10. package/dist/cjs/{lib → src/lib}/safe-message.js +0 -17
  11. package/dist/cjs/src/lib/safe.d.ts +21 -0
  12. package/dist/cjs/{lib → src/lib}/safe.js +12 -56
  13. package/dist/cjs/{tx-manager.d.ts → src/near-safe.d.ts} +22 -21
  14. package/dist/cjs/{tx-manager.js → src/near-safe.js} +65 -63
  15. package/dist/cjs/{types.d.ts → src/types.d.ts} +23 -1
  16. package/dist/esm/scripts/fetch-deployments.d.ts +17 -0
  17. package/dist/esm/scripts/fetch-deployments.js +54 -0
  18. package/dist/esm/src/_gen/deployments.d.ts +2 -0
  19. package/dist/esm/src/_gen/deployments.js +1886 -0
  20. package/dist/esm/{index.d.ts → src/index.d.ts} +1 -1
  21. package/dist/esm/{index.js → src/index.js} +1 -1
  22. package/dist/{cjs → esm/src}/lib/bundler.d.ts +1 -0
  23. package/dist/esm/{lib → src/lib}/bundler.js +14 -4
  24. package/dist/esm/{lib → src/lib}/safe-message.d.ts +2 -7
  25. package/dist/esm/{lib → src/lib}/safe-message.js +0 -16
  26. package/dist/esm/src/lib/safe.d.ts +21 -0
  27. package/dist/esm/{lib → src/lib}/safe.js +11 -55
  28. package/dist/esm/{tx-manager.d.ts → src/near-safe.d.ts} +22 -21
  29. package/dist/esm/{tx-manager.js → src/near-safe.js} +65 -64
  30. package/dist/esm/{types.d.ts → src/types.d.ts} +23 -1
  31. package/package.json +4 -3
  32. package/dist/cjs/lib/safe.d.ts +0 -27
  33. package/dist/esm/lib/safe.d.ts +0 -27
  34. /package/dist/cjs/{lib → src/lib}/multisend.d.ts +0 -0
  35. /package/dist/cjs/{lib → src/lib}/multisend.js +0 -0
  36. /package/dist/cjs/{types.js → src/types.js} +0 -0
  37. /package/dist/cjs/{util.d.ts → src/util.d.ts} +0 -0
  38. /package/dist/cjs/{util.js → src/util.js} +0 -0
  39. /package/dist/esm/{lib → src/lib}/multisend.d.ts +0 -0
  40. /package/dist/esm/{lib → src/lib}/multisend.js +0 -0
  41. /package/dist/esm/{types.js → src/types.js} +0 -0
  42. /package/dist/esm/{util.d.ts → src/util.d.ts} +0 -0
  43. /package/dist/esm/{util.js → src/util.js} +0 -0
@@ -1,4 +1,4 @@
1
- export * from "./tx-manager";
1
+ export * from "./near-safe";
2
2
  export * from "./types";
3
3
  export * from "./util";
4
4
  export { Network, BaseTx, SignRequestData, populateTx } from "near-ca";
@@ -15,7 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.populateTx = exports.Network = void 0;
18
- __exportStar(require("./tx-manager"), exports);
18
+ __exportStar(require("./near-safe"), exports);
19
19
  __exportStar(require("./types"), exports);
20
20
  __exportStar(require("./util"), exports);
21
21
  var near_ca_1 = require("near-ca");
@@ -34,4 +34,5 @@ export declare class Erc4337Bundler {
34
34
  getUserOpReceipt(userOpHash: Hash): Promise<UserOperationReceipt>;
35
35
  private _getUserOpReceiptInner;
36
36
  }
37
+ export declare function stripApiKey(error: unknown): string;
37
38
  export {};
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Erc4337Bundler = void 0;
4
+ exports.stripApiKey = stripApiKey;
4
5
  const viem_1 = require("viem");
5
6
  const util_1 = require("../util");
6
7
  function bundlerUrl(chainId, apikey) {
@@ -65,18 +66,19 @@ async function handleRequest(clientMethod) {
65
66
  return await clientMethod();
66
67
  }
67
68
  catch (error) {
69
+ const message = stripApiKey(error);
68
70
  if (error instanceof viem_1.HttpRequestError) {
69
71
  if (error.status === 401) {
70
- throw new Error("Unauthorized request. Please check your API key.");
72
+ throw new Error("Unauthorized request. Please check your Pimlico API key.");
71
73
  }
72
74
  else {
73
- console.error(`Request failed with status ${error.status}: ${error.message}`);
75
+ throw new Error(`Pimlico: ${message}`);
74
76
  }
75
77
  }
76
78
  else if (error instanceof viem_1.RpcError) {
77
- throw new Error(`Failed to send user op with: ${error.message}`);
79
+ throw new Error(`Failed to send user op with: ${message}`);
78
80
  }
79
- throw new Error(`Unexpected error ${error instanceof Error ? error.message : String(error)}`);
81
+ throw new Error(`Bundler Request: ${message}`);
80
82
  }
81
83
  }
82
84
  // TODO(bh2smith) Should probably get reasonable estimates here:
@@ -87,3 +89,12 @@ const defaultPaymasterData = (safeNotDeployed) => {
87
89
  preVerificationGas: (0, viem_1.toHex)(100000),
88
90
  };
89
91
  };
92
+ function stripApiKey(error) {
93
+ const message = error instanceof Error ? error.message : String(error);
94
+ return message.replace(/(apikey=)[^\s&]+/, "$1***");
95
+ // Could also do this with slicing.
96
+ // const keyStart = message.indexOf("apikey=") + 7;
97
+ // // If no apikey in the message, return it as is.
98
+ // if (keyStart === -1) return message;
99
+ // return `${message.slice(0, keyStart)}***${message.slice(keyStart + 36)}`;
100
+ }
@@ -1,6 +1,6 @@
1
1
  import { type SafeInfo } from "@safe-global/safe-gateway-typescript-sdk";
2
- import { EIP712TypedData, RecoveryData } from "near-ca";
3
- import { Address, Hash } from "viem";
2
+ import { EIP712TypedData } from "near-ca";
3
+ import { Hash } from "viem";
4
4
  export type DecodedSafeMessage = {
5
5
  decodedMessage: string | EIP712TypedData;
6
6
  safeMessageMessage: string;
@@ -20,8 +20,3 @@ export type MinimalSafeInfo = Pick<SafeInfo, "address" | "version" | "chainId">;
20
20
  * }`
21
21
  */
22
22
  export declare function decodeSafeMessage(message: string | EIP712TypedData, safe: MinimalSafeInfo): DecodedSafeMessage;
23
- export declare function safeMessageTxData(method: string, message: DecodedSafeMessage, sender: Address): {
24
- evmMessage: string;
25
- payload: number[];
26
- recoveryData: RecoveryData;
27
- };
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.decodeSafeMessage = decodeSafeMessage;
4
- exports.safeMessageTxData = safeMessageTxData;
5
- const near_ca_1 = require("near-ca");
6
4
  const semver_1 = require("semver");
7
5
  const viem_1 = require("viem");
8
6
  /*
@@ -84,21 +82,6 @@ function decodeSafeMessage(message, safe) {
84
82
  safeMessageHash: generateSafeMessageHash(safe, decodedMessage),
85
83
  };
86
84
  }
87
- function safeMessageTxData(method, message, sender) {
88
- return {
89
- evmMessage: message.safeMessageMessage,
90
- payload: (0, near_ca_1.toPayload)(message.safeMessageHash),
91
- recoveryData: {
92
- type: method,
93
- data: {
94
- address: sender,
95
- // TODO - Upgrade Signable Message in near-ca
96
- // @ts-expect-error: Type 'string | EIP712TypedData' is not assignable to type 'SignableMessage'.
97
- message: decodedMessage,
98
- },
99
- },
100
- };
101
- }
102
85
  // const isEIP712TypedData = (obj: any): obj is EIP712TypedData => {
103
86
  // return (
104
87
  // typeof obj === "object" &&
@@ -0,0 +1,21 @@
1
+ import { Address, Hash, Hex, PublicClient } from "viem";
2
+ import { Deployment, GasPrice, MetaTransaction, UnsignedUserOperation, UserOperation } from "../types";
3
+ /**
4
+ * All contracts used in account creation & execution
5
+ */
6
+ export declare class SafeContractSuite {
7
+ dummyClient: PublicClient;
8
+ singleton: Deployment;
9
+ proxyFactory: Deployment;
10
+ m4337: Deployment;
11
+ moduleSetup: Deployment;
12
+ entryPoint: Deployment;
13
+ constructor();
14
+ addressForSetup(setup: Hex, saltNonce?: string): Promise<Address>;
15
+ getSetup(owners: string[]): Hex;
16
+ addOwnerData(newOwner: Address): Hex;
17
+ getOpHash(unsignedUserOp: UserOperation): Promise<Hash>;
18
+ private factoryDataForSetup;
19
+ buildUserOp(nonce: bigint, txData: MetaTransaction, safeAddress: Address, feeData: GasPrice, setup: string, safeNotDeployed: boolean, safeSaltNonce: string): Promise<UnsignedUserOperation>;
20
+ getNonce(address: Address, chainId: number): Promise<bigint>;
21
+ }
@@ -1,54 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ContractSuite = void 0;
4
- const safe_deployments_1 = require("@safe-global/safe-deployments");
5
- const safe_modules_deployments_1 = require("@safe-global/safe-modules-deployments");
3
+ exports.SafeContractSuite = void 0;
6
4
  const viem_1 = require("viem");
5
+ const deployments_1 = require("../_gen/deployments");
7
6
  const util_1 = require("../util");
8
7
  /**
9
8
  * All contracts used in account creation & execution
10
9
  */
11
- class ContractSuite {
12
- constructor(client, singleton, proxyFactory, m4337, moduleSetup, entryPoint) {
13
- this.dummyClient = client;
14
- this.singleton = singleton;
15
- this.proxyFactory = proxyFactory;
16
- this.m4337 = m4337;
17
- this.moduleSetup = moduleSetup;
18
- this.entryPoint = entryPoint;
19
- }
20
- static async init() {
21
- // TODO - this is a cheeky hack.
22
- const client = (0, util_1.getClient)(11155111);
23
- const safeDeployment = (fn) => getDeployment(fn, { version: "1.4.1" });
24
- const m4337Deployment = async (fn) => {
25
- return getDeployment(fn, { version: "0.3.0" });
26
- };
27
- const [singleton, proxyFactory, moduleSetup, m4337] = await Promise.all([
28
- safeDeployment(safe_deployments_1.getSafeL2SingletonDeployment),
29
- safeDeployment(safe_deployments_1.getProxyFactoryDeployment),
30
- m4337Deployment(safe_modules_deployments_1.getSafeModuleSetupDeployment),
31
- m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment),
32
- ]);
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
- ]),
51
- });
10
+ class SafeContractSuite {
11
+ constructor() {
12
+ this.dummyClient = (0, util_1.getClient)(11155111);
13
+ const deployments = deployments_1.SAFE_DEPLOYMENTS;
14
+ this.singleton = deployments.singleton;
15
+ this.proxyFactory = deployments.proxyFactory;
16
+ this.m4337 = deployments.m4337;
17
+ this.moduleSetup = deployments.moduleSetup;
18
+ this.entryPoint = deployments.entryPoint;
52
19
  }
53
20
  async addressForSetup(setup, saltNonce) {
54
21
  // bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
@@ -159,15 +126,4 @@ class ContractSuite {
159
126
  return nonce;
160
127
  }
161
128
  }
162
- exports.ContractSuite = ContractSuite;
163
- async function getDeployment(fn, { version }) {
164
- const deployment = fn({ version });
165
- if (!deployment) {
166
- throw new Error(`Deployment not found for ${fn.name} version ${version}`);
167
- }
168
- // TODO: maybe call parseAbi on deployment.abi here.
169
- return {
170
- address: deployment.networkAddresses["11155111"],
171
- abi: deployment.abi,
172
- };
173
- }
129
+ exports.SafeContractSuite = SafeContractSuite;
@@ -1,29 +1,29 @@
1
+ import { NearConfig } from "near-api-js/lib/near";
1
2
  import { FinalExecutionOutcome } from "near-api-js/lib/providers";
2
- import { NearEthAdapter, SignRequestData, NearEthTxData, RecoveryData } from "near-ca";
3
+ import { NearEthAdapter, SignRequestData } from "near-ca";
3
4
  import { Address, Hash, Hex } from "viem";
4
- import { Erc4337Bundler } from "./lib/bundler";
5
- import { ContractSuite } from "./lib/safe";
6
- import { MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
7
- export declare class TransactionManager {
5
+ import { SafeContractSuite } from "./lib/safe";
6
+ import { EncodedTxData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
7
+ export interface NearSafeConfig {
8
+ accountId: string;
9
+ mpcContractId: string;
10
+ pimlicoKey: string;
11
+ nearConfig?: NearConfig;
12
+ privateKey?: string;
13
+ safeSaltNonce?: string;
14
+ }
15
+ export declare class NearSafe {
8
16
  readonly nearAdapter: NearEthAdapter;
9
17
  readonly address: Address;
10
18
  private safePack;
11
19
  private setup;
12
20
  private pimlicoKey;
13
21
  private safeSaltNonce;
14
- private deployedChains;
15
- constructor(nearAdapter: NearEthAdapter, safePack: ContractSuite, pimlicoKey: string, setup: string, safeAddress: Address, safeSaltNonce: string);
16
- static create(config: {
17
- accountId: string;
18
- mpcContractId: string;
19
- pimlicoKey: string;
20
- privateKey?: string;
21
- safeSaltNonce?: string;
22
- }): Promise<TransactionManager>;
22
+ static create(config: NearSafeConfig): Promise<NearSafe>;
23
+ constructor(nearAdapter: NearEthAdapter, safePack: SafeContractSuite, pimlicoKey: string, setup: string, safeAddress: Address, safeSaltNonce: string);
23
24
  get mpcAddress(): Address;
24
25
  get mpcContractId(): string;
25
26
  getBalance(chainId: number): Promise<bigint>;
26
- bundlerForChainId(chainId: number): Erc4337Bundler;
27
27
  buildTransaction(args: {
28
28
  chainId: number;
29
29
  transactions: MetaTransaction[];
@@ -31,15 +31,16 @@ export declare class TransactionManager {
31
31
  }): Promise<UserOperation>;
32
32
  signTransaction(safeOpHash: Hex): Promise<Hex>;
33
33
  opHash(userOp: UserOperation): Promise<Hash>;
34
- encodeSignRequest(signRequest: SignRequestData, usePaymaster: boolean): Promise<NearEthTxData>;
35
- executeTransaction(chainId: number, userOp: UserOperation): Promise<UserOperationReceipt>;
36
- safeDeployed(chainId: number): Promise<boolean>;
37
- addOwnerTx(address: Address): MetaTransaction;
38
- safeSufficientlyFunded(chainId: number, transactions: MetaTransaction[], gasCost: bigint): Promise<boolean>;
34
+ encodeSignRequest(signRequest: SignRequestData, usePaymaster: boolean): Promise<EncodedTxData>;
39
35
  broadcastEvm(chainId: number, outcome: FinalExecutionOutcome, unsignedUserOp: UserOperation): Promise<{
40
36
  signature: Hex;
41
37
  receipt: UserOperationReceipt;
42
38
  }>;
39
+ executeTransaction(chainId: number, userOp: UserOperation): Promise<UserOperationReceipt>;
40
+ safeDeployed(chainId: number): Promise<boolean>;
41
+ sufficientlyFunded(chainId: number, transactions: MetaTransaction[], gasCost: bigint): Promise<boolean>;
42
+ addOwnerTx(address: Address): MetaTransaction;
43
+ private bundlerForChainId;
43
44
  /**
44
45
  * Handles routing of signature requests based on the provided method, chain ID, and parameters.
45
46
  *
@@ -53,6 +54,6 @@ export declare class TransactionManager {
53
54
  requestRouter({ method, chainId, params }: SignRequestData, usePaymaster: boolean): Promise<{
54
55
  evmMessage: string;
55
56
  payload: number[];
56
- recoveryData: RecoveryData;
57
+ hash: Hash;
57
58
  }>;
58
59
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TransactionManager = void 0;
3
+ exports.NearSafe = void 0;
4
4
  const near_ca_1 = require("near-ca");
5
5
  const viem_1 = require("viem");
6
6
  const bundler_1 = require("./lib/bundler");
@@ -8,27 +8,28 @@ const multisend_1 = require("./lib/multisend");
8
8
  const safe_1 = require("./lib/safe");
9
9
  const safe_message_1 = require("./lib/safe-message");
10
10
  const util_1 = require("./util");
11
- class TransactionManager {
11
+ class NearSafe {
12
+ static async create(config) {
13
+ const { pimlicoKey, safeSaltNonce } = config;
14
+ const nearAdapter = await (0, near_ca_1.setupAdapter)({ ...config });
15
+ const safePack = new safe_1.SafeContractSuite();
16
+ const setup = safePack.getSetup([nearAdapter.address]);
17
+ const safeAddress = await safePack.addressForSetup(setup, safeSaltNonce);
18
+ console.log(`
19
+ Near Adapter:
20
+ Near Account ID: ${nearAdapter.nearAccountId()}
21
+ MPC EOA: ${nearAdapter.address}
22
+ Safe: ${safeAddress}
23
+ `);
24
+ return new NearSafe(nearAdapter, safePack, pimlicoKey, setup, safeAddress, safeSaltNonce || "0");
25
+ }
12
26
  constructor(nearAdapter, safePack, pimlicoKey, setup, safeAddress, safeSaltNonce) {
13
27
  this.nearAdapter = nearAdapter;
28
+ this.address = safeAddress;
29
+ this.setup = setup;
14
30
  this.safePack = safePack;
15
31
  this.pimlicoKey = pimlicoKey;
16
- this.setup = setup;
17
- this.address = safeAddress;
18
32
  this.safeSaltNonce = safeSaltNonce;
19
- this.deployedChains = new Set();
20
- }
21
- static async create(config) {
22
- const { pimlicoKey } = config;
23
- const [nearAdapter, safePack] = await Promise.all([
24
- (0, near_ca_1.setupAdapter)({ ...config }),
25
- safe_1.ContractSuite.init(),
26
- ]);
27
- console.log(`Near Adapter: ${nearAdapter.nearAccountId()} <> ${nearAdapter.address}`);
28
- const setup = safePack.getSetup([nearAdapter.address]);
29
- const safeAddress = await safePack.addressForSetup(setup, config.safeSaltNonce);
30
- console.log(`Safe Address: ${safeAddress}`);
31
- return new TransactionManager(nearAdapter, safePack, pimlicoKey, setup, safeAddress, config.safeSaltNonce || "0");
32
33
  }
33
34
  get mpcAddress() {
34
35
  return this.nearAdapter.address;
@@ -39,9 +40,6 @@ class TransactionManager {
39
40
  async getBalance(chainId) {
40
41
  return await (0, util_1.getClient)(chainId).getBalance({ address: this.address });
41
42
  }
42
- bundlerForChainId(chainId) {
43
- return new bundler_1.Erc4337Bundler(this.safePack.entryPoint.address, this.pimlicoKey, chainId);
44
- }
45
43
  async buildTransaction(args) {
46
44
  const { transactions, usePaymaster, chainId } = args;
47
45
  if (transactions.length === 0) {
@@ -68,16 +66,35 @@ class TransactionManager {
68
66
  return this.safePack.getOpHash(userOp);
69
67
  }
70
68
  async encodeSignRequest(signRequest, usePaymaster) {
71
- const data = await this.requestRouter(signRequest, usePaymaster);
69
+ const { payload, evmMessage, hash } = await this.requestRouter(signRequest, usePaymaster);
72
70
  return {
73
71
  nearPayload: await this.nearAdapter.mpcContract.encodeSignatureRequestTx({
74
72
  path: this.nearAdapter.derivationPath,
75
- payload: data.payload,
73
+ payload,
76
74
  key_version: 0,
77
75
  }),
78
- ...data,
76
+ evmData: {
77
+ chainId: signRequest.chainId,
78
+ data: evmMessage,
79
+ hash,
80
+ },
79
81
  };
80
82
  }
83
+ async broadcastEvm(chainId, outcome, unsignedUserOp) {
84
+ const signature = (0, util_1.packSignature)((0, viem_1.serializeSignature)((0, near_ca_1.signatureFromOutcome)(outcome)));
85
+ try {
86
+ return {
87
+ signature,
88
+ receipt: await this.executeTransaction(chainId, {
89
+ ...unsignedUserOp,
90
+ signature,
91
+ }),
92
+ };
93
+ }
94
+ catch (error) {
95
+ throw new Error(`Failed EVM broadcast: ${error instanceof Error ? error.message : String(error)}`);
96
+ }
97
+ }
81
98
  async executeTransaction(chainId, userOp) {
82
99
  const bundler = this.bundlerForChainId(chainId);
83
100
  const userOpHash = await bundler.sendUserOperation(userOp);
@@ -89,15 +106,15 @@ class TransactionManager {
89
106
  return userOpReceipt;
90
107
  }
91
108
  async safeDeployed(chainId) {
92
- // Early exit if already known.
93
- if (chainId in this.deployedChains) {
109
+ return (0, util_1.isContract)(this.address, chainId);
110
+ }
111
+ async sufficientlyFunded(chainId, transactions, gasCost) {
112
+ const txValue = transactions.reduce((acc, tx) => acc + BigInt(tx.value), 0n);
113
+ if (txValue + gasCost === 0n) {
94
114
  return true;
95
115
  }
96
- const deployed = await (0, util_1.isContract)(this.address, chainId);
97
- if (deployed) {
98
- this.deployedChains.add(chainId);
99
- }
100
- return deployed;
116
+ const safeBalance = await this.getBalance(chainId);
117
+ return txValue + gasCost < safeBalance;
101
118
  }
102
119
  addOwnerTx(address) {
103
120
  return {
@@ -106,28 +123,8 @@ class TransactionManager {
106
123
  data: this.safePack.addOwnerData(address),
107
124
  };
108
125
  }
109
- async safeSufficientlyFunded(chainId, transactions, gasCost) {
110
- const txValue = transactions.reduce((acc, tx) => acc + BigInt(tx.value), 0n);
111
- if (txValue + gasCost === 0n) {
112
- return true;
113
- }
114
- const safeBalance = await this.getBalance(chainId);
115
- return txValue + gasCost < safeBalance;
116
- }
117
- async broadcastEvm(chainId, outcome, unsignedUserOp) {
118
- const signature = (0, util_1.packSignature)((0, viem_1.serializeSignature)((0, near_ca_1.signatureFromOutcome)(outcome)));
119
- try {
120
- return {
121
- signature,
122
- receipt: await this.executeTransaction(chainId, {
123
- ...unsignedUserOp,
124
- signature,
125
- }),
126
- };
127
- }
128
- catch (error) {
129
- throw new Error(`Failed EVM broadcast: ${error instanceof Error ? error.message : String(error)}`);
130
- }
126
+ bundlerForChainId(chainId) {
127
+ return new bundler_1.Erc4337Bundler(this.safePack.entryPoint.address, this.pimlicoKey, chainId);
131
128
  }
132
129
  /**
133
130
  * Handles routing of signature requests based on the provided method, chain ID, and parameters.
@@ -152,12 +149,22 @@ class TransactionManager {
152
149
  case "eth_signTypedData":
153
150
  case "eth_signTypedData_v4":
154
151
  case "eth_sign": {
155
- const [sender, messageOrData] = params;
156
- return (0, safe_message_1.safeMessageTxData)(method, (0, safe_message_1.decodeSafeMessage)(messageOrData, safeInfo), sender);
152
+ const [_, messageOrData] = params;
153
+ const message = (0, safe_message_1.decodeSafeMessage)(messageOrData, safeInfo);
154
+ return {
155
+ evmMessage: message.safeMessageMessage,
156
+ payload: (0, near_ca_1.toPayload)(message.safeMessageHash),
157
+ hash: message.safeMessageHash,
158
+ };
157
159
  }
158
160
  case "personal_sign": {
159
- const [messageHash, sender] = params;
160
- return (0, safe_message_1.safeMessageTxData)(method, (0, safe_message_1.decodeSafeMessage)(messageHash, safeInfo), sender);
161
+ const [messageHash, _] = params;
162
+ const message = (0, safe_message_1.decodeSafeMessage)(messageHash, safeInfo);
163
+ return {
164
+ evmMessage: message.safeMessageMessage,
165
+ payload: (0, near_ca_1.toPayload)(message.safeMessageHash),
166
+ hash: message.safeMessageHash,
167
+ };
161
168
  }
162
169
  case "eth_sendTransaction": {
163
170
  const transactions = (0, util_1.metaTransactionsFromRequest)(params);
@@ -170,15 +177,10 @@ class TransactionManager {
170
177
  return {
171
178
  payload: (0, near_ca_1.toPayload)(opHash),
172
179
  evmMessage: JSON.stringify(userOp),
173
- recoveryData: {
174
- type: method,
175
- // TODO: Double check that this is sufficient for UI.
176
- // We may want to adapt and return the `MetaTransactions` instead.
177
- data: opHash,
178
- },
180
+ hash: await this.opHash(userOp),
179
181
  };
180
182
  }
181
183
  }
182
184
  }
183
185
  }
184
- exports.TransactionManager = TransactionManager;
186
+ exports.NearSafe = NearSafe;
@@ -1,4 +1,16 @@
1
- import { Address, Hex } from "viem";
1
+ import { FunctionCallTransaction, SignArgs } from "near-ca";
2
+ import { Address, Hash, Hex, ParseAbi, TransactionSerializable } from "viem";
3
+ export type SafeDeployments = {
4
+ singleton: Deployment;
5
+ proxyFactory: Deployment;
6
+ moduleSetup: Deployment;
7
+ m4337: Deployment;
8
+ entryPoint: Deployment;
9
+ };
10
+ export interface Deployment {
11
+ abi: unknown[] | ParseAbi<readonly string[]>;
12
+ address: Address;
13
+ }
2
14
  export interface UnsignedUserOperation {
3
15
  sender: Address;
4
16
  nonce: string;
@@ -89,4 +101,14 @@ export interface MetaTransaction {
89
101
  readonly data: string;
90
102
  readonly operation?: OperationType;
91
103
  }
104
+ export interface EncodedTxData {
105
+ evmData: {
106
+ chainId: number;
107
+ data: string | TransactionSerializable;
108
+ hash: Hash;
109
+ };
110
+ nearPayload: FunctionCallTransaction<{
111
+ request: SignArgs;
112
+ }>;
113
+ }
92
114
  export {};
@@ -0,0 +1,17 @@
1
+ import { Deployment, SafeDeployments } from "../src/types";
2
+ export declare const SAFE_VERSION = "1.4.1";
3
+ export declare const MODULE_VERSION = "0.3.0";
4
+ type DeploymentFn = (filter?: {
5
+ version: string;
6
+ }) => {
7
+ networkAddresses: {
8
+ [chainId: string]: string;
9
+ };
10
+ abi: unknown[];
11
+ } | undefined;
12
+ type DeploymentArgs = {
13
+ version: string;
14
+ };
15
+ export declare function getDeployment(fn: DeploymentFn, { version }: DeploymentArgs): Promise<Deployment>;
16
+ export declare function fetchDeployments(safeVersion?: string, moduleVersion?: string): Promise<SafeDeployments>;
17
+ export {};
@@ -0,0 +1,54 @@
1
+ import { getProxyFactoryDeployment, getSafeL2SingletonDeployment, } from "@safe-global/safe-deployments";
2
+ import { getSafe4337ModuleDeployment, getSafeModuleSetupDeployment, } from "@safe-global/safe-modules-deployments";
3
+ import { parseAbi } from "viem";
4
+ import { getClient } from "../src/util";
5
+ // Define the deployment version and chain ID (e.g., "1.4.1" for Safe contracts, "0.3.0" for modules)
6
+ export const SAFE_VERSION = "1.4.1";
7
+ export const MODULE_VERSION = "0.3.0";
8
+ export async function getDeployment(fn, { version }) {
9
+ const deployment = fn({ version });
10
+ if (!deployment) {
11
+ throw new Error(`Deployment not found for ${fn.name} version ${version}`);
12
+ }
13
+ // TODO: maybe call parseAbi on deployment.abi here.
14
+ return {
15
+ address: deployment.networkAddresses["11155111"],
16
+ abi: deployment.abi,
17
+ };
18
+ }
19
+ export async function fetchDeployments(safeVersion = SAFE_VERSION, moduleVersion = MODULE_VERSION) {
20
+ console.log("Fetching deployments...");
21
+ const safeDeployment = async (fn) => getDeployment(fn, { version: safeVersion });
22
+ const m4337Deployment = async (fn) => getDeployment(fn, { version: moduleVersion });
23
+ try {
24
+ // Fetch deployments for Safe and 4337 modules
25
+ const [singleton, proxyFactory, moduleSetup, m4337] = await Promise.all([
26
+ safeDeployment(getSafeL2SingletonDeployment),
27
+ safeDeployment(getProxyFactoryDeployment),
28
+ m4337Deployment(getSafeModuleSetupDeployment),
29
+ m4337Deployment(getSafe4337ModuleDeployment),
30
+ ]);
31
+ // TODO - this is a cheeky hack.
32
+ const client = getClient(11155111);
33
+ const entryPoint = {
34
+ address: (await client.readContract({
35
+ address: m4337.address,
36
+ abi: m4337.abi,
37
+ functionName: "SUPPORTED_ENTRYPOINT",
38
+ })),
39
+ abi: parseAbi([
40
+ "function getNonce(address, uint192 key) view returns (uint256 nonce)",
41
+ ]),
42
+ };
43
+ return {
44
+ singleton,
45
+ proxyFactory,
46
+ moduleSetup,
47
+ m4337,
48
+ entryPoint,
49
+ };
50
+ }
51
+ catch (error) {
52
+ throw new Error(`Error fetching deployments: ${error}`);
53
+ }
54
+ }
@@ -0,0 +1,2 @@
1
+ import { SafeDeployments } from "../types";
2
+ export declare const SAFE_DEPLOYMENTS: SafeDeployments;