@ostraagent/mcp 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/ostra-mcp.js +654 -134
- package/package.json +1 -1
package/dist/ostra-mcp.js
CHANGED
|
@@ -18,7 +18,7 @@ var __export = (target, all) => {
|
|
|
18
18
|
var define_OSTRA_PACKAGED_default;
|
|
19
19
|
var init_define_OSTRA_PACKAGED = __esm({
|
|
20
20
|
"<define:OSTRA_PACKAGED>"() {
|
|
21
|
-
define_OSTRA_PACKAGED_default = { version: "0.1.
|
|
21
|
+
define_OSTRA_PACKAGED_default = { version: "0.1.12", deployment: { version: 1, chainId: 4663, fromBlock: "91991509", token: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168", batchSettlement: "0x4020074e9dF2ce1deE5A9C1b5c3f541D02a10003", vaultImplementation: "0xec0ca4A1393D91c42cA809F7F9dd82Bd597E8E58", vaultBeacon: "0xE9F525B9EaeE48d13AEd28fE146F48f2832a18a0", vaultFactory: "0x043a15c514CFE2c797d33520bFF91a5DCdbf2979", poolImplementation: "0xC04d4a222dC1C966640B977608bE29949b0648ec", poolBeacon: "0x30669Ca534921038a531BBE27116d85bB7406fFF", pool: "0x6ea80F2462e5Fd783B0Ec3B2c7BaC96795980CD6", splitFactory: "0xAAf54A483B2c7c2c5ecFc1eDED5ed1619C1bA882", beaconOwner: "0x55533a51d9bd9b06F2D179d919BB31995EF96E5e", registry: "0xcE6Cc1f93744f4090DA1444Bb8590d9206157506", vaultModule: "0x55A89fF907f5F5756470e2ec5Dc5E4E1C54Da770", launchpad: { hook: "0x63A784afb8905452aDceC471a45E555F5caE68cC", fees: "0x8e79671DC9729476614C78aFcf2345D4c1963801", launchpad: "0xfC57162C0e3f9773F97fEa8d276e957d7c43A6C5", creatorSplit: "0x987994dE6A1d5303B9e3F50977cB0321BA4D033B", dispatcher: "0x44Bb65164b2855f8E80B142d5Fb9bDb72E869986", locker: "0xb593812363bAd70Ee381c7B54c4FC82b0BA3A4A7", devBuy: "0x0e1Fd799E136dcfEcad5695B07Ac5DAc5B2fF4bc", vesting: "0xadD9C1995910457312c156E7D8120D1b447E179a", airdrop: "0xBC798D956aF4c2B104FFC6106d5322294Bc103bb", owner: "0x6569E27A95a6A3E92A311B4Cc6600fed56aA50A2" }, breaker: "0x2E33244dE6A64007204f763e9ef81FC33F1a8e01" }, swapDeployment: { chainId: 4663, fromBlock: "94940585", router: "0x5b9686f384A5Fb768B2360cF0B893F0d1E960B01", stake: "0xaDA4FaB9c8aB9165bf4d6cD9d4Da6d6b32Bb4BC6", buyback: "0xd86083031b7Af66ecD5C9c5e90D4C6d8E661F3f5", spendVerifier: "0x0a0E28a81DE6289e5044950163FfE95b37180e3B", privatePool: "0xe4250895Da2499602Cee4e178Fb46A0cF39F5b76" }, prover: { wasm: "0xd5f3069334ab49a2f955e4b4be9493b80c3f7b2a85f4ff2073a327ef5fbc2747", glue: "0x4bc8bef7c755c83daaf833623f85473a20a7c40b390d8d639d9e4353618a0537" }, relayerUrl: "https://relayer.ostraagent.xyz", keeperUrl: "https://keeper.ostraagent.xyz", aggregatorUrl: "https://aggregator.ostraagent.xyz", aiUrl: "https://ai.ostraagent.xyz" };
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
|
|
@@ -13581,6 +13581,14 @@ var init_abi = __esm({
|
|
|
13581
13581
|
}
|
|
13582
13582
|
});
|
|
13583
13583
|
|
|
13584
|
+
// ../sdk/src/agent-card.ts
|
|
13585
|
+
var init_agent_card = __esm({
|
|
13586
|
+
"../sdk/src/agent-card.ts"() {
|
|
13587
|
+
"use strict";
|
|
13588
|
+
init_define_OSTRA_PACKAGED();
|
|
13589
|
+
}
|
|
13590
|
+
});
|
|
13591
|
+
|
|
13584
13592
|
// ../sdk/src/hash.ts
|
|
13585
13593
|
import { keccak_256 } from "@noble/hashes/sha3.js";
|
|
13586
13594
|
import { sha256 as sha256Hash } from "@noble/hashes/sha2.js";
|
|
@@ -15521,6 +15529,7 @@ async function readBorroPosition(client, stockVault, stock2) {
|
|
|
15521
15529
|
listed,
|
|
15522
15530
|
supply: e.totalSupplyAssets,
|
|
15523
15531
|
borrowed: e.totalBorrowAssets,
|
|
15532
|
+
borrowedShares: e.totalBorrowShares,
|
|
15524
15533
|
at: at.timestamp
|
|
15525
15534
|
};
|
|
15526
15535
|
}
|
|
@@ -15651,21 +15660,54 @@ var init_breaker = __esm({
|
|
|
15651
15660
|
|
|
15652
15661
|
// ../sdk/src/chain.ts
|
|
15653
15662
|
import { BaseError as BaseError2, createPublicClient, defineChain, http } from "viem";
|
|
15654
|
-
function
|
|
15655
|
-
const
|
|
15656
|
-
|
|
15663
|
+
function laggingRead(e) {
|
|
15664
|
+
const lag = (x) => {
|
|
15665
|
+
const o = x;
|
|
15666
|
+
if (o.code === -32602) return true;
|
|
15667
|
+
return o.code === -32e3 && /unsupported block number/i.test(`${String(o.details ?? "")} ${String(o.message ?? "")}`);
|
|
15668
|
+
};
|
|
15669
|
+
return e instanceof BaseError2 ? e.walk(lag) !== null : lag(e);
|
|
15670
|
+
}
|
|
15671
|
+
function transient(e) {
|
|
15672
|
+
const o = e;
|
|
15673
|
+
if (o === null || typeof o !== "object") return true;
|
|
15674
|
+
if (o.name === "AbortError") return false;
|
|
15675
|
+
if (typeof o.code === "number") return [-1, -32005, -32603, 429, -32007].includes(o.code);
|
|
15676
|
+
if (typeof o.status === "number" && o.status !== 0) return [403, 408, 413, 429, 500, 502, 503, 504].includes(o.status);
|
|
15677
|
+
return true;
|
|
15657
15678
|
}
|
|
15658
|
-
function
|
|
15659
|
-
const
|
|
15679
|
+
function failureText(e, url) {
|
|
15680
|
+
const o = e;
|
|
15681
|
+
const parts = [o?.shortMessage ?? o?.name ?? String(e)];
|
|
15682
|
+
if (typeof o?.code === "number") parts.push(`code ${o.code}`);
|
|
15683
|
+
if (typeof o?.status === "number" && o.status !== 0) parts.push(`HTTP ${o.status}`);
|
|
15684
|
+
if (typeof o?.details === "string" && o.details !== "" && o.details !== parts[0]) parts.push(o.details);
|
|
15685
|
+
return redact(parts.join("; "), url).slice(0, 300);
|
|
15686
|
+
}
|
|
15687
|
+
function retryingHttp(url, o) {
|
|
15688
|
+
const own = o !== void 0;
|
|
15689
|
+
const base = own ? http(url, { retryCount: 0, timeout: o.timeoutMs ?? RPC_TIMEOUT_MS }) : http(url, { retryCount: RPC_RETRIES, retryDelay: RPC_RETRY_WAIT_MS, timeout: RPC_TIMEOUT_MS });
|
|
15690
|
+
const retries = o?.retryCount ?? RPC_RETRIES;
|
|
15660
15691
|
return ((params) => {
|
|
15661
15692
|
const t = base(params);
|
|
15662
15693
|
const request = (async (args, options) => {
|
|
15663
|
-
|
|
15694
|
+
let lagging = 0;
|
|
15695
|
+
let failed = 0;
|
|
15696
|
+
for (; ; ) {
|
|
15664
15697
|
try {
|
|
15665
15698
|
return await t.request(args, options);
|
|
15666
15699
|
} catch (e) {
|
|
15667
|
-
|
|
15668
|
-
|
|
15700
|
+
let wait;
|
|
15701
|
+
if (lagging < INVALID_PARAMS_RETRIES && IDEMPOTENT_READS.has(args.method) && laggingRead(e)) {
|
|
15702
|
+
wait = INVALID_PARAMS_WAIT_MS * 2 ** lagging;
|
|
15703
|
+
lagging++;
|
|
15704
|
+
} else if (own && failed < retries && transient(e)) {
|
|
15705
|
+
const after = e.headers?.get?.("Retry-After");
|
|
15706
|
+
wait = after !== null && after !== void 0 && /^[0-9]+$/.test(after) ? Math.min(Number(after) * 1e3, RETRY_AFTER_MAX_MS) : RPC_RETRY_WAIT_MS * 2 ** failed;
|
|
15707
|
+
failed++;
|
|
15708
|
+
} else throw e;
|
|
15709
|
+
o?.onRetry?.({ method: args.method, retry: lagging + failed, waitMs: wait, error: failureText(e, url) });
|
|
15710
|
+
await new Promise((r) => setTimeout(r, wait));
|
|
15669
15711
|
}
|
|
15670
15712
|
}
|
|
15671
15713
|
});
|
|
@@ -15682,7 +15724,7 @@ async function assertRobinhoodChain(client) {
|
|
|
15682
15724
|
function redact(text3, secret2) {
|
|
15683
15725
|
return secret2 === "" ? text3 : text3.split(secret2).join("<rpc>");
|
|
15684
15726
|
}
|
|
15685
|
-
var robinhoodChain, IDEMPOTENT_READS, INVALID_PARAMS_RETRIES, INVALID_PARAMS_WAIT_MS;
|
|
15727
|
+
var robinhoodChain, IDEMPOTENT_READS, INVALID_PARAMS_RETRIES, INVALID_PARAMS_WAIT_MS, RPC_RETRIES, RPC_RETRY_WAIT_MS, RPC_TIMEOUT_MS, RETRY_AFTER_MAX_MS;
|
|
15686
15728
|
var init_chain = __esm({
|
|
15687
15729
|
"../sdk/src/chain.ts"() {
|
|
15688
15730
|
"use strict";
|
|
@@ -15699,6 +15741,10 @@ var init_chain = __esm({
|
|
|
15699
15741
|
IDEMPOTENT_READS = /* @__PURE__ */ new Set(["eth_call", "eth_getCode", "eth_getStorageAt", "eth_getBalance", "eth_getBlockByNumber", "eth_getBlockByHash", "eth_blockNumber", "eth_chainId", "eth_getTransactionReceipt", "eth_getTransactionByHash", "eth_getTransactionCount", "eth_gasPrice"]);
|
|
15700
15742
|
INVALID_PARAMS_RETRIES = 4;
|
|
15701
15743
|
INVALID_PARAMS_WAIT_MS = 1e3;
|
|
15744
|
+
RPC_RETRIES = 8;
|
|
15745
|
+
RPC_RETRY_WAIT_MS = 1e3;
|
|
15746
|
+
RPC_TIMEOUT_MS = 3e4;
|
|
15747
|
+
RETRY_AFTER_MAX_MS = 1e4;
|
|
15702
15748
|
}
|
|
15703
15749
|
});
|
|
15704
15750
|
|
|
@@ -19872,6 +19918,7 @@ var init_browser = __esm({
|
|
|
19872
19918
|
"use strict";
|
|
19873
19919
|
init_define_OSTRA_PACKAGED();
|
|
19874
19920
|
init_abi();
|
|
19921
|
+
init_agent_card();
|
|
19875
19922
|
init_aggregator();
|
|
19876
19923
|
init_airdrop();
|
|
19877
19924
|
init_backup();
|
|
@@ -20248,6 +20295,10 @@ import { decodeFunctionData as decodeFunctionData4, getAddress as getAddress17,
|
|
|
20248
20295
|
import { x402Client, x402HTTPClient } from "@x402/core/client";
|
|
20249
20296
|
import { toClientEvmSigner } from "@x402/evm";
|
|
20250
20297
|
import { BatchSettlementEvmScheme } from "@x402/evm/batch-settlement/client";
|
|
20298
|
+
function notLandedError(attempts, lastReason) {
|
|
20299
|
+
const reason = lastReason.trim().slice(0, NOT_SENT_MESSAGE_MAX);
|
|
20300
|
+
return new Error(`the relayer could not land the request in ${attempts} attempts${reason === "" ? "" : `; it answered last: ${reason}`}`);
|
|
20301
|
+
}
|
|
20251
20302
|
function address(value, what) {
|
|
20252
20303
|
if (typeof value !== "string" || !isAddress6(value, { strict: false })) throw new Error(`${what} is not an address`);
|
|
20253
20304
|
return getAddress17(value);
|
|
@@ -20296,6 +20347,25 @@ function relayerChannelDeposit(needed, vaultBalance, keep = 0n) {
|
|
|
20296
20347
|
const want = needed > RELAYER_CHANNEL_DEPOSIT ? needed : RELAYER_CHANNEL_DEPOSIT;
|
|
20297
20348
|
return want < available ? want : available;
|
|
20298
20349
|
}
|
|
20350
|
+
function relayerSpendPlan(p) {
|
|
20351
|
+
const rooms = [...p.rooms];
|
|
20352
|
+
let balance = p.balance;
|
|
20353
|
+
let debt = p.debt;
|
|
20354
|
+
for (const a of p.amounts) {
|
|
20355
|
+
const i = debt > 0n ? -1 : rooms.findIndex((r) => r >= a);
|
|
20356
|
+
if (i >= 0) {
|
|
20357
|
+
rooms[i] = rooms[i] - a;
|
|
20358
|
+
continue;
|
|
20359
|
+
}
|
|
20360
|
+
const needed = debt + p.openCost + a;
|
|
20361
|
+
if (balance < needed) return false;
|
|
20362
|
+
const deposit = relayerChannelDeposit(needed, balance);
|
|
20363
|
+
balance -= deposit;
|
|
20364
|
+
debt = 0n;
|
|
20365
|
+
rooms.push(deposit - needed);
|
|
20366
|
+
}
|
|
20367
|
+
return true;
|
|
20368
|
+
}
|
|
20299
20369
|
function relayerOfferProblem(r, want) {
|
|
20300
20370
|
if (r.scheme !== "batch-settlement") return `the offer is ${r.scheme}, not batch-settlement`;
|
|
20301
20371
|
if (r.network !== want.network) return `the offer is on ${r.network}, not ${want.network}`;
|
|
@@ -20330,7 +20400,7 @@ function openChannelCall(calls, vault, token) {
|
|
|
20330
20400
|
}
|
|
20331
20401
|
return null;
|
|
20332
20402
|
}
|
|
20333
|
-
var RELAYER_DIR, VAULT_SPEND_GAS, REQUEST_TIMEOUT_MS2, MAX_STEPS, MAX_RESENDS, LANDED_TIMEOUT_MS, OPEN_READ_TRIES, OPEN_READ_INTERVAL_MS, BPS_DENOMINATOR, now, LocalSender, RelayerUnavailableError, PendingSpendUnpaidError, RelayerError, RelayerStore, RelayerClient;
|
|
20403
|
+
var RELAYER_DIR, VAULT_SPEND_GAS, REQUEST_TIMEOUT_MS2, MAX_STEPS, MAX_RESENDS, NOT_SENT_MESSAGE_MAX, LANDED_TIMEOUT_MS, OPEN_READ_TRIES, OPEN_READ_INTERVAL_MS, BPS_DENOMINATOR, now, LocalSender, RelayerUnavailableError, PendingSpendUnpaidError, RelayerError, RelayerStore, RelayerClient;
|
|
20334
20404
|
var init_relay = __esm({
|
|
20335
20405
|
"../core/src/relay.ts"() {
|
|
20336
20406
|
"use strict";
|
|
@@ -20344,6 +20414,7 @@ var init_relay = __esm({
|
|
|
20344
20414
|
REQUEST_TIMEOUT_MS2 = 24e4;
|
|
20345
20415
|
MAX_STEPS = 8;
|
|
20346
20416
|
MAX_RESENDS = 3;
|
|
20417
|
+
NOT_SENT_MESSAGE_MAX = 500;
|
|
20347
20418
|
LANDED_TIMEOUT_MS = 6e4;
|
|
20348
20419
|
OPEN_READ_TRIES = 20;
|
|
20349
20420
|
OPEN_READ_INTERVAL_MS = 500;
|
|
@@ -20381,9 +20452,11 @@ var init_relay = __esm({
|
|
|
20381
20452
|
}
|
|
20382
20453
|
};
|
|
20383
20454
|
PendingSpendUnpaidError = class extends Error {
|
|
20384
|
-
|
|
20455
|
+
onCredit;
|
|
20456
|
+
constructor(message, onCredit) {
|
|
20385
20457
|
super(message);
|
|
20386
20458
|
this.name = "PendingSpendUnpaidError";
|
|
20459
|
+
this.onCredit = onCredit;
|
|
20387
20460
|
}
|
|
20388
20461
|
};
|
|
20389
20462
|
RelayerError = class extends Error {
|
|
@@ -20572,6 +20645,55 @@ var init_relay = __esm({
|
|
|
20572
20645
|
}
|
|
20573
20646
|
return null;
|
|
20574
20647
|
}
|
|
20648
|
+
/**
|
|
20649
|
+
* Read only (nothing is retired, opened or signed): why this vault cannot pay, now, vault spends that reserve `gases`
|
|
20650
|
+
* (each as VaultService.operate reserves it: reserve's amount for that gas), or null when it can. The spends are
|
|
20651
|
+
* played in order as reserve and #ensureChannel would pay them: each from a usable relayer channel with room for it,
|
|
20652
|
+
* or else from a new channel, whose open needs the vault's debt and the open's own spend (#spendBound) on top and
|
|
20653
|
+
* takes RELAYER_CHANNEL_DEPOSIT or what it needs, at most what the vault holds. The vault's credit at the relayer is
|
|
20654
|
+
* not counted: it lowers a price only after the reservation is made. An unpaid open the relayer holds for the vault
|
|
20655
|
+
* is refused here (it is paid before anything else). An operation that sends something first (an approval before the
|
|
20656
|
+
* call it allows) checks this before its first spend, so it does not leave the first done and the rest unpaid.
|
|
20657
|
+
*/
|
|
20658
|
+
async shortfall(gases) {
|
|
20659
|
+
const facts = await this.facts();
|
|
20660
|
+
const vault = await this.#buyerVault().vaultAddress();
|
|
20661
|
+
if (await readVault(this.#client, this.#config.deployment, vault) === null) return `the vault ${vault} does not exist yet`;
|
|
20662
|
+
const state = await this.vaultState(vault);
|
|
20663
|
+
if (state.unpaidOpen !== null) return `the relayer holds an unpaid open of the vault's relayer channel ${state.unpaidOpen.channel}: the vault's next relayed operation pays it first`;
|
|
20664
|
+
const amounts = [];
|
|
20665
|
+
for (const g of gases) amounts.push(await this.#reserveAmount(g));
|
|
20666
|
+
const bound2 = await this.#spendBound();
|
|
20667
|
+
const payer = await this.#payer();
|
|
20668
|
+
const rooms = [];
|
|
20669
|
+
for (const c of await this.#records()) {
|
|
20670
|
+
if (c.retired || now() >= c.openedAt + SESSION_MAX_AGE_SECONDS) continue;
|
|
20671
|
+
const free = this.#free(c, null);
|
|
20672
|
+
if (free <= 0n) continue;
|
|
20673
|
+
const ch = await readChannel(this.#client, this.#config.deployment.batchSettlement, c.channel);
|
|
20674
|
+
const usable = payer !== null && getAddress17(c.config.payer) === payer && getAddress17(c.config.receiverAuthorizer) === facts.vault && getAddress17(c.config.receiver) === facts.split && ch.pendingWithdrawal === null;
|
|
20675
|
+
const onChain = ch.balance - BigInt(c.cumulative);
|
|
20676
|
+
if (usable) rooms.push(free < onChain ? free : onChain);
|
|
20677
|
+
}
|
|
20678
|
+
const balance = await tokenBalance(this.#client, this.#config.deployment.token, vault);
|
|
20679
|
+
const plan = (held) => relayerSpendPlan({ amounts, rooms, balance: held, debt: state.debt, openCost: bound2 });
|
|
20680
|
+
if (plan(balance)) return null;
|
|
20681
|
+
let lo = balance;
|
|
20682
|
+
let hi = balance > 0n ? balance * 2n : 1n;
|
|
20683
|
+
while (!plan(hi)) hi *= 2n;
|
|
20684
|
+
while (hi - lo > 1n) {
|
|
20685
|
+
const mid = (lo + hi) / 2n;
|
|
20686
|
+
if (plan(mid)) hi = mid;
|
|
20687
|
+
else lo = mid;
|
|
20688
|
+
}
|
|
20689
|
+
const n = gases.length;
|
|
20690
|
+
return `the vault ${vault} holds ${formatTokenAmount(balance)} USDG: ${n === 1 ? "its relayed transaction needs" : `its ${n} relayed transactions need`} it to hold ${formatTokenAmount(hi)} USDG now (with what its relayer channels have left, and a new channel's open where needed)`;
|
|
20691
|
+
}
|
|
20692
|
+
/** What reserve sets aside for a spend of `gas` (and `extraWei` of ETH it sends): the relayer's price for it, margin and tolerance included. */
|
|
20693
|
+
async #reserveAmount(gas, extraWei = 0n) {
|
|
20694
|
+
const wei = withMargin(gas * await this.#client.getGasPrice()) + extraWei;
|
|
20695
|
+
return maxAcceptedQuote(weiToTokenUnits(wei, await this.#ethUsd(), TOKEN_DECIMALS));
|
|
20696
|
+
}
|
|
20575
20697
|
/** Base units a transaction of `wei` comes to at the Chainlink price, margin included (the relayer's rule). */
|
|
20576
20698
|
async #amountFor(wei) {
|
|
20577
20699
|
return weiToTokenUnits(withMargin(wei), await this.#ethUsd(), TOKEN_DECIMALS);
|
|
@@ -20610,8 +20732,7 @@ var init_relay = __esm({
|
|
|
20610
20732
|
await (openChannel ?? ((t) => this.#buyerVault().openRelayerChannel(t)))(terms);
|
|
20611
20733
|
}
|
|
20612
20734
|
async reserve(gas, openChannel, keep = 0n, extraWei = 0n) {
|
|
20613
|
-
const
|
|
20614
|
-
const amount = maxAcceptedQuote(weiToTokenUnits(wei, await this.#ethUsd(), TOKEN_DECIMALS));
|
|
20735
|
+
const amount = await this.#reserveAmount(gas, extraWei);
|
|
20615
20736
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
20616
20737
|
const c = await this.#serial(async () => {
|
|
20617
20738
|
const found = await this.#channelFor(amount, null);
|
|
@@ -20632,6 +20753,7 @@ var init_relay = __esm({
|
|
|
20632
20753
|
async #post(calls, extra, headers = {}) {
|
|
20633
20754
|
const body2 = { calls: calls.map((c) => ({ to: getAddress17(c.to), data: c.data })) };
|
|
20634
20755
|
if (extra.prepay === true) body2.prepay = true;
|
|
20756
|
+
if (extra.onCredit === true) body2.onCredit = true;
|
|
20635
20757
|
if (extra.payer !== null) body2.payer = extra.payer;
|
|
20636
20758
|
if (extra.allowFailedSwaps === true) body2.allowFailedSwaps = true;
|
|
20637
20759
|
return this.#http("POST", "/v1/relay", JSON.stringify(body2), headers);
|
|
@@ -20826,8 +20948,11 @@ var init_relay = __esm({
|
|
|
20826
20948
|
}
|
|
20827
20949
|
async send(calls, options = {}) {
|
|
20828
20950
|
await this.facts();
|
|
20951
|
+
const credit = options.onCredit === true;
|
|
20952
|
+
const post2 = async () => this.#post(calls, { prepay: options.prepay === true, payer: credit ? null : await this.#payer(), allowFailedSwaps: options.allowFailedSwaps === true, onCredit: credit });
|
|
20953
|
+
let notSent = "";
|
|
20829
20954
|
for (let resend = 0; resend < MAX_RESENDS; resend++) {
|
|
20830
|
-
let answer = await
|
|
20955
|
+
let answer = await post2();
|
|
20831
20956
|
let again = false;
|
|
20832
20957
|
for (let step2 = 0; step2 < MAX_STEPS && !again; step2++) {
|
|
20833
20958
|
const b = answer.body;
|
|
@@ -20837,17 +20962,19 @@ var init_relay = __esm({
|
|
|
20837
20962
|
await this.#landed(hash);
|
|
20838
20963
|
return hash;
|
|
20839
20964
|
}
|
|
20965
|
+
if (answer.status === 402 && credit) throw new RelayerError(402, "no_credit", "the relayer does not send this spend on credit (it asks for payment); nothing was sent");
|
|
20840
20966
|
if (answer.status === 402) {
|
|
20841
20967
|
answer = await this.#pay(calls, answer, options);
|
|
20842
20968
|
continue;
|
|
20843
20969
|
}
|
|
20844
20970
|
if (answer.status === 403 && (error === "vault_in_debt" || error === "open_unpaid")) {
|
|
20845
|
-
if (options.reservation !== void 0 && options.reservation !== null) throw new RelayerError(403, error, String(b?.message ?? error));
|
|
20971
|
+
if (credit || options.reservation !== void 0 && options.reservation !== null) throw new RelayerError(403, error, String(b?.message ?? error));
|
|
20846
20972
|
await this.#ensureChannel(1n, options.openChannel, null);
|
|
20847
|
-
answer = await
|
|
20973
|
+
answer = await post2();
|
|
20848
20974
|
continue;
|
|
20849
20975
|
}
|
|
20850
20976
|
if (answer.status === 409 && error === "not_sent") {
|
|
20977
|
+
notSent = typeof b?.message === "string" ? b.message : "";
|
|
20851
20978
|
again = true;
|
|
20852
20979
|
continue;
|
|
20853
20980
|
}
|
|
@@ -20866,7 +20993,7 @@ var init_relay = __esm({
|
|
|
20866
20993
|
}
|
|
20867
20994
|
if (!again) throw new Error(`the relayer did not relay the request after ${MAX_STEPS} answers`);
|
|
20868
20995
|
}
|
|
20869
|
-
throw
|
|
20996
|
+
throw notLandedError(MAX_RESENDS, notSent);
|
|
20870
20997
|
}
|
|
20871
20998
|
/**
|
|
20872
20999
|
* Relayer channels past SESSION_MAX_AGE_SECONDS stop paying; returns those
|
|
@@ -21388,10 +21515,14 @@ var init_vault = __esm({
|
|
|
21388
21515
|
* Runs `fn` with what a vault spend needs to be paid. With the relayer: a
|
|
21389
21516
|
* reservation of unused relayer channel deposit for its price (a channel is
|
|
21390
21517
|
* opened first if none has room), released once `fn` is done. When a spend
|
|
21391
|
-
* signed earlier waits and no relayer channel can pay for it
|
|
21392
|
-
*
|
|
21393
|
-
*
|
|
21394
|
-
*
|
|
21518
|
+
* signed earlier waits and no relayer channel can pay for it (its key is
|
|
21519
|
+
* the one a new channel's open needs), the relayer is asked to send it on
|
|
21520
|
+
* credit, as the vault's debt, and the channel opened next pays that debt
|
|
21521
|
+
* with its first voucher; `fn` then runs as usual and its result names what
|
|
21522
|
+
* was sent first (`sentFirst`). Only when the relayer does not send it so,
|
|
21523
|
+
* the local fee payer sends it if it holds the ETH. `moves` is what the
|
|
21524
|
+
* spend takes out of this vault: a relayer channel opened from the buyer
|
|
21525
|
+
* vault for it leaves that much in the buyer vault.
|
|
21395
21526
|
*/
|
|
21396
21527
|
async #paidSpend(sender, fn, moves = 0n, gas = VAULT_SPEND_GAS, extraWei = 0n) {
|
|
21397
21528
|
await this.#finishRecoveryFirst(sender);
|
|
@@ -21403,10 +21534,30 @@ var init_vault = __esm({
|
|
|
21403
21534
|
reservation = await sender.reserve(gas, sender === this.#sender ? this.#opener() : void 0, this.#paysRelayer() ? moves : 0n, extraWei);
|
|
21404
21535
|
} catch (err) {
|
|
21405
21536
|
if (!(err instanceof PendingSpendUnpaidError)) throw err;
|
|
21537
|
+
let refused = "";
|
|
21538
|
+
const credit = err.onCredit;
|
|
21539
|
+
if (sender.relayed && credit !== void 0) {
|
|
21540
|
+
let sentFirst = null;
|
|
21541
|
+
try {
|
|
21542
|
+
sentFirst = await (credit.owner === this ? credit.unqueued() : credit.queued());
|
|
21543
|
+
} catch (e) {
|
|
21544
|
+
if (!(e instanceof RelayerError)) throw e;
|
|
21545
|
+
refused = `; the relayer did not send it on credit (${e.message})`;
|
|
21546
|
+
}
|
|
21547
|
+
if (refused === "") {
|
|
21548
|
+
const again = await sender.reserve(gas, sender === this.#sender ? this.#opener() : void 0, this.#paysRelayer() ? moves : 0n, extraWei);
|
|
21549
|
+
try {
|
|
21550
|
+
const r = await fn(sender, again);
|
|
21551
|
+
return sentFirst !== null && r !== null && typeof r === "object" ? { ...r, sentFirst } : r;
|
|
21552
|
+
} finally {
|
|
21553
|
+
sender.release(again);
|
|
21554
|
+
}
|
|
21555
|
+
}
|
|
21556
|
+
}
|
|
21406
21557
|
const local = new LocalSender(this.#client, this.#transport, this.#keys.feePayer, this.#keys.escrow);
|
|
21407
21558
|
const need = gas * await this.#client.getGasPrice() * ETH_HEADROOM + extraWei;
|
|
21408
21559
|
if (await ethBalance(this.#client, this.#keys.feePayer.address) < need) {
|
|
21409
|
-
throw new Error(`${err.message}; send at least ${formatEth(need)} ETH to the fee payer ${this.#keys.feePayer.address} and call again: it sends that operation itself`);
|
|
21560
|
+
throw new Error(`${err.message}${refused}; send at least ${formatEth(need)} ETH to the fee payer ${this.#keys.feePayer.address} and call again: it sends that operation itself`);
|
|
21410
21561
|
}
|
|
21411
21562
|
return fn(local, null);
|
|
21412
21563
|
}
|
|
@@ -21416,6 +21567,25 @@ var init_vault = __esm({
|
|
|
21416
21567
|
sender.release(reservation);
|
|
21417
21568
|
}
|
|
21418
21569
|
}
|
|
21570
|
+
/**
|
|
21571
|
+
* Sends the spend signed earlier through the relayer on credit (SendOptions.onCredit): the vault owes its price, which
|
|
21572
|
+
* the first voucher of the channel opened next pays. Returns what was sent, or null when nothing waits any more.
|
|
21573
|
+
*/
|
|
21574
|
+
async #sendPendingOnCredit() {
|
|
21575
|
+
const sender = this.#sender;
|
|
21576
|
+
if (!sender.relayed) return null;
|
|
21577
|
+
const vault = await this.vaultAddress();
|
|
21578
|
+
const v = await this.#read(vault);
|
|
21579
|
+
if (v === null) return null;
|
|
21580
|
+
const credit = {
|
|
21581
|
+
relayed: true,
|
|
21582
|
+
payer: () => sender.payer(),
|
|
21583
|
+
send: (calls, o = {}) => sender.send(calls, { ...o, reservation: null, onCredit: true }),
|
|
21584
|
+
reserve: async () => null,
|
|
21585
|
+
release: () => void 0
|
|
21586
|
+
};
|
|
21587
|
+
return this.#sendPending(vault, v, credit, null);
|
|
21588
|
+
}
|
|
21419
21589
|
/**
|
|
21420
21590
|
* Version 3 vaults: the spend is run first with a throwaway key (sdk simulateVaultSpend) and refused before it is
|
|
21421
21591
|
* signed when it would revert, or land as a failure (a SupportRecovery the other vault refuses). A signed spend that
|
|
@@ -21645,7 +21815,11 @@ the signed channel open is kept; the next open_channel or withdraw call sends it
|
|
|
21645
21815
|
const v = await this.#read(vault);
|
|
21646
21816
|
if (v === null) throw new Error(this.#missing());
|
|
21647
21817
|
if (await this.#pending(v) !== null) {
|
|
21648
|
-
throw new PendingSpendUnpaidError("a vault operation signed earlier waits to be sent and no channel to the relayer has deposit left to pay for it"
|
|
21818
|
+
throw new PendingSpendUnpaidError("a vault operation signed earlier waits to be sent and no channel to the relayer has deposit left to pay for it", {
|
|
21819
|
+
owner: this,
|
|
21820
|
+
queued: () => this.#serial(() => this.#sendPendingOnCredit()),
|
|
21821
|
+
unqueued: () => this.#sendPendingOnCredit()
|
|
21822
|
+
});
|
|
21649
21823
|
}
|
|
21650
21824
|
await this.#notFrozen(vault, "the vault");
|
|
21651
21825
|
const balance = await this.#balance(vault);
|
|
@@ -22035,6 +22209,21 @@ var init_borro2 = __esm({
|
|
|
22035
22209
|
}
|
|
22036
22210
|
return { buyerVault: buyer, usdgLent: { shares: usdg2.shares.toString(), value: formatUnitsAmount(usdg2.value, TOKEN_DECIMALS) }, stocks };
|
|
22037
22211
|
}
|
|
22212
|
+
/**
|
|
22213
|
+
* Per Borro stock whose vault of this agent exists: its market, the stock vault's borrow shares, and the market's
|
|
22214
|
+
* borrows and borrow shares accrued to this block, so that any number of borrow shares is valued now as
|
|
22215
|
+
* toAssetsUp(shares, borrowed, borrowedShares) (what fundFromYield takes off as the debt's interest).
|
|
22216
|
+
*/
|
|
22217
|
+
async debtBook() {
|
|
22218
|
+
const out = [];
|
|
22219
|
+
for (const s of borroStocks()) {
|
|
22220
|
+
const v = await this.#p.tokenVault(s.token).vaultAddress();
|
|
22221
|
+
if (await readVault(this.#p.client, this.#p.config.deployment, v) === null) continue;
|
|
22222
|
+
const p = await readBorroPosition(this.#p.client, v, s);
|
|
22223
|
+
out.push({ symbol: s.symbol, marketId: s.marketId, borrowShares: p.borrowShares, borrowed: p.borrowed, borrowedShares: p.borrowedShares });
|
|
22224
|
+
}
|
|
22225
|
+
return out;
|
|
22226
|
+
}
|
|
22038
22227
|
// -------------------------------------------------------------------------
|
|
22039
22228
|
// Lend and redeem
|
|
22040
22229
|
// -------------------------------------------------------------------------
|
|
@@ -23458,24 +23647,17 @@ function imageUri(value) {
|
|
|
23458
23647
|
return value;
|
|
23459
23648
|
}
|
|
23460
23649
|
function profileFile(p) {
|
|
23461
|
-
const
|
|
23462
|
-
|
|
23463
|
-
const x = link2(p.x, "x");
|
|
23464
|
-
const telegram = link2(p.telegram, "telegram");
|
|
23465
|
-
if (website !== void 0) services.push({ name: "web", endpoint: website });
|
|
23466
|
-
if (x !== void 0) services.push({ name: "X", endpoint: x });
|
|
23467
|
-
if (telegram !== void 0) services.push({ name: "Telegram", endpoint: telegram });
|
|
23468
|
-
services.push({ name: "agentWallet", endpoint: `eip155:${ROBINHOOD_CHAIN_ID}:${p.vault}` });
|
|
23650
|
+
const id = p.agentId === void 0 || p.agentId === null ? null : p.agentId;
|
|
23651
|
+
if (id !== null && !/^(0|[1-9][0-9]{0,29})$/.test(id)) throw new RangeError("an agent id is a decimal number");
|
|
23469
23652
|
const image = imageUri(p.image);
|
|
23470
|
-
const description = text2(p.description, "description", 1e3);
|
|
23471
23653
|
return {
|
|
23472
23654
|
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
|
|
23473
|
-
name:
|
|
23474
|
-
|
|
23655
|
+
name: id === null ? AGENT_NAME : `${AGENT_NAME} #${id}`,
|
|
23656
|
+
description: AGENT_DESCRIPTION,
|
|
23475
23657
|
...image === void 0 ? {} : { image },
|
|
23476
|
-
services,
|
|
23658
|
+
services: [{ name: "agentWallet", endpoint: `eip155:${ROBINHOOD_CHAIN_ID}:${p.vault}` }],
|
|
23477
23659
|
active: true,
|
|
23478
|
-
registrations:
|
|
23660
|
+
registrations: id === null ? [] : [{ agentId: Number(id), agentRegistry: `eip155:${ROBINHOOD_CHAIN_ID}:${ERC8004_IDENTITY_REGISTRY}` }]
|
|
23479
23661
|
};
|
|
23480
23662
|
}
|
|
23481
23663
|
function tokenMetadataFile(m) {
|
|
@@ -23514,6 +23696,9 @@ function uploaderUrl(relayerUrl) {
|
|
|
23514
23696
|
function uploadJson(relayerUrl, value) {
|
|
23515
23697
|
return post(`${uploaderUrl(relayerUrl)}/json`, JSON.stringify(value), "application/json");
|
|
23516
23698
|
}
|
|
23699
|
+
function agentCardUri(relayerUrl, agentId) {
|
|
23700
|
+
return post(`${uploaderUrl(relayerUrl)}/agent-card`, JSON.stringify({ agentId }), "application/json");
|
|
23701
|
+
}
|
|
23517
23702
|
function uploadImage(relayerUrl, bytes) {
|
|
23518
23703
|
const base = uploaderUrl(relayerUrl);
|
|
23519
23704
|
if (bytes.length === 0 || bytes.length > MAX_UPLOAD_IMAGE_BYTES) throw new RangeError(`the image must be 1 to ${MAX_UPLOAD_IMAGE_BYTES} bytes (it is ${bytes.length})`);
|
|
@@ -23521,13 +23706,15 @@ function uploadImage(relayerUrl, bytes) {
|
|
|
23521
23706
|
if (type === null) throw new RangeError("the image is not a PNG, JPEG, WebP or GIF");
|
|
23522
23707
|
return post(`${base}/image`, new Blob([new Uint8Array(bytes)], { type }), type);
|
|
23523
23708
|
}
|
|
23524
|
-
var MAX_UPLOAD_IMAGE_BYTES;
|
|
23709
|
+
var MAX_UPLOAD_IMAGE_BYTES, AGENT_NAME, AGENT_DESCRIPTION;
|
|
23525
23710
|
var init_publish = __esm({
|
|
23526
23711
|
"../core/src/publish.ts"() {
|
|
23527
23712
|
"use strict";
|
|
23528
23713
|
init_define_OSTRA_PACKAGED();
|
|
23529
23714
|
init_src();
|
|
23530
23715
|
MAX_UPLOAD_IMAGE_BYTES = 1048576;
|
|
23716
|
+
AGENT_NAME = "Ostra Agent";
|
|
23717
|
+
AGENT_DESCRIPTION = "An AI agent with an Ostra post-quantum privacy vault on Robinhood Chain. Its earnings and payments stay in its own vault, signed with one-time keys.";
|
|
23531
23718
|
}
|
|
23532
23719
|
});
|
|
23533
23720
|
|
|
@@ -23562,7 +23749,7 @@ function simulatedGas(gasUsed) {
|
|
|
23562
23749
|
const g = gasUsed * 5n / 4n + SPEND_GAS_HEADROOM2;
|
|
23563
23750
|
return g > VAULT_SPEND_GAS ? g : VAULT_SPEND_GAS;
|
|
23564
23751
|
}
|
|
23565
|
-
var LAUNCHPAD_DIR, CREATE_VAULT_GAS2, LAUNCH_GAS_HEADROOM, PAIRS_READ_CONCURRENCY, SPEND_GAS_HEADROOM2, DAY, TOKEN_LIST_MAX, METADATA_MAX_BYTES, launchedEvent, POOL_SETTING_NAMES, LaunchpadService;
|
|
23752
|
+
var LAUNCHPAD_DIR, CREATE_VAULT_GAS2, LAUNCH_GAS_HEADROOM, PAIRS_READ_CONCURRENCY, SPEND_GAS_HEADROOM2, DAY, TOKEN_LIST_MAX, METADATA_MAX_BYTES, launchedEvent, POOL_SETTING_NAMES, WOTS_GAS_SPREAD, STAND_IN_URI, LaunchpadService;
|
|
23566
23753
|
var init_launchpad = __esm({
|
|
23567
23754
|
"../core/src/launchpad.ts"() {
|
|
23568
23755
|
"use strict";
|
|
@@ -23598,8 +23785,11 @@ var init_launchpad = __esm({
|
|
|
23598
23785
|
volatility_fee: POOL_SETTING.VOLATILITY_FEE,
|
|
23599
23786
|
max_tx_move: POOL_SETTING.MAX_TX_MOVE
|
|
23600
23787
|
};
|
|
23788
|
+
WOTS_GAS_SPREAD = 100000n;
|
|
23789
|
+
STAND_IN_URI = `ipfs://bafkrei${"a".repeat(52)}`;
|
|
23601
23790
|
LaunchpadService = class {
|
|
23602
23791
|
#client;
|
|
23792
|
+
#logsClient;
|
|
23603
23793
|
#transport;
|
|
23604
23794
|
#config;
|
|
23605
23795
|
#keys;
|
|
@@ -23614,6 +23804,7 @@ var init_launchpad = __esm({
|
|
|
23614
23804
|
constructor(p) {
|
|
23615
23805
|
if (p.creator.kind !== "creator" || p.buyer.kind !== "buyer") throw new Error("the launchpad takes the agent's buyer and creator vaults");
|
|
23616
23806
|
this.#client = p.client;
|
|
23807
|
+
this.#logsClient = p.logsClient ?? p.client;
|
|
23617
23808
|
this.#transport = p.transport;
|
|
23618
23809
|
this.#config = p.config;
|
|
23619
23810
|
this.#keys = p.keys;
|
|
@@ -24402,6 +24593,52 @@ var init_launchpad = __esm({
|
|
|
24402
24593
|
const text3 = await this.#folder.read("agent.json");
|
|
24403
24594
|
return text3 === void 0 ? null : JSON.parse(text3);
|
|
24404
24595
|
}
|
|
24596
|
+
/**
|
|
24597
|
+
* The agent's registration read from the chain when agent.json does not hold it: an identity its creator vault
|
|
24598
|
+
* registered (the Identity Registry's Registered events from the deployment's first block) and still owns. A
|
|
24599
|
+
* registration that landed after its call stopped (the relayer refused the send and a later operation sent the kept
|
|
24600
|
+
* spend, or the process stopped before agent.json was written) is found here and written to agent.json, so the agent
|
|
24601
|
+
* is never registered twice. An identity someone else registered and sent to the creator vault (an ERC-721 transfer
|
|
24602
|
+
* the vault accepts) is no registration of this agent: with no Registered event of the vault, this is null. A
|
|
24603
|
+
* registration sent again just now is read from its receipt instead (#recordFromReceipt), not from logs that may lag.
|
|
24604
|
+
*/
|
|
24605
|
+
async #recoverAgentRecord() {
|
|
24606
|
+
const vault = getAddress24(await this.#creator.vaultAddress());
|
|
24607
|
+
const owned = await this.#client.readContract({ address: ERC8004_IDENTITY_REGISTRY, abi: identityRegistryAbi, functionName: "balanceOf", args: [vault] });
|
|
24608
|
+
if (owned === 0n) return null;
|
|
24609
|
+
const to = await this.#logsClient.getBlockNumber({ cacheTime: 0 });
|
|
24610
|
+
const logs = await getLogsChunked(this.#logsClient, { address: ERC8004_IDENTITY_REGISTRY, event: agentRegisteredEvent, args: { owner: vault }, fromBlock: BigInt(this.#config.deployment.fromBlock), toBlock: to });
|
|
24611
|
+
for (const log2 of logs) {
|
|
24612
|
+
const { agentId, agentURI } = log2.args;
|
|
24613
|
+
const who = await readAgentIdentity(this.#client, agentId);
|
|
24614
|
+
if (who === null || getAddress24(who.owner) !== vault) continue;
|
|
24615
|
+
const record = { agentId: agentId.toString(), uri: agentURI, txHash: log2.transactionHash, at: Math.floor(Date.now() / 1e3) };
|
|
24616
|
+
await this.#folder.write("agent.json", JSON.stringify(record, null, 2));
|
|
24617
|
+
return record;
|
|
24618
|
+
}
|
|
24619
|
+
return null;
|
|
24620
|
+
}
|
|
24621
|
+
/**
|
|
24622
|
+
* The registration transaction `txHash` of the creator vault, read from its receipt (the vault's AgentRegistered
|
|
24623
|
+
* event) and written to agent.json; null when it registered nothing. `uri` is the file it registered with.
|
|
24624
|
+
*/
|
|
24625
|
+
async #recordFromReceipt(txHash, uri2) {
|
|
24626
|
+
const vault = getAddress24(await this.#creator.vaultAddress());
|
|
24627
|
+
const receipt = await this.#client.getTransactionReceipt({ hash: txHash });
|
|
24628
|
+
let agentId;
|
|
24629
|
+
for (const log2 of receipt.logs) {
|
|
24630
|
+
if (getAddress24(log2.address) !== vault) continue;
|
|
24631
|
+
try {
|
|
24632
|
+
const e = decodeEventLog3({ abi: ostraVaultAbi, data: log2.data, topics: log2.topics });
|
|
24633
|
+
if (e.eventName === "AgentRegistered") agentId = e.args.agentId.toString();
|
|
24634
|
+
} catch {
|
|
24635
|
+
}
|
|
24636
|
+
}
|
|
24637
|
+
if (agentId === void 0) return null;
|
|
24638
|
+
const record = { agentId, uri: uri2, txHash, at: Math.floor(Date.now() / 1e3) };
|
|
24639
|
+
await this.#folder.write("agent.json", JSON.stringify(record, null, 2));
|
|
24640
|
+
return record;
|
|
24641
|
+
}
|
|
24405
24642
|
/** The agent's identity: its creator vault, the profile URI it set and its ERC-8004 agent id; or, given `account`, that account's profile URI. */
|
|
24406
24643
|
async profile(accountText) {
|
|
24407
24644
|
const account = accountText === void 0 ? await this.#creator.vaultAddress() : address2(accountText, "account");
|
|
@@ -24418,32 +24655,21 @@ var init_launchpad = __esm({
|
|
|
24418
24655
|
/** Registers the creator vault as an agent in the ERC-8004 Identity Registry, its registration file at `uri`; the vault owns the identity and is its agentWallet. */
|
|
24419
24656
|
async registerAgent(uri2) {
|
|
24420
24657
|
checkUri(uri2);
|
|
24421
|
-
|
|
24422
|
-
const existing = await this.#agentRecord();
|
|
24423
|
-
if (existing !== null) throw new Error(`this agent is registered already as agent ${existing.agentId}:
|
|
24658
|
+
await this.#identityVault();
|
|
24659
|
+
const existing = await this.#agentRecord() ?? await this.#recoverAgentRecord();
|
|
24660
|
+
if (existing !== null) throw new Error(`this agent is registered already as agent ${existing.agentId}: publish_profile publishes its profile again; nothing was signed`);
|
|
24424
24661
|
const r = await this.#simulatedSpend(this.#creator, this.#creatorSender, VAULT_ACTION.REGISTER_AGENT, registerAgentParams(uri2), "agent registration");
|
|
24425
24662
|
if (r.status !== "sent") return r;
|
|
24426
|
-
const
|
|
24427
|
-
|
|
24428
|
-
|
|
24429
|
-
if (getAddress24(log2.address) !== vault) continue;
|
|
24430
|
-
try {
|
|
24431
|
-
const e = decodeEventLog3({ abi: ostraVaultAbi, data: log2.data, topics: log2.topics });
|
|
24432
|
-
if (e.eventName === "AgentRegistered") agentId = e.args.agentId.toString();
|
|
24433
|
-
} catch {
|
|
24434
|
-
}
|
|
24435
|
-
}
|
|
24436
|
-
if (agentId === void 0) throw new Error(`the registration ${r.txHash} landed without an AgentRegistered event`);
|
|
24437
|
-
const record = { agentId, uri: uri2, txHash: r.txHash, at: Math.floor(Date.now() / 1e3) };
|
|
24438
|
-
await this.#folder.write("agent.json", JSON.stringify(record, null, 2));
|
|
24439
|
-
return { ...r, agentId };
|
|
24663
|
+
const record = await this.#recordFromReceipt(r.txHash, uri2);
|
|
24664
|
+
if (record === null) throw new Error(`the registration ${r.txHash} landed without an AgentRegistered event`);
|
|
24665
|
+
return { ...r, agentId: record.agentId };
|
|
24440
24666
|
}
|
|
24441
24667
|
/** Points the agent's ERC-8004 identity at a new registration file. */
|
|
24442
24668
|
async setAgentUri(uri2) {
|
|
24443
24669
|
checkUri(uri2);
|
|
24444
24670
|
await this.#identityVault();
|
|
24445
24671
|
const record = await this.#agentRecord();
|
|
24446
|
-
if (record === null) throw new Error("this agent has no ERC-8004 identity yet:
|
|
24672
|
+
if (record === null) throw new Error("this agent has no ERC-8004 identity yet: publish_profile registers it; nothing was signed");
|
|
24447
24673
|
const r = await this.#simulatedSpend(this.#creator, this.#creatorSender, VAULT_ACTION.SET_AGENT_URI, setAgentUriParams({ agentId: BigInt(record.agentId), uri: uri2 }), "agent registration file");
|
|
24448
24674
|
if (r.status === "sent") await this.#folder.write("agent.json", JSON.stringify({ ...record, uri: uri2, at: Math.floor(Date.now() / 1e3) }, null, 2));
|
|
24449
24675
|
return r;
|
|
@@ -24469,15 +24695,38 @@ var init_launchpad = __esm({
|
|
|
24469
24695
|
if (version < VAULT_VERSION) throw new Error(`the creator vault ${s.vault} runs version ${version}, not ${VAULT_VERSION}; nothing was signed`);
|
|
24470
24696
|
}
|
|
24471
24697
|
/**
|
|
24472
|
-
* Publishes the agent's profile
|
|
24473
|
-
*
|
|
24474
|
-
*
|
|
24698
|
+
* Publishes the agent's Ostra profile, the same for every Ostra agent (profileFile: its name and number, Ostra's
|
|
24699
|
+
* description, its Ostra card, its creator vault as agentWallet), and registers the agent in ERC-8004 when it is not
|
|
24700
|
+
* registered yet: the profile without a number is published, the creator vault registers the agent with it, and the
|
|
24701
|
+
* profile is published again with the agent's number and card, its ERC-8004 identity pointed at it. Called again, it
|
|
24702
|
+
* carries on from where it stopped (what the chain and agent.json hold decides).
|
|
24475
24703
|
*/
|
|
24476
|
-
async publishProfile(
|
|
24477
|
-
const
|
|
24704
|
+
async publishProfile() {
|
|
24705
|
+
const before = await this.#agentRecord() ?? await this.#recoverAgentRecord();
|
|
24706
|
+
if (before !== null) return { agentId: before.agentId, registration: null, unnumbered: null, ...await this.#publishProfileFile(before) };
|
|
24707
|
+
const first = await this.#publishProfileFile(null);
|
|
24708
|
+
const unnumbered = { uri: first.uri, profile: first.profile };
|
|
24709
|
+
if (first.profile.status !== "sent") {
|
|
24710
|
+
const resent = first.profile.status === "resent_pending" ? first.profile.resent : null;
|
|
24711
|
+
const landed = resent !== null && resent.operation === "vault_spend" && resent.action === VAULT_ACTION.REGISTER_AGENT ? await this.#recordFromReceipt(resent.txHash, first.uri) : null;
|
|
24712
|
+
if (landed === null) return { agentId: null, registration: null, unnumbered, ...first };
|
|
24713
|
+
return { agentId: landed.agentId, registration: null, unnumbered, ...await this.#publishProfileFile(landed) };
|
|
24714
|
+
}
|
|
24715
|
+
const registration = await this.registerAgent(first.uri);
|
|
24478
24716
|
const record = await this.#agentRecord();
|
|
24479
|
-
|
|
24717
|
+
if (registration.status !== "sent" || record === null) return { agentId: null, registration, unnumbered, ...first };
|
|
24718
|
+
return { agentId: record.agentId, registration, unnumbered, ...await this.#publishProfileFile(record) };
|
|
24719
|
+
}
|
|
24720
|
+
/**
|
|
24721
|
+
* Builds the profile of the agent (`record`: its registration, or null before it has one), pins it through the
|
|
24722
|
+
* uploader, sets it in OstraRegistry (for the creator vaults of the other pairs it launched from too), and points the
|
|
24723
|
+
* ERC-8004 identity at it when the agent is registered.
|
|
24724
|
+
*/
|
|
24725
|
+
async #publishProfileFile(record) {
|
|
24726
|
+
const vault = await this.#identityVault();
|
|
24727
|
+
const agentId = record?.agentId ?? null;
|
|
24480
24728
|
uploaderUrl(this.#config.relayerUrl);
|
|
24729
|
+
const file = profileFile({ vault, agentId, image: await agentCardUri(this.#config.relayerUrl, agentId) });
|
|
24481
24730
|
const beforeUri = await this.#profileUri(vault);
|
|
24482
24731
|
const before = await readIpfsJson(beforeUri);
|
|
24483
24732
|
if (beforeUri !== null && beforeUri.startsWith("ipfs://") && before === null) throw new Error(`the profile published before (${beforeUri}) cannot be read now, so its Ostrapad listing could not be kept: try again later; nothing was signed`);
|
|
@@ -24503,6 +24752,32 @@ var init_launchpad = __esm({
|
|
|
24503
24752
|
if (profile.status !== "sent" || record === null) return { uri: uri2, profile, agentUri: null, pairCreators };
|
|
24504
24753
|
return { uri: uri2, profile, agentUri: await this.setAgentUri(uri2), pairCreators };
|
|
24505
24754
|
}
|
|
24755
|
+
/**
|
|
24756
|
+
* Read only: why the creator vault cannot pay for publishRegistrationFile now, or null when it can or does not pay
|
|
24757
|
+
* through the relayer. Its spends (the profile and, once the agent is registered, its agent URI) are simulated as
|
|
24758
|
+
* setProfile and setAgentUri send them, with the URI set now (or one of an ipfs:// URI's length) in place of the
|
|
24759
|
+
* file's, and each is counted at the gas it will be reserved (simulatedGas) with WOTS_GAS_SPREAD added (a simulation
|
|
24760
|
+
* signs with a throwaway key, and a WOTS signature's verification costs more or less with each message);
|
|
24761
|
+
* RelayerClient.shortfall replays their payment. A
|
|
24762
|
+
* spend the creator vault signed earlier and has not sent is refused here: its next operation would send that one
|
|
24763
|
+
* instead of the profile.
|
|
24764
|
+
*/
|
|
24765
|
+
async publishShortfall() {
|
|
24766
|
+
if (!(this.#creatorSender instanceof RelayerClient)) return null;
|
|
24767
|
+
const s = await this.#creator.state();
|
|
24768
|
+
if (!s.exists) return `the creator vault ${s.vault} does not exist yet`;
|
|
24769
|
+
if ((await this.#creator.spendSlot())?.pending != null) {
|
|
24770
|
+
return `the creator vault ${s.vault} signed a spend earlier that has not landed: its next operation sends that one first (publish_profile with the same fields does), then publish again`;
|
|
24771
|
+
}
|
|
24772
|
+
const record = await this.#agentRecord();
|
|
24773
|
+
const uri2 = record?.uri ?? await this.#profileUri(s.vault) ?? STAND_IN_URI;
|
|
24774
|
+
const relayer = await this.#creatorSender.payer();
|
|
24775
|
+
const gasOf = async (action, params) => simulatedGas((await simulateVaultSpend(this.#client, this.#config.deployment, { relayer, vault: s.vault, action, params })).gasUsed + WOTS_GAS_SPREAD);
|
|
24776
|
+
const gases = [await gasOf(VAULT_ACTION.SET_PROFILE, setProfileParams(uri2))];
|
|
24777
|
+
if (record !== null) gases.push(await gasOf(VAULT_ACTION.SET_AGENT_URI, setAgentUriParams({ agentId: BigInt(record.agentId), uri: uri2 })));
|
|
24778
|
+
const short = await this.#creatorSender.shortfall(gases);
|
|
24779
|
+
return short === null ? null : `${short}; fund_creator_vault moves USDG into it`;
|
|
24780
|
+
}
|
|
24506
24781
|
/**
|
|
24507
24782
|
* Pins `file`, a registration file built from the current one (Ostrapad's listing, pad.ts), and makes it the
|
|
24508
24783
|
* agent's profile in OstraRegistry and its ERC-8004 registration file when it is registered.
|
|
@@ -24809,7 +25084,7 @@ var init_pad2 = __esm({
|
|
|
24809
25084
|
publish(offers) {
|
|
24810
25085
|
return this.#serial(async () => {
|
|
24811
25086
|
const { agentId, creatorVault } = await this.#p.identity();
|
|
24812
|
-
if (agentId === null) throw new Error("this agent is not registered in ERC-8004 yet: publish_profile
|
|
25087
|
+
if (agentId === null) throw new Error("this agent is not registered in ERC-8004 yet: publish_profile registers it; nothing was signed");
|
|
24813
25088
|
const vault = await this.#vault();
|
|
24814
25089
|
const current = await this.#p.currentFile();
|
|
24815
25090
|
if (current === null) throw new Error("this agent has no published profile yet: publish_profile first; nothing was signed");
|
|
@@ -24818,7 +25093,11 @@ var init_pad2 = __esm({
|
|
|
24818
25093
|
if (offers !== null) {
|
|
24819
25094
|
const entry = padServiceEntry({ provider: vault, offers }, this.#pad, this.#p.config.chainId);
|
|
24820
25095
|
const digest = padListingDigest(agentId, creatorVault, this.#pad, this.#p.config.chainId);
|
|
24821
|
-
if (!await this.#approved(vault, digest))
|
|
25096
|
+
if (!await this.#approved(vault, digest)) {
|
|
25097
|
+
const short = this.#p.publishShortfall === void 0 ? null : await this.#p.publishShortfall();
|
|
25098
|
+
if (short !== null) throw new Error(`the creator vault could not publish the listing now, so its approval is not given: ${short}; nothing was signed`);
|
|
25099
|
+
approval = await this.#approveAlone(digest, "Ostrapad listing approval");
|
|
25100
|
+
}
|
|
24822
25101
|
services.push(entry);
|
|
24823
25102
|
}
|
|
24824
25103
|
const out = await this.#p.publishFile({ ...current, services });
|
|
@@ -25542,6 +25821,19 @@ var init_pay = __esm({
|
|
|
25542
25821
|
|
|
25543
25822
|
// ../core/src/raeto.ts
|
|
25544
25823
|
import { getAddress as getAddress27, hashMessage, isAddress as isAddress13, parseAbi as parseAbi6 } from "viem";
|
|
25824
|
+
function netYieldSince(mark, now3, book) {
|
|
25825
|
+
if (mark.debts === void 0) return null;
|
|
25826
|
+
const high = BigInt(mark.price);
|
|
25827
|
+
const earned = now3.price > high ? BigInt(mark.shares) * (now3.price - high) / now3.unit : 0n;
|
|
25828
|
+
let interest = 0n;
|
|
25829
|
+
for (const d of mark.debts) {
|
|
25830
|
+
const m = book.find((b) => b.marketId.toLowerCase() === d.marketId.toLowerCase());
|
|
25831
|
+
if (m === void 0) return null;
|
|
25832
|
+
const owesNow = toAssetsUp(BigInt(d.borrowShares), m.borrowed, m.borrowedShares);
|
|
25833
|
+
if (owesNow > BigInt(d.debt)) interest += owesNow - BigInt(d.debt);
|
|
25834
|
+
}
|
|
25835
|
+
return { earned, interest };
|
|
25836
|
+
}
|
|
25545
25837
|
function raetoImages(answer) {
|
|
25546
25838
|
const out = [];
|
|
25547
25839
|
const choices = answer?.choices;
|
|
@@ -25788,15 +26080,20 @@ var init_raeto = __esm({
|
|
|
25788
26080
|
return this.#scrub(await this.#call("POST", "/v1/chat/completions", request, await this.#key(), COMPLETION_TIMEOUT_MS));
|
|
25789
26081
|
}
|
|
25790
26082
|
/**
|
|
25791
|
-
* What the vault's cash vault shares earn, as credits. Kept here: a mark
|
|
25792
|
-
* a high-water mark, so a price that falls and comes back earns nothing
|
|
25793
|
-
*
|
|
25794
|
-
*
|
|
25795
|
-
*
|
|
25796
|
-
*
|
|
25797
|
-
*
|
|
25798
|
-
*
|
|
25799
|
-
* what
|
|
26083
|
+
* What the vault's cash vault shares earn, net of the agent's Borro debts' interest, as credits. Kept here: a mark
|
|
26084
|
+
* (the shares, the highest share price read: a high-water mark, so a price that falls and comes back earns nothing
|
|
26085
|
+
* until it passes its high; and each Borro debt's borrow shares with what they owed), what is owed (netYieldSince,
|
|
26086
|
+
* added on every call: the shares' rise over the high less the interest the marked debts accrued; it can fall below
|
|
26087
|
+
* zero, and nothing is sent until it is back above `min`), and USDG redeemed for it and not sent yet (`ready`), with
|
|
26088
|
+
* the vault's spend slot its transfer is signed at. The interest comes off because the carry strategy borrows USDG
|
|
26089
|
+
* from Borro into this same cash vault: the shares' rise is not earned while the loan behind them owes interest.
|
|
26090
|
+
* A call adds what was earned since the mark, moves the mark to now, sends what was redeemed and not sent first, and
|
|
26091
|
+
* else, when what is owed is at least `min` USDG, redeems that from the cash vault and sends what the redeem paid (at
|
|
26092
|
+
* most what is owed) to Raeto's payTo. A transfer of `ready` that another operation of the vault sent first (it sends
|
|
26093
|
+
* a signed spend before its own) is found at its slot and not paid again. Shares and debts added or removed count
|
|
26094
|
+
* from the read after; a full exit leaves what was owed until then. A mark kept before debts were marked (MCP 0.1.10
|
|
26095
|
+
* and earlier) earns nothing for the time since it, as that time's interest cannot be read back. Raeto's terms are
|
|
26096
|
+
* checked before anything is redeemed. Calls run one after the other.
|
|
25800
26097
|
*/
|
|
25801
26098
|
fundFromYield(min2 = "1") {
|
|
25802
26099
|
return this.#serial(async () => {
|
|
@@ -25810,20 +26107,25 @@ var init_raeto = __esm({
|
|
|
25810
26107
|
return { shares, unit, price };
|
|
25811
26108
|
};
|
|
25812
26109
|
const now3 = await read();
|
|
26110
|
+
const book = await this.#p.borro.debtBook();
|
|
26111
|
+
const debts = book.filter((b) => b.borrowShares > 0n).map((b) => ({ marketId: b.marketId, borrowShares: b.borrowShares.toString(), debt: toAssetsUp(b.borrowShares, b.borrowed, b.borrowedShares).toString() }));
|
|
25813
26112
|
const text3 = await this.#p.folder.read(YIELD_FILE);
|
|
25814
26113
|
const kept = text3 === void 0 ? null : JSON.parse(text3);
|
|
25815
|
-
const usd4 = (x) => formatUnitsAmount(x, TOKEN_DECIMALS);
|
|
26114
|
+
const usd4 = (x) => formatUnitsAmount(x > 0n ? x : 0n, TOKEN_DECIMALS);
|
|
25816
26115
|
const write = (m) => this.#p.folder.write(YIELD_FILE, JSON.stringify(m));
|
|
25817
26116
|
if (kept === null || getAddress27(kept.vault) !== target) {
|
|
25818
|
-
await write({ vault: target, shares: now3.shares.toString(), price: now3.price.toString(), owed: "0", ready: "0" });
|
|
25819
|
-
return { vault: target, owed: "0", sent: "0", note: "the mark is set now: what the shares earn from here is sent as credits by later calls" };
|
|
26117
|
+
await write({ vault: target, shares: now3.shares.toString(), price: now3.price.toString(), owed: "0", ready: "0", debts });
|
|
26118
|
+
return { vault: target, owed: "0", sent: "0", note: "the mark is set now: what the shares earn from here, less the Borro debts' interest, is sent as credits by later calls" };
|
|
25820
26119
|
}
|
|
25821
26120
|
const high = BigInt(kept.price);
|
|
25822
|
-
|
|
26121
|
+
const net = netYieldSince(kept, now3, book);
|
|
26122
|
+
let owed = BigInt(kept.owed) + (net === null ? 0n : net.earned - net.interest);
|
|
25823
26123
|
let ready = BigInt(kept.ready);
|
|
25824
|
-
const mark = { ...kept, vault: target, shares: now3.shares.toString(), price: (now3.price > high ? now3.price : high).toString(), owed: owed.toString(), ready: ready.toString() };
|
|
26124
|
+
const mark = { ...kept, vault: target, shares: now3.shares.toString(), price: (now3.price > high ? now3.price : high).toString(), owed: owed.toString(), ready: ready.toString(), debts };
|
|
25825
26125
|
await write(mark);
|
|
25826
|
-
|
|
26126
|
+
const unmarked = net === null ? "the mark did not follow the Borro debts yet (kept by an earlier version): nothing is counted for the time since it, and the mark now follows them; " : "";
|
|
26127
|
+
if (ready === 0n && owed < 0n) return { vault: target, owed: "0", sent: "0", note: `${unmarked}the Borro debts' interest since the mark is more than the shares earned: ${formatUnitsAmount(-owed, TOKEN_DECIMALS)} USDG to make up before anything is sent` };
|
|
26128
|
+
if (ready === 0n && (owed === 0n || owed < minimum)) return { vault: target, owed: usd4(owed), sent: "0", note: `${unmarked}under ${min2} USDG: kept for a later call` };
|
|
25827
26129
|
const { payTo } = await this.terms();
|
|
25828
26130
|
if (ready > 0n && mark.readySlot !== void 0) {
|
|
25829
26131
|
const slot2 = { nonce: BigInt(mark.readySlot.nonce), keyIndex: BigInt(mark.readySlot.keyIndex) };
|
|
@@ -25859,7 +26161,7 @@ var init_raeto = __esm({
|
|
|
25859
26161
|
ready = paid <= 0n ? 0n : paid < owed ? paid : owed;
|
|
25860
26162
|
owed -= ready;
|
|
25861
26163
|
const afterHigh = BigInt(mark.price) > after.price ? BigInt(mark.price) : after.price;
|
|
25862
|
-
await write({ vault: target, shares: after.shares.toString(), price: afterHigh.toString(), owed: owed.toString(), ready: ready.toString() });
|
|
26164
|
+
await write({ vault: target, shares: after.shares.toString(), price: afterHigh.toString(), owed: owed.toString(), ready: ready.toString(), debts });
|
|
25863
26165
|
if (ready === 0n) return { vault: target, owed: usd4(owed), sent: "0", note: "the redeem paid nothing into the vault", redeem };
|
|
25864
26166
|
}
|
|
25865
26167
|
const slot = await this.#p.buyer.spendSlot();
|
|
@@ -25879,10 +26181,10 @@ var init_raeto = __esm({
|
|
|
25879
26181
|
}
|
|
25880
26182
|
});
|
|
25881
26183
|
|
|
25882
|
-
//
|
|
26184
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/abi.ts
|
|
25883
26185
|
var ostraRouterAbi, ostraStakeAbi, ostraPrivatePoolAbi, OSTRA_SWAP_ESCROW_CREATION_CODE, OSTRA_SHIELD_ESCROW_CREATION_CODE, ostraQuoteBatchAbi, OSTRA_QUOTE_BATCH_CREATION_CODE;
|
|
25884
26186
|
var init_abi2 = __esm({
|
|
25885
|
-
"
|
|
26187
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/abi.ts"() {
|
|
25886
26188
|
"use strict";
|
|
25887
26189
|
init_define_OSTRA_PACKAGED();
|
|
25888
26190
|
ostraRouterAbi = [
|
|
@@ -28747,10 +29049,10 @@ var init_abi2 = __esm({
|
|
|
28747
29049
|
}
|
|
28748
29050
|
});
|
|
28749
29051
|
|
|
28750
|
-
//
|
|
29052
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/constants.ts
|
|
28751
29053
|
var LOG_WINDOW_BLOCKS2, USDG2, WETH2, HUBS, ETH, UNISWAP_V3_FACTORY, UNISWAP_V3_QUOTER_V2, V3_FEE_TIERS, UNISWAP_V4_POOL_MANAGER2, UNISWAP_V4_QUOTER, MULTICALL32, OSTRA_HOOK, PONS_HOOK2, ROUTABLE_HOOKS, FEE_TIERS, COMMAND, V4_ACTION, CONTRACT_BALANCE, MSG_SENDER, ADDRESS_THIS, OPEN_DELTA, QUOTE_GAS_LIMIT, QUOTES_PER_CALL, QUOTE_GAS_LIMIT_RETRY, QUOTES_PER_RETRY_CALL, QUOTE_BATCH_OVERHEAD_GAS, V3_MIN_SQRT_PRICE_LIMIT, V3_MAX_SQRT_PRICE_LIMIT, DEFAULT_SLIPPAGE_BPS, MAX_SLIPPAGE_BPS, DEFAULT_ORDER_TTL_SECONDS;
|
|
28752
29054
|
var init_constants2 = __esm({
|
|
28753
|
-
"
|
|
29055
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/constants.ts"() {
|
|
28754
29056
|
"use strict";
|
|
28755
29057
|
init_define_OSTRA_PACKAGED();
|
|
28756
29058
|
LOG_WINDOW_BLOCKS2 = 10000000n;
|
|
@@ -28792,11 +29094,11 @@ var init_constants2 = __esm({
|
|
|
28792
29094
|
}
|
|
28793
29095
|
});
|
|
28794
29096
|
|
|
28795
|
-
//
|
|
29097
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/uniswap.ts
|
|
28796
29098
|
import { parseAbi as parseAbi7, parseAbiItem as parseAbiItem6 } from "viem";
|
|
28797
29099
|
var v3FactoryAbi, v3PoolAbi, quoterV2Abi, poolKeyComponents, v4QuoterAbi, exactInputSingleParam, poolManagerAbi, initializeEvent, erc20Abi, multicall3Abi2;
|
|
28798
29100
|
var init_uniswap = __esm({
|
|
28799
|
-
"
|
|
29101
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/uniswap.ts"() {
|
|
28800
29102
|
"use strict";
|
|
28801
29103
|
init_define_OSTRA_PACKAGED();
|
|
28802
29104
|
v3FactoryAbi = parseAbi7(["function getPool(address tokenA, address tokenB, uint24 fee) view returns (address)"]);
|
|
@@ -28888,7 +29190,7 @@ var init_uniswap = __esm({
|
|
|
28888
29190
|
}
|
|
28889
29191
|
});
|
|
28890
29192
|
|
|
28891
|
-
//
|
|
29193
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/legs.ts
|
|
28892
29194
|
import { concatHex, encodeAbiParameters as encodeAbiParameters10, encodePacked as encodePacked4, getAddress as getAddress28, toHex as toHex5 } from "viem";
|
|
28893
29195
|
function legFor(pool, tokenIn, tokenOut, recipient = MSG_SENDER) {
|
|
28894
29196
|
const inAddr = getAddress28(tokenIn);
|
|
@@ -28925,7 +29227,7 @@ function legFor(pool, tokenIn, tokenOut, recipient = MSG_SENDER) {
|
|
|
28925
29227
|
}
|
|
28926
29228
|
var NO_LEG, byte;
|
|
28927
29229
|
var init_legs = __esm({
|
|
28928
|
-
"
|
|
29230
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/legs.ts"() {
|
|
28929
29231
|
"use strict";
|
|
28930
29232
|
init_define_OSTRA_PACKAGED();
|
|
28931
29233
|
init_constants2();
|
|
@@ -28935,7 +29237,7 @@ var init_legs = __esm({
|
|
|
28935
29237
|
}
|
|
28936
29238
|
});
|
|
28937
29239
|
|
|
28938
|
-
//
|
|
29240
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/pools.ts
|
|
28939
29241
|
import { encodeAbiParameters as encodeAbiParameters11, encodeFunctionData as encodeFunctionData12, decodeFunctionResult as decodeFunctionResult3, getAddress as getAddress29, hexToBigInt as hexToBigInt2, keccak256 as keccak25617, toHex as toHex6, zeroAddress as zeroAddress16 } from "viem";
|
|
28940
29242
|
function stateSlot(id, offset) {
|
|
28941
29243
|
const base = hexToBigInt2(keccak25617(encodeAbiParameters11([{ type: "bytes32" }, { type: "uint256" }], [id, POOLS_SLOT3])));
|
|
@@ -28998,7 +29300,7 @@ async function hubPools(client, logsClient, index, token, hub) {
|
|
|
28998
29300
|
}
|
|
28999
29301
|
var POOLS_SLOT3, LIQUIDITY_OFFSET2, PoolIndex;
|
|
29000
29302
|
var init_pools2 = __esm({
|
|
29001
|
-
"
|
|
29303
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/pools.ts"() {
|
|
29002
29304
|
"use strict";
|
|
29003
29305
|
init_define_OSTRA_PACKAGED();
|
|
29004
29306
|
init_constants2();
|
|
@@ -29044,7 +29346,7 @@ var init_pools2 = __esm({
|
|
|
29044
29346
|
}
|
|
29045
29347
|
});
|
|
29046
29348
|
|
|
29047
|
-
//
|
|
29349
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/route.ts
|
|
29048
29350
|
import { decodeAbiParameters as decodeAbiParameters5, decodeFunctionResult as decodeFunctionResult4, encodeDeployData as encodeDeployData2, encodeFunctionData as encodeFunctionData13, getAddress as getAddress30 } from "viem";
|
|
29049
29351
|
function routedToken(token) {
|
|
29050
29352
|
const t = getAddress30(token);
|
|
@@ -29168,7 +29470,7 @@ function routeLegs(route) {
|
|
|
29168
29470
|
}
|
|
29169
29471
|
var NoRouteError, quoteResults;
|
|
29170
29472
|
var init_route = __esm({
|
|
29171
|
-
"
|
|
29473
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/route.ts"() {
|
|
29172
29474
|
"use strict";
|
|
29173
29475
|
init_define_OSTRA_PACKAGED();
|
|
29174
29476
|
init_abi2();
|
|
@@ -29194,7 +29496,7 @@ var init_route = __esm({
|
|
|
29194
29496
|
}
|
|
29195
29497
|
});
|
|
29196
29498
|
|
|
29197
|
-
//
|
|
29499
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/orders.ts
|
|
29198
29500
|
import { encodeAbiParameters as encodeAbiParameters12, encodeFunctionData as encodeFunctionData14, getAddress as getAddress31, getContractAddress as getContractAddress4, isAddress as isAddress14, keccak256 as keccak25618, toHex as toHex7 } from "viem";
|
|
29199
29501
|
function parseSwapDeployment(json) {
|
|
29200
29502
|
const r = json;
|
|
@@ -29248,7 +29550,7 @@ function executeEscrowData(order, route) {
|
|
|
29248
29550
|
}
|
|
29249
29551
|
var ZERO, MAX_UINT32, MAX_UINT64, MAX_STANDING_ORDER_SECONDS, legParam, orderParam;
|
|
29250
29552
|
var init_orders = __esm({
|
|
29251
|
-
"
|
|
29553
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/orders.ts"() {
|
|
29252
29554
|
"use strict";
|
|
29253
29555
|
init_define_OSTRA_PACKAGED();
|
|
29254
29556
|
init_abi2();
|
|
@@ -29287,7 +29589,7 @@ var init_orders = __esm({
|
|
|
29287
29589
|
}
|
|
29288
29590
|
});
|
|
29289
29591
|
|
|
29290
|
-
//
|
|
29592
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/private.ts
|
|
29291
29593
|
import { encodeAbiParameters as encodeAbiParameters13, encodeFunctionData as encodeFunctionData15, getAbiItem, getAddress as getAddress32, getContractAddress as getContractAddress5, keccak256 as keccak25619, parseEventLogs, toHex as toHex8 } from "viem";
|
|
29292
29594
|
function packDigest(elements) {
|
|
29293
29595
|
if (elements.length !== 8) throw new Error("a digest has 8 field elements");
|
|
@@ -29487,7 +29789,7 @@ async function swapOutputNote(prover, sk, outRho, spend, swap, receipt, pool) {
|
|
|
29487
29789
|
}
|
|
29488
29790
|
var FIELD_P, TREE_DEPTH, PRIVATE_SWAP_FEE_BPS, UNSHIELD_DOMAIN, SWAP_DOMAIN, MAX_AMOUNT, MAX_UINT642, ZERO2, noteAddedEvent, PoolTrees;
|
|
29489
29791
|
var init_private = __esm({
|
|
29490
|
-
"
|
|
29792
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/private.ts"() {
|
|
29491
29793
|
"use strict";
|
|
29492
29794
|
init_define_OSTRA_PACKAGED();
|
|
29493
29795
|
init_abi2();
|
|
@@ -29603,19 +29905,19 @@ var init_private = __esm({
|
|
|
29603
29905
|
}
|
|
29604
29906
|
});
|
|
29605
29907
|
|
|
29606
|
-
//
|
|
29908
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/reads.ts
|
|
29607
29909
|
import { getAddress as getAddress33 } from "viem";
|
|
29608
29910
|
var init_reads2 = __esm({
|
|
29609
|
-
"
|
|
29911
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/reads.ts"() {
|
|
29610
29912
|
"use strict";
|
|
29611
29913
|
init_define_OSTRA_PACKAGED();
|
|
29612
29914
|
init_abi2();
|
|
29613
29915
|
}
|
|
29614
29916
|
});
|
|
29615
29917
|
|
|
29616
|
-
//
|
|
29918
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/index.ts
|
|
29617
29919
|
var init_src2 = __esm({
|
|
29618
|
-
"
|
|
29920
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/index.ts"() {
|
|
29619
29921
|
"use strict";
|
|
29620
29922
|
init_define_OSTRA_PACKAGED();
|
|
29621
29923
|
init_abi2();
|
|
@@ -31292,7 +31594,7 @@ var init_strategy2 = __esm({
|
|
|
31292
31594
|
if (who !== null && getAddress37(who.owner) === creatorVault && getAddress37(who.wallet) === creatorVault) return { agentId: id.toString(), creatorVault };
|
|
31293
31595
|
}
|
|
31294
31596
|
throw new StrategyGateError(
|
|
31295
|
-
`Ostra's strategies are for agents registered in the ERC-8004 Identity Registry through Ostra: the creator vault ${creatorVault} must own the agent's identity and be its agentWallet${ids.length === 0 ? " (it has none)" : ` (agent ${ids.map(String).join(", ")} is not)`}. Register with
|
|
31597
|
+
`Ostra's strategies are for agents registered in the ERC-8004 Identity Registry through Ostra: the creator vault ${creatorVault} must own the agent's identity and be its agentWallet${ids.length === 0 ? " (it has none)" : ` (agent ${ids.map(String).join(", ")} is not)`}. Register with publish_profile (it registers the agent), then ask again.`
|
|
31296
31598
|
);
|
|
31297
31599
|
}
|
|
31298
31600
|
// -------------------------------------------------------------------------------------------------------------------
|
|
@@ -32191,7 +32493,7 @@ function refusalOf(reason, outDecimals) {
|
|
|
32191
32493
|
return `revert data ${reason.slice(0, 2 + 8 * 2)}${reason.length > 18 ? "\u2026" : ""} (not one of OstraRouter's errors: from a pool or the Universal Router)`;
|
|
32192
32494
|
}
|
|
32193
32495
|
}
|
|
32194
|
-
var SWAP_DIR, ESCROW_SWAP_GAS, DEFAULT_SWAP_SLIPPAGE_BPS, MAX_SWAP_SLIPPAGE_BPS, DEFAULT_SWAP_MAX_IMPACT_BPS, MAX_SWAP_MAX_IMPACT_BPS, SPLIT_MAX_PARTS, SPLIT_INTERVAL_SECONDS, SPLIT_SLACK_SECONDS, POOL_INDEX2, ORDER_PREFIX, SPLIT_PREFIX, address4, SwapService;
|
|
32496
|
+
var SWAP_DIR, ESCROW_SWAP_GAS, DEFAULT_SWAP_SLIPPAGE_BPS, MAX_SWAP_SLIPPAGE_BPS, DEFAULT_SWAP_MAX_IMPACT_BPS, MAX_SWAP_MAX_IMPACT_BPS, SPLIT_MAX_PARTS, SPLIT_INTERVAL_SECONDS, SPLIT_SLACK_SECONDS, POOL_INDEX2, ORDER_PREFIX, SPLIT_PREFIX, DONE_PREFIX, DONE_ORDERS_KEPT, address4, SwapService;
|
|
32195
32497
|
var init_swap = __esm({
|
|
32196
32498
|
"../core/src/swap.ts"() {
|
|
32197
32499
|
"use strict";
|
|
@@ -32215,6 +32517,8 @@ var init_swap = __esm({
|
|
|
32215
32517
|
POOL_INDEX2 = "pool-index.json";
|
|
32216
32518
|
ORDER_PREFIX = "order-";
|
|
32217
32519
|
SPLIT_PREFIX = "split-";
|
|
32520
|
+
DONE_PREFIX = "done-";
|
|
32521
|
+
DONE_ORDERS_KEPT = 100;
|
|
32218
32522
|
address4 = (text3, what) => {
|
|
32219
32523
|
if (!/^0x[0-9a-fA-F]{40}$/.test(text3)) throw new RangeError(`${what} is not an address`);
|
|
32220
32524
|
return getAddress38(text3);
|
|
@@ -32427,7 +32731,23 @@ var init_swap = __esm({
|
|
|
32427
32731
|
const escrow = escrowAddress(this.#p.swap.router, order);
|
|
32428
32732
|
const execute = executeEscrowData(order, p.route);
|
|
32429
32733
|
await p.from.checkSpend(VAULT_ACTION.TRANSFER, transferParams({ to: escrow, amount: p.amountIn }), "the swap's transfer to its escrow", this.#p.sender);
|
|
32430
|
-
await this.#keep({
|
|
32734
|
+
await this.#keep({
|
|
32735
|
+
version: 1,
|
|
32736
|
+
hash: orderHash(order),
|
|
32737
|
+
escrow,
|
|
32738
|
+
tokenIn: p.tokenIn,
|
|
32739
|
+
amountIn: p.amountIn.toString(),
|
|
32740
|
+
vaultNonce: v.nonce.toString(),
|
|
32741
|
+
deadline: order.deadline.toString(),
|
|
32742
|
+
execute,
|
|
32743
|
+
at: Date.now(),
|
|
32744
|
+
fromBlock: fromBlock.toString(),
|
|
32745
|
+
tokenOut: p.tokenOut,
|
|
32746
|
+
from: vault,
|
|
32747
|
+
to: p.to,
|
|
32748
|
+
inDecimals: p.inDecimals,
|
|
32749
|
+
outDecimals: p.outDecimals
|
|
32750
|
+
});
|
|
32431
32751
|
await o.onOrder?.(orderHash(order), fromBlock, escrow);
|
|
32432
32752
|
const signed = await signVaultTransfer(keychain, v, { chainId, to: escrow, amount: p.amountIn });
|
|
32433
32753
|
const calls = [spendCall(vault, signed), { to: this.#p.swap.router, data: execute }];
|
|
@@ -32456,6 +32776,21 @@ var init_swap = __esm({
|
|
|
32456
32776
|
note: `the swap landed in ${result.txHash}; what it paid could not be read now (${e.message.split("\n")[0]}): do not send it again, its order ${orderHash(placed2)} is read again later`
|
|
32457
32777
|
};
|
|
32458
32778
|
}
|
|
32779
|
+
await this.#keepDone({
|
|
32780
|
+
version: 1,
|
|
32781
|
+
order: orderHash(placed2),
|
|
32782
|
+
txHash: result.txHash,
|
|
32783
|
+
swapped: outcome.swapped,
|
|
32784
|
+
tokenIn: p.tokenIn,
|
|
32785
|
+
tokenOut: p.tokenOut,
|
|
32786
|
+
amountIn: formatUnitsAmount(p.amountIn, p.inDecimals),
|
|
32787
|
+
amountOut: formatUnitsAmount(outcome.amountOut, p.outDecimals),
|
|
32788
|
+
minOut: formatUnitsAmount(p.route.minOut, p.outDecimals),
|
|
32789
|
+
from: p.fromVault,
|
|
32790
|
+
to: p.to,
|
|
32791
|
+
...outcome.swapped ? {} : { refusal: outcome.why ?? "OstraRouter gave no reason" },
|
|
32792
|
+
at: Date.now()
|
|
32793
|
+
});
|
|
32459
32794
|
await this.#p.folder.remove(`${ORDER_PREFIX}${orderHash(placed2)}.json`);
|
|
32460
32795
|
return {
|
|
32461
32796
|
status: "sent",
|
|
@@ -32792,6 +33127,92 @@ var init_swap = __esm({
|
|
|
32792
33127
|
if (swapped) return { swapped, amountOut };
|
|
32793
33128
|
return { swapped, amountOut: 0n, ...reason === null ? {} : { why: refusalOf(reason, outDecimals) } };
|
|
32794
33129
|
}
|
|
33130
|
+
/** Keeps a finished order for ostra_swap_orders, and drops the oldest beyond DONE_ORDERS_KEPT. */
|
|
33131
|
+
async #keepDone(d) {
|
|
33132
|
+
await this.#p.folder.ensure();
|
|
33133
|
+
await this.#p.folder.write(`${DONE_PREFIX}${d.order.toLowerCase()}.json`, `${JSON.stringify(d)}
|
|
33134
|
+
`);
|
|
33135
|
+
const names = (await this.#p.folder.list()).filter((n) => n.startsWith(DONE_PREFIX) && n.endsWith(".json"));
|
|
33136
|
+
if (names.length <= DONE_ORDERS_KEPT) return;
|
|
33137
|
+
const dated = [];
|
|
33138
|
+
for (const n of names) {
|
|
33139
|
+
const text3 = await this.#p.folder.read(n);
|
|
33140
|
+
dated.push({ name: n, at: text3 === void 0 ? 0 : Number(JSON.parse(text3).at) });
|
|
33141
|
+
}
|
|
33142
|
+
dated.sort((a, b) => a.at - b.at);
|
|
33143
|
+
for (const x of dated.slice(0, dated.length - DONE_ORDERS_KEPT)) await this.#p.folder.remove(x.name);
|
|
33144
|
+
}
|
|
33145
|
+
/**
|
|
33146
|
+
* Keeps what a kept order did once the sweep finishes it: from the transaction that executed it (`tx`), else from
|
|
33147
|
+
* OstraRouter's events from the record's block. Best effort: an order whose events cannot be read now is not kept
|
|
33148
|
+
* (a record from before 0.1.12 has no block to search from).
|
|
33149
|
+
*/
|
|
33150
|
+
async #doneFrom(r, tx) {
|
|
33151
|
+
try {
|
|
33152
|
+
let hash = tx;
|
|
33153
|
+
if (hash === null && r.fromBlock !== void 0) {
|
|
33154
|
+
const toBlock = await this.#p.logsClient.getBlockNumber({ cacheTime: 0 });
|
|
33155
|
+
const logs = await getLogsChunked(this.#p.logsClient, { address: this.#p.swap.router, event: getAbiItem2({ abi: ostraRouterAbi, name: "EscrowExecuted" }), args: { orderHash: r.hash }, fromBlock: BigInt(r.fromBlock), toBlock });
|
|
33156
|
+
const moved = logs.find((l) => l.args.received !== 0n);
|
|
33157
|
+
hash = moved === void 0 ? null : moved.transactionHash;
|
|
33158
|
+
}
|
|
33159
|
+
if (hash === null) return;
|
|
33160
|
+
const inDecimals = r.inDecimals ?? await tokenDecimals(this.#p.client, r.tokenIn);
|
|
33161
|
+
const outDecimals = r.outDecimals ?? (r.tokenOut === void 0 ? 18 : await tokenDecimals(this.#p.client, r.tokenOut));
|
|
33162
|
+
const o = await this.#outcome(hash, r.hash, outDecimals);
|
|
33163
|
+
await this.#keepDone({
|
|
33164
|
+
version: 1,
|
|
33165
|
+
order: r.hash,
|
|
33166
|
+
txHash: hash,
|
|
33167
|
+
swapped: o.swapped,
|
|
33168
|
+
tokenIn: r.tokenIn,
|
|
33169
|
+
tokenOut: r.tokenOut ?? null,
|
|
33170
|
+
amountIn: formatUnitsAmount(BigInt(r.amountIn), inDecimals),
|
|
33171
|
+
amountOut: formatUnitsAmount(o.amountOut, outDecimals),
|
|
33172
|
+
minOut: null,
|
|
33173
|
+
from: r.from ?? null,
|
|
33174
|
+
to: r.to ?? null,
|
|
33175
|
+
...o.swapped ? {} : { refusal: o.why ?? "OstraRouter gave no reason" },
|
|
33176
|
+
at: Date.now()
|
|
33177
|
+
});
|
|
33178
|
+
} catch {
|
|
33179
|
+
}
|
|
33180
|
+
}
|
|
33181
|
+
/**
|
|
33182
|
+
* The agent's orders kept here: those not finished (signed or about to be, or landed and being finished; oldest
|
|
33183
|
+
* first) and the finished ones (newest first, at most `limit`). With `order`, that order alone in either list.
|
|
33184
|
+
*/
|
|
33185
|
+
async orders(o = {}) {
|
|
33186
|
+
const want = o.order?.toLowerCase();
|
|
33187
|
+
const open3 = [];
|
|
33188
|
+
const finished = [];
|
|
33189
|
+
for (const name of await this.#p.folder.list()) {
|
|
33190
|
+
const isOrder = name.startsWith(ORDER_PREFIX);
|
|
33191
|
+
if (!isOrder && !name.startsWith(DONE_PREFIX) || !name.endsWith(".json")) continue;
|
|
33192
|
+
if (want !== void 0 && name.slice((isOrder ? ORDER_PREFIX : DONE_PREFIX).length, -".json".length).toLowerCase() !== want) continue;
|
|
33193
|
+
const text3 = await this.#p.folder.read(name);
|
|
33194
|
+
if (text3 === void 0) continue;
|
|
33195
|
+
if (!isOrder) {
|
|
33196
|
+
finished.push(JSON.parse(text3));
|
|
33197
|
+
continue;
|
|
33198
|
+
}
|
|
33199
|
+
const r = JSON.parse(text3);
|
|
33200
|
+
const inDecimals = r.inDecimals ?? await tokenDecimals(this.#p.client, r.tokenIn);
|
|
33201
|
+
const x = { order: r.hash, tokenIn: r.tokenIn, tokenOut: r.tokenOut ?? null, amountIn: formatUnitsAmount(BigInt(r.amountIn), inDecimals), escrow: r.escrow, state: "open", at: r.at };
|
|
33202
|
+
if (r.fromBlock !== void 0) {
|
|
33203
|
+
const res = await this.orderResult(r.hash, BigInt(r.fromBlock), r.escrow);
|
|
33204
|
+
if (res.spent > 0n || res.received > 0n) {
|
|
33205
|
+
x.state = "landed";
|
|
33206
|
+
x.spent = formatUnitsAmount(res.spent, inDecimals);
|
|
33207
|
+
x.received = formatUnitsAmount(res.received, r.outDecimals ?? 18);
|
|
33208
|
+
}
|
|
33209
|
+
}
|
|
33210
|
+
open3.push(x);
|
|
33211
|
+
}
|
|
33212
|
+
open3.sort((a, b) => a.at - b.at);
|
|
33213
|
+
finished.sort((a, b) => b.at - a.at);
|
|
33214
|
+
return { open: open3, finished: finished.slice(0, o.limit ?? 20) };
|
|
33215
|
+
}
|
|
32795
33216
|
/**
|
|
32796
33217
|
* Finishes the orders whose escrow was paid without being executed (a signed spend sent again on its own):
|
|
32797
33218
|
* executeEscrow sends the input along the order's route, or back to its vault past the deadline. Records of orders
|
|
@@ -32808,11 +33229,15 @@ var init_swap = __esm({
|
|
|
32808
33229
|
const nonce = (await this.#p.vaultFor(r.tokenIn).state()).nonce;
|
|
32809
33230
|
const held = await tokenBalance(this.#p.client, r.tokenIn, r.escrow);
|
|
32810
33231
|
if (held >= BigInt(r.amountIn)) {
|
|
32811
|
-
await this.#p.sender.send([{ to: this.#p.swap.router, data: r.execute }]);
|
|
33232
|
+
const tx = await this.#p.sender.send([{ to: this.#p.swap.router, data: r.execute }]);
|
|
33233
|
+
await this.#doneFrom(r, tx);
|
|
32812
33234
|
await this.#p.folder.remove(name);
|
|
32813
33235
|
continue;
|
|
32814
33236
|
}
|
|
32815
|
-
if (nonce !== null && nonce > BigInt(r.vaultNonce))
|
|
33237
|
+
if (nonce !== null && nonce > BigInt(r.vaultNonce)) {
|
|
33238
|
+
await this.#doneFrom(r, null);
|
|
33239
|
+
await this.#p.folder.remove(name);
|
|
33240
|
+
}
|
|
32816
33241
|
} catch (err) {
|
|
32817
33242
|
failures.push({ order: r.hash, error: err instanceof Error ? err.message : String(err) });
|
|
32818
33243
|
}
|
|
@@ -33676,7 +34101,7 @@ var init_backup_cli = __esm({
|
|
|
33676
34101
|
}
|
|
33677
34102
|
});
|
|
33678
34103
|
|
|
33679
|
-
//
|
|
34104
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/cli-prover.ts
|
|
33680
34105
|
import { spawn } from "node:child_process";
|
|
33681
34106
|
function cliProver(binary, timeoutMs = PROVER_TIMEOUT_MS) {
|
|
33682
34107
|
return (command, request) => new Promise((resolve, reject) => {
|
|
@@ -33717,14 +34142,14 @@ function cliProver(binary, timeoutMs = PROVER_TIMEOUT_MS) {
|
|
|
33717
34142
|
}
|
|
33718
34143
|
var PROVER_TIMEOUT_MS;
|
|
33719
34144
|
var init_cli_prover = __esm({
|
|
33720
|
-
"
|
|
34145
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/cli-prover.ts"() {
|
|
33721
34146
|
"use strict";
|
|
33722
34147
|
init_define_OSTRA_PACKAGED();
|
|
33723
34148
|
PROVER_TIMEOUT_MS = 12e4;
|
|
33724
34149
|
}
|
|
33725
34150
|
});
|
|
33726
34151
|
|
|
33727
|
-
//
|
|
34152
|
+
// ../../../../../../srv/apps/ostra-swap/sdk/src/wasm-prover.ts
|
|
33728
34153
|
import { bytesToHex as bytesToHex17 } from "viem";
|
|
33729
34154
|
async function sha256Hex(bytes) {
|
|
33730
34155
|
return bytesToHex17(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)));
|
|
@@ -33760,7 +34185,7 @@ async function wasmProver(glue, bytes, sha2564) {
|
|
|
33760
34185
|
}
|
|
33761
34186
|
var WasmProverTrapped, initialized, trapped;
|
|
33762
34187
|
var init_wasm_prover = __esm({
|
|
33763
|
-
"
|
|
34188
|
+
"../../../../../../srv/apps/ostra-swap/sdk/src/wasm-prover.ts"() {
|
|
33764
34189
|
"use strict";
|
|
33765
34190
|
init_define_OSTRA_PACKAGED();
|
|
33766
34191
|
WasmProverTrapped = class extends Error {
|
|
@@ -33881,7 +34306,7 @@ var init_agent = __esm({
|
|
|
33881
34306
|
this.creator = new VaultService(client, transport, config, p.creatorKeys, creatorSender, "creator");
|
|
33882
34307
|
this.creatorRelayer?.attachBuyerVault(this.creator);
|
|
33883
34308
|
this.creatorChannels = new ChannelService(client, config, p.creatorKeys, this.creator, creatorSender);
|
|
33884
|
-
this.launchpad = config.deployment.launchpad === void 0 ? null : new LaunchpadService({ client, transport, config, keys, buyer: this.buyer, buyerSender: this.sender, creator: this.creator, creatorSender });
|
|
34309
|
+
this.launchpad = config.deployment.launchpad === void 0 ? null : new LaunchpadService({ client, transport, config, keys, buyer: this.buyer, buyerSender: this.sender, creator: this.creator, creatorSender, logsClient: createPublicClient2({ chain: robinhoodChain, transport: http2(config.logsRpcUrl, { retryCount: 6, retryDelay: 2e3 }) }) });
|
|
33885
34310
|
this.shield = new ShieldService(client, config, keys, this.buyer, this.sender);
|
|
33886
34311
|
this.creatorShield = new ShieldService(client, config, keys, this.creator, creatorSender);
|
|
33887
34312
|
this.unshield = new UnshieldService(client, config, keys, this.shield, (index) => this.privateVault(index));
|
|
@@ -33955,6 +34380,7 @@ var init_agent = __esm({
|
|
|
33955
34380
|
return typeof p2.profile === "object" && p2.profile !== null && !Array.isArray(p2.profile) ? p2.profile : null;
|
|
33956
34381
|
},
|
|
33957
34382
|
publishFile: (file) => lp.publishRegistrationFile(file),
|
|
34383
|
+
publishShortfall: () => lp.publishShortfall(),
|
|
33958
34384
|
upload: (file) => uploadJson(config.relayerUrl, file),
|
|
33959
34385
|
indexerUrl: config.padIndexerUrl
|
|
33960
34386
|
});
|
|
@@ -34179,6 +34605,12 @@ async function proverConfig(env) {
|
|
|
34179
34605
|
}
|
|
34180
34606
|
return { kind: "wasm", dir, sha256: sha2564 };
|
|
34181
34607
|
}
|
|
34608
|
+
function swapAnswerMs(env) {
|
|
34609
|
+
const v = env.OSTRA_SWAP_ANSWER_MS;
|
|
34610
|
+
if (v === void 0 || v === "") return DEFAULT_SWAP_ANSWER_MS;
|
|
34611
|
+
if (!/^[1-9][0-9]{0,5}$/.test(v) || Number(v) > 6e5) throw new Error("OSTRA_SWAP_ANSWER_MS is a whole number of milliseconds from 1 to 600000");
|
|
34612
|
+
return Number(v);
|
|
34613
|
+
}
|
|
34182
34614
|
function serviceUrl(env, name, fallback) {
|
|
34183
34615
|
const value = env[name];
|
|
34184
34616
|
if (value === void 0 || value === "") return fallback;
|
|
@@ -34228,6 +34660,7 @@ async function loadConfig(env = process.env) {
|
|
|
34228
34660
|
swap,
|
|
34229
34661
|
logsRpcUrl,
|
|
34230
34662
|
privateLocalSpends: env.OSTRA_PRIVATE_LOCAL_SPENDS === "yes",
|
|
34663
|
+
swapAnswerMs: swapAnswerMs(env),
|
|
34231
34664
|
prover,
|
|
34232
34665
|
chainId: deployment.chainId,
|
|
34233
34666
|
rpcUrl: rpcUrl ?? ROBINHOOD_PUBLIC_RPC,
|
|
@@ -34239,7 +34672,7 @@ async function loadConfig(env = process.env) {
|
|
|
34239
34672
|
aiUrl: serviceUrl(env, "OSTRA_AI_URL", services?.aiUrl ?? null)
|
|
34240
34673
|
};
|
|
34241
34674
|
}
|
|
34242
|
-
var PROVER_WASM_FILES, PAD_INDEXER_URL, ETHEREUM_PUBLIC_RPC;
|
|
34675
|
+
var PROVER_WASM_FILES, PAD_INDEXER_URL, ETHEREUM_PUBLIC_RPC, DEFAULT_SWAP_ANSWER_MS;
|
|
34243
34676
|
var init_config2 = __esm({
|
|
34244
34677
|
"src/config.ts"() {
|
|
34245
34678
|
"use strict";
|
|
@@ -34252,10 +34685,12 @@ var init_config2 = __esm({
|
|
|
34252
34685
|
PROVER_WASM_FILES = ["ostra_prove.js", "ostra_prove_bg.wasm"];
|
|
34253
34686
|
PAD_INDEXER_URL = "https://app.ostraagent.xyz";
|
|
34254
34687
|
ETHEREUM_PUBLIC_RPC = "https://ethereum-rpc.publicnode.com";
|
|
34688
|
+
DEFAULT_SWAP_ANSWER_MS = 4e4;
|
|
34255
34689
|
}
|
|
34256
34690
|
});
|
|
34257
34691
|
|
|
34258
34692
|
// src/tools.ts
|
|
34693
|
+
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
34259
34694
|
import { readFile as readFile6, stat as stat4, writeFile as writeFile3 } from "node:fs/promises";
|
|
34260
34695
|
import { join as join7 } from "node:path";
|
|
34261
34696
|
import { z } from "zod";
|
|
@@ -34299,7 +34734,79 @@ function registerTools(server, agent) {
|
|
|
34299
34734
|
return agent.privateBalance;
|
|
34300
34735
|
};
|
|
34301
34736
|
const opt = (key, value) => value === void 0 ? {} : { [key]: value };
|
|
34302
|
-
const
|
|
34737
|
+
const rpcUrls2 = [agent.config.rpcUrl, agent.config.logsRpcUrl, ...agent.config.ethRpcUrl === null ? [] : [agent.config.ethRpcUrl]];
|
|
34738
|
+
const tool = (name, description, shape, fn) => CLOSED_LAUNCHPAD_TOOLS.has(name) ? void 0 : server.registerTool(name, { description, inputSchema: shape }, ((args) => run2(() => fn(args), rpcUrls2)));
|
|
34739
|
+
const answerMs = agent.config.swapAnswerMs;
|
|
34740
|
+
const swaps = /* @__PURE__ */ new Map();
|
|
34741
|
+
const swapView = (r) => ({
|
|
34742
|
+
swap: r.id,
|
|
34743
|
+
what: r.what,
|
|
34744
|
+
tokenIn: r.tokenIn,
|
|
34745
|
+
tokenOut: r.tokenOut,
|
|
34746
|
+
amount: r.amount,
|
|
34747
|
+
startedAt: new Date(r.startedAt).toISOString(),
|
|
34748
|
+
state: r.endedAt === void 0 ? "running" : r.error === void 0 ? "ended" : "failed",
|
|
34749
|
+
// False while its call still waits for it (a client that gave up on that call learns the result here).
|
|
34750
|
+
answeredPending: r.answered,
|
|
34751
|
+
...r.order === void 0 ? {} : { order: r.order },
|
|
34752
|
+
...r.split === void 0 ? {} : { split: r.split },
|
|
34753
|
+
...r.endedAt === void 0 ? {} : { endedAt: new Date(r.endedAt).toISOString() },
|
|
34754
|
+
...r.result === void 0 ? {} : { result: r.result },
|
|
34755
|
+
...r.error === void 0 ? {} : { error: r.error }
|
|
34756
|
+
});
|
|
34757
|
+
const boundedSwap = async (a, start) => {
|
|
34758
|
+
const busy = [...swaps.values()].find((x) => x.endedAt === void 0 && x.tokenIn.toLowerCase() === a.tokenIn.toLowerCase());
|
|
34759
|
+
if (busy !== void 0) {
|
|
34760
|
+
throw new Error(`a swap from the agent's vault of ${a.tokenIn} is still running (${busy.what} of ${busy.amount}, begun ${new Date(busy.startedAt).toISOString()}): nothing was signed for this call; ostra_swap_orders shows how that one ends, call again once it has`);
|
|
34761
|
+
}
|
|
34762
|
+
const r = { id: randomBytes6(8).toString("hex"), ...a, startedAt: Date.now(), answered: false };
|
|
34763
|
+
swaps.set(r.id, r);
|
|
34764
|
+
const work = Promise.resolve().then(() => start({
|
|
34765
|
+
onOrder: async (order) => {
|
|
34766
|
+
r.order = order;
|
|
34767
|
+
},
|
|
34768
|
+
onSplit: async (id) => {
|
|
34769
|
+
r.split = id;
|
|
34770
|
+
}
|
|
34771
|
+
}));
|
|
34772
|
+
let timer;
|
|
34773
|
+
const late = new Promise((resolve) => {
|
|
34774
|
+
timer = setTimeout(() => resolve(null), answerMs);
|
|
34775
|
+
});
|
|
34776
|
+
let first;
|
|
34777
|
+
try {
|
|
34778
|
+
first = await Promise.race([work.then((value) => ({ value })), late]);
|
|
34779
|
+
} catch (err) {
|
|
34780
|
+
swaps.delete(r.id);
|
|
34781
|
+
throw err;
|
|
34782
|
+
} finally {
|
|
34783
|
+
clearTimeout(timer);
|
|
34784
|
+
}
|
|
34785
|
+
if (first !== null) {
|
|
34786
|
+
swaps.delete(r.id);
|
|
34787
|
+
return first.value;
|
|
34788
|
+
}
|
|
34789
|
+
r.answered = true;
|
|
34790
|
+
work.then(
|
|
34791
|
+
(value) => {
|
|
34792
|
+
r.result = value;
|
|
34793
|
+
r.endedAt = Date.now();
|
|
34794
|
+
},
|
|
34795
|
+
(err) => {
|
|
34796
|
+
r.error = rpcUrls2.reduce((text3, url) => redact(text3, url), err instanceof Error ? err.message : String(err));
|
|
34797
|
+
r.endedAt = Date.now();
|
|
34798
|
+
}
|
|
34799
|
+
);
|
|
34800
|
+
const ended = [...swaps.values()].filter((x) => x.endedAt !== void 0).sort((x, y) => x.endedAt - y.endedAt);
|
|
34801
|
+
for (const x of ended.slice(0, Math.max(0, ended.length - ENDED_SWAPS_KEPT))) swaps.delete(x.id);
|
|
34802
|
+
return {
|
|
34803
|
+
status: "pending",
|
|
34804
|
+
swap: r.id,
|
|
34805
|
+
order: r.order ?? null,
|
|
34806
|
+
split: r.split ?? null,
|
|
34807
|
+
note: `${a.what} is still running after ${answerMs / 1e3} s and goes on in the MCP server: do not send it again. ostra_swap_orders shows how it ends (swap ${r.id}${r.order === void 0 ? "" : `, order ${r.order}`}${r.split === void 0 ? "" : `; split swap ${r.split}: ostra_swap_split list`}).`
|
|
34808
|
+
};
|
|
34809
|
+
};
|
|
34303
34810
|
tool("open_vault", "Creates the agent's vault (USDG on Robinhood Chain, post-quantum WOTS keys) or finds it. With the Ostra relayer, its creation is paid later from the vault.", {}, () => agent.buyer.open());
|
|
34304
34811
|
tool("balance", "The vault's balance, nonce, any operation signed and not landed, the relayer channels, and the creator vault.", {}, async () => ({
|
|
34305
34812
|
vault: await agent.buyer.status(),
|
|
@@ -34393,9 +34900,27 @@ function registerTools(server, agent) {
|
|
|
34393
34900
|
);
|
|
34394
34901
|
tool(
|
|
34395
34902
|
"ostra_swap",
|
|
34396
|
-
|
|
34903
|
+
`Swaps on Ostra Swap from the agent's vault of tokenIn to its vault of tokenOut, as an escrow order of OstraRouter: the vault signs one transfer into the order's escrow and the relayer executes it in the same transaction. The router pays at least minOut or sends the input back; where the tokens go is fixed by the escrow's address. A swap that moves the price more than maxImpactBps (default 1%) is split into up to 16 parts 60 seconds apart, each its own escrow order quoted again right before it is signed: a part waits while it would move the price more than the limit or pay less than the first part's quote less the slippage. The first part runs now and the next ones while the MCP server runs (ostra_swap_split); what is not swapped by the deadline stays in the vault. A swap not done within ${answerMs / 1e3} s answers status "pending" and goes on: do not send it again; ostra_swap_orders tells how it ended.`,
|
|
34397
34904
|
{ tokenIn: swapToken, tokenOut: swapToken, amount: units.describe("in tokenIn"), slippageBps: slippage2, maxImpactBps: maxImpact },
|
|
34398
|
-
(a) =>
|
|
34905
|
+
(a) => {
|
|
34906
|
+
const tokenIn = tokenAddress(a.tokenIn);
|
|
34907
|
+
const tokenOut = tokenAddress(a.tokenOut);
|
|
34908
|
+
return boundedSwap(
|
|
34909
|
+
{ what: "the swap", tokenIn, tokenOut, amount: a.amount },
|
|
34910
|
+
(hooks) => ostraSwap().swap({ tokenIn, tokenOut, amount: a.amount, ...opt("slippageBps", a.slippageBps), ...opt("maxImpactBps", a.maxImpactBps) }, hooks)
|
|
34911
|
+
);
|
|
34912
|
+
}
|
|
34913
|
+
);
|
|
34914
|
+
tool(
|
|
34915
|
+
"ostra_swap_orders",
|
|
34916
|
+
"The agent's Ostra Swap orders: swaps of this MCP server still running (their call waiting, or answered pending) and those that answered pending and then ended or failed, orders kept and not finished (signed or about to be, or landed and being finished by the MCP server's sweep each minute), and the last finished ones with what they spent and paid (refusal: why one did not swap, its input back in the vault). order: that order alone. Nothing is signed.",
|
|
34917
|
+
{ order: bytes323.optional() },
|
|
34918
|
+
async (a) => {
|
|
34919
|
+
const kept = await ostraSwap().orders(a.order === void 0 ? {} : { order: a.order });
|
|
34920
|
+
const want = a.order?.toLowerCase();
|
|
34921
|
+
const pending = [...swaps.values()].filter((x) => want === void 0 || x.order?.toLowerCase() === want).sort((x, y) => y.startedAt - x.startedAt);
|
|
34922
|
+
return { pending: pending.map(swapView), open: kept.open, finished: kept.finished };
|
|
34923
|
+
}
|
|
34399
34924
|
);
|
|
34400
34925
|
tool(
|
|
34401
34926
|
"ostra_swap_split",
|
|
@@ -34560,7 +35085,7 @@ function registerTools(server, agent) {
|
|
|
34560
35085
|
const earnings = z.record(z.string().regex(/^[A-Z]{1,8}$/), z.number().int().min(0)).optional().describe("earnings dates the agent knows, unix seconds by stock ticker (without one NVDA stays at most 60% of its LLTV)");
|
|
34561
35086
|
tool(
|
|
34562
35087
|
"strategy_plan",
|
|
34563
|
-
"Plans what the agent's vaults hold, computed from the chain now: a conservative plan (USDG into a cash vault that passes every check of Strategy 1) and, when a carry of the agent's SPY, QQQ or NVDA may open, a balanced one (Strategy 2: the stock lent to Borro as collateral, USDG borrowed into the cash vault), each with its steps, gas, what it earns in 30 days net of gas, risks, when it stops, and whether OstraBreaker watches (Strategy 3). Every step earns over 3x its gas in 30 days or is left out. The trading capital's cash (trading) stays in the vault. Nothing is signed. Only for an agent registered in ERC-8004 (
|
|
35088
|
+
"Plans what the agent's vaults hold, computed from the chain now: a conservative plan (USDG into a cash vault that passes every check of Strategy 1) and, when a carry of the agent's SPY, QQQ or NVDA may open, a balanced one (Strategy 2: the stock lent to Borro as collateral, USDG borrowed into the cash vault), each with its steps, gas, what it earns in 30 days net of gas, risks, when it stops, and whether OstraBreaker watches (Strategy 3). Every step earns over 3x its gas in 30 days or is left out. The trading capital's cash (trading) stays in the vault. Nothing is signed. Only for an agent registered in ERC-8004 (publish_profile).",
|
|
34564
35089
|
{ buffer: usdg.optional().describe("USDG kept for payments (default: what the vault spent over 7 days)"), earnings },
|
|
34565
35090
|
(a) => agent.strategy.plan({
|
|
34566
35091
|
...a.buffer === void 0 ? {} : { buffer: parseUsdg(a.buffer) },
|
|
@@ -34582,7 +35107,7 @@ function registerTools(server, agent) {
|
|
|
34582
35107
|
const bpsLimit = z.number().int().min(1).max(1e4).optional();
|
|
34583
35108
|
tool(
|
|
34584
35109
|
"trading",
|
|
34585
|
-
`The trading capital: USDG of the vault set aside for trades the agent decides, with Ostra's limits (an agent may only tighten them): a position at most 25% of the capital (positionMaxBps) and no larger than a buy whose quote moves the price 1% (maxImpactBps); buys stop for the day after a 5% loss of the capital that day (dailyLossBps) and for the week after 10% that week (weeklyLossBps). set: sets it (capital in USDG, the limits), only with no position open; the plans keep its cash out of the cash vaults. status: its value now (cash, positions at the quote of selling them), whether buys may happen and, with token, the most that position may be. buy: buys token with amount USDG of the capital, refused past those limits. sell: sells amount (or "all") of the capital's token, split like any large swap. end: ends it (positions stay in their vaults, untracked). Trades go through Ostra Swap; only for an agent registered in ERC-8004 (
|
|
35110
|
+
`The trading capital: USDG of the vault set aside for trades the agent decides, with Ostra's limits (an agent may only tighten them): a position at most 25% of the capital (positionMaxBps) and no larger than a buy whose quote moves the price 1% (maxImpactBps); buys stop for the day after a 5% loss of the capital that day (dailyLossBps) and for the week after 10% that week (weeklyLossBps). set: sets it (capital in USDG, the limits), only with no position open; the plans keep its cash out of the cash vaults. status: its value now (cash, positions at the quote of selling them), whether buys may happen and, with token, the most that position may be. buy: buys token with amount USDG of the capital, refused past those limits. sell: sells amount (or "all") of the capital's token, split like any large swap. A buy or sell not done in time (${agent.config.swapAnswerMs / 1e3} s) answers status "pending" and goes on: do not send it again; ostra_swap_orders tells how it ended. end: ends it (positions stay in their vaults, untracked). Trades go through Ostra Swap; only for an agent registered in ERC-8004 (publish_profile) to set it or buy.`,
|
|
34586
35111
|
{
|
|
34587
35112
|
action: z.enum(["set", "status", "buy", "sell", "end"]),
|
|
34588
35113
|
capital: usdg.optional(),
|
|
@@ -34612,9 +35137,11 @@ function registerTools(server, agent) {
|
|
|
34612
35137
|
const token = tokenAddress(a.token);
|
|
34613
35138
|
if (a.action === "buy") {
|
|
34614
35139
|
if (a.amount === "all") throw new RangeError("buy takes an amount of USDG");
|
|
34615
|
-
|
|
35140
|
+
const amount2 = a.amount;
|
|
35141
|
+
return boundedSwap({ what: "the trading buy", tokenIn: USDG, tokenOut: token, amount: amount2 }, () => t.buy({ token, amount: amount2, ...opt("slippageBps", a.slippageBps) }));
|
|
34616
35142
|
}
|
|
34617
|
-
|
|
35143
|
+
const amount = a.amount;
|
|
35144
|
+
return boundedSwap({ what: "the trading sell", tokenIn: token, tokenOut: USDG, amount }, () => t.sell({ token, amount, ...opt("slippageBps", a.slippageBps) }));
|
|
34618
35145
|
}
|
|
34619
35146
|
);
|
|
34620
35147
|
tool("strategy_report", "What the strategies earn: yield per day by route at the rates now, the share growth since the first run that held each cash vault, and each carry's distance to liquidation.", {}, () => agent.strategy.report());
|
|
@@ -34624,7 +35151,7 @@ function registerTools(server, agent) {
|
|
|
34624
35151
|
};
|
|
34625
35152
|
tool(
|
|
34626
35153
|
"raeto",
|
|
34627
|
-
"Raeto (raeto.cc): 400+ AI models (text, and image models such as google/gemini-2.5-flash-image and openai/gpt-5-image-mini) through one OpenAI-compatible API, paid in Raeto credits of the vault's own Raeto account. login: signs the USDG vault in as an agent with EIP-1271 (the vault approves Raeto's login message, then withdraws the approval; refused under the withdrawal lock), its API key kept on this machine and never shown (name: the account's name; limitUsd: its spending limit). me: the account's credits. models: the models and prices per token (output: image for the image models). fund: sends `amount` USDG from the vault to Raeto, as credits. fund_yield: sends what the cash vault shares earned since the last call (at least `min`, default 1 USDG), redeemed then sent. complete: a model call, `request` in the OpenAI chat format with Raeto's model id (images it returns are saved as files in the agent's directory).",
|
|
35154
|
+
"Raeto (raeto.cc): 400+ AI models (text, and image models such as google/gemini-2.5-flash-image and openai/gpt-5-image-mini) through one OpenAI-compatible API, paid in Raeto credits of the vault's own Raeto account. login: signs the USDG vault in as an agent with EIP-1271 (the vault approves Raeto's login message, then withdraws the approval; refused under the withdrawal lock), its API key kept on this machine and never shown (name: the account's name; limitUsd: its spending limit). me: the account's credits. models: the models and prices per token (output: image for the image models). fund: sends `amount` USDG from the vault to Raeto, as credits. fund_yield: sends what the cash vault shares earned since the last call, less the interest the agent's Borro loans accrued meanwhile (at least `min`, default 1 USDG), redeemed then sent. complete: a model call, `request` in the OpenAI chat format with Raeto's model id (images it returns are saved as files in the agent's directory).",
|
|
34628
35155
|
{
|
|
34629
35156
|
action: z.enum(["login", "me", "models", "fund", "fund_yield", "complete"]),
|
|
34630
35157
|
name: z.string().min(1).max(64).optional(),
|
|
@@ -34683,7 +35210,7 @@ function registerTools(server, agent) {
|
|
|
34683
35210
|
const files = z.array(z.string().max(200).regex(/^ipfs:\/\/[A-Za-z0-9]+(\/[A-Za-z0-9._-]+)*$/)).max(10).optional().describe("ipfs:// files (upload_image makes one)");
|
|
34684
35211
|
tool(
|
|
34685
35212
|
"pad_publish",
|
|
34686
|
-
"Ostrapad as a provider. publish: lists offers in the agent's ERC-8004 registration file, paid into its USDG vault (the vault approves the listing once, so a listing is its own); needs publish_profile and
|
|
35213
|
+
"Ostrapad as a provider. publish: lists offers in the agent's ERC-8004 registration file, paid into its USDG vault (the vault approves the listing once, so a listing is its own); needs publish_profile first (it registers the agent), and USDG in the creator vault for its relayed transactions (checked before the approval). unpublish: removes the listing. status: the agent's own listing as clients read it. bond / withdraw_bond: a voluntary provider bond (raises the limit per job to the bond, up to 500 USDG; a rejected job costs it 10% of the budget plus the evaluator fee). return_bond_box: returns USDG left in the provider bond box (a deposit whose second step failed) to the USDG vault.",
|
|
34687
35214
|
{ action: z.enum(["publish", "unpublish", "status", "bond", "withdraw_bond", "return_bond_box"]), offers: z.array(offer).min(1).max(20).optional(), amount: usdg.optional() },
|
|
34688
35215
|
async (a) => {
|
|
34689
35216
|
if (a.action === "publish") {
|
|
@@ -34833,17 +35360,9 @@ function registerTools(server, agent) {
|
|
|
34833
35360
|
(a) => lp().tokenInfo(a.token)
|
|
34834
35361
|
);
|
|
34835
35362
|
tool("profile", "The agent's public identity, its creator vault: the profile URI it set, that profile read from IPFS, and its ERC-8004 agent id; or another account's profile.", { account: address5.optional() }, (a) => lp().profile(a.account));
|
|
34836
|
-
tool(
|
|
34837
|
-
"set_profile",
|
|
34838
|
-
"Sets the agent's profile in OstraRegistry from its creator vault, with a WOTS-signed spend: uri is an ipfs:// (or https://) JSON file with name, description, image and links, ideally an ERC-8004 registration file.",
|
|
34839
|
-
{ uri },
|
|
34840
|
-
(a) => lp().setProfile(a.uri)
|
|
34841
|
-
);
|
|
34842
|
-
tool("register_agent", "Registers the agent in the ERC-8004 Identity Registry, once: its creator vault owns the identity and is its agentWallet; uri is its ERC-8004 registration file.", { uri }, (a) => lp().registerAgent(a.uri));
|
|
34843
|
-
tool("set_agent_uri", "Points the agent's ERC-8004 identity at a new registration file.", { uri }, (a) => lp().setAgentUri(a.uri));
|
|
34844
35363
|
tool(
|
|
34845
35364
|
"upload_image",
|
|
34846
|
-
`Pins an image file on this machine (PNG, JPEG, WebP or GIF, at most ${MAX_UPLOAD_IMAGE_BYTES} bytes) to IPFS through the Ostra uploader and returns its ipfs:// URI, for
|
|
35365
|
+
`Pins an image file on this machine (PNG, JPEG, WebP or GIF, at most ${MAX_UPLOAD_IMAGE_BYTES} bytes) to IPFS through the Ostra uploader and returns its ipfs:// URI, for the files of an Ostrapad order or delivery.`,
|
|
34847
35366
|
{ path: z.string().min(1).max(4096) },
|
|
34848
35367
|
async (a) => {
|
|
34849
35368
|
const s = await stat4(a.path);
|
|
@@ -34853,9 +35372,9 @@ function registerTools(server, agent) {
|
|
|
34853
35372
|
);
|
|
34854
35373
|
tool(
|
|
34855
35374
|
"publish_profile",
|
|
34856
|
-
|
|
34857
|
-
{
|
|
34858
|
-
(
|
|
35375
|
+
`Publishes the agent's Ostra profile and registers it in the ERC-8004 Identity Registry, with nothing to fill in: the same for every Ostra agent ("Ostra Agent #<id>", Ostra's description, the Ostra agent card as its image, its creator vault as agentWallet). The first call publishes the profile, registers the agent (its creator vault owns the identity) and publishes the profile again with the agent's number; a later call publishes it again (an Ostrapad listing in it is kept). Needs USDG in the creator vault (fund_creator_vault).`,
|
|
35376
|
+
{},
|
|
35377
|
+
() => lp().publishProfile()
|
|
34859
35378
|
);
|
|
34860
35379
|
tool(
|
|
34861
35380
|
"publish_token_metadata",
|
|
@@ -34918,7 +35437,7 @@ function launchOptions(raw) {
|
|
|
34918
35437
|
}
|
|
34919
35438
|
return out;
|
|
34920
35439
|
}
|
|
34921
|
-
var toJson, address5, usdg, units, pair2, slippage2, bytes323, maxImpact, swapToken, tokenAddress, uri, publicFields, AI_DIR, MAX_VIDEO_BYTES, FINAL_JOB, CLOSED_LAUNCHPAD_TOOLS, BIGINT_FIELDS, ALLOWED_OPTIONS;
|
|
35440
|
+
var toJson, address5, usdg, units, pair2, slippage2, bytes323, maxImpact, swapToken, tokenAddress, uri, publicFields, AI_DIR, MAX_VIDEO_BYTES, FINAL_JOB, CLOSED_LAUNCHPAD_TOOLS, ENDED_SWAPS_KEPT, BIGINT_FIELDS, ALLOWED_OPTIONS;
|
|
34922
35441
|
var init_tools = __esm({
|
|
34923
35442
|
"src/tools.ts"() {
|
|
34924
35443
|
"use strict";
|
|
@@ -34971,6 +35490,7 @@ var init_tools = __esm({
|
|
|
34971
35490
|
"airdrop_fund",
|
|
34972
35491
|
"airdrop_start"
|
|
34973
35492
|
]);
|
|
35493
|
+
ENDED_SWAPS_KEPT = 20;
|
|
34974
35494
|
BIGINT_FIELDS = /* @__PURE__ */ new Set(["minDividendBalance", "maxBuy", "maxWallet", "graduationThreshold"]);
|
|
34975
35495
|
ALLOWED_OPTIONS = /* @__PURE__ */ new Set([
|
|
34976
35496
|
"tiers",
|