UNPKG

dria-oracle-sdk

Version:

An on-chain LLM Oracle SDK for Dria

1,186 lines (1,178 loc) 32.9 kB
'use strict'; var viem = require('viem'); var Irys = require('@irys/sdk'); var TaskStatus = /* @__PURE__ */ ((TaskStatus2) => { TaskStatus2[TaskStatus2["None"] = 0] = "None"; TaskStatus2[TaskStatus2["PendingGeneration"] = 1] = "PendingGeneration"; TaskStatus2[TaskStatus2["PendingValidation"] = 2] = "PendingValidation"; TaskStatus2[TaskStatus2["Completed"] = 3] = "Completed"; return TaskStatus2; })(TaskStatus || {}); async function stringToContractBytesWithStorage(input, storage) { const inputBytes = viem.stringToBytes(input); if (storage && inputBytes.length > storage.bytesLimit) { const key = await storage.put(Buffer.from(inputBytes)); return `0x${Buffer.from(JSON.stringify(key)).toString("hex")}`; } else { return `0x${Buffer.from(inputBytes).toString("hex")}`; } } async function contractBytesToStringWithStorage(input, storage) { const inputStr = viem.bytesToString(Buffer.from(input.slice(2), "hex")); if (storage) { const key = storage.isKey(inputStr); if (key == null) { return inputStr; } const data = await storage.get(key); if (data == null) { return null; } return data.toString(); } else { return inputStr; } } function stringToBytes32(input) { return viem.toHex(input, { size: 32 }); } function bytes32ToString(input) { return viem.fromHex(input, { size: 32, to: "string" }); } var coordinatorAbi = [ { type: "constructor", inputs: [], stateMutability: "nonpayable" }, { type: "function", name: "UPGRADE_INTERFACE_VERSION", inputs: [], outputs: [{ name: "", type: "string", internalType: "string" }], stateMutability: "view" }, { type: "function", name: "feeToken", inputs: [], outputs: [{ name: "", type: "address", internalType: "contract ERC20" }], stateMutability: "view" }, { type: "function", name: "generationDeviationFactor", inputs: [], outputs: [{ name: "", type: "uint64", internalType: "uint64" }], stateMutability: "view" }, { type: "function", name: "generationFee", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "getBestResponse", inputs: [{ name: "taskId", type: "uint256", internalType: "uint256" }], outputs: [ { name: "", type: "tuple", internalType: "struct LLMOracleTask.TaskResponse", components: [ { name: "responder", type: "address", internalType: "address" }, { name: "nonce", type: "uint256", internalType: "uint256" }, { name: "score", type: "uint256", internalType: "uint256" }, { name: "output", type: "bytes", internalType: "bytes" }, { name: "metadata", type: "bytes", internalType: "bytes" } ] } ], stateMutability: "view" }, { type: "function", name: "getFee", inputs: [ { name: "parameters", type: "tuple", internalType: "struct LLMOracleTaskParameters", components: [ { name: "difficulty", type: "uint8", internalType: "uint8" }, { name: "numGenerations", type: "uint40", internalType: "uint40" }, { name: "numValidations", type: "uint40", internalType: "uint40" } ] } ], outputs: [ { name: "totalFee", type: "uint256", internalType: "uint256" }, { name: "generatorFee", type: "uint256", internalType: "uint256" }, { name: "validatorFee", type: "uint256", internalType: "uint256" } ], stateMutability: "view" }, { type: "function", name: "getResponses", inputs: [{ name: "taskId", type: "uint256", internalType: "uint256" }], outputs: [ { name: "", type: "tuple[]", internalType: "struct LLMOracleTask.TaskResponse[]", components: [ { name: "responder", type: "address", internalType: "address" }, { name: "nonce", type: "uint256", internalType: "uint256" }, { name: "score", type: "uint256", internalType: "uint256" }, { name: "output", type: "bytes", internalType: "bytes" }, { name: "metadata", type: "bytes", internalType: "bytes" } ] } ], stateMutability: "view" }, { type: "function", name: "getValidations", inputs: [{ name: "taskId", type: "uint256", internalType: "uint256" }], outputs: [ { name: "", type: "tuple[]", internalType: "struct LLMOracleTask.TaskValidation[]", components: [ { name: "validator", type: "address", internalType: "address" }, { name: "nonce", type: "uint256", internalType: "uint256" }, { name: "scores", type: "uint256[]", internalType: "uint256[]" }, { name: "metadata", type: "bytes", internalType: "bytes" } ] } ], stateMutability: "view" }, { type: "function", name: "initialize", inputs: [ { name: "_oracleRegistry", type: "address", internalType: "address" }, { name: "_feeToken", type: "address", internalType: "address" }, { name: "_platformFee", type: "uint256", internalType: "uint256" }, { name: "_generationFee", type: "uint256", internalType: "uint256" }, { name: "_validationFee", type: "uint256", internalType: "uint256" }, { name: "_minScore", type: "uint256", internalType: "uint256" }, { name: "_maxScore", type: "uint256", internalType: "uint256" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "maxScore", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "minScore", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "nextTaskId", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "owner", inputs: [], outputs: [{ name: "", type: "address", internalType: "address" }], stateMutability: "view" }, { type: "function", name: "platformFee", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "platformFeeBalance", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "proxiableUUID", inputs: [], outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], stateMutability: "view" }, { type: "function", name: "registry", inputs: [], outputs: [ { name: "", type: "address", internalType: "contract LLMOracleRegistry" } ], stateMutability: "view" }, { type: "function", name: "renounceOwnership", inputs: [], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "request", inputs: [ { name: "protocol", type: "bytes32", internalType: "bytes32" }, { name: "input", type: "bytes", internalType: "bytes" }, { name: "models", type: "bytes", internalType: "bytes" }, { name: "parameters", type: "tuple", internalType: "struct LLMOracleTaskParameters", components: [ { name: "difficulty", type: "uint8", internalType: "uint8" }, { name: "numGenerations", type: "uint40", internalType: "uint40" }, { name: "numValidations", type: "uint40", internalType: "uint40" } ] } ], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "nonpayable" }, { type: "function", name: "requests", inputs: [{ name: "taskId", type: "uint256", internalType: "uint256" }], outputs: [ { name: "requester", type: "address", internalType: "address" }, { name: "protocol", type: "bytes32", internalType: "bytes32" }, { name: "parameters", type: "tuple", internalType: "struct LLMOracleTaskParameters", components: [ { name: "difficulty", type: "uint8", internalType: "uint8" }, { name: "numGenerations", type: "uint40", internalType: "uint40" }, { name: "numValidations", type: "uint40", internalType: "uint40" } ] }, { name: "status", type: "uint8", internalType: "enum LLMOracleTask.TaskStatus" }, { name: "generatorFee", type: "uint256", internalType: "uint256" }, { name: "validatorFee", type: "uint256", internalType: "uint256" }, { name: "platformFee", type: "uint256", internalType: "uint256" }, { name: "input", type: "bytes", internalType: "bytes" }, { name: "models", type: "bytes", internalType: "bytes" } ], stateMutability: "view" }, { type: "function", name: "respond", inputs: [ { name: "taskId", type: "uint256", internalType: "uint256" }, { name: "nonce", type: "uint256", internalType: "uint256" }, { name: "output", type: "bytes", internalType: "bytes" }, { name: "metadata", type: "bytes", internalType: "bytes" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "responses", inputs: [ { name: "taskId", type: "uint256", internalType: "uint256" }, { name: "", type: "uint256", internalType: "uint256" } ], outputs: [ { name: "responder", type: "address", internalType: "address" }, { name: "nonce", type: "uint256", internalType: "uint256" }, { name: "score", type: "uint256", internalType: "uint256" }, { name: "output", type: "bytes", internalType: "bytes" }, { name: "metadata", type: "bytes", internalType: "bytes" } ], stateMutability: "view" }, { type: "function", name: "setFees", inputs: [ { name: "_platformFee", type: "uint256", internalType: "uint256" }, { name: "_generationFee", type: "uint256", internalType: "uint256" }, { name: "_validationFee", type: "uint256", internalType: "uint256" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "setGenerationDeviationFactor", inputs: [ { name: "_generationDeviationFactor", type: "uint64", internalType: "uint64" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "setParameters", inputs: [ { name: "minimums", type: "tuple", internalType: "struct LLMOracleTaskParameters", components: [ { name: "difficulty", type: "uint8", internalType: "uint8" }, { name: "numGenerations", type: "uint40", internalType: "uint40" }, { name: "numValidations", type: "uint40", internalType: "uint40" } ] }, { name: "maximums", type: "tuple", internalType: "struct LLMOracleTaskParameters", components: [ { name: "difficulty", type: "uint8", internalType: "uint8" }, { name: "numGenerations", type: "uint40", internalType: "uint40" }, { name: "numValidations", type: "uint40", internalType: "uint40" } ] } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "transferOwnership", inputs: [{ name: "newOwner", type: "address", internalType: "address" }], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "upgradeToAndCall", inputs: [ { name: "newImplementation", type: "address", internalType: "address" }, { name: "data", type: "bytes", internalType: "bytes" } ], outputs: [], stateMutability: "payable" }, { type: "function", name: "validate", inputs: [ { name: "taskId", type: "uint256", internalType: "uint256" }, { name: "nonce", type: "uint256", internalType: "uint256" }, { name: "scores", type: "uint256[]", internalType: "uint256[]" }, { name: "metadata", type: "bytes", internalType: "bytes" } ], outputs: [], stateMutability: "nonpayable" }, { type: "function", name: "validationFee", inputs: [], outputs: [{ name: "", type: "uint256", internalType: "uint256" }], stateMutability: "view" }, { type: "function", name: "validations", inputs: [ { name: "taskId", type: "uint256", internalType: "uint256" }, { name: "", type: "uint256", internalType: "uint256" } ], outputs: [ { name: "validator", type: "address", internalType: "address" }, { name: "nonce", type: "uint256", internalType: "uint256" }, { name: "metadata", type: "bytes", internalType: "bytes" } ], stateMutability: "view" }, { type: "function", name: "withdrawPlatformFees", inputs: [], outputs: [], stateMutability: "nonpayable" }, { type: "event", name: "Initialized", inputs: [ { name: "version", type: "uint64", indexed: false, internalType: "uint64" } ], anonymous: false }, { type: "event", name: "OwnershipTransferred", inputs: [ { name: "previousOwner", type: "address", indexed: true, internalType: "address" }, { name: "newOwner", type: "address", indexed: true, internalType: "address" } ], anonymous: false }, { type: "event", name: "Request", inputs: [ { name: "taskId", type: "uint256", indexed: true, internalType: "uint256" }, { name: "requester", type: "address", indexed: true, internalType: "address" }, { name: "protocol", type: "bytes32", indexed: true, internalType: "bytes32" } ], anonymous: false }, { type: "event", name: "Response", inputs: [ { name: "taskId", type: "uint256", indexed: true, internalType: "uint256" }, { name: "responder", type: "address", indexed: true, internalType: "address" } ], anonymous: false }, { type: "event", name: "StatusUpdate", inputs: [ { name: "taskId", type: "uint256", indexed: true, internalType: "uint256" }, { name: "protocol", type: "bytes32", indexed: true, internalType: "bytes32" }, { name: "statusBefore", type: "uint8", indexed: false, internalType: "enum LLMOracleTask.TaskStatus" }, { name: "statusAfter", type: "uint8", indexed: false, internalType: "enum LLMOracleTask.TaskStatus" } ], anonymous: false }, { type: "event", name: "Upgraded", inputs: [ { name: "implementation", type: "address", indexed: true, internalType: "address" } ], anonymous: false }, { type: "event", name: "Validation", inputs: [ { name: "taskId", type: "uint256", indexed: true, internalType: "uint256" }, { name: "validator", type: "address", indexed: true, internalType: "address" } ], anonymous: false }, { type: "error", name: "AddressEmptyCode", inputs: [{ name: "target", type: "address", internalType: "address" }] }, { type: "error", name: "AlreadyResponded", inputs: [ { name: "taskId", type: "uint256", internalType: "uint256" }, { name: "oracle", type: "address", internalType: "address" } ] }, { type: "error", name: "ComputeError", inputs: [] }, { type: "error", name: "ERC1967InvalidImplementation", inputs: [ { name: "implementation", type: "address", internalType: "address" } ] }, { type: "error", name: "ERC1967NonPayable", inputs: [] }, { type: "error", name: "FailedCall", inputs: [] }, { type: "error", name: "InsufficientFees", inputs: [ { name: "have", type: "uint256", internalType: "uint256" }, { name: "want", type: "uint256", internalType: "uint256" } ] }, { type: "error", name: "InvalidInitialization", inputs: [] }, { type: "error", name: "InvalidInput", inputs: [] }, { type: "error", name: "InvalidNonce", inputs: [ { name: "taskId", type: "uint256", internalType: "uint256" }, { name: "nonce", type: "uint256", internalType: "uint256" } ] }, { type: "error", name: "InvalidParameterRange", inputs: [ { name: "have", type: "uint256", internalType: "uint256" }, { name: "min", type: "uint256", internalType: "uint256" }, { name: "max", type: "uint256", internalType: "uint256" } ] }, { type: "error", name: "InvalidTaskStatus", inputs: [ { name: "taskId", type: "uint256", internalType: "uint256" }, { name: "have", type: "uint8", internalType: "enum LLMOracleTask.TaskStatus" }, { name: "want", type: "uint8", internalType: "enum LLMOracleTask.TaskStatus" } ] }, { type: "error", name: "InvalidValidation", inputs: [ { name: "taskId", type: "uint256", internalType: "uint256" }, { name: "validator", type: "address", internalType: "address" } ] }, { type: "error", name: "NotInitializing", inputs: [] }, { type: "error", name: "NotRegistered", inputs: [{ name: "oracle", type: "address", internalType: "address" }] }, { type: "error", name: "NotWhitelisted", inputs: [{ name: "validator", type: "address", internalType: "address" }] }, { type: "error", name: "OwnableInvalidOwner", inputs: [{ name: "owner", type: "address", internalType: "address" }] }, { type: "error", name: "OwnableUnauthorizedAccount", inputs: [{ name: "account", type: "address", internalType: "address" }] }, { type: "error", name: "UUPSUnauthorizedCallContext", inputs: [] }, { type: "error", name: "UUPSUnsupportedProxiableUUID", inputs: [{ name: "slot", type: "bytes32", internalType: "bytes32" }] } ]; class Oracle { constructor(client, storage) { this.client = client; this.storage = storage; // defaults this.taskParameters = { difficulty: 2, numGenerations: 2, numValidations: 2 }; this.protocol = "dria-oracle-sdk/0.0.x"; } /** * Initialize the oracle client by setting up contract instances. * @param coordinatorAddress coordinator contract address * @returns initialized oracle client */ async init(coordinatorAddress) { this.coordinator = this.Coordinator(coordinatorAddress); const tokenAddr = await this.coordinator.read.feeToken(); this.token = this.Token(tokenAddr); return this; } /** * Change the underlying default task parameters. * @param opts new default task parameters */ withParameters(opts) { this.taskParameters = { ...this.taskParameters, ...opts }; return this; } /** * Change the underlying default protocol. * * The protocol is a string that should fit a `bytes32` type in Solidity. It is used * to identify the source of the request, and can be used within event filters. * * It should have to format `name/version`, e.g. `dria-oracle-sdk/0.x.x`. * @param protocol protocol name */ withProtocol(protocol) { if (protocol.split("/").length !== 2) { throw new Error("Invalid protocol format."); } if (Buffer.from(protocol).length > 32) { throw new Error("Protocol string is too long."); } this.protocol = protocol; return this; } /** Returns a new instance of the LLM coordinator contract. * @warning This is an internal method, and making it `private` will break * the type export due to the size of ABI-inferred types. */ Coordinator(address) { return viem.getContract({ address, abi: coordinatorAbi, client: this.client }); } /** Returns a new instance of an ERC20 token contract. * @warning This is an internal method, and making it `private` will break * the type export due to the size of ABI-inferred types. */ Token(address) { return viem.getContract({ address, abi: viem.erc20Abi, client: this.client }); } async request(input, models = "*", opts = {}) { if (this.coordinator === void 0) { throw new Error("SDK not initialized."); } const taskParameters = { ...this.taskParameters, ...opts.taskParameters }; if (taskParameters.numGenerations === 0) { throw new Error("Number of generations cant be 0."); } const modelsString = Array.isArray(models) ? models.join(",") : models; if (typeof input !== "string") { if (!await this.isCompleted(input.history_id)) { throw new Error("Chat history task is not completed."); } input = JSON.stringify(input); } const inputBytes = await stringToContractBytesWithStorage(input, this.storage); const modelBytes = await stringToContractBytesWithStorage(modelsString, void 0); const protocol = opts.protocol ?? this.protocol; const protocolBytes = stringToBytes32(protocol); const txHash = await this.coordinator.write.request([protocolBytes, inputBytes, modelBytes, taskParameters], { chain: this.client.wallet.chain, account: this.client.wallet.account }); return { txHash, protocol, input, models, taskParameters }; } /** * Waits until the request transaction is mined and returns the task id. * @param txHash transaction hash for the request (see `request`) * @returns taskId */ async waitRequest(txHash) { const receipt = await this.client.public.waitForTransactionReceipt({ hash: txHash }); const logs = viem.parseEventLogs({ abi: viem.parseAbi(["event Request(uint256 indexed taskId, address indexed requester, bytes32 indexed protocol)"]), logs: receipt.logs, eventName: "Request" }); if (logs.length === 0) { throw new Error(`Request event not found in logs: ${JSON.stringify(logs)}`); } const taskId = logs[0].args.taskId; return taskId; } /** * Alias for `getBestResponse` followed by `processResponse`. * @param taskId task id * @param kind task kind, e.g. `chat` for conversational models * @returns processed task response */ async read(taskId) { const response = await this.getBestResponse(taskId); return this.processResponse(response); } /** * Returns a boolean indicating if the task is completed. * @param taskId task id * @returns true if the task is completed, or `taskId` is 0 */ async isCompleted(taskId) { if (BigInt(taskId) === 0n) { return true; } if (this.coordinator === void 0) { throw new Error("SDK not initialized."); } const requestRaw = await this.coordinator.read.requests([BigInt(taskId)]); return requestRaw[3] === TaskStatus.Completed; } /** * Returns the task request for a given task id. * @param taskId task id * @returns task request */ async getRequest(taskId) { if (this.coordinator === void 0) { throw new Error("SDK not initialized."); } const request = await this.coordinator.read.requests([BigInt(taskId)]); return { requester: request[0], protocol: bytes32ToString(request[1]), parameters: request[2], status: request[3], generatorFee: request[4], validatorFee: request[5], platformFee: request[6], input: await contractBytesToStringWithStorage(request[7], this.storage) ?? "", models: bytes32ToString(request[8]) }; } /** * Returns the highest scored response of a task. * Will throw an error if the task is not completed yet! * @param taskId task id * @returns task response with the highest score */ async getBestResponse(taskId) { if (this.coordinator === void 0) { throw new Error("SDK not initialized."); } return await this.coordinator.read.getBestResponse([BigInt(taskId)]); } /** * Returns the validations of all generation responses for a task. * @param taskId task id * @returns array of task validations */ async getValidations(taskId) { if (this.coordinator === void 0) { throw new Error("SDK not initialized."); } return this.coordinator.read.getValidations([BigInt(taskId)]); } /** * Returns the generation responses for a task. * @param taskId task id * @returns array of task responses */ async getResponses(taskId) { if (this.coordinator === void 0) { throw new Error("SDK not initialized."); } return await this.coordinator.read.getResponses([BigInt(taskId)]); } /** * Process the `output` and `metadata` of a task, with respect to the given storage. * @param response existing response object * @returns response object with processed `output` and `metadata` */ async processResponse(response) { const output = await contractBytesToStringWithStorage(response.output, this.storage); const metadata = await contractBytesToStringWithStorage(response.metadata, this.storage); return { ...response, output, metadata }; } /** * Process the `metadata` of a task, with respect to the given storage. * @param response existing validation object * @returns validation object with processed `metadata` */ async processValidation(validation) { const metadata = await contractBytesToStringWithStorage(validation.metadata, this.storage); if (!metadata) { throw new Error("Validation metadata not found."); } try { return { ...validation, // here we assume the type like this, because validators are trusted metadata: JSON.parse(metadata) }; } catch (err) { console.error("Error parsing metadata:", err); throw err; } } /** Shorthand to parse a string input to a chat history response. */ toChatHistory(input) { return JSON.parse(input); } /** * Fetches the task events from the coordinator contract and returns its args. * A returned task event has the taskId, protocol, statusBefore, and statusAfter. * For a completed task, we are looking for the statusAfter to be `Completed` which is `3`. * * @param opts options for fetching tasks * - `protocol`: protocol name * - `from`: block to start from * - `to`: block to end at * - `status`: task status to filter by * @returns array of task events */ async getTaskEvents(opts) { if (this.coordinator === void 0) { throw new Error("SDK not initialized."); } const protocol = opts.protocol ? stringToBytes32(opts.protocol) : void 0; const fromBlock = opts.from ?? "earliest"; const toBlock = opts.to ?? "latest"; const events = await this.coordinator.getEvents.StatusUpdate({ protocol }, { fromBlock, toBlock }); const taskEvents = events.map((event) => event.args); if (opts.status) { return taskEvents.filter((e) => e.statusAfter === opts.status); } else { return taskEvents; } } /** * Waits for a task to be completed, i.e. it should have all the required * generations and validations be done. * @param taskId task id */ async wait(taskId) { if (this.coordinator === void 0) { throw new Error("SDK not initialized."); } if (await this.isCompleted(taskId)) { return; } return new Promise((resolve, reject) => { const unwatch = this.coordinator.watchEvent.StatusUpdate( { taskId: BigInt(taskId), protocol: void 0 }, { onLogs: (logs) => { const status = logs[0].args.statusAfter; if (status === TaskStatus.Completed) { unwatch(); resolve(); } } // onError: (err) => reject(err), // TODO: should we handle any stuff here? } ); }); } /** Returns the allowance of the client for the coordinator. * @returns allowance amount */ async allowance() { if (this.token === void 0) { throw new Error("SDK not initialized."); } return this.token.read.allowance([this.client.wallet.account.address, this.coordinator.address]); } /** * Approves the coordinator to spend the client's tokens. * @param amount amount to approve, defaults to max uint256 (infinite) * @returns transaction hash */ async approve(amount) { if (this.token === void 0) { throw new Error("SDK not initialized."); } amount = amount ?? viem.maxUint256; return this.token.write.approve([this.coordinator.address, amount], { chain: this.client.wallet.chain, account: this.client.wallet.account }); } } class ArweaveStorage { constructor() { /** Byte threshold, beyond which data is uploaded to Arweave. */ this.bytesLimit = Number.MAX_SAFE_INTEGER; /** Base URL of the gateway. */ this.baseUrl = "https://gateway.irys.xyz"; } /** * Initializes the Arweave storage with the given key. * @param key Arweave wallet object. * @param bytesLimit Number of bytes such that smaller data are not uploaded, default is 1024 bytes. */ init(key, bytesLimit = 1024) { const network = "mainnet"; const token = "arweave"; this.irys = new Irys({ network, // "mainnet" or "devnet" token, // Token used for payment and signing key // Arweave wallet }); this.bytesLimit = bytesLimit; } /** Return an `ArweaveKey` object if `key` is a stringified object of the form `{ arweave: string }`. * * @example // a valid key * { arweave: "Zg6CZYfxXCWYnCuKEpnZCYfy7ghit1_v4-BCe53iWuA" } */ isKey(key) { try { const obj = JSON.parse(key); if (obj.arweave && typeof obj.arweave === "string") { return { arweave: obj.arweave }; } } catch { } return null; } async get(key) { const url = `${this.baseUrl}/${key.arweave}`; const res = await fetch(url); if (!res.ok) { if (res.status === 404) { return null; } else { throw new Error(`Failed to fetch data: ${await res.text()}`); } } else { return Buffer.from(await res.arrayBuffer()); } } /** * Uploads the given value to Arweave and returns the key. * * _Requires `init` to have been called._ * * @param value Value to upload. * @returns Key to access the value. */ async put(value) { if (!this.irys) { throw new Error("Arweave client not initialized"); } const receipt = await this.irys.upload(value); return { arweave: receipt.id }; } /** * Returns the balance of the Arweave wallet. * * _Requires `init` to have been called._ * * @returns Balance in `bigint`. */ async balance() { if (!this.irys) { throw new Error("Arweave client not initialized"); } const balance = await this.irys.getBalance(this.irys.address); return BigInt(`0x${balance.toString(16)}`); } describe() { return "Arweave"; } } exports.ArweaveStorage = ArweaveStorage; exports.Oracle = Oracle; exports.TaskStatus = TaskStatus; exports.contractBytesToStringWithStorage = contractBytesToStringWithStorage; exports.stringToContractBytesWithStorage = stringToContractBytesWithStorage;