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.
@@ -1,19 +1,20 @@
1
- import { ethers } from "ethers";
2
1
  import { getProxyFactoryDeployment, getSafeL2SingletonDeployment, } from "@safe-global/safe-deployments";
3
2
  import { getSafe4337ModuleDeployment, getSafeModuleSetupDeployment, } from "@safe-global/safe-modules-deployments";
4
- import { PLACEHOLDER_SIG, packGas, packPaymasterData } from "../util";
3
+ import { encodeFunctionData, encodePacked, getCreate2Address, keccak256, parseAbi, toHex, zeroAddress, } from "viem";
4
+ import { PLACEHOLDER_SIG, getClient, packGas, packPaymasterData, } from "../util";
5
5
  /**
6
6
  * All contracts used in account creation & execution
7
7
  */
8
8
  export class ContractSuite {
9
- provider;
9
+ // Used only for stateless contract reads.
10
+ dummyClient;
10
11
  singleton;
11
12
  proxyFactory;
12
13
  m4337;
13
14
  moduleSetup;
14
15
  entryPoint;
15
- constructor(provider, singleton, proxyFactory, m4337, moduleSetup, entryPoint) {
16
- this.provider = provider;
16
+ constructor(client, singleton, proxyFactory, m4337, moduleSetup, entryPoint) {
17
+ this.dummyClient = client;
17
18
  this.singleton = singleton;
18
19
  this.proxyFactory = proxyFactory;
19
20
  this.m4337 = m4337;
@@ -22,108 +23,154 @@ export class ContractSuite {
22
23
  }
23
24
  static async init() {
24
25
  // TODO - this is a cheeky hack.
25
- const provider = new ethers.JsonRpcProvider("https://rpc2.sepolia.org");
26
- const safeDeployment = (fn) => getDeployment(fn, { provider, version: "1.4.1" });
26
+ const client = getClient(11155111);
27
+ const safeDeployment = (fn) => getDeployment(fn, { version: "1.4.1" });
27
28
  const m4337Deployment = async (fn) => {
28
- return getDeployment(fn, { provider, version: "0.3.0" });
29
+ return getDeployment(fn, { version: "0.3.0" });
29
30
  };
30
- // Need this first to get entryPoint address
31
- const m4337 = await m4337Deployment(getSafe4337ModuleDeployment);
32
- const [singleton, proxyFactory, moduleSetup, supportedEntryPoint] = await Promise.all([
31
+ const [singleton, proxyFactory, moduleSetup, m4337] = await Promise.all([
33
32
  safeDeployment(getSafeL2SingletonDeployment),
34
33
  safeDeployment(getProxyFactoryDeployment),
35
34
  m4337Deployment(getSafeModuleSetupDeployment),
36
- m4337.SUPPORTED_ENTRYPOINT(),
35
+ m4337Deployment(getSafe4337ModuleDeployment),
37
36
  ]);
38
- const entryPoint = new ethers.Contract(supportedEntryPoint, ["function getNonce(address, uint192 key) view returns (uint256 nonce)"], provider);
39
- console.log("Initialized ERC4337 & Safe Module Contracts:", {
40
- singleton: await singleton.getAddress(),
41
- proxyFactory: await proxyFactory.getAddress(),
42
- m4337: await m4337.getAddress(),
43
- moduleSetup: await moduleSetup.getAddress(),
44
- entryPoint: await entryPoint.getAddress(),
37
+ // console.log("Initialized ERC4337 & Safe Module Contracts:", {
38
+ // singleton: await singleton.getAddress(),
39
+ // proxyFactory: await proxyFactory.getAddress(),
40
+ // m4337: await m4337.getAddress(),
41
+ // moduleSetup: await moduleSetup.getAddress(),
42
+ // entryPoint: await entryPoint.getAddress(),
43
+ // });
44
+ return new ContractSuite(client, singleton, proxyFactory, m4337, moduleSetup,
45
+ // EntryPoint:
46
+ {
47
+ address: (await client.readContract({
48
+ address: m4337.address,
49
+ abi: m4337.abi,
50
+ functionName: "SUPPORTED_ENTRYPOINT",
51
+ })),
52
+ abi: parseAbi([
53
+ "function getNonce(address, uint192 key) view returns (uint256 nonce)",
54
+ ]),
45
55
  });
46
- return new ContractSuite(provider, singleton, proxyFactory, m4337, moduleSetup, entryPoint);
47
56
  }
48
57
  async addressForSetup(setup, saltNonce) {
49
58
  // bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
50
59
  // cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L58
51
- const salt = ethers.keccak256(ethers.solidityPacked(["bytes32", "uint256"], [ethers.keccak256(setup), saltNonce || 0]));
60
+ const salt = keccak256(encodePacked(["bytes32", "uint256"], [keccak256(setup), BigInt(saltNonce || "0")]));
52
61
  // abi.encodePacked(type(SafeProxy).creationCode, uint256(uint160(_singleton)));
53
62
  // cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L29
54
- const initCode = ethers.solidityPacked(["bytes", "uint256"], [
55
- await this.proxyFactory.proxyCreationCode(),
56
- await this.singleton.getAddress(),
63
+ const initCode = encodePacked(["bytes", "uint256"], [
64
+ (await this.dummyClient.readContract({
65
+ address: this.proxyFactory.address,
66
+ abi: this.proxyFactory.abi,
67
+ functionName: "proxyCreationCode",
68
+ })),
69
+ BigInt(this.singleton.address),
57
70
  ]);
58
- return ethers.getCreate2Address(await this.proxyFactory.getAddress(), salt, ethers.keccak256(initCode));
71
+ return getCreate2Address({
72
+ from: this.proxyFactory.address,
73
+ salt,
74
+ bytecodeHash: keccak256(initCode),
75
+ });
59
76
  }
60
- async getSetup(owners) {
61
- const setup = await this.singleton.interface.encodeFunctionData("setup", [
62
- owners,
63
- 1, // We use sign threshold of 1.
64
- this.moduleSetup.target,
65
- this.moduleSetup.interface.encodeFunctionData("enableModules", [
66
- [this.m4337.target],
67
- ]),
68
- this.m4337.target,
69
- ethers.ZeroAddress,
70
- 0,
71
- ethers.ZeroAddress,
72
- ]);
73
- return setup;
77
+ getSetup(owners) {
78
+ return encodeFunctionData({
79
+ abi: this.singleton.abi,
80
+ functionName: "setup",
81
+ args: [
82
+ owners,
83
+ 1, // We use sign threshold of 1.
84
+ this.moduleSetup.address,
85
+ encodeFunctionData({
86
+ abi: this.moduleSetup.abi,
87
+ functionName: "enableModules",
88
+ args: [[this.m4337.address]],
89
+ }),
90
+ this.m4337.address,
91
+ zeroAddress,
92
+ 0,
93
+ zeroAddress,
94
+ ],
95
+ });
96
+ }
97
+ addOwnerData(newOwner) {
98
+ return encodeFunctionData({
99
+ abi: this.singleton.abi,
100
+ functionName: "addOwnerWithThreshold",
101
+ args: [newOwner, 1],
102
+ });
74
103
  }
75
104
  async getOpHash(unsignedUserOp) {
76
105
  const { factory, factoryData, verificationGasLimit, callGasLimit, maxPriorityFeePerGas, maxFeePerGas, } = unsignedUserOp;
77
- return this.m4337.getOperationHash({
78
- ...unsignedUserOp,
79
- initCode: factory
80
- ? ethers.solidityPacked(["address", "bytes"], [factory, factoryData])
81
- : "0x",
82
- accountGasLimits: packGas(verificationGasLimit, callGasLimit),
83
- gasFees: packGas(maxPriorityFeePerGas, maxFeePerGas),
84
- paymasterAndData: packPaymasterData(unsignedUserOp),
85
- signature: PLACEHOLDER_SIG,
106
+ const opHash = await this.dummyClient.readContract({
107
+ address: this.m4337.address,
108
+ abi: this.m4337.abi,
109
+ functionName: "getOperationHash",
110
+ args: [
111
+ {
112
+ ...unsignedUserOp,
113
+ initCode: factory
114
+ ? encodePacked(["address", "bytes"], [factory, factoryData])
115
+ : "0x",
116
+ accountGasLimits: packGas(verificationGasLimit, callGasLimit),
117
+ gasFees: packGas(maxPriorityFeePerGas, maxFeePerGas),
118
+ paymasterAndData: packPaymasterData(unsignedUserOp),
119
+ signature: PLACEHOLDER_SIG,
120
+ },
121
+ ],
86
122
  });
123
+ return opHash;
87
124
  }
88
125
  factoryDataForSetup(safeNotDeployed, setup, safeSaltNonce) {
89
126
  return safeNotDeployed
90
127
  ? {
91
- factory: this.proxyFactory.target,
92
- factoryData: this.proxyFactory.interface.encodeFunctionData("createProxyWithNonce", [this.singleton.target, setup, safeSaltNonce]),
128
+ factory: this.proxyFactory.address,
129
+ factoryData: encodeFunctionData({
130
+ abi: this.proxyFactory.abi,
131
+ functionName: "createProxyWithNonce",
132
+ args: [this.singleton.address, setup, safeSaltNonce],
133
+ }),
93
134
  }
94
135
  : {};
95
136
  }
96
- async buildUserOp(txData, safeAddress, feeData, setup, safeNotDeployed, safeSaltNonce) {
97
- const rawUserOp = {
137
+ async buildUserOp(nonce, txData, safeAddress, feeData, setup, safeNotDeployed, safeSaltNonce) {
138
+ return {
98
139
  sender: safeAddress,
99
- nonce: ethers.toBeHex(await this.entryPoint.getNonce(safeAddress, 0)),
140
+ nonce: toHex(nonce),
100
141
  ...this.factoryDataForSetup(safeNotDeployed, setup, safeSaltNonce),
101
142
  // <https://github.com/safe-global/safe-modules/blob/9a18245f546bf2a8ed9bdc2b04aae44f949ec7a0/modules/4337/contracts/Safe4337Module.sol#L172>
102
- callData: this.m4337.interface.encodeFunctionData("executeUserOp", [
103
- txData.to,
104
- BigInt(txData.value),
105
- txData.data,
106
- txData.operation || 0,
107
- ]),
143
+ callData: encodeFunctionData({
144
+ abi: this.m4337.abi,
145
+ functionName: "executeUserOp",
146
+ args: [
147
+ txData.to,
148
+ BigInt(txData.value),
149
+ txData.data,
150
+ txData.operation || 0,
151
+ ],
152
+ }),
108
153
  ...feeData,
109
154
  };
110
- return rawUserOp;
155
+ }
156
+ async getNonce(address, chainId) {
157
+ const nonce = (await getClient(chainId).readContract({
158
+ abi: this.entryPoint.abi,
159
+ address: this.entryPoint.address,
160
+ functionName: "getNonce",
161
+ args: [address, 0],
162
+ }));
163
+ return nonce;
111
164
  }
112
165
  }
113
- async function getDeployment(fn, { provider, version }) {
114
- const { chainId } = await provider.getNetwork();
166
+ async function getDeployment(fn, { version }) {
115
167
  const deployment = fn({ version });
116
168
  if (!deployment) {
117
- throw new Error(`Deployment not found for ${fn.name} version ${version} on chainId ${chainId}`);
118
- }
119
- let address = deployment.networkAddresses[`${chainId}`];
120
- if (!address) {
121
- // console.warn(
122
- // `Deployment asset ${fn.name} not listed on chainId ${chainId}, using likely fallback. For more info visit https://github.com/safe-global/safe-modules-deployments`
123
- // );
124
- // TODO: This is a cheeky hack. Real solution proposed in
125
- // https://github.com/Mintbase/near-safe/issues/42
126
- address = deployment.networkAddresses["11155111"];
169
+ throw new Error(`Deployment not found for ${fn.name} version ${version}`);
127
170
  }
128
- return new ethers.Contract(address, deployment.abi, provider);
171
+ // TODO: maybe call parseAbi on deployment.abi here.
172
+ return {
173
+ address: deployment.networkAddresses["11155111"],
174
+ abi: deployment.abi,
175
+ };
129
176
  }
@@ -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
  }
@@ -1,59 +1,65 @@
1
- import { Network } from "near-ca";
1
+ import { setupAdapter, signatureFromOutcome, } from "near-ca";
2
+ import { serializeSignature } from "viem";
2
3
  import { Erc4337Bundler } from "./lib/bundler";
3
- import { packSignature } from "./util";
4
- import { encodeMulti } from "ethers-multisend";
4
+ import { encodeMulti } from "./lib/multisend";
5
5
  import { ContractSuite } from "./lib/safe";
6
+ import { getClient, isContract, packSignature } from "./util";
6
7
  export class TransactionManager {
7
8
  nearAdapter;
8
9
  address;
9
- entryPointAddress;
10
10
  safePack;
11
11
  setup;
12
12
  pimlicoKey;
13
13
  safeSaltNonce;
14
14
  deployedChains;
15
- constructor(nearAdapter, safePack, pimlicoKey, setup, safeAddress, entryPointAddress, safeSaltNonce) {
15
+ constructor(nearAdapter, safePack, pimlicoKey, setup, safeAddress, safeSaltNonce) {
16
16
  this.nearAdapter = nearAdapter;
17
17
  this.safePack = safePack;
18
18
  this.pimlicoKey = pimlicoKey;
19
- this.entryPointAddress = entryPointAddress;
20
19
  this.setup = setup;
21
20
  this.address = safeAddress;
22
21
  this.safeSaltNonce = safeSaltNonce;
23
22
  this.deployedChains = new Set();
24
23
  }
25
24
  static async create(config) {
26
- const { nearAdapter, pimlicoKey } = config;
27
- const safePack = await ContractSuite.init();
25
+ const { pimlicoKey } = config;
26
+ const [nearAdapter, safePack] = await Promise.all([
27
+ setupAdapter({ ...config }),
28
+ ContractSuite.init(),
29
+ ]);
28
30
  console.log(`Near Adapter: ${nearAdapter.nearAccountId()} <> ${nearAdapter.address}`);
29
- const setup = await safePack.getSetup([nearAdapter.address]);
31
+ const setup = safePack.getSetup([nearAdapter.address]);
30
32
  const safeAddress = await safePack.addressForSetup(setup, config.safeSaltNonce);
31
- const entryPointAddress = (await safePack.entryPoint.getAddress());
32
33
  console.log(`Safe Address: ${safeAddress}`);
33
- return new TransactionManager(nearAdapter, safePack, pimlicoKey, setup, safeAddress, entryPointAddress, config.safeSaltNonce || "0");
34
+ return new TransactionManager(nearAdapter, safePack, pimlicoKey, setup, safeAddress, config.safeSaltNonce || "0");
34
35
  }
35
36
  get mpcAddress() {
36
37
  return this.nearAdapter.address;
37
38
  }
39
+ get mpcContractId() {
40
+ return this.nearAdapter.mpcContract.contract.contractId;
41
+ }
38
42
  async getBalance(chainId) {
39
- const provider = Network.fromChainId(chainId).client;
40
- return await provider.getBalance({ address: this.address });
43
+ return await getClient(chainId).getBalance({ address: this.address });
41
44
  }
42
45
  bundlerForChainId(chainId) {
43
- return new Erc4337Bundler(this.entryPointAddress, this.pimlicoKey, chainId);
46
+ return new Erc4337Bundler(this.safePack.entryPoint.address, this.pimlicoKey, chainId);
44
47
  }
45
48
  async buildTransaction(args) {
46
49
  const { transactions, usePaymaster, chainId } = args;
47
- const bundler = this.bundlerForChainId(chainId);
48
- const gasFees = (await bundler.getGasPrice()).fast;
49
- // Build Singular MetaTransaction for Multisend from transaction list.
50
50
  if (transactions.length === 0) {
51
51
  throw new Error("Empty transaction set!");
52
52
  }
53
+ const bundler = this.bundlerForChainId(chainId);
54
+ const [gasFees, nonce, safeDeployed] = await Promise.all([
55
+ bundler.getGasPrice(),
56
+ this.safePack.getNonce(this.address, chainId),
57
+ this.safeDeployed(chainId),
58
+ ]);
59
+ // Build Singular MetaTransaction for Multisend from transaction list.
53
60
  const tx = transactions.length > 1 ? encodeMulti(transactions) : transactions[0];
54
- const safeNotDeployed = !(await this.safeDeployed(chainId));
55
- const rawUserOp = await this.safePack.buildUserOp(tx, this.address, gasFees, this.setup, safeNotDeployed, this.safeSaltNonce);
56
- const paymasterData = await bundler.getPaymasterData(rawUserOp, usePaymaster, safeNotDeployed);
61
+ const rawUserOp = await this.safePack.buildUserOp(nonce, tx, this.address, gasFees.fast, this.setup, !safeDeployed, this.safeSaltNonce);
62
+ const paymasterData = await bundler.getPaymasterData(rawUserOp, usePaymaster, !safeDeployed);
57
63
  const unsignedUserOp = { ...rawUserOp, ...paymasterData };
58
64
  return unsignedUserOp;
59
65
  }
@@ -98,11 +104,11 @@ export class TransactionManager {
98
104
  return userOpReceipt;
99
105
  }
100
106
  async safeDeployed(chainId) {
107
+ // Early exit if already known.
101
108
  if (chainId in this.deployedChains) {
102
109
  return true;
103
110
  }
104
- const provider = Network.fromChainId(chainId).client;
105
- const deployed = (await provider.getCode({ address: this.address })) !== "0x";
111
+ const deployed = await isContract(this.address, chainId);
106
112
  if (deployed) {
107
113
  this.deployedChains.add(chainId);
108
114
  }
@@ -112,7 +118,7 @@ export class TransactionManager {
112
118
  return {
113
119
  to: this.address,
114
120
  value: "0",
115
- data: this.safePack.singleton.interface.encodeFunctionData("addOwnerWithThreshold", [address, 1]),
121
+ data: this.safePack.addOwnerData(address),
116
122
  };
117
123
  }
118
124
  async safeSufficientlyFunded(chainId, transactions, gasCost) {
@@ -123,4 +129,19 @@ export class TransactionManager {
123
129
  const safeBalance = await this.getBalance(chainId);
124
130
  return txValue + gasCost < safeBalance;
125
131
  }
132
+ async broadcastEvm(chainId, outcome, unsignedUserOp) {
133
+ const signature = packSignature(serializeSignature(signatureFromOutcome(outcome)));
134
+ try {
135
+ return {
136
+ signature,
137
+ receipt: await this.executeTransaction(chainId, {
138
+ ...unsignedUserOp,
139
+ signature,
140
+ }),
141
+ };
142
+ }
143
+ catch (error) {
144
+ throw new Error(`Failed EVM broadcast: ${error instanceof Error ? error.message : String(error)}`);
145
+ }
146
+ }
126
147
  }
@@ -79,4 +79,14 @@ export interface GasPrice {
79
79
  maxFeePerGas: Hex;
80
80
  maxPriorityFeePerGas: Hex;
81
81
  }
82
+ export declare enum OperationType {
83
+ Call = 0,
84
+ DelegateCall = 1
85
+ }
86
+ export interface MetaTransaction {
87
+ readonly to: string;
88
+ readonly value: string;
89
+ readonly data: string;
90
+ readonly operation?: OperationType;
91
+ }
82
92
  export {};
package/dist/esm/types.js CHANGED
@@ -1 +1,5 @@
1
- export {};
1
+ export var OperationType;
2
+ (function (OperationType) {
3
+ OperationType[OperationType["Call"] = 0] = "Call";
4
+ OperationType[OperationType["DelegateCall"] = 1] = "DelegateCall";
5
+ })(OperationType || (OperationType = {}));
@@ -1,10 +1,11 @@
1
- import { PaymasterData } from "./types.js";
2
- import { MetaTransaction } from "ethers-multisend";
3
- import { Hex } from "viem";
1
+ import { Address, Hex, PublicClient } from "viem";
2
+ import { PaymasterData, MetaTransaction } from "./types";
4
3
  export declare const PLACEHOLDER_SIG: `0x${string}`;
5
4
  type IntLike = Hex | bigint | string | number;
6
5
  export declare const packGas: (hi: IntLike, lo: IntLike) => string;
7
6
  export declare function packSignature(signature: `0x${string}`, validFrom?: number, validTo?: number): Hex;
8
7
  export declare function packPaymasterData(data: PaymasterData): Hex;
9
8
  export declare function containsValue(transactions: MetaTransaction[]): boolean;
9
+ export declare function isContract(address: Address, chainId: number): Promise<boolean>;
10
+ export declare function getClient(chainId: number): PublicClient;
10
11
  export {};
package/dist/esm/util.js CHANGED
@@ -1,4 +1,5 @@
1
- import { concatHex, encodePacked, toHex } from "viem";
1
+ import { Network } from "near-ca";
2
+ import { concatHex, encodePacked, toHex, } from "viem";
2
3
  export const PLACEHOLDER_SIG = encodePacked(["uint48", "uint48"], [0, 0]);
3
4
  export const packGas = (hi, lo) => encodePacked(["uint128", "uint128"], [BigInt(hi), BigInt(lo)]);
4
5
  export function packSignature(signature, validFrom = 0, validTo = 0) {
@@ -17,3 +18,9 @@ export function packPaymasterData(data) {
17
18
  export function containsValue(transactions) {
18
19
  return transactions.some((tx) => tx.value !== "0");
19
20
  }
21
+ export async function isContract(address, chainId) {
22
+ return (await getClient(chainId).getCode({ address })) !== undefined;
23
+ }
24
+ export function getClient(chainId) {
25
+ return Network.fromChainId(chainId).client;
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "near-safe",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "description": "An SDK for controlling Ethereum Smart Accounts via ERC4337 from a Near Account.",
6
6
  "author": "bh2smith",
@@ -36,18 +36,15 @@
36
36
  "example": "tsx examples/send-tx.ts",
37
37
  "lint": "eslint . --ignore-pattern dist/",
38
38
  "test": "jest",
39
- "fmt": "prettier --write '{src,examples,tests}/**/*.{js,jsx,ts,tsx}'",
39
+ "fmt": "prettier --write '{src,examples,tests}/**/*.{js,jsx,ts,tsx}' && yarn lint --fix",
40
40
  "all": "yarn fmt && yarn lint && yarn build"
41
41
  },
42
42
  "dependencies": {
43
43
  "@safe-global/safe-deployments": "^1.37.0",
44
44
  "@safe-global/safe-modules-deployments": "^2.2.0",
45
- "ethers": "^6.13.1",
46
- "ethers-multisend": "^3.1.0",
47
45
  "near-api-js": "^5.0.0",
48
46
  "near-ca": "^0.5.2",
49
- "viem": "^2.16.5",
50
- "yargs": "^17.7.2"
47
+ "viem": "^2.16.5"
51
48
  },
52
49
  "devDependencies": {
53
50
  "@types/jest": "^29.5.12",
@@ -57,11 +54,17 @@
57
54
  "@typescript-eslint/parser": "^8.1.0",
58
55
  "dotenv": "^16.4.5",
59
56
  "eslint": "^9.6.0",
57
+ "eslint-plugin-import": "^2.30.0",
58
+ "ethers": "^6.13.1",
60
59
  "jest": "^29.7.0",
61
60
  "prettier": "^3.3.2",
62
61
  "ts-jest": "^29.1.5",
63
62
  "tsx": "^4.16.0",
64
63
  "typescript": "^5.5.2",
65
64
  "yargs": "^17.7.2"
65
+ },
66
+ "resolutions": {
67
+ "glob": "^9.0.0",
68
+ "base-x": "^3.0.0"
66
69
  }
67
70
  }