near-safe 0.4.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. package/dist/cjs/{src/lib → lib}/multisend.d.ts +1 -0
  2. package/dist/cjs/{src/lib → lib}/multisend.js +6 -0
  3. package/dist/{esm/src → cjs}/near-safe.d.ts +6 -1
  4. package/dist/cjs/{src/near-safe.js → near-safe.js} +28 -0
  5. package/dist/cjs/{src/types.d.ts → types.d.ts} +7 -6
  6. package/dist/esm/{src/lib → lib}/multisend.d.ts +1 -0
  7. package/dist/esm/{src/lib → lib}/multisend.js +5 -0
  8. package/dist/{cjs/src → esm}/near-safe.d.ts +6 -1
  9. package/dist/esm/{src/near-safe.js → near-safe.js} +30 -2
  10. package/dist/esm/{src/types.d.ts → types.d.ts} +7 -6
  11. package/package.json +3 -3
  12. package/dist/cjs/scripts/fetch-deployments.d.ts +0 -17
  13. package/dist/cjs/scripts/fetch-deployments.js +0 -59
  14. package/dist/esm/scripts/fetch-deployments.d.ts +0 -17
  15. package/dist/esm/scripts/fetch-deployments.js +0 -54
  16. /package/dist/cjs/{src/_gen → _gen}/deployments.d.ts +0 -0
  17. /package/dist/cjs/{src/_gen → _gen}/deployments.js +0 -0
  18. /package/dist/cjs/{src/index.d.ts → index.d.ts} +0 -0
  19. /package/dist/cjs/{src/index.js → index.js} +0 -0
  20. /package/dist/cjs/{src/lib → lib}/bundler.d.ts +0 -0
  21. /package/dist/cjs/{src/lib → lib}/bundler.js +0 -0
  22. /package/dist/cjs/{src/lib → lib}/safe-message.d.ts +0 -0
  23. /package/dist/cjs/{src/lib → lib}/safe-message.js +0 -0
  24. /package/dist/cjs/{src/lib → lib}/safe.d.ts +0 -0
  25. /package/dist/cjs/{src/lib → lib}/safe.js +0 -0
  26. /package/dist/cjs/{src/types.js → types.js} +0 -0
  27. /package/dist/cjs/{src/util.d.ts → util.d.ts} +0 -0
  28. /package/dist/cjs/{src/util.js → util.js} +0 -0
  29. /package/dist/esm/{src/_gen → _gen}/deployments.d.ts +0 -0
  30. /package/dist/esm/{src/_gen → _gen}/deployments.js +0 -0
  31. /package/dist/esm/{src/index.d.ts → index.d.ts} +0 -0
  32. /package/dist/esm/{src/index.js → index.js} +0 -0
  33. /package/dist/esm/{src/lib → lib}/bundler.d.ts +0 -0
  34. /package/dist/esm/{src/lib → lib}/bundler.js +0 -0
  35. /package/dist/esm/{src/lib → lib}/safe-message.d.ts +0 -0
  36. /package/dist/esm/{src/lib → lib}/safe-message.js +0 -0
  37. /package/dist/esm/{src/lib → lib}/safe.d.ts +0 -0
  38. /package/dist/esm/{src/lib → lib}/safe.js +0 -0
  39. /package/dist/esm/{src/types.js → types.js} +0 -0
  40. /package/dist/esm/{src/util.d.ts → util.d.ts} +0 -0
  41. /package/dist/esm/{src/util.js → util.js} +0 -0
@@ -1,3 +1,4 @@
1
1
  import { MetaTransaction } from "../types";
2
2
  export declare const MULTI_SEND_ABI: string[];
3
3
  export declare function encodeMulti(transactions: readonly MetaTransaction[], multiSendContractAddress?: string): MetaTransaction;
4
+ export declare function isMultisendTx(args: readonly unknown[]): boolean;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MULTI_SEND_ABI = void 0;
4
4
  exports.encodeMulti = encodeMulti;
5
+ exports.isMultisendTx = isMultisendTx;
5
6
  const viem_1 = require("viem");
6
7
  const types_1 = require("../types");
7
8
  exports.MULTI_SEND_ABI = ["function multiSend(bytes memory transactions)"];
@@ -38,3 +39,8 @@ function encodeMulti(transactions, multiSendContractAddress = transactions.some(
38
39
  }),
39
40
  };
40
41
  }
