UNPKG

@silvana-one/mina-utils

Version:
1,384 lines (1,357 loc) 1.91 MB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // dist/node/index.js var index_exports = {}; __export(index_exports, { BLS_FR: () => BLS_FR, Devnet: () => Devnet, Fr: () => Fr, Lightnet: () => Lightnet, Local: () => Local, Mainnet: () => Mainnet, Memory: () => Memory, R: () => R, S: () => S, TABLE0: () => TABLE0, TABLE0_ROOT: () => TABLE0_ROOT, TABLE1: () => TABLE1, TABLE1_ROOT: () => TABLE1_ROOT, TABLE2: () => TABLE22, TABLE2_ROOT: () => TABLE2_ROOT, TinyContract: () => TinyContract, WITNESSES0: () => WITNESSES0, WITNESSES1: () => WITNESSES1, WITNESSES2: () => WITNESSES2, Witness: () => Witness, Zeko: () => Zeko, ZekoAlphaNet: () => ZekoAlphaNet, accountBalance: () => accountBalance, accountBalanceMina: () => accountBalanceMina, accountExists: () => accountExists, bigintFromBase56: () => bigintFromBase56, bigintFromBase64: () => bigintFromBase64, bigintToBase56: () => bigintToBase56, bigintToBase64: () => bigintToBase64, blsCommitment: () => blsCommitment, checkAddress: () => checkAddress, checkMinaZkappTransaction: () => checkMinaZkappTransaction, commit: () => commit, createIpfsURL: () => createIpfsURL, createMerkleTree: () => createMerkleTree, createTransactionPayloads: () => createTransactionPayloads, currentNetwork: () => currentNetwork, deserializeFields: () => deserializeFields, deserializeIndexedMerkleMap: () => deserializeIndexedMerkleMap, digestStruct: () => digestStruct, fee: () => fee, fetchMinaAccount: () => fetchMinaAccount, fetchMinaActions: () => fetchMinaActions, fieldFromBase56: () => fieldFromBase56, fieldFromBase64: () => fieldFromBase64, fieldToBase56: () => fieldToBase56, fieldToBase64: () => fieldToBase64, formatTime: () => formatTime, fromBase: () => fromBase, getAccountNonce: () => getAccountNonce, getCurrentNetwork: () => getCurrentNetwork, getDeployer: () => getDeployer, getNetworkIdHash: () => getNetworkIdHash, getNonce: () => getNonce, getPaymentTxsFromBlockBerry: () => getPaymentTxsFromBlockBerry, getR: () => getR, getTable0Entry: () => getTable0Entry, getTable1Entry: () => getTable1Entry, getTable2Entry: () => getTable2Entry, getTxStatusFast: () => getTxStatusFast, getZkAppFromBlockBerry: () => getZkAppFromBlockBerry, getZkAppTxFromBlockBerry: () => getZkAppTxFromBlockBerry, getZkAppTxsFromBlockBerry: () => getZkAppTxsFromBlockBerry, initBlockchain: () => initBlockchain, loadIndexedMerkleMap: () => loadIndexedMerkleMap, makeString: () => makeString, networks: () => networks, parseIndexedMapSerialized: () => parseIndexedMapSerialized, parseTransactionPayloads: () => parseTransactionPayloads, pinJSON: () => pinJSON, rScalarPow: () => rScalarPow, rScalarPowLegacy: () => rScalarPowLegacy, rScalarPowProvable: () => rScalarPowProvable, saveIndexedMerkleMap: () => saveIndexedMerkleMap, scalar: () => scalar, sendTx: () => sendTx, serializeFields: () => serializeFields, serializeIndexedMap: () => serializeIndexedMap, serializeTransaction: () => serializeTransaction, sleep: () => sleep, toBase: () => toBase, tokenBalance: () => tokenBalance, transactionParams: () => transactionParams, txStatusBlockberry: () => txStatusBlockberry, update: () => update }); module.exports = __toCommonJS(index_exports); // dist/node/utils/base64-field.js var import_o1js = require("o1js"); // dist/node/utils/base64.js var TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; function bigintToBase56(value) { const digits = toBase(value, 56n); const str = digits.map((x) => TABLE[Number(x)]).join(""); return str; } function bigintFromBase56(str) { const base56Digits = str.split("").map((x2) => BigInt(TABLE.indexOf(x2))); const x = fromBase(base56Digits, 56n); return x; } function bigintToBase64(value) { const digits = toBase(value, 64n); const str = digits.map((x) => TABLE[Number(x)]).join(""); return str; } function bigintFromBase64(str) { const base64Digits = str.split("").map((x2) => BigInt(TABLE.indexOf(x2))); const x = fromBase(base64Digits, 64n); return x; } function fromBase(digits, base) { if (base <= 0n) throw Error("fromBase: base must be positive"); let basePowers = []; for (let power = base, n = 1; n < digits.length; power **= 2n, n *= 2) { basePowers.push(power); } let k = basePowers.length; digits = digits.concat(Array(2 ** k - digits.length).fill(0n)); for (let i = 0; i < k; i++) { let newDigits = Array(digits.length >> 1); let basePower = basePowers[i]; for (let j = 0; j < newDigits.length; j++) { newDigits[j] = digits[2 * j] + basePower * digits[2 * j + 1]; } digits = newDigits; } console.assert(digits.length === 1); let [digit] = digits; return digit; } function toBase(x, base) { if (base <= 0n) throw Error("toBase: base must be positive"); let basePowers = []; for (let power = base; power <= x; power **= 2n) { basePowers.push(power); } let digits = [x]; let k = basePowers.length; for (let i = 0; i < k; i++) { let newDigits = Array(2 * digits.length); let basePower = basePowers[k - 1 - i]; for (let j = 0; j < digits.length; j++) { let x2 = digits[j]; let high = x2 / basePower; newDigits[2 * j + 1] = high; newDigits[2 * j] = x2 - high * basePower; } digits = newDigits; } while (digits[digits.length - 1] === 0n) { digits.pop(); } return digits; } // dist/node/utils/base64-field.js var TABLE2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; function fieldToBase56(field) { const digits = toBase(field.toBigInt(), 56n); const str = digits.map((x) => TABLE2[Number(x)]).join(""); return str; } function fieldFromBase56(str) { const base56Digits = str.split("").map((x2) => BigInt(TABLE2.indexOf(x2))); const x = fromBase(base56Digits, 56n); return (0, import_o1js.Field)(x); } function fieldToBase64(field) { const digits = toBase(field.toBigInt(), 64n); const str = digits.map((x) => TABLE2[Number(x)]).join(""); return str; } function fieldFromBase64(str) { const base64Digits = str.split("").map((x2) => BigInt(TABLE2.indexOf(x2))); const x = fromBase(base64Digits, 64n); return (0, import_o1js.Field)(x); } // dist/node/utils/fetch.js var import_o1js2 = require("o1js"); // dist/node/utils/utils.js function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } function makeString(length) { let outString = ``; const inOptions = `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`; for (let i = 0; i < length; i++) { outString += inOptions.charAt(Math.floor(Math.random() * inOptions.length)); } return outString; } function formatTime(ms) { if (ms === void 0) return ""; if (ms < 1e3) return ms.toString() + " ms"; if (ms < 60 * 1e3) return parseInt((ms / 1e3).toString()).toString() + " sec"; if (ms < 60 * 60 * 1e3) { const minutes = parseInt((ms / 1e3 / 60).toString()); const seconds = parseInt(((ms - minutes * 60 * 1e3) / 1e3).toString()); return minutes.toString() + " min " + seconds.toString() + " sec"; } else { const hours = parseInt((ms / 1e3 / 60 / 60).toString()); const minutes = parseInt(((ms - hours * 60 * 60 * 1e3) / 1e3 / 60).toString()); return hours.toString() + " h " + minutes.toString() + " min"; } } var _Memory = class _Memory { constructor() { _Memory.rss = 0; } // eslint-disable-next-line @typescript-eslint/no-inferrable-types static info(description = ``, fullInfo = false) { const memoryData = process.memoryUsage(); const formatMemoryUsage = (data) => `${Math.round(data / 1024 / 1024)} MB`; const oldRSS = _Memory.rss; _Memory.rss = Math.round(memoryData.rss / 1024 / 1024); const memoryUsage = fullInfo ? { step: `${description}:`, rssDelta: `${(oldRSS === 0 ? 0 : _Memory.rss - oldRSS).toString()} MB -> Resident Set Size memory change`, rss: `${formatMemoryUsage(memoryData.rss)} -> Resident Set Size - total memory allocated`, heapTotal: `${formatMemoryUsage(memoryData.heapTotal)} -> total size of the allocated heap`, heapUsed: `${formatMemoryUsage(memoryData.heapUsed)} -> actual memory used during the execution`, external: `${formatMemoryUsage(memoryData.external)} -> V8 external memory` } : `RSS memory ${description}: ${formatMemoryUsage(memoryData.rss)}${oldRSS === 0 ? `` : `, changed by ` + (_Memory.rss - oldRSS).toString() + ` MB`}`; console.log(memoryUsage); } }; _Memory.rss = 0; var Memory = _Memory; // dist/node/utils/fetch.js async function fetchMinaAccount(params) { const { publicKey, tokenId, force = false } = params; const timeout = 1e3 * 60 * 3; let attempt = 0; const startTime = Date.now(); let result = { account: void 0 }; while (Date.now() - startTime < timeout) { try { const result2 = await (0, import_o1js2.fetchAccount)({ publicKey, tokenId }, void 0, { timeout: 5 * 1e3 }); return result2; } catch (error) { if (force === true) console.log("Error in fetchMinaAccount:", { error, publicKey: typeof publicKey === "string" ? publicKey : publicKey.toBase58(), tokenId: tokenId?.toString(), force }); else { console.log("fetchMinaAccount error", { error, publicKey: typeof publicKey === "string" ? publicKey : publicKey.toBase58(), tokenId: tokenId?.toString(), force }); return result; } } attempt++; await sleep(1e3 * 6 * attempt); } if (force === true) throw new Error(`fetchMinaAccount timeout ${{ publicKey: typeof publicKey === "string" ? publicKey : publicKey.toBase58(), tokenId: tokenId?.toString(), force }}`); else console.log("fetchMinaAccount timeout", typeof publicKey === "string" ? publicKey : publicKey.toBase58(), tokenId?.toString(), force); return result; } async function fetchMinaActions(publicKey, fromActionState, endActionState) { const timeout = 1e3 * 60 * 600; const startTime = Date.now(); while (Date.now() - startTime < timeout) { try { let actions = await import_o1js2.Mina.fetchActions(publicKey, { fromActionState, endActionState }); if (Array.isArray(actions)) return actions; else console.log("Cannot fetch actions - wrong format"); } catch (error) { console.log("Error in fetchMinaActions", error.toString().substring(0, 300)); } await sleep(1e3 * 60 * 2); } console.log("Timeout in fetchMinaActions"); return void 0; } async function checkMinaZkappTransaction(hash) { try { const result = await (0, import_o1js2.checkZkappTransaction)(hash); return result; } catch (error) { console.error("Error in checkZkappTransaction:", error); return { success: false }; } } // dist/node/utils/fields.js var import_o1js3 = require("o1js"); function serializeFields(fields) { const hash = import_o1js3.Poseidon.hash(fields); const value = [(0, import_o1js3.Field)(fields.length), hash, ...fields]; return value.map((f) => fieldToBase64(f)).join("."); } function deserializeFields(s) { try { const value = s.split(".").map((n) => fieldFromBase64(n)); const length = value[0]; if ((0, import_o1js3.Field)(value.length - 2).equals(length).toBoolean() === false) throw new Error("deserializeFields: invalid length"); const hash = import_o1js3.Poseidon.hash(value.slice(2)); if (hash.equals(value[1]).toBoolean()) { return value.slice(2); } else throw new Error("deserializeFields: invalid hash: data mismatch"); } catch (e) { throw new Error(`deserializeFields: invalid string: ${s}: ${e}`); } } // dist/node/utils/fee.js var import_o1js4 = require("o1js"); // dist/node/config.js var config = { MINAFEE: "200000000" }; var config_default = config; // dist/node/utils/fee.js async function fee() { return import_o1js4.UInt64.fromJSON(config_default.MINAFEE); } // dist/node/utils/mina.js var import_o1js5 = require("o1js"); // dist/node/networks.js var Mainnet = { mina: [ //"https://proxy.devnet.minaexplorer.com/graphql", "https://api.minascan.io/node/mainnet/v1/graphql" ], archive: [ "https://api.minascan.io/archive/mainnet/v1/graphql" //"https://archive.devnet.minaexplorer.com", ], explorerAccountUrl: "https://minascan.io/mainnet/account/", explorerTransactionUrl: "https://minascan.io/mainnet/tx/", chainId: "mainnet", name: "Mainnet" }; var Local = { mina: [], archive: [], chainId: "local" }; var Devnet = { mina: [ "https://api.minascan.io/node/devnet/v1/graphql" //"https://proxy.devnet.minaexplorer.com/graphql", ], archive: [ "https://api.minascan.io/archive/devnet/v1/graphql" //"https://archive.devnet.minaexplorer.com", ], explorerAccountUrl: "https://minascan.io/devnet/account/", explorerTransactionUrl: "https://minascan.io/devnet/tx/", chainId: "devnet", name: "Devnet", faucet: "https://faucet.minaprotocol.com" }; var Zeko = { mina: ["https://devnet.zeko.io/graphql"], archive: ["https://devnet.zeko.io/graphql"], explorerAccountUrl: "https://zekoscan.io/devnet/account/", explorerTransactionUrl: "https://zekoscan.io/devnet/tx/", chainId: "zeko", name: "Zeko", faucet: "https://zeko.io/faucet" }; var ZekoAlphaNet = { mina: ["http://m1.zeko.io/graphql"], archive: ["http://m1.zeko.io/graphql"], explorerAccountUrl: "", explorerTransactionUrl: "", chainId: "zeko:alphanet", name: "Zeko AlphaNet", faucet: "" }; var Lightnet = { mina: ["http://localhost:8080/graphql"], archive: ["http://localhost:8282"], accountManager: "http://localhost:8181", chainId: "lightnet", name: "Lightnet" }; var networks = [Mainnet, Local, Devnet, Zeko, Lightnet]; // dist/node/utils/mina.js var currentNetwork = void 0; function getNetworkIdHash() { if (currentNetwork === void 0) { throw new Error("Network is not initialized"); } return currentNetwork.networkIdHash; } function getCurrentNetwork() { if (currentNetwork === void 0) { throw new Error("Network is not initialized"); } return currentNetwork; } function getDeployer() { if (currentNetwork === void 0) { throw new Error("Network is not initialized"); } if (currentNetwork.keys.length < 1) return void 0; return currentNetwork.keys[0]; } async function initBlockchain(instance, deployersNumber = 0, proofsEnabled = true, customMinaNodeUrl = void 0, customMinaArchiveNodeUrl = void 0) { if (currentNetwork !== void 0) { if (currentNetwork?.network.chainId === instance) { return currentNetwork; } else { throw new Error(`Network is already initialized to different chain ${currentNetwork.network.chainId}, cannot initialize to ${instance}`); } } const networkIdHash = import_o1js5.CircuitString.fromString(instance).hash(); if (instance === "local") { const local = await import_o1js5.Mina.LocalBlockchain({ proofsEnabled }); import_o1js5.Mina.setActiveInstance(local); if (deployersNumber > local.testAccounts.length) throw new Error("Not enough test accounts"); currentNetwork = { keys: local.testAccounts, network: Local, networkIdHash }; return currentNetwork; } const network = networks.find((n) => n.chainId === instance); if (network === void 0) { throw new Error("Unknown network"); } const networkInstance = import_o1js5.Mina.Network({ mina: process.env.MINA_NODE_URL ?? process.env.NEXT_PUBLIC_MINA_NODE_URL ?? customMinaNodeUrl ?? network.mina, archive: process.env.MINA_ARCHIVE_NODE_URL ?? process.env.NEXT_PUBLIC_MINA_ARCHIVE_NODE_URL ?? customMinaArchiveNodeUrl ?? network.archive, lightnetAccountManager: network.accountManager, networkId: instance === "mainnet" ? "mainnet" : "testnet", bypassTransactionLimits: instance === "zeko" }); import_o1js5.Mina.setActiveInstance(networkInstance); const keys = []; if (deployersNumber > 0) { if (instance === "lightnet") { for (let i = 0; i < deployersNumber; i++) { const keyPair = await import_o1js5.Lightnet.acquireKeyPair(); const key = import_o1js5.Mina.TestPublicKey(keyPair.privateKey); keys.push(key); } } else { const deployers = process.env.DEPLOYERS; if (deployers === void 0 || Array.isArray(deployers) === false || deployers.length < deployersNumber) throw new Error("Deployers are not set"); for (let i = 0; i < deployersNumber; i++) { const privateKey = import_o1js5.PrivateKey.fromBase58(deployers[i]); const key = import_o1js5.Mina.TestPublicKey(privateKey); keys.push(key); } } } currentNetwork = { keys, network, networkIdHash }; return currentNetwork; } async function accountBalance(address) { await (0, import_o1js5.fetchAccount)({ publicKey: address }); if (import_o1js5.Mina.hasAccount(address)) return import_o1js5.Mina.getBalance(address); else return import_o1js5.UInt64.from(0); } async function accountBalanceMina(address) { return Number((await accountBalance(address)).toBigInt()) / 1e9; } // dist/node/utils/indexed-map.js var import_o1js6 = require("o1js"); // dist/node/storage/pinata.js async function pinJSON(params) { const { data, name = "data.json", keyvalues = { library: "zkcloudworker" } } = params; const auth = params.auth ?? process.env.PINATA_JWT ?? process.env.NEXT_PUBLIC_PINATA_JWT ?? process.env.REACT_APP_PINATA_JWT; if (!auth) throw new Error("pinJSON: auth, PINATA_JWT, NEXT_PUBLIC_PINATA_JWT or REACT_APP_PINATA_JWT should be defined"); try { const pinataData = { pinataOptions: { cidVersion: 1 }, pinataMetadata: { name, keyvalues }, pinataContent: data }; const res = await fetch("https://api.pinata.cloud/pinning/pinJSONToIPFS", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer " + auth }, body: JSON.stringify(pinataData) }); if (!res.ok) { throw new Error(`Pinata error: status: ${res.status} ${res.statusText}`); } const responseData = await res.json(); console.log("saveToIPFS result:", responseData); return responseData?.IpfsHash; } catch (error) { console.error("saveToIPFS error:", error?.message); return void 0; } } // dist/node/utils/indexed-map.js var { IndexedMerkleMap } = import_o1js6.Experimental; async function loadIndexedMerkleMap(params) { const { url, type, timeout = 6e4, attempts = 5 } = params; let attempt = 0; const start = Date.now(); let response = await fetch(url); while (!response.ok && attempt < attempts && Date.now() - start < timeout) { attempt++; await sleep(5e3 * attempt); response = await fetch(url); } if (!response.ok) { throw new Error("Failed to fetch IndexedMerkleMap"); } const json = await response.json(); const serializedIndexedMap = json.map; if (!serializedIndexedMap) throw new Error("wrong IndexedMerkleMap json format"); const map = deserializeIndexedMerkleMapInternal({ serializedIndexedMap, type }); if (!map) { throw new Error("Failed to deserialize whitelist"); } return map; } async function saveIndexedMerkleMap(params) { const { map, name = "indexed-map", keyvalues, auth } = params; const serialized = serializeIndexedMap(map); const ipfsHash = await pinJSON({ data: { map: serialized }, name, keyvalues, auth }); return ipfsHash; } function serializeIndexedMap(map) { return { height: map.height, root: map.root.toJSON(), length: map.length.toJSON(), nodes: JSON.stringify(map.data.get().nodes, (_, v) => typeof v === "bigint" ? "n" + bigintToBase64(v) : v), sortedLeaves: JSON.stringify(map.data.get().sortedLeaves.map((v) => [ bigintToBase64(v.key), bigintToBase64(v.nextKey), bigintToBase64(v.value), bigintToBase64(BigInt(v.index)) ])) }; } function deserializeIndexedMerkleMap(params) { try { const { serializedIndexedMap, type } = params; return deserializeIndexedMerkleMapInternal({ serializedIndexedMap, type: type ?? IndexedMerkleMap(serializedIndexedMap.height) }); } catch (error) { console.error("Error deserializing map:", error?.message ?? error); return void 0; } } function parseIndexedMapSerialized(serializedMap) { const json = JSON.parse(serializedMap); if (json.height === void 0 || json.root === void 0 || json.length === void 0 || json.nodes === void 0 || json.sortedLeaves === void 0) throw new Error("wrong IndexedMerkleMap json format"); if (typeof json.height !== "number") throw new Error("wrong IndexedMerkleMap height format"); if (typeof json.root !== "string") throw new Error("wrong IndexedMerkleMap root format"); if (typeof json.length !== "string") throw new Error("wrong IndexedMerkleMap length format"); if (typeof json.nodes !== "string") throw new Error("wrong IndexedMerkleMap nodes format"); if (typeof json.sortedLeaves !== "string") throw new Error("wrong IndexedMerkleMap sortedLeaves format"); return json; } function deserializeIndexedMerkleMapInternal(params) { const { serializedIndexedMap, type } = params; const map = new type(); if (serializedIndexedMap.height !== map.height) { throw new Error("wrong IndexedMap height"); } const nodes = JSON.parse(serializedIndexedMap.nodes, (_, v) => { if (typeof v === "string" && v[0] === "n") { return bigintFromBase64(v.slice(1)); } return v; }); const sortedLeaves = JSON.parse(serializedIndexedMap.sortedLeaves).map((row) => { return { key: bigintFromBase64(row[0]), nextKey: bigintFromBase64(row[1]), value: bigintFromBase64(row[2]), index: Number(bigintFromBase64(row[3])) }; }); map.root = import_o1js6.Field.fromJSON(serializedIndexedMap.root); map.length = import_o1js6.Field.fromJSON(serializedIndexedMap.length); map.data.updateAsProver(() => { return { nodes: nodes.map((row) => [...row]), sortedLeaves: [...sortedLeaves] }; }); return map; } // dist/node/storage/ipfs.js function createIpfsURL(params) { let { hash, gateway, apiToken } = params; gateway ??= process.env.PINATA_IPFS_GATEWAY ?? process.env.NEXT_PUBLIC_PINATA_IPFS_GATEWAY ?? process.env.REACT_APP_PINATA_IPFS_GATEWAY; apiToken ??= process.env.PINATA_GATEWAY_TOKEN ?? process.env.NEXT_PUBLIC_PINATA_GATEWAY_TOKEN ?? process.env.REACT_APP_PINATA_GATEWAY_TOKEN; if (!gateway) { gateway = "https://gateway.pinata.cloud/ipfs/"; } return gateway + hash + (apiToken ? "?pinataGatewayToken=" + apiToken : ""); } // dist/node/transactions/blockberry.js var TIMEOUT = 1e4; async function getZkAppTxsFromBlockBerry(params) { const { account, chain, blockBerryApiKey } = params; const options = { method: "GET", headers: { accept: "application/json", "x-api-key": blockBerryApiKey } }; try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), TIMEOUT); const response = await fetch(`https://api.blockberry.one/mina-${chain}/v1/zkapps/accounts/${account}/txs?size=10&orderBy=DESC&sortBy=AGE`, { ...options, signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { console.error("Cannot fetch zkApp txs for account:", account, chain, response.statusText); return void 0; } const result = await response.json(); return result; } catch (err) { console.error("Cannot fetch zkApp txs for account - catch:", account, chain, err); return void 0; } } async function getPaymentTxsFromBlockBerry(params) { const { account, chain, blockBerryApiKey } = params; const options = { method: "GET", headers: { accept: "application/json", "x-api-key": blockBerryApiKey } }; try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), TIMEOUT); const response = await fetch(`https://api.blockberry.one/mina-${chain}/v1/accounts/` + account + "/txs?page=0&size=1&orderBy=DESC&sortBy=AGE&direction=OUT", { ...options, signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { console.error("Cannot fetch payment txs for account:", account, chain, response.statusText); return void 0; } const result = await response.json(); return result; } catch (err) { console.error("Cannot fetch payment txs for account - catch:", account, chain, err); return void 0; } } async function getZkAppTxFromBlockBerry(params) { const { hash, chain, blockBerryApiKey } = params; const options = { method: "GET", headers: { accept: "application/json", "x-api-key": blockBerryApiKey } }; try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), TIMEOUT); const response = await fetch(`https://api.blockberry.one/mina-${chain}/v1/zkapps/txs/${hash}`, { ...options, signal: controller.signal }); clearTimeout(timeoutId); if (response.ok) { const result = await response.json(); return result; } else { console.error("getZkAppTxFromBlockBerry error while getting hash - not ok", { hash, chain, text: response.statusText, status: response.status }); return void 0; } } catch (err) { console.error("getZkAppTxFromBlockBerry error while getting mainnet hash - catch", hash, chain, err); return void 0; } } async function getZkAppFromBlockBerry(params) { const { account, chain, blockBerryApiKey } = params; const options = { method: "GET", headers: { accept: "application/json", "x-api-key": blockBerryApiKey } }; try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), TIMEOUT); const response = await fetch(`https://api.blockberry.one/mina-${chain}/v1/zkapps/${account}`, { ...options, signal: controller.signal }); clearTimeout(timeoutId); if (response.ok) { const result = await response.json(); return result; } else { console.error("getZkAppFromBlockBerry error while getting account", { account, chain, text: response.statusText, status: response.status }); return void 0; } } catch (err) { console.error("getZkAppFromBlockBerry error while getting account - catch", account, chain, err); return void 0; } } // dist/node/transactions/nonce.js var import_o1js7 = require("o1js"); async function getNonce(params) { const { account, chain, blockBerryApiKey } = params; try { if (account === void 0 || account === null || account === "") { return { success: false, nonce: -1, message: "Account is required" }; } if (blockBerryApiKey === void 0 || blockBerryApiKey === null || blockBerryApiKey === "") { return { success: false, nonce: -1, message: "blockBerryApiKey is required" }; } const zkAppTxsPromise = getZkAppTxsFromBlockBerry({ account, chain, blockBerryApiKey }); const paymentTxs = getPaymentTxsFromBlockBerry({ account, chain, blockBerryApiKey }); const paymentNonce = (await paymentTxs)?.data[0]?.nonce ?? -1; let zkNonce = -1; let found = false; const zkAppTxs = await zkAppTxsPromise; const size = zkAppTxs?.data?.length ?? 0; let i = 0; while (!found && i < size) { if (zkAppTxs?.data[i]?.proverAddress === account) { zkNonce = zkAppTxs?.data[i]?.nonce; found = true; } i++; } const nonce = Math.max(zkNonce, paymentNonce); return { success: true, nonce }; } catch (error) { return { success: false, nonce: -1, message: String(error) }; } } async function getAccountNonce(params) { const { account, chain = getCurrentNetwork().network.chainId, blockBerryApiKey, verbose = true } = params; const canUseBlockBerry = blockBerryApiKey !== void 0 && (chain === "devnet" || chain === "mainnet"); if (chain === "zeko") { const publicKey = import_o1js7.PublicKey.fromBase58(account); await fetchMinaAccount({ publicKey }); const nonce = Number(import_o1js7.Mina.getAccount(publicKey).nonce.toBigint()); return nonce; } else { const blockberryNoncePromise = canUseBlockBerry ? getNonce({ account, blockBerryApiKey, chain }) : void 0; const publicKey = import_o1js7.PublicKey.fromBase58(account); await fetchMinaAccount({ publicKey }); const senderNonce = Number(import_o1js7.Mina.getAccount(publicKey).nonce.toBigint()); const blockberryNonce = blockberryNoncePromise ? (await blockberryNoncePromise).nonce ?? -1 : -1; const nonce = Math.max(senderNonce, blockberryNonce + 1); if (verbose && nonce > senderNonce) console.log(`Nonce changed from ${senderNonce} to ${nonce} for ${account}`); return nonce; } } // dist/node/transactions/transaction.js var import_o1js8 = require("o1js"); function createTransactionPayloads(tx) { const transaction = tx.toJSON(); const txJSON = JSON.parse(transaction); const signedData = JSON.stringify({ zkappCommand: txJSON }); const proverPayload = serializeTransaction(tx); const fee2 = tx.transaction.feePayer.body.fee.toJSON(); const sender = tx.transaction.feePayer.body.publicKey.toBase58(); const nonce = Number(tx.transaction.feePayer.body.nonce.toBigint()); const memo = tx.transaction.memo; const minaSignerPayload = { zkappCommand: txJSON, feePayer: { feePayer: sender, fee: fee2, nonce, memo } }; const walletPayload = { transaction, nonce, onlySign: true, feePayer: { fee: fee2, memo } }; return { sender, nonce, memo, fee: fee2, walletPayload, minaSignerPayload, proverPayload, signedData, transaction }; } function transactionParams(params) { const { proverPayload, signedData } = params; const signedJson = JSON.parse(signedData); const { sender, tx } = JSON.parse(proverPayload); const transaction = import_o1js8.Mina.Transaction.fromJSON(JSON.parse(tx)); const memo = transaction.transaction.memo; return { fee: import_o1js8.UInt64.from(signedJson.zkappCommand.feePayer.body.fee), sender: import_o1js8.PublicKey.fromBase58(sender), nonce: Number(signedJson.zkappCommand.feePayer.body.nonce), memo }; } function parseTransactionPayloads(params) { const { txNew } = params; const proverPayload = "payloads" in params ? params.payloads.proverPayload : params.proverPayload; const signedData = "payloads" in params ? params.payloads.signedData : params.signedData; const signedJson = JSON.parse(signedData); const { tx, blindingValues, length, forestJSONs } = JSON.parse(proverPayload); const transaction = import_o1js8.Mina.Transaction.fromJSON(JSON.parse(tx)); const forests = forestJSONs.map((f) => JSON.parse(f)); if (length !== txNew.transaction.accountUpdates.length) { throw new Error(`New Transaction length mismatch: ${length} !== ${txNew.transaction.accountUpdates.length}`); } if (length !== transaction.transaction.accountUpdates.length) { throw new Error(`Serialized Transaction length mismatch: ${length} !== ${transaction.transaction.accountUpdates.length}`); } for (let i = 0; i < length; i++) { transaction.transaction.accountUpdates[i].lazyAuthorization = txNew.transaction.accountUpdates[i].lazyAuthorization; if (blindingValues[i] !== "") { if (transaction.transaction.accountUpdates[i].lazyAuthorization === void 0 || transaction.transaction.accountUpdates[i].lazyAuthorization.blindingValue === void 0) { throw new Error(`Lazy authorization blinding value is undefined for item ${i}`); } transaction.transaction.accountUpdates[i].lazyAuthorization.blindingValue = import_o1js8.Field.fromJSON(blindingValues[i]); } if (forests[i].length > 0) { if (transaction.transaction.accountUpdates[i].lazyAuthorization === void 0 || transaction.transaction.accountUpdates[i].lazyAuthorization.args === void 0) { throw new Error(`Lazy authorization args is undefined for item ${i}`); } deserializeLazyAuthorization(transaction.transaction.accountUpdates[i].lazyAuthorization.args, forests[i]); if (forests[i].restoredItems !== forests[i].length) { throw new Error(`Forest ${i} not fully restored`); } } } transaction.transaction.feePayer.authorization = signedJson.zkappCommand.feePayer.authorization; transaction.transaction.feePayer.body.fee = import_o1js8.UInt64.from(signedJson.zkappCommand.feePayer.body.fee); for (let i = 0; i < length; i++) { const signature = signedJson.zkappCommand.accountUpdates[i].authorization.signature; if (signature !== void 0 && signature !== null) { transaction.transaction.accountUpdates[i].authorization.signature = signedJson.zkappCommand.accountUpdates[i].authorization.signature; } } return transaction; } function serializeTransaction(tx) { const length = tx.transaction.accountUpdates.length; let i; const blindingValues = []; const forests = []; for (i = 0; i < length; i++) { const la = tx.transaction.accountUpdates[i].lazyAuthorization; if (la !== void 0 && la.blindingValue !== void 0 && la.kind === "lazy-proof") blindingValues.push(la.blindingValue.toJSON()); else blindingValues.push(""); const forest = { length: 0, items: [] }; serializeLazyAuthorization(tx.transaction.accountUpdates[i].lazyAuthorization?.args, forest); forests.push(forest); } const serializedTransaction = JSON.stringify({ tx: tx.toJSON(), blindingValues, forestJSONs: forests.map((f) => JSON.stringify(f)), length, fee: tx.transaction.feePayer.body.fee.toJSON(), sender: tx.transaction.feePayer.body.publicKey.toBase58(), nonce: tx.transaction.feePayer.body.nonce.toBigint().toString() }, null, 2); return serializedTransaction; } function serializeLazyAuthorization(lazyAuthorization, serialized) { if (lazyAuthorization?.hash !== void 0 && lazyAuthorization.hash.toJSON) { serialized.items.push({ h: fieldToBase64(lazyAuthorization.hash) }); } if (lazyAuthorization?.previousHash !== void 0 && lazyAuthorization.previousHash.toJSON) { serialized.items.push({ p: fieldToBase64(lazyAuthorization.previousHash) }); } if (lazyAuthorization?.callData !== void 0 && lazyAuthorization.callData.toJSON) { serialized.items.push({ c: fieldToBase64(lazyAuthorization.callData) }); } if (lazyAuthorization?.id !== void 0) { serialized.items.push({ i: lazyAuthorization.id }); } if (Array.isArray(lazyAuthorization)) { for (const item of lazyAuthorization) { serializeLazyAuthorization(item, serialized); } } if (typeof lazyAuthorization === "object") { for (const key in lazyAuthorization) { serializeLazyAuthorization(lazyAuthorization[key], serialized); } } serialized.length = serialized.items.length; } function deserializeLazyAuthorization(lazyAuthorization, serialized) { if (serialized.restoredItems === void 0) serialized.restoredItems = 0; if (lazyAuthorization?.hash !== void 0 && lazyAuthorization.hash.toJSON) { if (serialized.restoredItems >= serialized.length) throw new Error("Restored more items than expected"); const hash = serialized.items[serialized.restoredItems].h; if (hash === void 0) throw new Error(`Hash is undefined for item ${serialized.restoredItems}`); lazyAuthorization.hash = fieldFromBase64(hash); serialized.restoredItems++; } if (lazyAuthorization?.previousHash !== void 0 && lazyAuthorization.previousHash.toJSON) { if (serialized.restoredItems >= serialized.length) throw new Error("Restored more items than expected"); const previousHash = serialized.items[serialized.restoredItems].p; if (previousHash === void 0) throw new Error(`Previous hash is undefined for item ${serialized.restoredItems}`); lazyAuthorization.previousHash = fieldFromBase64(previousHash); serialized.restoredItems++; } if (lazyAuthorization?.callData !== void 0 && lazyAuthorization.callData.toJSON) { if (serialized.restoredItems >= serialized.length) throw new Error("Restored more items than expected"); const callData = serialized.items[serialized.restoredItems].c; if (callData === void 0) throw new Error(`Call data is undefined for item ${serialized.restoredItems}`); lazyAuthorization.callData = fieldFromBase64(callData); serialized.restoredItems++; } if (lazyAuthorization?.id !== void 0) { if (serialized.restoredItems >= serialized.length) throw new Error("Restored more items than expected"); const id = serialized.items[serialized.restoredItems].i; if (id === void 0) throw new Error(`Id is undefined for item ${serialized.restoredItems}`); lazyAuthorization.id = id; serialized.restoredItems++; } if (Array.isArray(lazyAuthorization)) { for (const item of lazyAuthorization) { deserializeLazyAuthorization(item, serialized); } } if (typeof lazyAuthorization === "object") { for (const key in lazyAuthorization) { deserializeLazyAuthorization(lazyAuthorization[key], serialized); } } } // dist/node/transactions/txstatus.js var TIMEOUT2 = 1e3 * 60 * 21; async function txStatusBlockberry(params) { const { hash, chain, time, blockBerryApiKey } = params; const tx = await getZkAppTxFromBlockBerry({ hash, chain, blockBerryApiKey }); if (tx?.txStatus) return tx?.txStatus; if (Date.now() - time > (params.timeout ?? TIMEOUT2)) { console.error("txStatus: Timeout while checking tx with blockberry", chain, hash); return "replaced"; } else { return "pending"; } } // dist/node/transactions/tiny-contract.js var import_tslib = require("tslib"); var import_o1js9 = require("o1js"); var TinyContract = class extends import_o1js9.SmartContract { constructor() { super(...arguments); this.value = (0, import_o1js9.State)(); } async setValue(value) { this.value.set(value); } }; (0, import_tslib.__decorate)([ (0, import_o1js9.state)(import_o1js9.Field), (0, import_tslib.__metadata)("design:type", Object) ], TinyContract.prototype, "value", void 0); (0, import_tslib.__decorate)([ import_o1js9.method, (0, import_tslib.__metadata)("design:type", Function), (0, import_tslib.__metadata)("design:paramtypes", [import_o1js9.Field]), (0, import_tslib.__metadata)("design:returntype", Promise) ], TinyContract.prototype, "setValue", null); // dist/node/transactions/send.js var import_o1js10 = require("o1js"); async function sendTx(params) { const { tx, description = "", verbose = true, wait = true, chain = getCurrentNetwork().network.chainId, delay = chain === "zeko" || chain === "lightnet" ? 5e3 : 6e4, retry = 30 } = params; const accountUpdates = JSON.parse(tx.toJSON()).accountUpdates; const auCount = []; let proofAuthorizationCount = 0; for (const au of accountUpdates) { const { publicKey, tokenId, authorizationKind } = au.body; if (au.authorization.proof) { proofAuthorizationCount++; if (authorizationKind.isProved === false) console.error("Proof authorization exists but isProved is false"); } else if (authorizationKind.isProved === true) console.error("isProved is true but no proof authorization"); const index = auCount.findIndex((item) => item.publicKey === publicKey && item.tokenId === tokenId); if (index === -1) auCount.push({ publicKey, tokenId, count: 1 }); else auCount[index].count++; } if (verbose) console.log(`Account updates for ${description ?? "tx"}: ${auCount.length}, proof authorizations: ${proofAuthorizationCount}`); for (const au of auCount) { if (au.count > 1) { if (verbose) console.log(`DUPLICATE AU ${description ?? ""}: ${au.publicKey} ${au.tokenId !== "wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf" ? "tokenId: " + au.tokenId : ""} count: ${au.count}`); } } try { let txSent; let sent = false; let attempt = 1; while (!sent && attempt <= retry) { txSent = await tx.safeSend(); if (txSent.status === "pending") { sent = true; if (verbose) console.log(`${description ?? ""} tx sent: hash: ${txSent.hash} status: ${txSent.status}`); } else if (chain !== "local") { attempt++; console.error(`${description} tx NOT sent: hash: ${txSent?.hash} status: ${txSent?.status}, errors: ${String(txSent.errors ?? "")}`); if (verbose) console.log(`Retrying ${chain} tx, retry:`, attempt); await sleep(1e4 * attempt); } else attempt = retry + 1; } if (txSent === void 0) throw new Error("txSent is undefined"); if ((txSent.errors?.length ?? 0) > 0) { console.error(`${description ?? ""} tx error: hash: ${txSent.hash} status: ${txSent.status} errors: ${String(txSent.errors ?? "")}`); } if (txSent.status === "pending" && wait !== false && chain !== "zeko") { if (verbose) console.log(`Waiting for tx inclusion...`); let txIncluded = await txSent.safeWait(); if (txIncluded.status !== "included") { console.error(`${description ?? ""} tx NOT included into block: hash: ${txIncluded.hash} status: ${txIncluded.status}, errors: ${String(txIncluded.errors ?? "")}`); } if (chain !== "local") { const { publicKey, nonce } = tx.transaction.feePayer.body; const started = Date.now(); while (Date.now() - started < 1e3 * 60 * 10) { const newNonce = (await fetchMinaAccount({ publicKey, force: true })).account?.nonce; if (newNonce && Number(newNonce.toBigint()) > Number(nonce.toBigint())) { let txIncluded2 = await txSent.safeWait(); if (txIncluded2.status === "included") { if (verbose) console.log(`${description ?? ""} tx included into block: hash: ${txIncluded2.hash} status: ${txIncluded2.status}`); if (delay > 0) await sleep(delay); return txIncluded2; } else if (txIncluded2.status === "rejected") { console.error(`tx rejected: ${chain}: hash: ${txIncluded2.hash} status: ${txIncluded2.status} errors: ${txIncluded2.errors}`); await sleep(3e4); txIncluded2 = await txSent.safeWait(); if (txIncluded2.status === "included") { if (verbose) console.log(`${description ?? ""} tx included into block: hash: ${txIncluded2.hash} status: ${txIncluded2.status}`); if (delay > 0) await sleep(delay); return txIncluded2; } console.error(`tx failed: ${chain}: hash: ${txIncluded2.hash} status: ${txIncluded2.status} errors: ${txIncluded2.errors}`); return txIncluded2; } } if (verbose) console.log(`Waiting for ${chain} to update state for ${Math.floor((Date.now() - started) / 1e3)} sec...`); await sleep(3e4); } console.error(`${chain} do not reflect nonce update for tx ${txIncluded.hash} with status ${txIncluded.status}`); } if (verbose) console.log(`${description ?? ""} tx included into block: hash: ${txIncluded.hash} status: ${txIncluded.status}`); return txIncluded; } else return txSent; } catch (error) { if (chain !== "zeko") console.error("Error sending tx", error); } } async function getTxStatusFast(params) { const { hash, chain = getCurrentNetwork().network.chainId } = params; if (chain === "local" || chain === "zeko") return { success: true, result: true }; try { const txStatus = await (0, import_o1js10.checkZkappTransaction)(hash); return { success: true, result: txStatus?.success ?? false }; } catch (error) { console.error("getTxStatusFast error while getting tx status - catch", hash, error); return { success: false, error: error?.message ?? "Cannot get tx status" }; } } // dist/node/transactions/account.js var import_o1js11 = require("o1js"); async function accountExists(address, tokenId) { try { const publicKey = typeof address === "string" ? import_o1js11.PublicKey.fromBase58(address) : address; await fetchMinaAccount({ publicKey, tokenId, force: false }); return import_o1js11.Mina.hasAccount(publicKey, tokenId); } catch (error) { return false; } } async function tokenBalance(address, tokenId) { try { const publicKey = typeof address === "string" ? import_o1js11.PublicKey.fromBase58(address) : address; await fetchMinaAccount({ publicKey, tokenId, force: false }); return import_o1js11.Mina.hasAccount(publicKey, tokenId) ? Number(import_o1js11.Mina.getAccount(publicKey, tokenId).balance.toBigInt()) : void 0; } catch (error) { console.error("Cannot fetch account balance", error); return void 0; } } async function checkAddress(address) { if (!address || typeof address !== "string") { console.error("checkAddress params are invalid:", address); return false; } try { const publicKey = import_o1js11.PublicKey.fromBase58(address); if (address !== publicKey.toBase58()) { console.log("checkAddress: address is not valid", address, publicKey.toBase58()); return false; } return true; } catch (error) { console.error("checkAddress catch", { address, error }); return false; } } // dist/node/commitment/commitment.js var import_o1js15 = require("o1js"); // dist/node/commitment/constants.js var import_o1js12 = require("o1js"); var BLS_FR = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n; var Fr = (0, import_o1js12.createForeignField)(BLS_FR); var R_VALUE = 0x149fa8c209ab655fd480a3aff7d16dc72b6a3943e4b95fcf7909f42d9c17a552n; function getR() { return Fr.from(R_VALUE); } function getTable0Entry(index) { if (index >= 1024) throw new Error("TABLE0 index out of bounds"); return Fr.from(TABLE0[index]); } function getTable1Entry(index) { if (index >= 1024) throw new Error("TABLE1 index out of bounds"); return Fr.from(TABLE1[index]); } function getTable2Entry(index) { if (index >= 1024) throw new Error("TABLE2 index out of bounds"); return Fr.from(TABLE22[index]); } var TABLE0 = [ 0x0000000000000000000000000000000000000000000000000000000000000001n, // R^0 = 1 0x149fa8c209ab655fd480a3aff7d16dc72b6a3943e4b95fcf7909f42d9c17a552n, // R^1 = R 0x5df995de0eb4fd377c1c4487338e6b2cac86012ba7ad28007b511f2e832ca5dfn, // R^2 0x4b3ead8c3dfd654f6e562478086b876b1b00635d558749f78d9e67bc730e33e8n, // R^3 0x1b7627cf3b0816f9e23fd6455446e6131fa1a6e39ada47481e8d13563cbf28f3n, // R^4 0x5e8ff2b9cdf997eaf93fff82ba1ad706e126842cda04aa98e5823641f0e104aen, // R^5 0x1fc84f346a381aaf5a83870a6c99fcd60ad57a819c5d0358158a71df8f30ca9bn, // R^6 0x6e2c601106ed0953badad4c2002a1cb669b68f97dc64bd1e6e65c4ff37a9c19fn, // R^7 0x7366a137b8ae4e5a287f8197096a179cbfc3ebf633d6e9de9c61d319c23f931an, // R^8 0x1cf1dabd25b6d47c5f55eab1e5da855faead0c3e0ea1f006f26d96603b370070n, // R^9 0x28b5085e0883923a5fe9bf9d108f8be3a432bd97156020d87dfce14ca429a152n, // R^10 0x5830b95fdb00a073da69509b71a80f3343004a16aa1018dfd8ff13bc73f974b5n, // R^11 0x5a32550797ab926c17788923bd556bdbda00d919d6bb8fec5406edb5d9d24bbfn, // R^12 0x1b6f299e48c145f90a27df014c50086b6f08e41702e19e1ebea3a998090c372dn, // R^13 0x53f29e90c29a5292a2699e9d56fd4d3ed80c583ab292c81c6f96d8667ad2a326n, // R^14 0x3ffe313e31dbf4382757ad449c2c8135e31b5460b7ebc15a18b13f8bedcc7217n, // R^15 0x3becfe52d6af64a31dedb53bc29ed2bc860fe0c214357baf25b840156666f865n, // R^16 0x1b027a226b227e964410ee322cde8e09e17d95ac365f6fe415f0862b29bb14e8n, // R^17 0x19aebbf7b44580dab6b54d212722234f73fda2644517b892f5bbd641953544a3n, // R^18 0x4a405283f982615a3128fb0dad9d309559c5277b6c2553ce65d5d7186b1b5855n, // R^19 0x71048a6425b6aa932506dc55a0dfe6cd695b168977abd8c8429b8d38dfd173ean, // R^20 0x62dee991e60cecc791f149ba4b96ec037fdde9e88b456d1c138e6f9ad5afb9fbn, // R^21 0x49dffef70692d2cbb8b5a4852ba3c9f25912563756921205ff289b1a34473ec5n, // R^22 0x2324bad90fc4792859c95ec12fb97248513bcdd6b4ce61c3e337edea3d677056n, // R^23 0x085ca5093e7a3e8d6408f73828aef93b6a95a489191fd769c028187f029ffa8dn, // R^24 0x3a61a8141101de545fb223b0b81f529690fa9ff542b9a8bdec88b6e14e047017n, // R^25