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.
- 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 +31 -9
- package/dist/cjs/lib/bundler.js +46 -27
- package/dist/cjs/lib/multisend.d.ts +3 -0
- package/dist/cjs/lib/multisend.js +40 -0
- package/dist/cjs/lib/safe.d.ts +20 -18
- package/dist/cjs/lib/safe.js +117 -71
- package/dist/cjs/tx-manager.d.ts +13 -7
- package/dist/cjs/tx-manager.js +44 -22
- package/dist/cjs/types.d.ts +10 -0
- package/dist/cjs/types.js +6 -0
- package/dist/cjs/util.d.ts +4 -3
- package/dist/cjs/util.js +9 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/lib/bundler.d.ts +31 -9
- package/dist/esm/lib/bundler.js +48 -29
- package/dist/esm/lib/multisend.d.ts +3 -0
- package/dist/esm/lib/multisend.js +36 -0
- package/dist/esm/lib/safe.d.ts +20 -18
- package/dist/esm/lib/safe.js +120 -73
- package/dist/esm/tx-manager.d.ts +13 -7
- package/dist/esm/tx-manager.js +44 -23
- package/dist/esm/types.d.ts +10 -0
- package/dist/esm/types.js +5 -1
- package/dist/esm/util.d.ts +4 -3
- package/dist/esm/util.js +8 -1
- package/package.json +9 -6
    
        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; } });
         | 
| @@ -1,15 +1,37 @@ | |
| 1 | 
            -
            import {  | 
| 2 | 
            -
            import { GasPrices, PaymasterData, UnsignedUserOperation, UserOperation, UserOperationReceipt } from "../types | 
| 1 | 
            +
            import { Address, Hash, PublicClient, Transport } from "viem";
         | 
| 2 | 
            +
            import { GasPrices, PaymasterData, UnsignedUserOperation, UserOperation, UserOperationReceipt } from "../types";
         | 
| 3 | 
            +
            type BundlerRpcSchema = [
         | 
| 4 | 
            +
                {
         | 
| 5 | 
            +
                    Method: "pm_sponsorUserOperation";
         | 
| 6 | 
            +
                    Parameters: [UnsignedUserOperation, Address];
         | 
| 7 | 
            +
                    ReturnType: PaymasterData;
         | 
| 8 | 
            +
                },
         | 
| 9 | 
            +
                {
         | 
| 10 | 
            +
                    Method: "eth_sendUserOperation";
         | 
| 11 | 
            +
                    Parameters: [UserOperation, Address];
         | 
| 12 | 
            +
                    ReturnType: Hash;
         | 
| 13 | 
            +
                },
         | 
| 14 | 
            +
                {
         | 
| 15 | 
            +
                    Method: "pimlico_getUserOperationGasPrice";
         | 
| 16 | 
            +
                    Parameters: [];
         | 
| 17 | 
            +
                    ReturnType: GasPrices;
         | 
| 18 | 
            +
                },
         | 
| 19 | 
            +
                {
         | 
| 20 | 
            +
                    Method: "eth_getUserOperationReceipt";
         | 
| 21 | 
            +
                    Parameters: [Hash];
         | 
| 22 | 
            +
                    ReturnType: UserOperationReceipt | null;
         | 
| 23 | 
            +
                }
         | 
| 24 | 
            +
            ];
         | 
| 3 25 | 
             
            export declare class Erc4337Bundler {
         | 
| 4 | 
            -
                 | 
| 5 | 
            -
                entryPointAddress:  | 
| 26 | 
            +
                client: PublicClient<Transport, undefined, undefined, BundlerRpcSchema>;
         | 
| 27 | 
            +
                entryPointAddress: Address;
         | 
| 6 28 | 
             
                apiKey: string;
         | 
| 7 29 | 
             
                chainId: number;
         | 
| 8 | 
            -
                constructor(entryPointAddress:  | 
| 9 | 
            -
                client(chainId: number): ethers.JsonRpcProvider;
         | 
| 30 | 
            +
                constructor(entryPointAddress: Address, apiKey: string, chainId: number);
         | 
| 10 31 | 
             
                getPaymasterData(rawUserOp: UnsignedUserOperation, usePaymaster: boolean, safeNotDeployed: boolean): Promise<PaymasterData>;
         | 
| 11 | 
            -
                sendUserOperation(userOp: UserOperation): Promise< | 
| 32 | 
            +
                sendUserOperation(userOp: UserOperation): Promise<Hash>;
         | 
| 12 33 | 
             
                getGasPrice(): Promise<GasPrices>;
         | 
| 13 | 
            -
                 | 
| 14 | 
            -
                 | 
| 34 | 
            +
                getUserOpReceipt(userOpHash: Hash): Promise<UserOperationReceipt>;
         | 
| 35 | 
            +
                private _getUserOpReceiptInner;
         | 
| 15 36 | 
             
            }
         | 
| 37 | 
            +
            export {};
         | 
    
        package/dist/cjs/lib/bundler.js
    CHANGED
    
    | @@ -1,10 +1,8 @@ | |
| 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
         | 
| 5 | 
            -
            const ethers_1 = require("ethers");
         | 
| 6 | 
            -
            const util_js_1 = require("../util.js");
         | 
| 7 4 | 
             
            const viem_1 = require("viem");
         | 
| 5 | 
            +
            const util_1 = require("../util");
         | 
| 8 6 | 
             
            function bundlerUrl(chainId, apikey) {
         | 
| 9 7 | 
             
                return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${apikey}`;
         | 
| 10 8 | 
             
            }
         | 
| @@ -13,41 +11,37 @@ class Erc4337Bundler { | |
| 13 11 | 
             
                    this.entryPointAddress = entryPointAddress;
         | 
| 14 12 | 
             
                    this.apiKey = apiKey;
         | 
| 15 13 | 
             
                    this.chainId = chainId;
         | 
| 16 | 
            -
                    this. | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
                     | 
| 14 | 
            +
                    this.client = (0, viem_1.createPublicClient)({
         | 
| 15 | 
            +
                        transport: (0, viem_1.http)(bundlerUrl(chainId, this.apiKey)),
         | 
| 16 | 
            +
                        rpcSchema: (0, viem_1.rpcSchema)(),
         | 
| 17 | 
            +
                    });
         | 
| 20 18 | 
             
                }
         | 
| 21 19 | 
             
                async getPaymasterData(rawUserOp, usePaymaster, safeNotDeployed) {
         | 
| 22 20 | 
             
                    // TODO: Keep this option out of the bundler
         | 
| 23 21 | 
             
                    if (usePaymaster) {
         | 
| 24 22 | 
             
                        console.log("Requesting paymaster data...");
         | 
| 25 | 
            -
                         | 
| 26 | 
            -
                             | 
| 27 | 
            -
                             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 23 | 
            +
                        return handleRequest(() => this.client.request({
         | 
| 24 | 
            +
                            method: "pm_sponsorUserOperation",
         | 
| 25 | 
            +
                            params: [
         | 
| 26 | 
            +
                                { ...rawUserOp, signature: util_1.PLACEHOLDER_SIG },
         | 
| 27 | 
            +
                                this.entryPointAddress,
         | 
| 28 | 
            +
                            ],
         | 
| 29 | 
            +
                        }));
         | 
| 30 30 | 
             
                    }
         | 
| 31 31 | 
             
                    return defaultPaymasterData(safeNotDeployed);
         | 
| 32 32 | 
             
                }
         | 
| 33 33 | 
             
                async sendUserOperation(userOp) {
         | 
| 34 | 
            -
                     | 
| 35 | 
            -
                         | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
                        return userOpHash;
         | 
| 40 | 
            -
                    }
         | 
| 41 | 
            -
                    catch (err) {
         | 
| 42 | 
            -
                        const error = err.error;
         | 
| 43 | 
            -
                        throw new Error(`Failed to send user op with: ${error.message}`);
         | 
| 44 | 
            -
                    }
         | 
| 34 | 
            +
                    return handleRequest(() => this.client.request({
         | 
| 35 | 
            +
                        method: "eth_sendUserOperation",
         | 
| 36 | 
            +
                        params: [userOp, this.entryPointAddress],
         | 
| 37 | 
            +
                    }));
         | 
| 38 | 
            +
                    // throw new Error(`Failed to send user op with: ${error.message}`);
         | 
| 45 39 | 
             
                }
         | 
| 46 40 | 
             
                async getGasPrice() {
         | 
| 47 | 
            -
                    return this. | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
                     | 
| 41 | 
            +
                    return handleRequest(() => this.client.request({
         | 
| 42 | 
            +
                        method: "pimlico_getUserOperationGasPrice",
         | 
| 43 | 
            +
                        params: [],
         | 
| 44 | 
            +
                    }));
         | 
| 51 45 | 
             
                }
         | 
| 52 46 | 
             
                async getUserOpReceipt(userOpHash) {
         | 
| 53 47 | 
             
                    let userOpReceipt = null;
         | 
| @@ -58,8 +52,33 @@ class Erc4337Bundler { | |
| 58 52 | 
             
                    }
         | 
| 59 53 | 
             
                    return userOpReceipt;
         | 
| 60 54 | 
             
                }
         | 
| 55 | 
            +
                async _getUserOpReceiptInner(userOpHash) {
         | 
| 56 | 
            +
                    return handleRequest(() => this.client.request({
         | 
| 57 | 
            +
                        method: "eth_getUserOperationReceipt",
         | 
| 58 | 
            +
                        params: [userOpHash],
         | 
| 59 | 
            +
                    }));
         | 
| 60 | 
            +
                }
         | 
| 61 61 | 
             
            }
         | 
| 62 62 | 
             
            exports.Erc4337Bundler = Erc4337Bundler;
         | 
| 63 | 
            +
            async function handleRequest(clientMethod) {
         | 
| 64 | 
            +
                try {
         | 
| 65 | 
            +
                    return await clientMethod();
         | 
| 66 | 
            +
                }
         | 
| 67 | 
            +
                catch (error) {
         | 
| 68 | 
            +
                    if (error instanceof viem_1.HttpRequestError) {
         | 
| 69 | 
            +
                        if (error.status === 401) {
         | 
| 70 | 
            +
                            throw new Error("Unauthorized request. Please check your API key.");
         | 
| 71 | 
            +
                        }
         | 
| 72 | 
            +
                        else {
         | 
| 73 | 
            +
                            console.error(`Request failed with status ${error.status}: ${error.message}`);
         | 
| 74 | 
            +
                        }
         | 
| 75 | 
            +
                    }
         | 
| 76 | 
            +
                    else if (error instanceof viem_1.RpcError) {
         | 
| 77 | 
            +
                        throw new Error(`Failed to send user op with: ${error.message}`);
         | 
| 78 | 
            +
                    }
         | 
| 79 | 
            +
                    throw new Error(`Unexpected error ${error instanceof Error ? error.message : String(error)}`);
         | 
| 80 | 
            +
                }
         | 
| 81 | 
            +
            }
         | 
| 63 82 | 
             
            // TODO(bh2smith) Should probably get reasonable estimates here:
         | 
| 64 83 | 
             
            const defaultPaymasterData = (safeNotDeployed) => {
         | 
| 65 84 | 
             
                return {
         | 
| @@ -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,25 +1,27 @@ | |
| 1 | 
            -
            import {  | 
| 2 | 
            -
            import { GasPrice, UnsignedUserOperation, UserOperation } from "../types";
         | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 1 | 
            +
            import { Address, Hash, Hex, ParseAbi, PublicClient } from "viem";
         | 
| 2 | 
            +
            import { GasPrice, MetaTransaction, UnsignedUserOperation, UserOperation } from "../types";
         | 
| 3 | 
            +
            interface DeploymentData {
         | 
| 4 | 
            +
                abi: unknown[] | ParseAbi<readonly string[]>;
         | 
| 5 | 
            +
                address: `0x${string}`;
         | 
| 6 | 
            +
            }
         | 
| 5 7 | 
             
            /**
         | 
| 6 8 | 
             
             * All contracts used in account creation & execution
         | 
| 7 9 | 
             
             */
         | 
| 8 10 | 
             
            export declare class ContractSuite {
         | 
| 9 | 
            -
                 | 
| 10 | 
            -
                singleton:  | 
| 11 | 
            -
                proxyFactory:  | 
| 12 | 
            -
                m4337:  | 
| 13 | 
            -
                moduleSetup:  | 
| 14 | 
            -
                entryPoint:  | 
| 15 | 
            -
                constructor( | 
| 11 | 
            +
                dummyClient: PublicClient;
         | 
| 12 | 
            +
                singleton: DeploymentData;
         | 
| 13 | 
            +
                proxyFactory: DeploymentData;
         | 
| 14 | 
            +
                m4337: DeploymentData;
         | 
| 15 | 
            +
                moduleSetup: DeploymentData;
         | 
| 16 | 
            +
                entryPoint: DeploymentData;
         | 
| 17 | 
            +
                constructor(client: PublicClient, singleton: DeploymentData, proxyFactory: DeploymentData, m4337: DeploymentData, moduleSetup: DeploymentData, entryPoint: DeploymentData);
         | 
| 16 18 | 
             
                static init(): Promise<ContractSuite>;
         | 
| 17 | 
            -
                addressForSetup(setup:  | 
| 18 | 
            -
                getSetup(owners: string[]):  | 
| 19 | 
            +
                addressForSetup(setup: Hex, saltNonce?: string): Promise<Address>;
         | 
| 20 | 
            +
                getSetup(owners: string[]): Hex;
         | 
| 21 | 
            +
                addOwnerData(newOwner: Address): Hex;
         | 
| 19 22 | 
             
                getOpHash(unsignedUserOp: UserOperation): Promise<Hash>;
         | 
| 20 | 
            -
                factoryDataForSetup | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
                };
         | 
| 24 | 
            -
                buildUserOp(txData: MetaTransaction, safeAddress: Address, feeData: GasPrice, setup: string, safeNotDeployed: boolean, safeSaltNonce: string): Promise<UnsignedUserOperation>;
         | 
| 23 | 
            +
                private factoryDataForSetup;
         | 
| 24 | 
            +
                buildUserOp(nonce: bigint, txData: MetaTransaction, safeAddress: Address, feeData: GasPrice, setup: string, safeNotDeployed: boolean, safeSaltNonce: string): Promise<UnsignedUserOperation>;
         | 
| 25 | 
            +
                getNonce(address: Address, chainId: number): Promise<bigint>;
         | 
| 25 26 | 
             
            }
         | 
| 27 | 
            +
            export {};
         | 
    
        package/dist/cjs/lib/safe.js
    CHANGED
    
    | @@ -1,16 +1,16 @@ | |
| 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 viem_1 = require("viem");
         | 
| 7 7 | 
             
            const util_1 = require("../util");
         | 
| 8 8 | 
             
            /**
         | 
| 9 9 | 
             
             * All contracts used in account creation & execution
         | 
| 10 10 | 
             
             */
         | 
| 11 11 | 
             
            class ContractSuite {
         | 
| 12 | 
            -
                constructor( | 
| 13 | 
            -
                    this. | 
| 12 | 
            +
                constructor(client, singleton, proxyFactory, m4337, moduleSetup, entryPoint) {
         | 
| 13 | 
            +
                    this.dummyClient = client;
         | 
| 14 14 | 
             
                    this.singleton = singleton;
         | 
| 15 15 | 
             
                    this.proxyFactory = proxyFactory;
         | 
| 16 16 | 
             
                    this.m4337 = m4337;
         | 
| @@ -19,109 +19,155 @@ class ContractSuite { | |
| 19 19 | 
             
                }
         | 
| 20 20 | 
             
                static async init() {
         | 
| 21 21 | 
             
                    // TODO - this is a cheeky hack.
         | 
| 22 | 
            -
                    const  | 
| 23 | 
            -
                    const safeDeployment = (fn) => getDeployment(fn, {  | 
| 22 | 
            +
                    const client = (0, util_1.getClient)(11155111);
         | 
| 23 | 
            +
                    const safeDeployment = (fn) => getDeployment(fn, { version: "1.4.1" });
         | 
| 24 24 | 
             
                    const m4337Deployment = async (fn) => {
         | 
| 25 | 
            -
                        return getDeployment(fn, {  | 
| 25 | 
            +
                        return getDeployment(fn, { version: "0.3.0" });
         | 
| 26 26 | 
             
                    };
         | 
| 27 | 
            -
                     | 
| 28 | 
            -
                    const m4337 = await m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment);
         | 
| 29 | 
            -
                    const [singleton, proxyFactory, moduleSetup, supportedEntryPoint] = await Promise.all([
         | 
| 27 | 
            +
                    const [singleton, proxyFactory, moduleSetup, m4337] = await Promise.all([
         | 
| 30 28 | 
             
                        safeDeployment(safe_deployments_1.getSafeL2SingletonDeployment),
         | 
| 31 29 | 
             
                        safeDeployment(safe_deployments_1.getProxyFactoryDeployment),
         | 
| 32 30 | 
             
                        m4337Deployment(safe_modules_deployments_1.getSafeModuleSetupDeployment),
         | 
| 33 | 
            -
                         | 
| 31 | 
            +
                        m4337Deployment(safe_modules_deployments_1.getSafe4337ModuleDeployment),
         | 
| 34 32 | 
             
                    ]);
         | 
| 35 | 
            -
                     | 
| 36 | 
            -
                     | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 33 | 
            +
                    // console.log("Initialized ERC4337 & Safe Module Contracts:", {
         | 
| 34 | 
            +
                    //   singleton: await singleton.getAddress(),
         | 
| 35 | 
            +
                    //   proxyFactory: await proxyFactory.getAddress(),
         | 
| 36 | 
            +
                    //   m4337: await m4337.getAddress(),
         | 
| 37 | 
            +
                    //   moduleSetup: await moduleSetup.getAddress(),
         | 
| 38 | 
            +
                    //   entryPoint: await entryPoint.getAddress(),
         | 
| 39 | 
            +
                    // });
         | 
| 40 | 
            +
                    return new ContractSuite(client, singleton, proxyFactory, m4337, moduleSetup, 
         | 
| 41 | 
            +
                    // EntryPoint:
         | 
| 42 | 
            +
                    {
         | 
| 43 | 
            +
                        address: (await client.readContract({
         | 
| 44 | 
            +
                            address: m4337.address,
         | 
| 45 | 
            +
                            abi: m4337.abi,
         | 
| 46 | 
            +
                            functionName: "SUPPORTED_ENTRYPOINT",
         | 
| 47 | 
            +
                        })),
         | 
| 48 | 
            +
                        abi: (0, viem_1.parseAbi)([
         | 
| 49 | 
            +
                            "function getNonce(address, uint192 key) view returns (uint256 nonce)",
         | 
| 50 | 
            +
                        ]),
         | 
| 42 51 | 
             
                    });
         | 
| 43 | 
            -
                    return new ContractSuite(provider, singleton, proxyFactory, m4337, moduleSetup, entryPoint);
         | 
| 44 52 | 
             
                }
         | 
| 45 53 | 
             
                async addressForSetup(setup, saltNonce) {
         | 
| 46 54 | 
             
                    // bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
         | 
| 47 55 | 
             
                    // cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L58
         | 
| 48 | 
            -
                    const salt =  | 
| 56 | 
            +
                    const salt = (0, viem_1.keccak256)((0, viem_1.encodePacked)(["bytes32", "uint256"], [(0, viem_1.keccak256)(setup), BigInt(saltNonce || "0")]));
         | 
| 49 57 | 
             
                    // abi.encodePacked(type(SafeProxy).creationCode, uint256(uint160(_singleton)));
         | 
| 50 58 | 
             
                    // cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L29
         | 
| 51 | 
            -
                    const initCode =  | 
| 52 | 
            -
                        await this. | 
| 53 | 
            -
             | 
| 59 | 
            +
                    const initCode = (0, viem_1.encodePacked)(["bytes", "uint256"], [
         | 
| 60 | 
            +
                        (await this.dummyClient.readContract({
         | 
| 61 | 
            +
                            address: this.proxyFactory.address,
         | 
| 62 | 
            +
                            abi: this.proxyFactory.abi,
         | 
| 63 | 
            +
                            functionName: "proxyCreationCode",
         | 
| 64 | 
            +
                        })),
         | 
| 65 | 
            +
                        BigInt(this.singleton.address),
         | 
| 54 66 | 
             
                    ]);
         | 
| 55 | 
            -
                    return  | 
| 67 | 
            +
                    return (0, viem_1.getCreate2Address)({
         | 
| 68 | 
            +
                        from: this.proxyFactory.address,
         | 
| 69 | 
            +
                        salt,
         | 
| 70 | 
            +
                        bytecodeHash: (0, viem_1.keccak256)(initCode),
         | 
| 71 | 
            +
                    });
         | 
| 56 72 | 
             
                }
         | 
| 57 | 
            -
                 | 
| 58 | 
            -
                     | 
| 59 | 
            -
                         | 
| 60 | 
            -
                         | 
| 61 | 
            -
                         | 
| 62 | 
            -
             | 
| 63 | 
            -
                             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 73 | 
            +
                getSetup(owners) {
         | 
| 74 | 
            +
                    return (0, viem_1.encodeFunctionData)({
         | 
| 75 | 
            +
                        abi: this.singleton.abi,
         | 
| 76 | 
            +
                        functionName: "setup",
         | 
| 77 | 
            +
                        args: [
         | 
| 78 | 
            +
                            owners,
         | 
| 79 | 
            +
                            1, // We use sign threshold of 1.
         | 
| 80 | 
            +
                            this.moduleSetup.address,
         | 
| 81 | 
            +
                            (0, viem_1.encodeFunctionData)({
         | 
| 82 | 
            +
                                abi: this.moduleSetup.abi,
         | 
| 83 | 
            +
                                functionName: "enableModules",
         | 
| 84 | 
            +
                                args: [[this.m4337.address]],
         | 
| 85 | 
            +
                            }),
         | 
| 86 | 
            +
                            this.m4337.address,
         | 
| 87 | 
            +
                            viem_1.zeroAddress,
         | 
| 88 | 
            +
                            0,
         | 
| 89 | 
            +
                            viem_1.zeroAddress,
         | 
| 90 | 
            +
                        ],
         | 
| 91 | 
            +
                    });
         | 
| 92 | 
            +
                }
         | 
| 93 | 
            +
                addOwnerData(newOwner) {
         | 
| 94 | 
            +
                    return (0, viem_1.encodeFunctionData)({
         | 
| 95 | 
            +
                        abi: this.singleton.abi,
         | 
| 96 | 
            +
                        functionName: "addOwnerWithThreshold",
         | 
| 97 | 
            +
                        args: [newOwner, 1],
         | 
| 98 | 
            +
                    });
         | 
| 71 99 | 
             
                }
         | 
| 72 100 | 
             
                async getOpHash(unsignedUserOp) {
         | 
| 73 101 | 
             
                    const { factory, factoryData, verificationGasLimit, callGasLimit, maxPriorityFeePerGas, maxFeePerGas, } = unsignedUserOp;
         | 
| 74 | 
            -
                     | 
| 75 | 
            -
                         | 
| 76 | 
            -
                         | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 102 | 
            +
                    const opHash = await this.dummyClient.readContract({
         | 
| 103 | 
            +
                        address: this.m4337.address,
         | 
| 104 | 
            +
                        abi: this.m4337.abi,
         | 
| 105 | 
            +
                        functionName: "getOperationHash",
         | 
| 106 | 
            +
                        args: [
         | 
| 107 | 
            +
                            {
         | 
| 108 | 
            +
                                ...unsignedUserOp,
         | 
| 109 | 
            +
                                initCode: factory
         | 
| 110 | 
            +
                                    ? (0, viem_1.encodePacked)(["address", "bytes"], [factory, factoryData])
         | 
| 111 | 
            +
                                    : "0x",
         | 
| 112 | 
            +
                                accountGasLimits: (0, util_1.packGas)(verificationGasLimit, callGasLimit),
         | 
| 113 | 
            +
                                gasFees: (0, util_1.packGas)(maxPriorityFeePerGas, maxFeePerGas),
         | 
| 114 | 
            +
                                paymasterAndData: (0, util_1.packPaymasterData)(unsignedUserOp),
         | 
| 115 | 
            +
                                signature: util_1.PLACEHOLDER_SIG,
         | 
| 116 | 
            +
                            },
         | 
| 117 | 
            +
                        ],
         | 
| 83 118 | 
             
                    });
         | 
| 119 | 
            +
                    return opHash;
         | 
| 84 120 | 
             
                }
         | 
| 85 121 | 
             
                factoryDataForSetup(safeNotDeployed, setup, safeSaltNonce) {
         | 
| 86 122 | 
             
                    return safeNotDeployed
         | 
| 87 123 | 
             
                        ? {
         | 
| 88 | 
            -
                            factory: this.proxyFactory. | 
| 89 | 
            -
                            factoryData:  | 
| 124 | 
            +
                            factory: this.proxyFactory.address,
         | 
| 125 | 
            +
                            factoryData: (0, viem_1.encodeFunctionData)({
         | 
| 126 | 
            +
                                abi: this.proxyFactory.abi,
         | 
| 127 | 
            +
                                functionName: "createProxyWithNonce",
         | 
| 128 | 
            +
                                args: [this.singleton.address, setup, safeSaltNonce],
         | 
| 129 | 
            +
                            }),
         | 
| 90 130 | 
             
                        }
         | 
| 91 131 | 
             
                        : {};
         | 
| 92 132 | 
             
                }
         | 
| 93 | 
            -
                async buildUserOp(txData, safeAddress, feeData, setup, safeNotDeployed, safeSaltNonce) {
         | 
| 94 | 
            -
                     | 
| 133 | 
            +
                async buildUserOp(nonce, txData, safeAddress, feeData, setup, safeNotDeployed, safeSaltNonce) {
         | 
| 134 | 
            +
                    return {
         | 
| 95 135 | 
             
                        sender: safeAddress,
         | 
| 96 | 
            -
                        nonce:  | 
| 136 | 
            +
                        nonce: (0, viem_1.toHex)(nonce),
         | 
| 97 137 | 
             
                        ...this.factoryDataForSetup(safeNotDeployed, setup, safeSaltNonce),
         | 
| 98 138 | 
             
                        // <https://github.com/safe-global/safe-modules/blob/9a18245f546bf2a8ed9bdc2b04aae44f949ec7a0/modules/4337/contracts/Safe4337Module.sol#L172>
         | 
| 99 | 
            -
                        callData:  | 
| 100 | 
            -
                             | 
| 101 | 
            -
                             | 
| 102 | 
            -
                             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 139 | 
            +
                        callData: (0, viem_1.encodeFunctionData)({
         | 
| 140 | 
            +
                            abi: this.m4337.abi,
         | 
| 141 | 
            +
                            functionName: "executeUserOp",
         | 
| 142 | 
            +
                            args: [
         | 
| 143 | 
            +
                                txData.to,
         | 
| 144 | 
            +
                                BigInt(txData.value),
         | 
| 145 | 
            +
                                txData.data,
         | 
| 146 | 
            +
                                txData.operation || 0,
         | 
| 147 | 
            +
                            ],
         | 
| 148 | 
            +
                        }),
         | 
| 105 149 | 
             
                        ...feeData,
         | 
| 106 150 | 
             
                    };
         | 
| 107 | 
            -
             | 
| 151 | 
            +
                }
         | 
| 152 | 
            +
                async getNonce(address, chainId) {
         | 
| 153 | 
            +
                    const nonce = (await (0, util_1.getClient)(chainId).readContract({
         | 
| 154 | 
            +
                        abi: this.entryPoint.abi,
         | 
| 155 | 
            +
                        address: this.entryPoint.address,
         | 
| 156 | 
            +
                        functionName: "getNonce",
         | 
| 157 | 
            +
                        args: [address, 0],
         | 
| 158 | 
            +
                    }));
         | 
| 159 | 
            +
                    return nonce;
         | 
| 108 160 | 
             
                }
         | 
| 109 161 | 
             
            }
         | 
| 110 162 | 
             
            exports.ContractSuite = ContractSuite;
         | 
| 111 | 
            -
            async function getDeployment(fn, {  | 
| 112 | 
            -
                const { chainId } = await provider.getNetwork();
         | 
| 163 | 
            +
            async function getDeployment(fn, { version }) {
         | 
| 113 164 | 
             
                const deployment = fn({ version });
         | 
| 114 165 | 
             
                if (!deployment) {
         | 
| 115 | 
            -
                    throw new Error(`Deployment not found for ${fn.name} version ${version} | 
| 116 | 
            -
                }
         | 
| 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"];
         | 
| 166 | 
            +
                    throw new Error(`Deployment not found for ${fn.name} version ${version}`);
         | 
| 125 167 | 
             
                }
         | 
| 126 | 
            -
                 | 
| 168 | 
            +
                // TODO: maybe call parseAbi on deployment.abi here.
         | 
| 169 | 
            +
                return {
         | 
| 170 | 
            +
                    address: deployment.networkAddresses["11155111"],
         | 
| 171 | 
            +
                    abi: deployment.abi,
         | 
| 172 | 
            +
                };
         | 
| 127 173 | 
             
            }
         | 
    
        package/dist/cjs/tx-manager.d.ts
    CHANGED
    
    | @@ -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 {  | 
| 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,  | 
| 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 | 
            -
                     | 
| 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:  | 
| 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 | 
             
            }
         |