near-safe 0.1.1 → 0.2.1
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.
- package/README.md +5 -4
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/lib/bundler.d.ts +4 -1
- package/dist/cjs/lib/bundler.js +15 -5
- package/dist/cjs/lib/multisend.d.ts +3 -0
- package/dist/cjs/lib/multisend.js +40 -0
- package/dist/cjs/lib/safe.d.ts +9 -9
- package/dist/cjs/lib/safe.js +22 -18
- package/dist/cjs/tx-manager.d.ts +24 -23
- package/dist/cjs/tx-manager.js +63 -48
- package/dist/cjs/types.d.ts +34 -27
- package/dist/cjs/types.js +6 -0
- package/dist/cjs/util.d.ts +8 -7
- package/dist/cjs/util.js +10 -10
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/lib/bundler.d.ts +4 -1
- package/dist/esm/lib/bundler.js +17 -5
- package/dist/esm/lib/multisend.d.ts +3 -0
- package/dist/esm/lib/multisend.js +36 -0
- package/dist/esm/lib/safe.d.ts +9 -9
- package/dist/esm/lib/safe.js +22 -18
- package/dist/esm/tx-manager.d.ts +24 -23
- package/dist/esm/tx-manager.js +67 -53
- package/dist/esm/types.d.ts +34 -27
- package/dist/esm/types.js +5 -1
- package/dist/esm/util.d.ts +8 -7
- package/dist/esm/util.js +10 -10
- package/package.json +10 -4
- package/dist/cjs/lib/near.d.ts +0 -3
- package/dist/cjs/lib/near.js +0 -14
- package/dist/esm/lib/near.d.ts +0 -3
- package/dist/esm/lib/near.js +0 -11
package/README.md
CHANGED
@@ -27,15 +27,16 @@ yarn install
|
|
27
27
|
Create a `.env` (or use our `.env.sample`) file in the root of the project and add the following environment variables:
|
28
28
|
|
29
29
|
```sh
|
30
|
-
ETH_RPC=https://rpc2.sepolia.org
|
31
|
-
|
32
30
|
NEAR_ACCOUNT_ID=
|
33
|
-
NEAR_ACCOUNT_PRIVATE_KEY=
|
34
|
-
|
35
31
|
# Head to https://www.pimlico.io/ for an API key
|
36
32
|
PIMLICO_KEY=
|
37
33
|
```
|
38
34
|
|
35
|
+
To use the CLI tool provided here in `examples/*` you will also need to provide a privateKey for your Near account.
|
36
|
+
|
37
|
+
```sh
|
38
|
+
NEAR_ACCOUNT_PRIVATE_KEY=
|
39
|
+
```
|
39
40
|
|
40
41
|
## Usage
|
41
42
|
|
package/dist/cjs/index.d.ts
CHANGED
package/dist/cjs/index.js
CHANGED
@@ -14,6 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
15
|
};
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
|
+
exports.populateTx = exports.Network = void 0;
|
17
18
|
__exportStar(require("./tx-manager"), exports);
|
18
19
|
__exportStar(require("./types"), exports);
|
19
20
|
__exportStar(require("./util"), exports);
|
21
|
+
var near_ca_1 = require("near-ca");
|
22
|
+
Object.defineProperty(exports, "Network", { enumerable: true, get: function () { return near_ca_1.Network; } });
|
23
|
+
Object.defineProperty(exports, "populateTx", { enumerable: true, get: function () { return near_ca_1.populateTx; } });
|
@@ -3,7 +3,10 @@ import { GasPrices, PaymasterData, UnsignedUserOperation, UserOperation, UserOpe
|
|
3
3
|
export declare class Erc4337Bundler {
|
4
4
|
provider: ethers.JsonRpcProvider;
|
5
5
|
entryPointAddress: string;
|
6
|
-
|
6
|
+
apiKey: string;
|
7
|
+
chainId: number;
|
8
|
+
constructor(entryPointAddress: string, apiKey: string, chainId: number);
|
9
|
+
client(chainId: number): ethers.JsonRpcProvider;
|
7
10
|
getPaymasterData(rawUserOp: UnsignedUserOperation, usePaymaster: boolean, safeNotDeployed: boolean): Promise<PaymasterData>;
|
8
11
|
sendUserOperation(userOp: UserOperation): Promise<string>;
|
9
12
|
getGasPrice(): Promise<GasPrices>;
|
package/dist/cjs/lib/bundler.js
CHANGED
@@ -1,12 +1,22 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.Erc4337Bundler = void 0;
|
4
|
+
// TODO: Ethers dependency is only for Generic HTTP Provider
|
4
5
|
const ethers_1 = require("ethers");
|
6
|
+
const viem_1 = require("viem");
|
5
7
|
const util_1 = require("../util");
|
8
|
+
function bundlerUrl(chainId, apikey) {
|
9
|
+
return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${apikey}`;
|
10
|
+
}
|
6
11
|
class Erc4337Bundler {
|
7
|
-
constructor(
|
12
|
+
constructor(entryPointAddress, apiKey, chainId) {
|
8
13
|
this.entryPointAddress = entryPointAddress;
|
9
|
-
this.
|
14
|
+
this.apiKey = apiKey;
|
15
|
+
this.chainId = chainId;
|
16
|
+
this.provider = new ethers_1.ethers.JsonRpcProvider(bundlerUrl(chainId, apiKey));
|
17
|
+
}
|
18
|
+
client(chainId) {
|
19
|
+
return new ethers_1.ethers.JsonRpcProvider(bundlerUrl(chainId, this.apiKey));
|
10
20
|
}
|
11
21
|
async getPaymasterData(rawUserOp, usePaymaster, safeNotDeployed) {
|
12
22
|
// TODO: Keep this option out of the bundler
|
@@ -53,8 +63,8 @@ exports.Erc4337Bundler = Erc4337Bundler;
|
|
53
63
|
// TODO(bh2smith) Should probably get reasonable estimates here:
|
54
64
|
const defaultPaymasterData = (safeNotDeployed) => {
|
55
65
|
return {
|
56
|
-
verificationGasLimit:
|
57
|
-
callGasLimit:
|
58
|
-
preVerificationGas:
|
66
|
+
verificationGasLimit: (0, viem_1.toHex)(safeNotDeployed ? 500000 : 100000),
|
67
|
+
callGasLimit: (0, viem_1.toHex)(100000),
|
68
|
+
preVerificationGas: (0, viem_1.toHex)(100000),
|
59
69
|
};
|
60
70
|
};
|
@@ -0,0 +1,40 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.MULTI_SEND_ABI = void 0;
|
4
|
+
exports.encodeMulti = encodeMulti;
|
5
|
+
const viem_1 = require("viem");
|
6
|
+
const types_1 = require("../types");
|
7
|
+
exports.MULTI_SEND_ABI = ["function multiSend(bytes memory transactions)"];
|
8
|
+
const MULTISEND_141 = "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526";
|
9
|
+
const MULTISEND_CALLONLY_141 = "0x9641d764fc13c8B624c04430C7356C1C7C8102e2";
|
10
|
+
/// Encodes the transaction as packed bytes of:
|
11
|
+
/// - `operation` as a `uint8` with `0` for a `call` or `1` for a `delegatecall` (=> 1 byte),
|
12
|
+
/// - `to` as an `address` (=> 20 bytes),
|
13
|
+
/// - `value` as a `uint256` (=> 32 bytes),
|
14
|
+
/// - length of `data` as a `uint256` (=> 32 bytes),
|
15
|
+
/// - `data` as `bytes`.
|
16
|
+
const encodeMetaTx = (tx) => (0, viem_1.encodePacked)(["uint8", "address", "uint256", "uint256", "bytes"], [
|
17
|
+
tx.operation || types_1.OperationType.Call,
|
18
|
+
tx.to,
|
19
|
+
BigInt(tx.value),
|
20
|
+
BigInt((0, viem_1.size)(tx.data)),
|
21
|
+
tx.data,
|
22
|
+
]);
|
23
|
+
const remove0x = (hexString) => hexString.slice(2);
|
24
|
+
// Encodes a batch of module transactions into a single multiSend module transaction.
|
25
|
+
// A module transaction is an object with fields corresponding to a Gnosis Safe's (i.e., Zodiac IAvatar's) `execTransactionFromModule` method parameters.
|
26
|
+
function encodeMulti(transactions, multiSendContractAddress = transactions.some((t) => t.operation === types_1.OperationType.DelegateCall)
|
27
|
+
? MULTISEND_141
|
28
|
+
: MULTISEND_CALLONLY_141) {
|
29
|
+
const encodedTransactions = "0x" + transactions.map(encodeMetaTx).map(remove0x).join("");
|
30
|
+
return {
|
31
|
+
operation: types_1.OperationType.DelegateCall,
|
32
|
+
to: multiSendContractAddress,
|
33
|
+
value: "0x00",
|
34
|
+
data: (0, viem_1.encodeFunctionData)({
|
35
|
+
abi: (0, viem_1.parseAbi)(exports.MULTI_SEND_ABI),
|
36
|
+
functionName: "multiSend",
|
37
|
+
args: [encodedTransactions],
|
38
|
+
}),
|
39
|
+
};
|
40
|
+
}
|
package/dist/cjs/lib/safe.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { ethers } from "ethers";
|
2
|
-
import {
|
3
|
-
import { MetaTransaction } from "
|
2
|
+
import { Address, Hash, Hex } from "viem";
|
3
|
+
import { GasPrice, MetaTransaction, UnsignedUserOperation, UserOperation } from "../types";
|
4
4
|
/**
|
5
5
|
* All contracts used in account creation & execution
|
6
6
|
*/
|
@@ -12,13 +12,13 @@ export declare class ContractSuite {
|
|
12
12
|
moduleSetup: ethers.Contract;
|
13
13
|
entryPoint: ethers.Contract;
|
14
14
|
constructor(provider: ethers.JsonRpcProvider, singleton: ethers.Contract, proxyFactory: ethers.Contract, m4337: ethers.Contract, moduleSetup: ethers.Contract, entryPoint: ethers.Contract);
|
15
|
-
static init(
|
16
|
-
addressForSetup(setup: ethers.BytesLike, saltNonce?: string): Promise<
|
17
|
-
getSetup(owners: string[]): Promise<
|
18
|
-
getOpHash(unsignedUserOp: UserOperation): Promise<
|
15
|
+
static init(): Promise<ContractSuite>;
|
16
|
+
addressForSetup(setup: ethers.BytesLike, saltNonce?: string): Promise<Address>;
|
17
|
+
getSetup(owners: string[]): Promise<Hex>;
|
18
|
+
getOpHash(unsignedUserOp: UserOperation): Promise<Hash>;
|
19
19
|
factoryDataForSetup(safeNotDeployed: boolean, setup: string, safeSaltNonce: string): {
|
20
|
-
factory?:
|
21
|
-
factoryData?:
|
20
|
+
factory?: Address;
|
21
|
+
factoryData?: Hex;
|
22
22
|
};
|
23
|
-
buildUserOp(txData: MetaTransaction, safeAddress:
|
23
|
+
buildUserOp(txData: MetaTransaction, safeAddress: Address, feeData: GasPrice, setup: string, safeNotDeployed: boolean, safeSaltNonce: string): Promise<UnsignedUserOperation>;
|
24
24
|
}
|
package/dist/cjs/lib/safe.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.ContractSuite = void 0;
|
4
|
-
const ethers_1 = require("ethers");
|
5
4
|
const safe_deployments_1 = require("@safe-global/safe-deployments");
|
6
5
|
const safe_modules_deployments_1 = require("@safe-global/safe-modules-deployments");
|
6
|
+
const ethers_1 = require("ethers");
|
7
7
|
const util_1 = require("../util");
|
8
8
|
/**
|
9
9
|
* All contracts used in account creation & execution
|
@@ -17,16 +17,12 @@ class ContractSuite {
|
|
17
17
|
this.moduleSetup = moduleSetup;
|
18
18
|
this.entryPoint = entryPoint;
|
19
19
|
}
|
20
|
-
static async init(
|
20
|
+
static async init() {
|
21
|
+
// TODO - this is a cheeky hack.
|
22
|
+
const provider = new ethers_1.ethers.JsonRpcProvider("https://rpc2.sepolia.org");
|
21
23
|
const safeDeployment = (fn) => getDeployment(fn, { provider, version: "1.4.1" });
|
22
24
|
const m4337Deployment = async (fn) => {
|
23
|
-
|
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
|
-
}
|
25
|
+
return getDeployment(fn, { provider, version: "0.3.0" });
|
30
26
|
};
|
31
27
|
// Need this first to get entryPoint address
|
32
28
|
const m4337 = await m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment);
|
@@ -73,16 +69,15 @@ class ContractSuite {
|
|
73
69
|
]);
|
74
70
|
return setup;
|
75
71
|
}
|
76
|
-
async getOpHash(unsignedUserOp
|
77
|
-
|
78
|
-
) {
|
72
|
+
async getOpHash(unsignedUserOp) {
|
73
|
+
const { factory, factoryData, verificationGasLimit, callGasLimit, maxPriorityFeePerGas, maxFeePerGas, } = unsignedUserOp;
|
79
74
|
return this.m4337.getOperationHash({
|
80
75
|
...unsignedUserOp,
|
81
|
-
initCode:
|
82
|
-
? ethers_1.ethers.solidityPacked(["address", "bytes"], [
|
76
|
+
initCode: factory
|
77
|
+
? ethers_1.ethers.solidityPacked(["address", "bytes"], [factory, factoryData])
|
83
78
|
: "0x",
|
84
|
-
accountGasLimits: (0, util_1.packGas)(
|
85
|
-
gasFees: (0, util_1.packGas)(
|
79
|
+
accountGasLimits: (0, util_1.packGas)(verificationGasLimit, callGasLimit),
|
80
|
+
gasFees: (0, util_1.packGas)(maxPriorityFeePerGas, maxFeePerGas),
|
86
81
|
paymasterAndData: (0, util_1.packPaymasterData)(unsignedUserOp),
|
87
82
|
signature: util_1.PLACEHOLDER_SIG,
|
88
83
|
});
|
@@ -116,8 +111,17 @@ exports.ContractSuite = ContractSuite;
|
|
116
111
|
async function getDeployment(fn, { provider, version }) {
|
117
112
|
const { chainId } = await provider.getNetwork();
|
118
113
|
const deployment = fn({ version });
|
119
|
-
if (!deployment
|
114
|
+
if (!deployment) {
|
120
115
|
throw new Error(`Deployment not found for ${fn.name} version ${version} on chainId ${chainId}`);
|
121
116
|
}
|
122
|
-
|
117
|
+
let address = deployment.networkAddresses[`${chainId}`];
|
118
|
+
if (!address) {
|
119
|
+
// console.warn(
|
120
|
+
// `Deployment asset ${fn.name} not listed on chainId ${chainId}, using likely fallback. For more info visit https://github.com/safe-global/safe-modules-deployments`
|
121
|
+
// );
|
122
|
+
// TODO: This is a cheeky hack. Real solution proposed in
|
123
|
+
// https://github.com/Mintbase/near-safe/issues/42
|
124
|
+
address = deployment.networkAddresses["11155111"];
|
125
|
+
}
|
126
|
+
return new ethers_1.ethers.Contract(address, deployment.abi, provider);
|
123
127
|
}
|
package/dist/cjs/tx-manager.d.ts
CHANGED
@@ -1,42 +1,43 @@
|
|
1
|
-
import {
|
1
|
+
import { FinalExecutionOutcome } from "near-api-js/lib/providers";
|
2
2
|
import { NearEthAdapter, NearEthTxData, BaseTx } from "near-ca";
|
3
|
+
import { Address, Hash, Hex } from "viem";
|
3
4
|
import { Erc4337Bundler } from "./lib/bundler";
|
4
|
-
import { UserOperation, UserOperationReceipt } from "./types";
|
5
|
-
import { MetaTransaction } from "ethers-multisend";
|
6
5
|
import { ContractSuite } from "./lib/safe";
|
6
|
+
import { MetaTransaction, UserOperation, UserOperationReceipt } from "./types";
|
7
7
|
export declare class TransactionManager {
|
8
|
-
readonly provider: ethers.JsonRpcProvider;
|
9
8
|
readonly nearAdapter: NearEthAdapter;
|
9
|
+
readonly address: Address;
|
10
|
+
readonly entryPointAddress: Address;
|
10
11
|
private safePack;
|
11
|
-
private bundler;
|
12
12
|
private setup;
|
13
|
-
|
14
|
-
readonly chainId: number;
|
13
|
+
private pimlicoKey;
|
15
14
|
private safeSaltNonce;
|
16
|
-
private
|
17
|
-
constructor(
|
15
|
+
private deployedChains;
|
16
|
+
constructor(nearAdapter: NearEthAdapter, safePack: ContractSuite, pimlicoKey: string, setup: string, safeAddress: Address, entryPointAddress: Address, safeSaltNonce: string);
|
18
17
|
static create(config: {
|
19
|
-
|
18
|
+
accountId: string;
|
19
|
+
mpcContractId: string;
|
20
20
|
pimlicoKey: string;
|
21
|
-
|
21
|
+
privateKey?: string;
|
22
22
|
safeSaltNonce?: string;
|
23
23
|
}): Promise<TransactionManager>;
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
pimlicoKey: string;
|
28
|
-
}): Promise<TransactionManager>;
|
29
|
-
get safeNotDeployed(): boolean;
|
30
|
-
get mpcAddress(): `0x${string}`;
|
31
|
-
getSafeBalance(): Promise<bigint>;
|
24
|
+
get mpcAddress(): Address;
|
25
|
+
getBalance(chainId: number): Promise<bigint>;
|
26
|
+
bundlerForChainId(chainId: number): Erc4337Bundler;
|
32
27
|
buildTransaction(args: {
|
28
|
+
chainId: number;
|
33
29
|
transactions: MetaTransaction[];
|
34
30
|
usePaymaster: boolean;
|
35
31
|
}): Promise<UserOperation>;
|
36
|
-
signTransaction(safeOpHash:
|
37
|
-
opHash(userOp: UserOperation): Promise<
|
32
|
+
signTransaction(safeOpHash: Hex): Promise<Hex>;
|
33
|
+
opHash(userOp: UserOperation): Promise<Hash>;
|
38
34
|
encodeSignRequest(tx: BaseTx): Promise<NearEthTxData>;
|
39
|
-
executeTransaction(userOp: UserOperation): Promise<UserOperationReceipt>;
|
35
|
+
executeTransaction(chainId: number, userOp: UserOperation): Promise<UserOperationReceipt>;
|
36
|
+
safeDeployed(chainId: number): Promise<boolean>;
|
40
37
|
addOwnerTx(address: string): MetaTransaction;
|
41
|
-
safeSufficientlyFunded(transactions: MetaTransaction[], gasCost: bigint): Promise<boolean>;
|
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
|
+
}>;
|
42
43
|
}
|
package/dist/cjs/tx-manager.js
CHANGED
@@ -1,82 +1,71 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.TransactionManager = void 0;
|
4
|
-
const ethers_1 = require("ethers");
|
5
4
|
const near_ca_1 = require("near-ca");
|
5
|
+
const viem_1 = require("viem");
|
6
6
|
const bundler_1 = require("./lib/bundler");
|
7
|
-
const
|
8
|
-
const near_1 = require("./lib/near");
|
9
|
-
const ethers_multisend_1 = require("ethers-multisend");
|
7
|
+
const multisend_1 = require("./lib/multisend");
|
10
8
|
const safe_1 = require("./lib/safe");
|
9
|
+
const util_1 = require("./util");
|
11
10
|
class TransactionManager {
|
12
|
-
constructor(
|
13
|
-
this.provider = provider;
|
11
|
+
constructor(nearAdapter, safePack, pimlicoKey, setup, safeAddress, entryPointAddress, safeSaltNonce) {
|
14
12
|
this.nearAdapter = nearAdapter;
|
15
13
|
this.safePack = safePack;
|
16
|
-
this.
|
14
|
+
this.pimlicoKey = pimlicoKey;
|
15
|
+
this.entryPointAddress = entryPointAddress;
|
17
16
|
this.setup = setup;
|
18
|
-
this.chainId = chainId;
|
19
17
|
this.address = safeAddress;
|
20
18
|
this.safeSaltNonce = safeSaltNonce;
|
21
|
-
this.
|
19
|
+
this.deployedChains = new Set();
|
22
20
|
}
|
23
21
|
static async create(config) {
|
24
|
-
const {
|
25
|
-
const
|
26
|
-
|
27
|
-
|
22
|
+
const { pimlicoKey } = config;
|
23
|
+
const [nearAdapter, safePack] = await Promise.all([
|
24
|
+
(0, near_ca_1.setupAdapter)({ ...config }),
|
25
|
+
safe_1.ContractSuite.init(),
|
26
|
+
]);
|
28
27
|
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
28
|
const setup = await safePack.getSetup([nearAdapter.address]);
|
31
29
|
const safeAddress = await safePack.addressForSetup(setup, config.safeSaltNonce);
|
32
|
-
const
|
33
|
-
console.log(`Safe Address: ${safeAddress}
|
34
|
-
return new TransactionManager(
|
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
|
-
});
|
43
|
-
}
|
44
|
-
get safeNotDeployed() {
|
45
|
-
return this._safeNotDeployed;
|
30
|
+
const entryPointAddress = (await safePack.entryPoint.getAddress());
|
31
|
+
console.log(`Safe Address: ${safeAddress}`);
|
32
|
+
return new TransactionManager(nearAdapter, safePack, pimlicoKey, setup, safeAddress, entryPointAddress, config.safeSaltNonce || "0");
|
46
33
|
}
|
47
34
|
get mpcAddress() {
|
48
35
|
return this.nearAdapter.address;
|
49
36
|
}
|
50
|
-
async
|
51
|
-
|
37
|
+
async getBalance(chainId) {
|
38
|
+
const provider = near_ca_1.Network.fromChainId(chainId).client;
|
39
|
+
return await provider.getBalance({ address: this.address });
|
40
|
+
}
|
41
|
+
bundlerForChainId(chainId) {
|
42
|
+
return new bundler_1.Erc4337Bundler(this.entryPointAddress, this.pimlicoKey, chainId);
|
52
43
|
}
|
53
44
|
async buildTransaction(args) {
|
54
|
-
const { transactions, usePaymaster } = args;
|
55
|
-
const
|
56
|
-
|
45
|
+
const { transactions, usePaymaster, chainId } = args;
|
46
|
+
const bundler = this.bundlerForChainId(chainId);
|
47
|
+
const gasFees = (await bundler.getGasPrice()).fast;
|
57
48
|
// Build Singular MetaTransaction for Multisend from transaction list.
|
58
49
|
if (transactions.length === 0) {
|
59
50
|
throw new Error("Empty transaction set!");
|
60
51
|
}
|
61
|
-
const tx = transactions.length > 1 ? (0,
|
62
|
-
const
|
63
|
-
const
|
52
|
+
const tx = transactions.length > 1 ? (0, multisend_1.encodeMulti)(transactions) : transactions[0];
|
53
|
+
const safeNotDeployed = !(await this.safeDeployed(chainId));
|
54
|
+
const rawUserOp = await this.safePack.buildUserOp(tx, this.address, gasFees, this.setup, safeNotDeployed, this.safeSaltNonce);
|
55
|
+
const paymasterData = await bundler.getPaymasterData(rawUserOp, usePaymaster, safeNotDeployed);
|
64
56
|
const unsignedUserOp = { ...rawUserOp, ...paymasterData };
|
65
57
|
return unsignedUserOp;
|
66
58
|
}
|
67
59
|
async signTransaction(safeOpHash) {
|
68
|
-
const signature = await
|
60
|
+
const signature = await this.nearAdapter.sign(safeOpHash);
|
69
61
|
return (0, util_1.packSignature)(signature);
|
70
62
|
}
|
71
63
|
async opHash(userOp) {
|
72
64
|
return this.safePack.getOpHash(userOp);
|
73
65
|
}
|
74
66
|
async encodeSignRequest(tx) {
|
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
|
-
}
|
79
67
|
const unsignedUserOp = await this.buildTransaction({
|
68
|
+
chainId: tx.chainId,
|
80
69
|
transactions: [
|
81
70
|
{
|
82
71
|
to: tx.to,
|
@@ -97,16 +86,27 @@ class TransactionManager {
|
|
97
86
|
evmMessage: JSON.stringify(unsignedUserOp),
|
98
87
|
};
|
99
88
|
}
|
100
|
-
async executeTransaction(userOp) {
|
101
|
-
const
|
89
|
+
async executeTransaction(chainId, userOp) {
|
90
|
+
const bundler = this.bundlerForChainId(chainId);
|
91
|
+
const userOpHash = await bundler.sendUserOperation(userOp);
|
102
92
|
console.log("UserOp Hash", userOpHash);
|
103
|
-
const userOpReceipt = await
|
93
|
+
const userOpReceipt = await bundler.getUserOpReceipt(userOpHash);
|
104
94
|
console.log("userOp Receipt", userOpReceipt);
|
105
95
|
// Update safeNotDeployed after the first transaction
|
106
|
-
this.
|
107
|
-
(await this.provider.getCode(this.address)) === "0x";
|
96
|
+
this.safeDeployed(chainId);
|
108
97
|
return userOpReceipt;
|
109
98
|
}
|
99
|
+
async safeDeployed(chainId) {
|
100
|
+
if (chainId in this.deployedChains) {
|
101
|
+
return true;
|
102
|
+
}
|
103
|
+
const provider = near_ca_1.Network.fromChainId(chainId).client;
|
104
|
+
const deployed = (await provider.getCode({ address: this.address })) !== "0x";
|
105
|
+
if (deployed) {
|
106
|
+
this.deployedChains.add(chainId);
|
107
|
+
}
|
108
|
+
return deployed;
|
109
|
+
}
|
110
110
|
addOwnerTx(address) {
|
111
111
|
return {
|
112
112
|
to: this.address,
|
@@ -114,13 +114,28 @@ class TransactionManager {
|
|
114
114
|
data: this.safePack.singleton.interface.encodeFunctionData("addOwnerWithThreshold", [address, 1]),
|
115
115
|
};
|
116
116
|
}
|
117
|
-
async safeSufficientlyFunded(transactions, gasCost) {
|
117
|
+
async safeSufficientlyFunded(chainId, transactions, gasCost) {
|
118
118
|
const txValue = transactions.reduce((acc, tx) => acc + BigInt(tx.value), 0n);
|
119
119
|
if (txValue + gasCost === 0n) {
|
120
120
|
return true;
|
121
121
|
}
|
122
|
-
const safeBalance = await this.
|
122
|
+
const safeBalance = await this.getBalance(chainId);
|
123
123
|
return txValue + gasCost < safeBalance;
|
124
124
|
}
|
125
|
+
async broadcastEvm(chainId, outcome, unsignedUserOp) {
|
126
|
+
const signature = (0, util_1.packSignature)((0, viem_1.serializeSignature)((0, near_ca_1.signatureFromOutcome)(outcome)));
|
127
|
+
try {
|
128
|
+
return {
|
129
|
+
signature,
|
130
|
+
receipt: await this.executeTransaction(chainId, {
|
131
|
+
...unsignedUserOp,
|
132
|
+
signature,
|
133
|
+
}),
|
134
|
+
};
|
135
|
+
}
|
136
|
+
catch (error) {
|
137
|
+
throw new Error(`Failed EVM broadcast: ${error instanceof Error ? error.message : String(error)}`);
|
138
|
+
}
|
139
|
+
}
|
125
140
|
}
|
126
141
|
exports.TransactionManager = TransactionManager;
|
package/dist/cjs/types.d.ts
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
import {
|
1
|
+
import { Address, Hex } from "viem";
|
2
2
|
export interface UnsignedUserOperation {
|
3
|
-
sender:
|
3
|
+
sender: Address;
|
4
4
|
nonce: string;
|
5
|
-
factory?:
|
6
|
-
factoryData?:
|
7
|
-
callData:
|
8
|
-
maxPriorityFeePerGas:
|
9
|
-
maxFeePerGas:
|
5
|
+
factory?: Address;
|
6
|
+
factoryData?: Hex;
|
7
|
+
callData: Hex;
|
8
|
+
maxPriorityFeePerGas: Hex;
|
9
|
+
maxFeePerGas: Hex;
|
10
10
|
}
|
11
11
|
/**
|
12
12
|
* Supported Representation of UserOperation for EntryPoint v0.7
|
13
13
|
*/
|
14
14
|
export interface UserOperation extends UnsignedUserOperation {
|
15
|
-
verificationGasLimit:
|
16
|
-
callGasLimit:
|
17
|
-
preVerificationGas:
|
18
|
-
signature?:
|
15
|
+
verificationGasLimit: Hex;
|
16
|
+
callGasLimit: Hex;
|
17
|
+
preVerificationGas: Hex;
|
18
|
+
signature?: Hex;
|
19
19
|
}
|
20
20
|
export interface PaymasterData {
|
21
|
-
paymaster?:
|
22
|
-
paymasterData?:
|
23
|
-
paymasterVerificationGasLimit?:
|
24
|
-
paymasterPostOpGasLimit?:
|
25
|
-
verificationGasLimit:
|
26
|
-
callGasLimit:
|
27
|
-
preVerificationGas:
|
21
|
+
paymaster?: Address;
|
22
|
+
paymasterData?: Hex;
|
23
|
+
paymasterVerificationGasLimit?: Hex;
|
24
|
+
paymasterPostOpGasLimit?: Hex;
|
25
|
+
verificationGasLimit: Hex;
|
26
|
+
callGasLimit: Hex;
|
27
|
+
preVerificationGas: Hex;
|
28
28
|
}
|
29
29
|
export interface UserOptions {
|
30
30
|
usePaymaster: boolean;
|
@@ -32,10 +32,7 @@ export interface UserOptions {
|
|
32
32
|
mpcContractId: string;
|
33
33
|
recoveryAddress?: string;
|
34
34
|
}
|
35
|
-
export type
|
36
|
-
export type Address = ethers.AddressLike;
|
37
|
-
export type Hex = `0x${string}`;
|
38
|
-
export type Hash = `0x${string}`;
|
35
|
+
export type TxStatus = "success" | "reverted";
|
39
36
|
interface Log {
|
40
37
|
logIndex: string;
|
41
38
|
transactionIndex: string;
|
@@ -49,19 +46,19 @@ interface Log {
|
|
49
46
|
interface Receipt {
|
50
47
|
transactionHash: Hex;
|
51
48
|
transactionIndex: bigint;
|
52
|
-
blockHash:
|
49
|
+
blockHash: Hex;
|
53
50
|
blockNumber: bigint;
|
54
51
|
from: Address;
|
55
|
-
to
|
52
|
+
to?: Address;
|
56
53
|
cumulativeGasUsed: bigint;
|
57
|
-
status:
|
54
|
+
status: TxStatus;
|
58
55
|
gasUsed: bigint;
|
59
|
-
contractAddress
|
56
|
+
contractAddress?: Address;
|
60
57
|
logsBloom: Hex;
|
61
58
|
effectiveGasPrice: bigint;
|
62
59
|
}
|
63
60
|
export type UserOperationReceipt = {
|
64
|
-
userOpHash:
|
61
|
+
userOpHash: Hex;
|
65
62
|
entryPoint: Address;
|
66
63
|
sender: Address;
|
67
64
|
nonce: bigint;
|
@@ -82,4 +79,14 @@ export interface GasPrice {
|
|
82
79
|
maxFeePerGas: Hex;
|
83
80
|
maxPriorityFeePerGas: Hex;
|
84
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
|
+
}
|
85
92
|
export {};
|
package/dist/cjs/types.js
CHANGED
@@ -1,2 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.OperationType = void 0;
|
4
|
+
var OperationType;
|
5
|
+
(function (OperationType) {
|
6
|
+
OperationType[OperationType["Call"] = 0] = "Call";
|
7
|
+
OperationType[OperationType["DelegateCall"] = 1] = "DelegateCall";
|
8
|
+
})(OperationType || (exports.OperationType = OperationType = {}));
|
package/dist/cjs/util.d.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
import {
|
2
|
-
import { PaymasterData } from "./types";
|
3
|
-
|
4
|
-
|
5
|
-
export declare const packGas: (hi:
|
6
|
-
export declare function packSignature(signature: string
|
7
|
-
export declare function packPaymasterData(data: PaymasterData):
|
1
|
+
import { Hex } from "viem";
|
2
|
+
import { PaymasterData, MetaTransaction } from "./types";
|
3
|
+
export declare const PLACEHOLDER_SIG: `0x${string}`;
|
4
|
+
type IntLike = Hex | bigint | string | number;
|
5
|
+
export declare const packGas: (hi: IntLike, lo: IntLike) => string;
|
6
|
+
export declare function packSignature(signature: `0x${string}`, validFrom?: number, validTo?: number): Hex;
|
7
|
+
export declare function packPaymasterData(data: PaymasterData): Hex;
|
8
8
|
export declare function containsValue(transactions: MetaTransaction[]): boolean;
|
9
|
+
export {};
|
package/dist/cjs/util.js
CHANGED
@@ -4,22 +4,22 @@ exports.packGas = exports.PLACEHOLDER_SIG = void 0;
|
|
4
4
|
exports.packSignature = packSignature;
|
5
5
|
exports.packPaymasterData = packPaymasterData;
|
6
6
|
exports.containsValue = containsValue;
|
7
|
-
const
|
8
|
-
exports.PLACEHOLDER_SIG =
|
9
|
-
const packGas = (hi, lo) =>
|
7
|
+
const viem_1 = require("viem");
|
8
|
+
exports.PLACEHOLDER_SIG = (0, viem_1.encodePacked)(["uint48", "uint48"], [0, 0]);
|
9
|
+
const packGas = (hi, lo) => (0, viem_1.encodePacked)(["uint128", "uint128"], [BigInt(hi), BigInt(lo)]);
|
10
10
|
exports.packGas = packGas;
|
11
11
|
function packSignature(signature, validFrom = 0, validTo = 0) {
|
12
|
-
return
|
12
|
+
return (0, viem_1.encodePacked)(["uint48", "uint48", "bytes"], [validFrom, validTo, signature]);
|
13
13
|
}
|
14
14
|
function packPaymasterData(data) {
|
15
|
-
return data.paymaster
|
16
|
-
?
|
15
|
+
return (data.paymaster
|
16
|
+
? (0, viem_1.concatHex)([
|
17
17
|
data.paymaster,
|
18
|
-
|
19
|
-
|
18
|
+
(0, viem_1.toHex)(BigInt(data.paymasterVerificationGasLimit || 0n), { size: 16 }),
|
19
|
+
(0, viem_1.toHex)(BigInt(data.paymasterPostOpGasLimit || 0n), { size: 16 }),
|
20
20
|
data.paymasterData || "0x",
|
21
|
-
])
|
22
|
-
: "0x";
|
21
|
+
])
|
22
|
+
: "0x");
|
23
23
|
}
|
24
24
|
function containsValue(transactions) {
|
25
25
|
return transactions.some((tx) => tx.value !== "0");
|