UNPKG

near-ca

Version:

An SDK for controlling Ethereum Accounts from a Near Account.

127 lines (126 loc) 4.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MpcContract = void 0; const near_api_js_1 = require("near-api-js"); const utils_1 = require("./utils"); const chains_1 = require("./chains"); /** * High-level interface for the Near MPC-Recovery Contract * located in: https://github.com/near/mpc-recovery */ class MpcContract { /** * Creates a new MPC Contract instance * * @param account - The NEAR account to use * @param contractId - The contract ID * @param rootPublicKey - Optional root public key */ constructor(account, contractId, rootPublicKey) { /** * Derives an Ethereum address from a derivation path * * @param derivationPath - The path to derive the address from * @returns The derived Ethereum address */ this.deriveEthAddress = async (derivationPath) => { if (!this.rootPublicKey) { this.rootPublicKey = await this.contract.public_key(); } const publicKey = (0, utils_1.deriveChildPublicKey)((0, utils_1.najPublicKeyStrToUncompressedHexPoint)(this.rootPublicKey), this.connectedAccount.accountId, derivationPath); return (0, utils_1.uncompressedHexPointToEvmAddress)(publicKey); }; /** * Gets the required deposit for the signature * * @returns The required deposit amount as a string */ this.getDeposit = async () => { try { const deposit = await this.contract.experimental_signature_deposit(); return BigInt(deposit.toLocaleString("fullwide", { useGrouping: false })).toString(); } catch { // They are phasing out experimental_signature_deposit. // required deposit is 1 yocto (see v1.signer-prod.testnet). return "1"; } }; /** * Requests a signature from the MPC contract * * @param signArgs - The arguments for the signature request * @param gas - Optional gas limit * @returns The signature */ this.requestSignature = async (signArgs, gas) => { const transaction = await this.encodeSignatureRequestTx(signArgs, gas); const outcome = await this.signAndSendSignRequest(transaction); return (0, utils_1.signatureFromOutcome)(outcome); }; this.connectedAccount = account; this.rootPublicKey = rootPublicKey; this.contract = new near_api_js_1.Contract(account.getConnection(), contractId, { changeMethods: ["sign"], viewMethods: ["public_key", "experimental_signature_deposit"], useLocalViewExecution: false, }); } /** * Gets the contract ID * * @returns The contract ID */ accountId() { return this.contract.contractId; } /** * Encodes a signature request into a transaction * * @param signArgs - The arguments for the signature request * @param gas - Optional gas limit * @returns The encoded transaction */ async encodeSignatureRequestTx(signArgs, gas) { return { signerId: this.connectedAccount.accountId, receiverId: this.contract.contractId, actions: [ { type: "FunctionCall", params: { methodName: "sign", args: { request: signArgs }, gas: gasOrDefault(gas), deposit: await this.getDeposit(), }, }, ], }; } /** * Signs and sends a signature request * * @param transaction - The transaction to sign and send * @param blockTimeout - Optional timeout in blocks * @returns The execution outcome */ async signAndSendSignRequest(transaction) { const account = this.connectedAccount; const signedTx = await account.createSignedTransaction(this.contract.contractId, transaction.actions.map(({ params: { args, gas, deposit } }) => near_api_js_1.transactions.functionCall("sign", args, BigInt(gas), BigInt(deposit)))); return account.provider.sendTransactionUntil(signedTx, "EXECUTED"); } } exports.MpcContract = MpcContract; /** * Returns the gas value or a default if not provided * * @param gas - Optional gas value * @returns The gas value as a string */ function gasOrDefault(gas) { if (gas !== undefined) { return gas.toString(); } return (chains_1.TGAS * 250n).toString(); }