42
+ function isMultisendTx(args) {
43
+ const to = args[0].toLowerCase();
44
+ return (to === MULTISEND_141.toLowerCase() ||
45
+ to === MULTISEND_CALLONLY_141.toLowerCase());
46
+ }
@@ -3,7 +3,7 @@ import { FinalExecutionOutcome } from "near-api-js/lib/providers";
3
3
  import { NearEthAdapter, SignRequestData } from "near-ca";
4
4
  import { Address, Hash, Hex } from "viem";
5
5
  import { SafeContractSuite } from "./lib/safe";
6
- import { EncodedTxData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
6
+ import { EncodedTxData, EvmTransactionData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
7
7
  export interface NearSafeConfig {
8
8
  accountId: string;
9
9
  mpcContractId: string;
@@ -41,6 +41,11 @@ export declare class NearSafe {
41
41
  sufficientlyFunded(chainId: number, transactions: MetaTransaction[], gasCost: bigint): Promise<boolean>;
42
42
  addOwnerTx(address: Address): MetaTransaction;
43
43
  private bundlerForChainId;
44
+ decodeTxData(data: EvmTransactionData): {
45
+ chainId: number;
46
+ costEstimate: string;
47
+ transactions: MetaTransaction[];
48
+ };
44
49
  /**
45
50
  * Handles routing of signature requests based on the provided method, chain ID, and parameters.
46
51
  *
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NearSafe = void 0;
4
+ const ethers_multisend_1 = require("ethers-multisend");
4
5
  const near_ca_1 = require("near-ca");
5
6
  const viem_1 = require("viem");
6
7
  const bundler_1 = require("./lib/bundler");
@@ -126,6 +127,33 @@ class NearSafe {
126
127
  bundlerForChainId(chainId) {
127
128
  return new bundler_1.Erc4337Bundler(this.safePack.entryPoint.address, this.pimlicoKey, chainId);
128
129
  }
130
+ decodeTxData(data) {
131
+ // TODO: data.data may not always parse to UserOperation. We will have to handle the other cases.
132
+ const userOp = JSON.parse(data.data);
133
+ const { callGasLimit, maxFeePerGas, maxPriorityFeePerGas } = userOp;
134
+ const maxGasPrice = BigInt(maxFeePerGas) + BigInt(maxPriorityFeePerGas);
135
+ const { args } = (0, viem_1.decodeFunctionData)({
136
+ abi: this.safePack.m4337.abi,
137
+ data: userOp.callData,
138
+ });
139
+ // Determine if sungular or double!
140
+ const transactions = (0, multisend_1.isMultisendTx)(args)
141
+ ? (0, ethers_multisend_1.decodeMulti)(args[2])
142
+ : [
143
+ {
144
+ to: args[0],
145
+ value: args[1],
146
+ data: args[2],
147
+ operation: args[3],
148
+ },
149
+ ];
150
+ return {
151
+ chainId: data.chainId,
152
+ // This is an upper bound on the gas fees (could be lower)
153
+ costEstimate: (0, viem_1.formatEther)(BigInt(callGasLimit) * maxGasPrice),
154
+ transactions,
155
+ };
156
+ }
129
157
  /**
130
158
  * Handles routing of signature requests based on the provided method, chain ID, and parameters.
131
159
  *
@@ -1,5 +1,5 @@
1
1
  import { FunctionCallTransaction, SignArgs } from "near-ca";
2
- import { Address, Hash, Hex, ParseAbi, TransactionSerializable } from "viem";
2
+ import { Address, Hex, ParseAbi } from "viem";
3
3
  export type SafeDeployments = {
4
4
  singleton: Deployment;
5
5
  proxyFactory: Deployment;
@@ -101,12 +101,13 @@ export interface MetaTransaction {
101
101
  readonly data: string;
102
102
  readonly operation?: OperationType;
103
103
  }
104
+ export interface EvmTransactionData {
105
+ chainId: number;
106
+ data: string;
107
+ hash: string;
108
+ }
104
109
  export interface EncodedTxData {
105
- evmData: {
106
- chainId: number;
107
- data: string | TransactionSerializable;
108
- hash: Hash;
109
- };
110
+ evmData: EvmTransactionData;
110
111
  nearPayload: FunctionCallTransaction<{
111
112
  request: SignArgs;
112
113
  }>;
@@ -1,3 +1,4 @@
1
1
  import { MetaTransaction } from "../types";
2
2
  export declare const MULTI_SEND_ABI: string[];
3
3
  export declare function encodeMulti(transactions: readonly MetaTransaction[], multiSendContractAddress?: string): MetaTransaction;
4
+ export declare function isMultisendTx(args: readonly unknown[]): boolean;
@@ -34,3 +34,8 @@ export function encodeMulti(transactions, multiSendContractAddress = transaction
34
34
  }),
35
35
  };
36
36
  }
37
+ export function isMultisendTx(args) {
38
+ const to = args[0].toLowerCase();
39
+ return (to === MULTISEND_141.toLowerCase() ||
40
+ to === MULTISEND_CALLONLY_141.toLowerCase());
41
+ }
@@ -3,7 +3,7 @@ import { FinalExecutionOutcome } from "near-api-js/lib/providers";
3
3
  import { NearEthAdapter, SignRequestData } from "near-ca";
4
4
  import { Address, Hash, Hex } from "viem";
5
5
  import { SafeContractSuite } from "./lib/safe";
6
- import { EncodedTxData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
6
+ import { EncodedTxData, EvmTransactionData, MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
7
7
  export interface NearSafeConfig {
8
8
  accountId: string;
9
9
  mpcContractId: string;
@@ -41,6 +41,11 @@ export declare class NearSafe {
41
41
  sufficientlyFunded(chainId: number, transactions: MetaTransaction[], gasCost: bigint): Promise<boolean>;
42
42
  addOwnerTx(address: Address): MetaTransaction;
43
43
  private bundlerForChainId;
44
+ decodeTxData(data: EvmTransactionData): {
45
+ chainId: number;
46
+ costEstimate: string;
47
+ transactions: MetaTransaction[];
48
+ };
44
49
  /**
45
50
  * Handles routing of signature requests based on the provided method, chain ID, and parameters.
46
51
  *
@@ -1,7 +1,8 @@
1
+ import { decodeMulti } from "ethers-multisend";
1
2
  import { setupAdapter, signatureFromOutcome, toPayload, } from "near-ca";
2
- import { serializeSignature } from "viem";
3
+ import { decodeFunctionData, formatEther, serializeSignature, } from "viem";
3
4
  import { Erc4337Bundler } from "./lib/bundler";
4
- import { encodeMulti } from "./lib/multisend";
5
+ import { encodeMulti, isMultisendTx } from "./lib/multisend";
5
6
  import { SafeContractSuite } from "./lib/safe";
6
7
  import { decodeSafeMessage } from "./lib/safe-message";
7
8
  import { getClient, isContract, metaTransactionsFromRequest, packSignature, } from "./util";
@@ -129,6 +130,33 @@ export class NearSafe {
129
130
  bundlerForChainId(chainId) {
130
131
  return new Erc4337Bundler(this.safePack.entryPoint.address, this.pimlicoKey, chainId);
131
132
  }
133
+ decodeTxData(data) {
134
+ // TODO: data.data may not always parse to UserOperation. We will have to handle the other cases.
135
+ const userOp = JSON.parse(data.data);
136
+ const { callGasLimit, maxFeePerGas, maxPriorityFeePerGas } = userOp;
137
+ const maxGasPrice = BigInt(maxFeePerGas) + BigInt(maxPriorityFeePerGas);
138
+ const { args } = decodeFunctionData({
139
+ abi: this.safePack.m4337.abi,
140
+ data: userOp.callData,
141
+ });
142
+ // Determine if sungular or double!
143
+ const transactions = isMultisendTx(args)
144
+ ? decodeMulti(args[2])
145
+ : [
146
+ {
147
+ to: args[0],
148
+ value: args[1],
149
+ data: args[2],
150
+ operation: args[3],
151
+ },
152
+ ];
153
+ return {
154
+ chainId: data.chainId,
155
+ // This is an upper bound on the gas fees (could be lower)
156
+ costEstimate: formatEther(BigInt(callGasLimit) * maxGasPrice),
157
+ transactions,
158
+ };
159
+ }
132
160
  /**
133
161
  * Handles routing of signature requests based on the provided method, chain ID, and parameters.
134
162
  *
@@ -1,5 +1,5 @@
1
1
  import { FunctionCallTransaction, SignArgs } from "near-ca";
2
- import { Address, Hash, Hex, ParseAbi, TransactionSerializable } from "viem";
2
+ import { Address, Hex, ParseAbi } from "viem";
3
3
  export type SafeDeployments = {
4
4
  singleton: Deployment;
5
5
  proxyFactory: Deployment;
@@ -101,12 +101,13 @@ export interface MetaTransaction {
101
101
  readonly data: string;
102
102
  readonly operation?: OperationType;
103
103
  }
104
+ export interface EvmTransactionData {
105
+ chainId: number;
106
+ data: string;
107
+ hash: string;
108
+ }
104
109
  export interface EncodedTxData {
105
- evmData: {
106
- chainId: number;
107
- data: string | TransactionSerializable;
108
- hash: Hash;
109
- };
110
+ evmData: EvmTransactionData;
110
111
  nearPayload: FunctionCallTransaction<{
111
112
  request: SignArgs;
112
113
  }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "near-safe",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "license": "MIT",
5
5
  "description": "An SDK for controlling Ethereum Smart Accounts via ERC4337 from a Near Account.",
6
6
  "author": "bh2smith",
@@ -42,6 +42,7 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@safe-global/safe-gateway-typescript-sdk": "^3.22.2",
45
+ "ethers-multisend": "^3.1.0",
45
46
  "near-api-js": "^5.0.0",
46
47
  "near-ca": "^0.5.6",
47
48
  "semver": "^7.6.3",
@@ -68,7 +69,6 @@
68
69
  "yargs": "^17.7.2"
69
70
  },
70
71
  "resolutions": {
71
- "glob": "^9.0.0",
72
- "base-x": "^3.0.0"
72
+ "glob": "^11.0.0"
73
73
  }
74
74
  }
@@ -1,17 +0,0 @@
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 {};
@@ -1,59 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MODULE_VERSION = exports.SAFE_VERSION = void 0;
4
- exports.getDeployment = getDeployment;
5
- exports.fetchDeployments = fetchDeployments;
6
- const safe_deployments_1 = require("@safe-global/safe-deployments");
7
- const safe_modules_deployments_1 = require("@safe-global/safe-modules-deployments");
8
- const viem_1 = require("viem");
9
- const util_1 = require("../src/util");
10
- // Define the deployment version and chain ID (e.g., "1.4.1" for Safe contracts, "0.3.0" for modules)
11
- exports.SAFE_VERSION = "1.4.1";
12
- exports.MODULE_VERSION = "0.3.0";
13
- async function getDeployment(fn, { version }) {
14
- const deployment = fn({ version });
15
- if (!deployment) {
16
- throw new Error(`Deployment not found for ${fn.name} version ${version}`);
17
- }
18
- // TODO: maybe call parseAbi on deployment.abi here.
19
- return {
20
- address: deployment.networkAddresses["11155111"],
21
- abi: deployment.abi,
22
- };
23
- }
24
- async function fetchDeployments(safeVersion = exports.SAFE_VERSION, moduleVersion = exports.MODULE_VERSION) {
25
- console.log("Fetching deployments...");
26
- const safeDeployment = async (fn) => getDeployment(fn, { version: safeVersion });
27
- const m4337Deployment = async (fn) => getDeployment(fn, { version: moduleVersion });
28
- try {
29
- // Fetch deployments for Safe and 4337 modules
30
- const [singleton, proxyFactory, moduleSetup, m4337] = await Promise.all([
31
- safeDeployment(safe_deployments_1.getSafeL2SingletonDeployment),
32
- safeDeployment(safe_deployments_1.getProxyFactoryDeployment),
33
- m4337Deployment(safe_modules_deployments_1.getSafeModuleSetupDeployment),
34
- m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment),
35
- ]);
36
- // TODO - this is a cheeky hack.
37
- const client = (0, util_1.getClient)(11155111);
38
- const entryPoint = {
39
- address: (await client.readContract({
40
- address: m4337.address,
41
- abi: m4337.abi,
42
- functionName: "SUPPORTED_ENTRYPOINT",
43
- })),
44
- abi: (0, viem_1.parseAbi)([
45
- "function getNonce(address, uint192 key) view returns (uint256 nonce)",
46
- ]),
47
- };
48
- return {
49
- singleton,
50
- proxyFactory,
51
- moduleSetup,
52
- m4337,
53
- entryPoint,
54
- };
55
- }
56
- catch (error) {
57
- throw new Error(`Error fetching deployments: ${error}`);
58
- }
59
- }
@@ -1,17 +0,0 @@
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 {};
@@ -1,54 +0,0 @@
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
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes