near-safe 0.8.4 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,3 +5,13 @@ export declare function decodeTransactionSerializable(chainId: number, tx: Trans
5
5
  export declare function decodeRlpHex(chainId: number, tx: Hex): DecodedTxData;
6
6
  export declare function decodeTypedData(chainId: number, data: EIP712TypedData): DecodedTxData;
7
7
  export declare function decodeUserOperation(chainId: number, userOp: UserOperation): DecodedTxData;
8
+ export declare enum OperationType {
9
+ Call = 0,
10
+ DelegateCall = 1
11
+ }
12
+ export interface MetaTransaction {
13
+ readonly to: string;
14
+ readonly value: string;
15
+ readonly data: string;
16
+ readonly operation?: OperationType;
17
+ }
@@ -4,7 +4,6 @@ exports.decodeTransactionSerializable = decodeTransactionSerializable;
4
4
  exports.decodeRlpHex = decodeRlpHex;
5
5
  exports.decodeTypedData = decodeTypedData;
6
6
  exports.decodeUserOperation = decodeUserOperation;
7
- const ethers_multisend_1 = require("ethers-multisend");
8
7
  const viem_1 = require("viem");
9
8
  const deployments_1 = require("../_gen/deployments");
10
9
  const multisend_1 = require("../lib/multisend");
@@ -52,7 +51,7 @@ function decodeUserOperation(chainId, userOp) {
52
51
  });
53
52
  // Determine if singular or double!
54
53
  const transactions = (0, multisend_1.isMultisendTx)(args)
55
- ? (0, ethers_multisend_1.decodeMulti)(args[2])
54
+ ? (0, multisend_1.decodeMulti)(args[2])
56
55
  : [
57
56
  {
58
57
  to: args[0],
@@ -1,4 +1,6 @@
1
+ import { Hex } from "viem";
1
2
  import { MetaTransaction } from "../types";
2
3
  export declare const MULTI_SEND_ABI: string[];
3
4
  export declare function encodeMulti(transactions: readonly MetaTransaction[], multiSendContractAddress?: string): MetaTransaction;
4
5
  export declare function isMultisendTx(args: readonly unknown[]): boolean;
6
+ export declare function decodeMulti(data: Hex): MetaTransaction[];
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MULTI_SEND_ABI = void 0;
4
4
  exports.encodeMulti = encodeMulti;
5
5
  exports.isMultisendTx = isMultisendTx;
6
+ exports.decodeMulti = decodeMulti;
6
7
  const viem_1 = require("viem");
7
8
  const types_1 = require("../types");
8
9
  exports.MULTI_SEND_ABI = ["function multiSend(bytes memory transactions)"];
@@ -44,3 +45,37 @@ function isMultisendTx(args) {
44
45
  return (to === MULTISEND_141.toLowerCase() ||
45
46
  to === MULTISEND_CALLONLY_141.toLowerCase());
46
47
  }
48
+ function unpack(packed, startIndex) {
49
+ // read operation from first 8 bits (= 2 hex digits)
50
+ const operation = parseInt(packed.substring(startIndex, startIndex + 2), 16);
51
+ // the next 40 characters are the to address
52
+ const to = (0, viem_1.getAddress)(`0x${packed.substring(startIndex + 2, startIndex + 42)}`);
53
+ // then comes the uint256 value (= 64 hex digits)
54
+ const value = (0, viem_1.toHex)(BigInt(`0x${packed.substring(startIndex + 42, startIndex + 106)}`));
55
+ // and the uint256 data length (= 64 hex digits)
56
+ const hexDataLength = parseInt(packed.substring(startIndex + 106, startIndex + 170), 16);
57
+ const endIndex = startIndex + 170 + hexDataLength * 2; // * 2 because each hex item is represented with 2 digits
58
+ const data = `0x${packed.substring(startIndex + 170, endIndex)}`;
59
+ return {
60
+ operation,
61
+ to,
62
+ value,
63
+ data,
64
+ endIndex,
65
+ };
66
+ }
67
+ function decodeMulti(data) {
68
+ const tx = (0, viem_1.decodeFunctionData)({
69
+ abi: (0, viem_1.parseAbi)(exports.MULTI_SEND_ABI),
70
+ data,
71
+ });
72
+ const [transactionsEncoded] = tx.args;
73
+ const result = [];
74
+ let startIndex = 2; // skip over 0x
75
+ while (startIndex < transactionsEncoded.length) {
76
+ const { endIndex, ...tx } = unpack(transactionsEncoded, startIndex);
77
+ result.push(tx);
78
+ startIndex = endIndex;
79
+ }
80
+ return result;
81
+ }
@@ -1,5 +1,4 @@
1
1
  import { NearConfig } from "near-api-js/lib/near";
2
- import { FinalExecutionOutcome } from "near-api-js/lib/providers";
3
2
  import { NearEthAdapter, SignRequestData, EncodedSignRequest } from "near-ca";
4
3
  import { Address, Hash, Hex } from "viem";
5
4
  import { SafeContractSuite } from "./lib/safe";
@@ -99,15 +98,12 @@ export declare class NearSafe {
99
98
  * Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
100
99
  *
101
100
  * @param {number} chainId - The ID of the EVM network to which the transaction should be broadcasted.
102
- * @param {FinalExecutionOutcome} outcome - The result of the NEAR transaction execution, which contains the necessary data to construct an EVM signature.
101
+ * @param {Signature} signature - The valid signature of the unsignedUserOp.
103
102
  * @param {UserOperation} unsignedUserOp - The unsigned user operation to be broadcasted. This includes transaction data such as the destination address and data payload.
104
- * @returns {Promise<{ signature: Hex; opHash: Hash }>} - A promise that resolves to an object containing the signature used and the hash of the executed user operation.
103
+ * @returns {Promise<Hash>} - A promise that resolves hash of the executed user operation.
105
104
  * @throws {Error} - Throws an error if the EVM broadcast fails, including the error message for debugging.
106
105
  */
107
- broadcastEvm(chainId: number, outcome: FinalExecutionOutcome, unsignedUserOp: UserOperation): Promise<{
108
- signature: Hex;
109
- opHash: Hash;
110
- }>;
106
+ broadcastBundler(chainId: number, signatureHex: Hex, unsignedUserOp: UserOperation): Promise<Hash>;
111
107
  /**
112
108
  * Executes a user operation on the specified blockchain network.
113
109
  * Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
@@ -150,24 +150,20 @@ class NearSafe {
150
150
  * Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
151
151
  *
152
152
  * @param {number} chainId - The ID of the EVM network to which the transaction should be broadcasted.
153
- * @param {FinalExecutionOutcome} outcome - The result of the NEAR transaction execution, which contains the necessary data to construct an EVM signature.
153
+ * @param {Signature} signature - The valid signature of the unsignedUserOp.
154
154
  * @param {UserOperation} unsignedUserOp - The unsigned user operation to be broadcasted. This includes transaction data such as the destination address and data payload.
155
- * @returns {Promise<{ signature: Hex; opHash: Hash }>} - A promise that resolves to an object containing the signature used and the hash of the executed user operation.
155
+ * @returns {Promise<Hash>} - A promise that resolves hash of the executed user operation.
156
156
  * @throws {Error} - Throws an error if the EVM broadcast fails, including the error message for debugging.
157
157
  */
158
- async broadcastEvm(chainId, outcome, unsignedUserOp) {
159
- const signature = (0, util_1.packSignature)((0, viem_1.serializeSignature)((0, near_ca_1.signatureFromOutcome)(outcome)));
158
+ async broadcastBundler(chainId, signatureHex, unsignedUserOp) {
160
159
  try {
161
- return {
162
- signature,
163
- opHash: await this.executeTransaction(chainId, {
164
- ...unsignedUserOp,
165
- signature,
166
- }),
167
- };
160
+ return this.executeTransaction(chainId, {
161
+ ...unsignedUserOp,
162
+ signature: (0, util_1.packSignature)(signatureHex),
163
+ });
168
164
  }
169
165
  catch (error) {
170
- throw new Error(`Failed EVM broadcast: ${error instanceof Error ? error.message : String(error)}`);
166
+ throw new Error(`Failed Bundler broadcast: ${error instanceof Error ? error.message : String(error)}`);
171
167
  }
172
168
  }
173
169
  /**
@@ -5,3 +5,13 @@ export declare function decodeTransactionSerializable(chainId: number, tx: Trans
5
5
  export declare function decodeRlpHex(chainId: number, tx: Hex): DecodedTxData;
6
6
  export declare function decodeTypedData(chainId: number, data: EIP712TypedData): DecodedTxData;
7
7
  export declare function decodeUserOperation(chainId: number, userOp: UserOperation): DecodedTxData;
8
+ export declare enum OperationType {
9
+ Call = 0,
10
+ DelegateCall = 1
11
+ }
12
+ export interface MetaTransaction {
13
+ readonly to: string;
14
+ readonly value: string;
15
+ readonly data: string;
16
+ readonly operation?: OperationType;
17
+ }
@@ -1,7 +1,6 @@
1
- import { decodeMulti } from "ethers-multisend";
2
1
  import { decodeFunctionData, formatEther, parseTransaction, serializeTransaction, } from "viem";
3
2
  import { SAFE_DEPLOYMENTS } from "../_gen/deployments";
4
- import { isMultisendTx } from "../lib/multisend";
3
+ import { decodeMulti, isMultisendTx } from "../lib/multisend";
5
4
  export function decodeTransactionSerializable(chainId, tx) {
6
5
  const { gas, maxFeePerGas, maxPriorityFeePerGas, to } = tx;
7
6
  if (chainId !== tx.chainId) {
@@ -1,4 +1,6 @@
1
+ import { Hex } from "viem";
1
2
  import { MetaTransaction } from "../types";
2
3
  export declare const MULTI_SEND_ABI: string[];
3
4
  export declare function encodeMulti(transactions: readonly MetaTransaction[], multiSendContractAddress?: string): MetaTransaction;
4
5
  export declare function isMultisendTx(args: readonly unknown[]): boolean;
6
+ export declare function decodeMulti(data: Hex): MetaTransaction[];
@@ -1,4 +1,4 @@
1
- import { encodeFunctionData, encodePacked, parseAbi, size, } from "viem";
1
+ import { decodeFunctionData, encodeFunctionData, encodePacked, getAddress, parseAbi, size, toHex, } from "viem";
2
2
  import { OperationType } from "../types";
3
3
  export const MULTI_SEND_ABI = ["function multiSend(bytes memory transactions)"];
4
4
  const MULTISEND_141 = "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526";
@@ -39,3 +39,37 @@ export function isMultisendTx(args) {
39
39
  return (to === MULTISEND_141.toLowerCase() ||
40
40
  to === MULTISEND_CALLONLY_141.toLowerCase());
41
41
  }
42
+ function unpack(packed, startIndex) {
43
+ // read operation from first 8 bits (= 2 hex digits)
44
+ const operation = parseInt(packed.substring(startIndex, startIndex + 2), 16);
45
+ // the next 40 characters are the to address
46
+ const to = getAddress(`0x${packed.substring(startIndex + 2, startIndex + 42)}`);
47
+ // then comes the uint256 value (= 64 hex digits)
48
+ const value = toHex(BigInt(`0x${packed.substring(startIndex + 42, startIndex + 106)}`));
49
+ // and the uint256 data length (= 64 hex digits)
50
+ const hexDataLength = parseInt(packed.substring(startIndex + 106, startIndex + 170), 16);
51
+ const endIndex = startIndex + 170 + hexDataLength * 2; // * 2 because each hex item is represented with 2 digits
52
+ const data = `0x${packed.substring(startIndex + 170, endIndex)}`;
53
+ return {
54
+ operation,
55
+ to,
56
+ value,
57
+ data,
58
+ endIndex,
59
+ };
60
+ }
61
+ export function decodeMulti(data) {
62
+ const tx = decodeFunctionData({
63
+ abi: parseAbi(MULTI_SEND_ABI),
64
+ data,
65
+ });
66
+ const [transactionsEncoded] = tx.args;
67
+ const result = [];
68
+ let startIndex = 2; // skip over 0x
69
+ while (startIndex < transactionsEncoded.length) {
70
+ const { endIndex, ...tx } = unpack(transactionsEncoded, startIndex);
71
+ result.push(tx);
72
+ startIndex = endIndex;
73
+ }
74
+ return result;
75
+ }
@@ -1,5 +1,4 @@
1
1
  import { NearConfig } from "near-api-js/lib/near";
2
- import { FinalExecutionOutcome } from "near-api-js/lib/providers";
3
2
  import { NearEthAdapter, SignRequestData, EncodedSignRequest } from "near-ca";
4
3
  import { Address, Hash, Hex } from "viem";
5
4
  import { SafeContractSuite } from "./lib/safe";
@@ -99,15 +98,12 @@ export declare class NearSafe {
99
98
  * Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
100
99
  *
101
100
  * @param {number} chainId - The ID of the EVM network to which the transaction should be broadcasted.
102
- * @param {FinalExecutionOutcome} outcome - The result of the NEAR transaction execution, which contains the necessary data to construct an EVM signature.
101
+ * @param {Signature} signature - The valid signature of the unsignedUserOp.
103
102
  * @param {UserOperation} unsignedUserOp - The unsigned user operation to be broadcasted. This includes transaction data such as the destination address and data payload.
104
- * @returns {Promise<{ signature: Hex; opHash: Hash }>} - A promise that resolves to an object containing the signature used and the hash of the executed user operation.
103
+ * @returns {Promise<Hash>} - A promise that resolves hash of the executed user operation.
105
104
  * @throws {Error} - Throws an error if the EVM broadcast fails, including the error message for debugging.
106
105
  */
107
- broadcastEvm(chainId: number, outcome: FinalExecutionOutcome, unsignedUserOp: UserOperation): Promise<{
108
- signature: Hex;
109
- opHash: Hash;
110
- }>;
106
+ broadcastBundler(chainId: number, signatureHex: Hex, unsignedUserOp: UserOperation): Promise<Hash>;
111
107
  /**
112
108
  * Executes a user operation on the specified blockchain network.
113
109
  * Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
@@ -1,5 +1,5 @@
1
- import { setupAdapter, signatureFromOutcome, toPayload, requestRouter as mpcRequestRouter, } from "near-ca";
2
- import { serializeSignature, zeroAddress } from "viem";
1
+ import { setupAdapter, toPayload, requestRouter as mpcRequestRouter, } from "near-ca";
2
+ import { zeroAddress } from "viem";
3
3
  import { DEFAULT_SAFE_SALT_NONCE } from "./constants";
4
4
  import { Erc4337Bundler } from "./lib/bundler";
5
5
  import { encodeMulti } from "./lib/multisend";
@@ -153,24 +153,20 @@ export class NearSafe {
153
153
  * Warning: Uses a private ethRPC with sensitive Pimlico API key (should be run server side).
154
154
  *
155
155
  * @param {number} chainId - The ID of the EVM network to which the transaction should be broadcasted.
156
- * @param {FinalExecutionOutcome} outcome - The result of the NEAR transaction execution, which contains the necessary data to construct an EVM signature.
156
+ * @param {Signature} signature - The valid signature of the unsignedUserOp.
157
157
  * @param {UserOperation} unsignedUserOp - The unsigned user operation to be broadcasted. This includes transaction data such as the destination address and data payload.
158
- * @returns {Promise<{ signature: Hex; opHash: Hash }>} - A promise that resolves to an object containing the signature used and the hash of the executed user operation.
158
+ * @returns {Promise<Hash>} - A promise that resolves hash of the executed user operation.
159
159
  * @throws {Error} - Throws an error if the EVM broadcast fails, including the error message for debugging.
160
160
  */
161
- async broadcastEvm(chainId, outcome, unsignedUserOp) {
162
- const signature = packSignature(serializeSignature(signatureFromOutcome(outcome)));
161
+ async broadcastBundler(chainId, signatureHex, unsignedUserOp) {
163
162
  try {
164
- return {
165
- signature,
166
- opHash: await this.executeTransaction(chainId, {
167
- ...unsignedUserOp,
168
- signature,
169
- }),
170
- };
163
+ return this.executeTransaction(chainId, {
164
+ ...unsignedUserOp,
165
+ signature: packSignature(signatureHex),
166
+ });
171
167
  }
172
168
  catch (error) {
173
- throw new Error(`Failed EVM broadcast: ${error instanceof Error ? error.message : String(error)}`);
169
+ throw new Error(`Failed Bundler broadcast: ${error instanceof Error ? error.message : String(error)}`);
174
170
  }
175
171
  }
176
172
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "near-safe",
3
- "version": "0.8.4",
3
+ "version": "0.8.5",
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,7 +42,6 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@safe-global/safe-gateway-typescript-sdk": "^3.22.2",
45
- "ethers-multisend": "^3.1.0",
46
45
  "near-api-js": "^5.0.0",
47
46
  "near-ca": "^0.6.0",
48
47
  "semver": "^7.6.3",
@@ -61,6 +60,7 @@
61
60
  "eslint": "^9.6.0",
62
61
  "eslint-plugin-import": "^2.30.0",
63
62
  "ethers": "^6.13.1",
63
+ "ethers-multisend": "^3.1.0",
64
64
  "jest": "^29.7.0",
65
65
  "prettier": "^3.3.2",
66
66
  "ts-jest": "^29.1.5",