UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

200 lines (198 loc) • 6.41 kB
let effect = require("effect"); let node_crypto = require("node:crypto"); let execa = require("execa"); //#region src/near-cli.ts const INSTALLER_URL = `https://github.com/near/near-cli-rs/releases/download/v0.23.5/near-cli-rs-installer.sh`; const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; var NearCliNotFoundError = class extends effect.Data.TaggedError("NearCliNotFoundError") { get message() { return "NEAR CLI not found"; } }; var NearTransactionError = class extends effect.Data.TaggedError("NearTransactionError") { constructor(detail) { super({ detail }); } get message() { return this.detail; } }; function base64UrlToBytes(input) { const normalized = input.replace(/-/g, "+").replace(/_/g, "/"); return new Uint8Array(Buffer.from(normalized, "base64")); } function base58Encode(input) { if (input.length === 0) return ""; const digits = [0]; for (const byte of input) { let carry = byte; for (let i = 0; i < digits.length; i++) { carry += digits[i] << 8; digits[i] = carry % 58; carry = Math.floor(carry / 58); } while (carry > 0) { digits.push(carry % 58); carry = Math.floor(carry / 58); } } let output = ""; for (const byte of input) if (byte === 0) output += BASE58_ALPHABET[0]; else break; for (let i = digits.length - 1; i >= 0; i--) output += BASE58_ALPHABET[digits[i]]; return output; } function generateNearKeyPair() { const { publicKey, privateKey } = (0, node_crypto.generateKeyPairSync)("ed25519"); const publicJwk = publicKey.export({ format: "jwk" }); const privateJwk = privateKey.export({ format: "jwk" }); if (!publicJwk.x || !privateJwk.d) throw new Error("Failed to generate NEAR keypair"); const publicBytes = base64UrlToBytes(publicJwk.x); const privateSeed = base64UrlToBytes(privateJwk.d); const secretBytes = new Uint8Array(privateSeed.length + publicBytes.length); secretBytes.set(privateSeed, 0); secretBytes.set(publicBytes, privateSeed.length); return { publicKey: `ed25519:${base58Encode(publicBytes)}`, privateKey: `ed25519:${base58Encode(secretBytes)}` }; } async function isNearCliInstalled() { try { await (0, execa.execa)("near", ["--version"], { stdio: "pipe" }); return true; } catch { return false; } } function combineNearOutput(stdout, stderr) { return [stdout, stderr].filter((value) => value && value.trim().length > 0).join("\n"); } function extractTransactionHash(output) { return output.match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1]; } async function executeKeychainTransaction(config) { if (!process.stdin.isTTY) throw new NearTransactionError("No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally."); const gas = "300Tgas"; const deposit = "0NEAR"; const argsBase64 = Buffer.from(JSON.stringify(config.args)).toString("base64"); const args = [ "contract", "call-function", "as-transaction", config.contract, config.method, "base64-args", argsBase64, "prepaid-gas", gas, "attached-deposit", deposit, "sign-as", config.account, "network-config", config.network, "sign-with-keychain", "send" ]; const result = await (0, execa.execa)("near", args, { stdin: "inherit", stdout: "pipe", stderr: "pipe", reject: false, timeout: 3e5 }); const combined = combineNearOutput(result.stdout, result.stderr); const txHash = extractTransactionHash(combined); const hasCodeDoesNotExist = /CodeDoesNotExist/i.test(combined); if (result.exitCode === 0 || hasCodeDoesNotExist) return { success: true, txHash }; throw new NearTransactionError(combined || `Transaction failed with code ${result.exitCode}`); } async function runNearCommand(args) { if (!process.stdin.isTTY) throw new NearTransactionError("No TTY available for keychain signing. Set NEAR_PRIVATE_KEY environment variable to sign locally."); await (0, execa.execa)("near", args, { stdin: "inherit", stdout: "inherit", stderr: "inherit" }); } const ensureNearCli = effect.Effect.gen(function* () { if (yield* effect.Effect.promise(() => isNearCliInstalled())) return; yield* effect.Effect.log(""); yield* effect.Effect.log(" NEAR CLI not found"); yield* effect.Effect.log(""); yield* effect.Effect.log(` To install manually: curl --proto '=https' --tlsv1.2 -LsSf ${INSTALLER_URL} | sh`); yield* effect.Effect.log(""); return yield* new NearCliNotFoundError({}); }); async function listPublishKeys(config) { const listResult = await (0, execa.execa)("near", [ "account", "list-keys", config.account, "network-config", config.network, "now" ], { stdout: "pipe", stderr: "pipe", reject: false }); if (listResult.exitCode !== 0) throw new NearTransactionError(`Failed to list account keys: ${listResult.stderr || listResult.stdout || "unknown error"}`); const output = listResult.stdout ?? ""; const oldKeys = []; for (const line of output.split("\n")) if (line.includes(config.contract) && line.includes("__fastdata_kv")) { const match = line.match(/ed25519:[A-Za-z0-9]+/); if (match) oldKeys.push(match[0]); } return oldKeys; } async function deleteAccessKeys(account, publicKeys, network) { await runNearCommand([ "account", "delete-keys", account, "public-keys", publicKeys.join(","), "network-config", network, "sign-with-keychain", "send" ]); } async function addFunctionCallAccessKey(config) { const keyPair = config.keyPair ?? generateNearKeyPair(); await runNearCommand([ "account", "add-key", config.account, "grant-function-call-access", "--allowance", config.allowance, "--contract-account-id", config.contract, "--function-names", config.functionNames.join(", "), "use-manually-provided-public-key", keyPair.publicKey, "network-config", config.network || (config.account.endsWith(".testnet") ? "testnet" : "mainnet"), "sign-with-keychain", "send" ]); return keyPair; } //#endregion exports.NearCliNotFoundError = NearCliNotFoundError; exports.NearTransactionError = NearTransactionError; exports.addFunctionCallAccessKey = addFunctionCallAccessKey; exports.deleteAccessKeys = deleteAccessKeys; exports.ensureNearCli = ensureNearCli; exports.executeKeychainTransaction = executeKeychainTransaction; exports.generateNearKeyPair = generateNearKeyPair; exports.isNearCliInstalled = isNearCliInstalled; exports.listPublishKeys = listPublishKeys; //# sourceMappingURL=near-cli.cjs.map