near-safe 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +1 -1
- package/dist/cjs/lib/safe.js +17 -2
- package/dist/cjs/tx-manager.d.ts +10 -4
- package/dist/cjs/tx-manager.js +26 -12
- package/dist/esm/lib/safe.js +17 -2
- package/dist/esm/tx-manager.d.ts +10 -4
- package/dist/esm/tx-manager.js +28 -13
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/cjs/lib/safe.js
CHANGED
@@ -19,7 +19,15 @@ class ContractSuite {
|
|
19
19
|
}
|
20
20
|
static async init(provider) {
|
21
21
|
const safeDeployment = (fn) => getDeployment(fn, { provider, version: "1.4.1" });
|
22
|
-
const m4337Deployment = (fn) =>
|
22
|
+
const m4337Deployment = async (fn) => {
|
23
|
+
try {
|
24
|
+
return await getDeployment(fn, { provider, version: "0.3.0" });
|
25
|
+
}
|
26
|
+
catch (error) {
|
27
|
+
console.warn(error.message, "using v0.2.0");
|
28
|
+
return getDeployment(fn, { provider, version: "0.2.0" });
|
29
|
+
}
|
30
|
+
};
|
23
31
|
// Need this first to get entryPoint address
|
24
32
|
const m4337 = await m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment);
|
25
33
|
const [singleton, proxyFactory, moduleSetup, supportedEntryPoint] = await Promise.all([
|
@@ -29,6 +37,13 @@ class ContractSuite {
|
|
29
37
|
m4337.SUPPORTED_ENTRYPOINT(),
|
30
38
|
]);
|
31
39
|
const entryPoint = new ethers_1.ethers.Contract(supportedEntryPoint, ["function getNonce(address, uint192 key) view returns (uint256 nonce)"], provider);
|
40
|
+
console.log("Initialized ERC4337 & Safe Module Contracts:", {
|
41
|
+
singleton: await singleton.getAddress(),
|
42
|
+
proxyFactory: await proxyFactory.getAddress(),
|
43
|
+
m4337: await m4337.getAddress(),
|
44
|
+
moduleSetup: await moduleSetup.getAddress(),
|
45
|
+
entryPoint: await entryPoint.getAddress(),
|
46
|
+
});
|
32
47
|
return new ContractSuite(provider, singleton, proxyFactory, m4337, moduleSetup, entryPoint);
|
33
48
|
}
|
34
49
|
async addressForSetup(setup, saltNonce) {
|
@@ -102,7 +117,7 @@ async function getDeployment(fn, { provider, version }) {
|
|
102
117
|
const { chainId } = await provider.getNetwork();
|
103
118
|
const deployment = fn({ version });
|
104
119
|
if (!deployment || !deployment.networkAddresses[`${chainId}`]) {
|
105
|
-
throw new Error(`Deployment not found for version ${version}
|
120
|
+
throw new Error(`Deployment not found for ${fn.name} version ${version} on chainId ${chainId}`);
|
106
121
|
}
|
107
122
|
return new ethers_1.ethers.Contract(deployment.networkAddresses[`${chainId}`], deployment.abi, provider);
|
108
123
|
}
|
package/dist/cjs/tx-manager.d.ts
CHANGED
@@ -10,18 +10,24 @@ export declare class TransactionManager {
|
|
10
10
|
private safePack;
|
11
11
|
private bundler;
|
12
12
|
private setup;
|
13
|
-
readonly
|
13
|
+
readonly address: string;
|
14
|
+
readonly chainId: number;
|
14
15
|
private safeSaltNonce;
|
15
16
|
private _safeNotDeployed;
|
16
|
-
constructor(provider: ethers.JsonRpcProvider, nearAdapter: NearEthAdapter, safePack: ContractSuite, bundler: Erc4337Bundler, setup: string, safeAddress: string, safeSaltNonce: string, safeNotDeployed: boolean);
|
17
|
+
constructor(provider: ethers.JsonRpcProvider, nearAdapter: NearEthAdapter, safePack: ContractSuite, bundler: Erc4337Bundler, setup: string, chainId: number, safeAddress: string, safeSaltNonce: string, safeNotDeployed: boolean);
|
17
18
|
static create(config: {
|
18
19
|
ethRpc: string;
|
19
|
-
|
20
|
+
pimlicoKey: string;
|
20
21
|
nearAdapter: NearEthAdapter;
|
21
22
|
safeSaltNonce?: string;
|
22
23
|
}): Promise<TransactionManager>;
|
24
|
+
static fromChainId(args: {
|
25
|
+
chainId: number;
|
26
|
+
nearAdapter: NearEthAdapter;
|
27
|
+
pimlicoKey: string;
|
28
|
+
}): Promise<TransactionManager>;
|
23
29
|
get safeNotDeployed(): boolean;
|
24
|
-
get
|
30
|
+
get mpcAddress(): `0x${string}`;
|
25
31
|
getSafeBalance(): Promise<bigint>;
|
26
32
|
buildTransaction(args: {
|
27
33
|
transactions: MetaTransaction[];
|
package/dist/cjs/tx-manager.js
CHANGED
@@ -2,42 +2,53 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.TransactionManager = void 0;
|
4
4
|
const ethers_1 = require("ethers");
|
5
|
+
const near_ca_1 = require("near-ca");
|
5
6
|
const bundler_1 = require("./lib/bundler");
|
6
7
|
const util_1 = require("./util");
|
7
8
|
const near_1 = require("./lib/near");
|
8
9
|
const ethers_multisend_1 = require("ethers-multisend");
|
9
10
|
const safe_1 = require("./lib/safe");
|
10
11
|
class TransactionManager {
|
11
|
-
constructor(provider, nearAdapter, safePack, bundler, setup, safeAddress, safeSaltNonce, safeNotDeployed) {
|
12
|
+
constructor(provider, nearAdapter, safePack, bundler, setup, chainId, safeAddress, safeSaltNonce, safeNotDeployed) {
|
12
13
|
this.provider = provider;
|
13
14
|
this.nearAdapter = nearAdapter;
|
14
15
|
this.safePack = safePack;
|
15
16
|
this.bundler = bundler;
|
16
17
|
this.setup = setup;
|
17
|
-
this.
|
18
|
+
this.chainId = chainId;
|
19
|
+
this.address = safeAddress;
|
18
20
|
this.safeSaltNonce = safeSaltNonce;
|
19
21
|
this._safeNotDeployed = safeNotDeployed;
|
20
22
|
}
|
21
23
|
static async create(config) {
|
22
|
-
const
|
24
|
+
const { nearAdapter, pimlicoKey } = config;
|
23
25
|
const provider = new ethers_1.ethers.JsonRpcProvider(config.ethRpc);
|
26
|
+
const chainId = (await provider.getNetwork()).chainId;
|
24
27
|
const safePack = await safe_1.ContractSuite.init(provider);
|
25
|
-
console.log(`Near Adapter: ${
|
26
|
-
const bundler = new bundler_1.Erc4337Bundler(
|
27
|
-
const setup = await safePack.getSetup([
|
28
|
+
console.log(`Near Adapter: ${nearAdapter.nearAccountId()} <> ${nearAdapter.address}`);
|
29
|
+
const bundler = new bundler_1.Erc4337Bundler(`https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoKey}`, await safePack.entryPoint.getAddress());
|
30
|
+
const setup = await safePack.getSetup([nearAdapter.address]);
|
28
31
|
const safeAddress = await safePack.addressForSetup(setup, config.safeSaltNonce);
|
29
32
|
const safeNotDeployed = (await provider.getCode(safeAddress)) === "0x";
|
30
33
|
console.log(`Safe Address: ${safeAddress} - deployed? ${!safeNotDeployed}`);
|
31
|
-
return new TransactionManager(provider,
|
34
|
+
return new TransactionManager(provider, nearAdapter, safePack, bundler, setup, parseInt(chainId.toString()), safeAddress, config.safeSaltNonce || "0", safeNotDeployed);
|
35
|
+
}
|
36
|
+
static async fromChainId(args) {
|
37
|
+
const { pimlicoKey, nearAdapter } = args;
|
38
|
+
return TransactionManager.create({
|
39
|
+
ethRpc: near_ca_1.Network.fromChainId(args.chainId).rpcUrl,
|
40
|
+
pimlicoKey,
|
41
|
+
nearAdapter,
|
42
|
+
});
|
32
43
|
}
|
33
44
|
get safeNotDeployed() {
|
34
45
|
return this._safeNotDeployed;
|
35
46
|
}
|
36
|
-
get
|
47
|
+
get mpcAddress() {
|
37
48
|
return this.nearAdapter.address;
|
38
49
|
}
|
39
50
|
async getSafeBalance() {
|
40
|
-
return await this.provider.getBalance(this.
|
51
|
+
return await this.provider.getBalance(this.address);
|
41
52
|
}
|
42
53
|
async buildTransaction(args) {
|
43
54
|
const { transactions, usePaymaster } = args;
|
@@ -48,7 +59,7 @@ class TransactionManager {
|
|
48
59
|
throw new Error("Empty transaction set!");
|
49
60
|
}
|
50
61
|
const tx = transactions.length > 1 ? (0, ethers_multisend_1.encodeMulti)(transactions) : transactions[0];
|
51
|
-
const rawUserOp = await this.safePack.buildUserOp(tx, this.
|
62
|
+
const rawUserOp = await this.safePack.buildUserOp(tx, this.address, gasFees, this.setup, this.safeNotDeployed, this.safeSaltNonce);
|
52
63
|
const paymasterData = await this.bundler.getPaymasterData(rawUserOp, usePaymaster, this.safeNotDeployed);
|
53
64
|
const unsignedUserOp = { ...rawUserOp, ...paymasterData };
|
54
65
|
return unsignedUserOp;
|
@@ -62,6 +73,9 @@ class TransactionManager {
|
|
62
73
|
}
|
63
74
|
async encodeSignRequest(tx) {
|
64
75
|
// TODO - This is sloppy and ignores ChainId!
|
76
|
+
if (tx.chainId !== this.chainId) {
|
77
|
+
throw new Error(`Transaciton request for invalid ChainId ${tx.chainId} != ${this.chainId}`);
|
78
|
+
}
|
65
79
|
const unsignedUserOp = await this.buildTransaction({
|
66
80
|
transactions: [
|
67
81
|
{
|
@@ -90,12 +104,12 @@ class TransactionManager {
|
|
90
104
|
console.log("userOp Receipt", userOpReceipt);
|
91
105
|
// Update safeNotDeployed after the first transaction
|
92
106
|
this._safeNotDeployed =
|
93
|
-
(await this.provider.getCode(this.
|
107
|
+
(await this.provider.getCode(this.address)) === "0x";
|
94
108
|
return userOpReceipt;
|
95
109
|
}
|
96
110
|
addOwnerTx(address) {
|
97
111
|
return {
|
98
|
-
to: this.
|
112
|
+
to: this.address,
|
99
113
|
value: "0",
|
100
114
|
data: this.safePack.singleton.interface.encodeFunctionData("addOwnerWithThreshold", [address, 1]),
|
101
115
|
};
|
package/dist/esm/lib/safe.js
CHANGED
@@ -22,7 +22,15 @@ export class ContractSuite {
|
|
22
22
|
}
|
23
23
|
static async init(provider) {
|
24
24
|
const safeDeployment = (fn) => getDeployment(fn, { provider, version: "1.4.1" });
|
25
|
-
const m4337Deployment = (fn) =>
|
25
|
+
const m4337Deployment = async (fn) => {
|
26
|
+
try {
|
27
|
+
return await getDeployment(fn, { provider, version: "0.3.0" });
|
28
|
+
}
|
29
|
+
catch (error) {
|
30
|
+
console.warn(error.message, "using v0.2.0");
|
31
|
+
return getDeployment(fn, { provider, version: "0.2.0" });
|
32
|
+
}
|
33
|
+
};
|
26
34
|
// Need this first to get entryPoint address
|
27
35
|
const m4337 = await m4337Deployment(getSafe4337ModuleDeployment);
|
28
36
|
const [singleton, proxyFactory, moduleSetup, supportedEntryPoint] = await Promise.all([
|
@@ -32,6 +40,13 @@ export class ContractSuite {
|
|
32
40
|
m4337.SUPPORTED_ENTRYPOINT(),
|
33
41
|
]);
|
34
42
|
const entryPoint = new ethers.Contract(supportedEntryPoint, ["function getNonce(address, uint192 key) view returns (uint256 nonce)"], provider);
|
43
|
+
console.log("Initialized ERC4337 & Safe Module Contracts:", {
|
44
|
+
singleton: await singleton.getAddress(),
|
45
|
+
proxyFactory: await proxyFactory.getAddress(),
|
46
|
+
m4337: await m4337.getAddress(),
|
47
|
+
moduleSetup: await moduleSetup.getAddress(),
|
48
|
+
entryPoint: await entryPoint.getAddress(),
|
49
|
+
});
|
35
50
|
return new ContractSuite(provider, singleton, proxyFactory, m4337, moduleSetup, entryPoint);
|
36
51
|
}
|
37
52
|
async addressForSetup(setup, saltNonce) {
|
@@ -104,7 +119,7 @@ async function getDeployment(fn, { provider, version }) {
|
|
104
119
|
const { chainId } = await provider.getNetwork();
|
105
120
|
const deployment = fn({ version });
|
106
121
|
if (!deployment || !deployment.networkAddresses[`${chainId}`]) {
|
107
|
-
throw new Error(`Deployment not found for version ${version}
|
122
|
+
throw new Error(`Deployment not found for ${fn.name} version ${version} on chainId ${chainId}`);
|
108
123
|
}
|
109
124
|
return new ethers.Contract(deployment.networkAddresses[`${chainId}`], deployment.abi, provider);
|
110
125
|
}
|
package/dist/esm/tx-manager.d.ts
CHANGED
@@ -10,18 +10,24 @@ export declare class TransactionManager {
|
|
10
10
|
private safePack;
|
11
11
|
private bundler;
|
12
12
|
private setup;
|
13
|
-
readonly
|
13
|
+
readonly address: string;
|
14
|
+
readonly chainId: number;
|
14
15
|
private safeSaltNonce;
|
15
16
|
private _safeNotDeployed;
|
16
|
-
constructor(provider: ethers.JsonRpcProvider, nearAdapter: NearEthAdapter, safePack: ContractSuite, bundler: Erc4337Bundler, setup: string, safeAddress: string, safeSaltNonce: string, safeNotDeployed: boolean);
|
17
|
+
constructor(provider: ethers.JsonRpcProvider, nearAdapter: NearEthAdapter, safePack: ContractSuite, bundler: Erc4337Bundler, setup: string, chainId: number, safeAddress: string, safeSaltNonce: string, safeNotDeployed: boolean);
|
17
18
|
static create(config: {
|
18
19
|
ethRpc: string;
|
19
|
-
|
20
|
+
pimlicoKey: string;
|
20
21
|
nearAdapter: NearEthAdapter;
|
21
22
|
safeSaltNonce?: string;
|
22
23
|
}): Promise<TransactionManager>;
|
24
|
+
static fromChainId(args: {
|
25
|
+
chainId: number;
|
26
|
+
nearAdapter: NearEthAdapter;
|
27
|
+
pimlicoKey: string;
|
28
|
+
}): Promise<TransactionManager>;
|
23
29
|
get safeNotDeployed(): boolean;
|
24
|
-
get
|
30
|
+
get mpcAddress(): `0x${string}`;
|
25
31
|
getSafeBalance(): Promise<bigint>;
|
26
32
|
buildTransaction(args: {
|
27
33
|
transactions: MetaTransaction[];
|
package/dist/esm/tx-manager.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { ethers } from "ethers";
|
2
|
+
import { Network } from "near-ca";
|
2
3
|
import { Erc4337Bundler } from "./lib/bundler";
|
3
4
|
import { packSignature } from "./util";
|
4
5
|
import { getNearSignature } from "./lib/near";
|
@@ -10,39 +11,50 @@ export class TransactionManager {
|
|
10
11
|
safePack;
|
11
12
|
bundler;
|
12
13
|
setup;
|
13
|
-
|
14
|
+
address;
|
15
|
+
chainId;
|
14
16
|
safeSaltNonce;
|
15
17
|
_safeNotDeployed;
|
16
|
-
constructor(provider, nearAdapter, safePack, bundler, setup, safeAddress, safeSaltNonce, safeNotDeployed) {
|
18
|
+
constructor(provider, nearAdapter, safePack, bundler, setup, chainId, safeAddress, safeSaltNonce, safeNotDeployed) {
|
17
19
|
this.provider = provider;
|
18
20
|
this.nearAdapter = nearAdapter;
|
19
21
|
this.safePack = safePack;
|
20
22
|
this.bundler = bundler;
|
21
23
|
this.setup = setup;
|
22
|
-
this.
|
24
|
+
this.chainId = chainId;
|
25
|
+
this.address = safeAddress;
|
23
26
|
this.safeSaltNonce = safeSaltNonce;
|
24
27
|
this._safeNotDeployed = safeNotDeployed;
|
25
28
|
}
|
26
29
|
static async create(config) {
|
27
|
-
const
|
30
|
+
const { nearAdapter, pimlicoKey } = config;
|
28
31
|
const provider = new ethers.JsonRpcProvider(config.ethRpc);
|
32
|
+
const chainId = (await provider.getNetwork()).chainId;
|
29
33
|
const safePack = await ContractSuite.init(provider);
|
30
|
-
console.log(`Near Adapter: ${
|
31
|
-
const bundler = new Erc4337Bundler(
|
32
|
-
const setup = await safePack.getSetup([
|
34
|
+
console.log(`Near Adapter: ${nearAdapter.nearAccountId()} <> ${nearAdapter.address}`);
|
35
|
+
const bundler = new Erc4337Bundler(`https://api.pimlico.io/v2/${chainId}/rpc?apikey=${pimlicoKey}`, await safePack.entryPoint.getAddress());
|
36
|
+
const setup = await safePack.getSetup([nearAdapter.address]);
|
33
37
|
const safeAddress = await safePack.addressForSetup(setup, config.safeSaltNonce);
|
34
38
|
const safeNotDeployed = (await provider.getCode(safeAddress)) === "0x";
|
35
39
|
console.log(`Safe Address: ${safeAddress} - deployed? ${!safeNotDeployed}`);
|
36
|
-
return new TransactionManager(provider,
|
40
|
+
return new TransactionManager(provider, nearAdapter, safePack, bundler, setup, parseInt(chainId.toString()), safeAddress, config.safeSaltNonce || "0", safeNotDeployed);
|
41
|
+
}
|
42
|
+
static async fromChainId(args) {
|
43
|
+
const { pimlicoKey, nearAdapter } = args;
|
44
|
+
return TransactionManager.create({
|
45
|
+
ethRpc: Network.fromChainId(args.chainId).rpcUrl,
|
46
|
+
pimlicoKey,
|
47
|
+
nearAdapter,
|
48
|
+
});
|
37
49
|
}
|
38
50
|
get safeNotDeployed() {
|
39
51
|
return this._safeNotDeployed;
|
40
52
|
}
|
41
|
-
get
|
53
|
+
get mpcAddress() {
|
42
54
|
return this.nearAdapter.address;
|
43
55
|
}
|
44
56
|
async getSafeBalance() {
|
45
|
-
return await this.provider.getBalance(this.
|
57
|
+
return await this.provider.getBalance(this.address);
|
46
58
|
}
|
47
59
|
async buildTransaction(args) {
|
48
60
|
const { transactions, usePaymaster } = args;
|
@@ -53,7 +65,7 @@ export class TransactionManager {
|
|
53
65
|
throw new Error("Empty transaction set!");
|
54
66
|
}
|
55
67
|
const tx = transactions.length > 1 ? encodeMulti(transactions) : transactions[0];
|
56
|
-
const rawUserOp = await this.safePack.buildUserOp(tx, this.
|
68
|
+
const rawUserOp = await this.safePack.buildUserOp(tx, this.address, gasFees, this.setup, this.safeNotDeployed, this.safeSaltNonce);
|
57
69
|
const paymasterData = await this.bundler.getPaymasterData(rawUserOp, usePaymaster, this.safeNotDeployed);
|
58
70
|
const unsignedUserOp = { ...rawUserOp, ...paymasterData };
|
59
71
|
return unsignedUserOp;
|
@@ -67,6 +79,9 @@ export class TransactionManager {
|
|
67
79
|
}
|
68
80
|
async encodeSignRequest(tx) {
|
69
81
|
// TODO - This is sloppy and ignores ChainId!
|
82
|
+
if (tx.chainId !== this.chainId) {
|
83
|
+
throw new Error(`Transaciton request for invalid ChainId ${tx.chainId} != ${this.chainId}`);
|
84
|
+
}
|
70
85
|
const unsignedUserOp = await this.buildTransaction({
|
71
86
|
transactions: [
|
72
87
|
{
|
@@ -95,12 +110,12 @@ export class TransactionManager {
|
|
95
110
|
console.log("userOp Receipt", userOpReceipt);
|
96
111
|
// Update safeNotDeployed after the first transaction
|
97
112
|
this._safeNotDeployed =
|
98
|
-
(await this.provider.getCode(this.
|
113
|
+
(await this.provider.getCode(this.address)) === "0x";
|
99
114
|
return userOpReceipt;
|
100
115
|
}
|
101
116
|
addOwnerTx(address) {
|
102
117
|
return {
|
103
|
-
to: this.
|
118
|
+
to: this.address,
|
104
119
|
value: "0",
|
105
120
|
data: this.safePack.singleton.interface.encodeFunctionData("addOwnerWithThreshold", [address, 1]),
|
106
121
|
};
|