diff --git a/src/ao/messaging/DryRunFIFO.ts b/src/ao/messaging/DryRunFIFO.ts new file mode 100644 index 0000000..ddffe2c --- /dev/null +++ b/src/ao/messaging/DryRunFIFO.ts @@ -0,0 +1,75 @@ +import { DryRun, DryRunResult, MessageInput } from "@permaweb/aoconnect/dist/lib/dryrun"; +import { connect } from "@permaweb/aoconnect"; + +interface DryRunQueueItem { + msg: MessageInput; + resolve: (result: DryRunResult) => void; + reject: (reason?: any) => void; +} + +export class DryRunFIFO { + #queue: DryRunQueueItem[]; + #running: boolean; + #availableDryRuns: DryRunList; + + constructor(CUs: string[], delay = 500) { + this.#queue = []; + this.#running = false; + this.#availableDryRuns = new DryRunList(CUs.map( + (CU_URL) => connect({ MODE: "legacy", CU_URL }).dryrun + ), delay); + } + + put(msg: MessageInput) { + return new Promise((resolve, reject) => { + this.#queue.push({ msg, resolve, reject }); + this.#run(); + }); + } + + async #run() { + if (this.#running) return; + this.#running = true; + + while (this.#queue.length > 0) { + const dryrun = await this.#availableDryRuns.waitForOne(); + const { msg, resolve, reject } = this.#queue.shift()!; + + dryrun(msg) + .then(resolve) + .catch(reject) + .finally(() => this.#availableDryRuns.push(dryrun)); + } + + this.#running = false; + } +} + +class DryRunList { + #list: DryRun[]; + #delay: number; + #resolves: Array<(val: DryRun) => void>; + + constructor(list: DryRun[] = [], delay: number) { + this.#list = list; + this.#delay = delay; + this.#resolves = []; + } + + push(item: DryRun) { + setTimeout(() => { + const nextRequest = this.#resolves.shift(); + if (nextRequest) nextRequest(item); + else this.#list.push(item); + }, this.#delay); + } + + async waitForOne() { + const next = this.#list.shift(); + if (next) return next; + + return new Promise((resolve) => { + this.#resolves.push(resolve); + }); + } +} diff --git a/src/ao/messaging/getData.ts b/src/ao/messaging/getData.ts index 6874977..46d54c3 100644 --- a/src/ao/messaging/getData.ts +++ b/src/ao/messaging/getData.ts @@ -1,5 +1,8 @@ -import { DryRunResult } from "@permaweb/aoconnect/dist/lib/dryrun"; +import { DryRun, DryRunResult, MessageInput } from "@permaweb/aoconnect/dist/lib/dryrun"; import { connectToAO, Services } from "../utils/connect"; +import { dryRunAwait } from "../utils/dryRunAwait"; +import { connect } from "@permaweb/aoconnect"; +import LiquidOps from "../.."; interface MessageTags { Target: string; @@ -35,12 +38,15 @@ export async function getData( try { const { dryrun } = connectToAO(config); - const { Messages, Spawns, Output, Error } = await dryrun({ + const msg = { process: targetProcessID, data: "", tags: convertedMessageTags, Owner: messageTags.Owner || "1234", - }); + }; + const { Messages, Spawns, Output, Error } = LiquidOps.dryRunFifo ? + await LiquidOps.dryRunFifo.put(msg) : + await dryrun(msg); return { Messages, diff --git a/src/index.ts b/src/index.ts index ca02d40..e8b60b5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -124,11 +124,14 @@ import { GetEarnings, GetEarningsRes, } from "./functions/lend/getEarnings"; +import { DryRunFIFO } from "./ao/messaging/DryRunFIFO"; class LiquidOps { private signer: any; private configs: Omit; + static dryRunFifo?: DryRunFIFO; + constructor(signer: any, configs: Omit = {}) { if (!signer) { throw new Error("Please specify a ao createDataItemSigner signer"); @@ -352,4 +355,5 @@ export { tokenInput, tokenData, lqdTokenAddress, + DryRunFIFO, };