@ostraagent/mcp 0.1.10 → 0.1.11
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/dist/ostra-mcp.js +171 -25
- 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.11", 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
|
|
|
@@ -15521,6 +15521,7 @@ async function readBorroPosition(client, stockVault, stock2) {
|
|
|
15521
15521
|
listed,
|
|
15522
15522
|
supply: e.totalSupplyAssets,
|
|
15523
15523
|
borrowed: e.totalBorrowAssets,
|
|
15524
|
+
borrowedShares: e.totalBorrowShares,
|
|
15524
15525
|
at: at.timestamp
|
|
15525
15526
|
};
|
|
15526
15527
|
}
|
|
@@ -20248,6 +20249,10 @@ import { decodeFunctionData as decodeFunctionData4, getAddress as getAddress17,
|
|
|
20248
20249
|
import { x402Client, x402HTTPClient } from "@x402/core/client";
|
|
20249
20250
|
import { toClientEvmSigner } from "@x402/evm";
|
|
20250
20251
|
import { BatchSettlementEvmScheme } from "@x402/evm/batch-settlement/client";
|
|
20252
|
+
function notLandedError(attempts, lastReason) {
|
|
20253
|
+
const reason = lastReason.trim().slice(0, NOT_SENT_MESSAGE_MAX);
|
|
20254
|
+
return new Error(`the relayer could not land the request in ${attempts} attempts${reason === "" ? "" : `; it answered last: ${reason}`}`);
|
|
20255
|
+
}
|
|
20251
20256
|
function address(value, what) {
|
|
20252
20257
|
if (typeof value !== "string" || !isAddress6(value, { strict: false })) throw new Error(`${what} is not an address`);
|
|
20253
20258
|
return getAddress17(value);
|
|
@@ -20296,6 +20301,25 @@ function relayerChannelDeposit(needed, vaultBalance, keep = 0n) {
|
|
|
20296
20301
|
const want = needed > RELAYER_CHANNEL_DEPOSIT ? needed : RELAYER_CHANNEL_DEPOSIT;
|
|
20297
20302
|
return want < available ? want : available;
|
|
20298
20303
|
}
|
|
20304
|
+
function relayerSpendPlan(p) {
|
|
20305
|
+
const rooms = [...p.rooms];
|
|
20306
|
+
let balance = p.balance;
|
|
20307
|
+
let debt = p.debt;
|
|
20308
|
+
for (const a of p.amounts) {
|
|
20309
|
+
const i = debt > 0n ? -1 : rooms.findIndex((r) => r >= a);
|
|
20310
|
+
if (i >= 0) {
|
|
20311
|
+
rooms[i] = rooms[i] - a;
|
|
20312
|
+
continue;
|
|
20313
|
+
}
|
|
20314
|
+
const needed = debt + p.openCost + a;
|
|
20315
|
+
if (balance < needed) return false;
|
|
20316
|
+
const deposit = relayerChannelDeposit(needed, balance);
|
|
20317
|
+
balance -= deposit;
|
|
20318
|
+
debt = 0n;
|
|
20319
|
+
rooms.push(deposit - needed);
|
|
20320
|
+
}
|
|
20321
|
+
return true;
|
|
20322
|
+
}
|
|
20299
20323
|
function relayerOfferProblem(r, want) {
|
|
20300
20324
|
if (r.scheme !== "batch-settlement") return `the offer is ${r.scheme}, not batch-settlement`;
|
|
20301
20325
|
if (r.network !== want.network) return `the offer is on ${r.network}, not ${want.network}`;
|
|
@@ -20330,7 +20354,7 @@ function openChannelCall(calls, vault, token) {
|
|
|
20330
20354
|
}
|
|
20331
20355
|
return null;
|
|
20332
20356
|
}
|
|
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;
|
|
20357
|
+
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
20358
|
var init_relay = __esm({
|
|
20335
20359
|
"../core/src/relay.ts"() {
|
|
20336
20360
|
"use strict";
|
|
@@ -20344,6 +20368,7 @@ var init_relay = __esm({
|
|
|
20344
20368
|
REQUEST_TIMEOUT_MS2 = 24e4;
|
|
20345
20369
|
MAX_STEPS = 8;
|
|
20346
20370
|
MAX_RESENDS = 3;
|
|
20371
|
+
NOT_SENT_MESSAGE_MAX = 500;
|
|
20347
20372
|
LANDED_TIMEOUT_MS = 6e4;
|
|
20348
20373
|
OPEN_READ_TRIES = 20;
|
|
20349
20374
|
OPEN_READ_INTERVAL_MS = 500;
|
|
@@ -20572,6 +20597,55 @@ var init_relay = __esm({
|
|
|
20572
20597
|
}
|
|
20573
20598
|
return null;
|
|
20574
20599
|
}
|
|
20600
|
+
/**
|
|
20601
|
+
* Read only (nothing is retired, opened or signed): why this vault cannot pay, now, vault spends that reserve `gases`
|
|
20602
|
+
* (each as VaultService.operate reserves it: reserve's amount for that gas), or null when it can. The spends are
|
|
20603
|
+
* played in order as reserve and #ensureChannel would pay them: each from a usable relayer channel with room for it,
|
|
20604
|
+
* or else from a new channel, whose open needs the vault's debt and the open's own spend (#spendBound) on top and
|
|
20605
|
+
* takes RELAYER_CHANNEL_DEPOSIT or what it needs, at most what the vault holds. The vault's credit at the relayer is
|
|
20606
|
+
* not counted: it lowers a price only after the reservation is made. An unpaid open the relayer holds for the vault
|
|
20607
|
+
* is refused here (it is paid before anything else). An operation that sends something first (an approval before the
|
|
20608
|
+
* call it allows) checks this before its first spend, so it does not leave the first done and the rest unpaid.
|
|
20609
|
+
*/
|
|
20610
|
+
async shortfall(gases) {
|
|
20611
|
+
const facts = await this.facts();
|
|
20612
|
+
const vault = await this.#buyerVault().vaultAddress();
|
|
20613
|
+
if (await readVault(this.#client, this.#config.deployment, vault) === null) return `the vault ${vault} does not exist yet`;
|
|
20614
|
+
const state = await this.vaultState(vault);
|
|
20615
|
+
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`;
|
|
20616
|
+
const amounts = [];
|
|
20617
|
+
for (const g of gases) amounts.push(await this.#reserveAmount(g));
|
|
20618
|
+
const bound2 = await this.#spendBound();
|
|
20619
|
+
const payer = await this.#payer();
|
|
20620
|
+
const rooms = [];
|
|
20621
|
+
for (const c of await this.#records()) {
|
|
20622
|
+
if (c.retired || now() >= c.openedAt + SESSION_MAX_AGE_SECONDS) continue;
|
|
20623
|
+
const free = this.#free(c, null);
|
|
20624
|
+
if (free <= 0n) continue;
|
|
20625
|
+
const ch = await readChannel(this.#client, this.#config.deployment.batchSettlement, c.channel);
|
|
20626
|
+
const usable = payer !== null && getAddress17(c.config.payer) === payer && getAddress17(c.config.receiverAuthorizer) === facts.vault && getAddress17(c.config.receiver) === facts.split && ch.pendingWithdrawal === null;
|
|
20627
|
+
const onChain = ch.balance - BigInt(c.cumulative);
|
|
20628
|
+
if (usable) rooms.push(free < onChain ? free : onChain);
|
|
20629
|
+
}
|
|
20630
|
+
const balance = await tokenBalance(this.#client, this.#config.deployment.token, vault);
|
|
20631
|
+
const plan = (held) => relayerSpendPlan({ amounts, rooms, balance: held, debt: state.debt, openCost: bound2 });
|
|
20632
|
+
if (plan(balance)) return null;
|
|
20633
|
+
let lo = balance;
|
|
20634
|
+
let hi = balance > 0n ? balance * 2n : 1n;
|
|
20635
|
+
while (!plan(hi)) hi *= 2n;
|
|
20636
|
+
while (hi - lo > 1n) {
|
|
20637
|
+
const mid = (lo + hi) / 2n;
|
|
20638
|
+
if (plan(mid)) hi = mid;
|
|
20639
|
+
else lo = mid;
|
|
20640
|
+
}
|
|
20641
|
+
const n = gases.length;
|
|
20642
|
+
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)`;
|
|
20643
|
+
}
|
|
20644
|
+
/** 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. */
|
|
20645
|
+
async #reserveAmount(gas, extraWei = 0n) {
|
|
20646
|
+
const wei = withMargin(gas * await this.#client.getGasPrice()) + extraWei;
|
|
20647
|
+
return maxAcceptedQuote(weiToTokenUnits(wei, await this.#ethUsd(), TOKEN_DECIMALS));
|
|
20648
|
+
}
|
|
20575
20649
|
/** Base units a transaction of `wei` comes to at the Chainlink price, margin included (the relayer's rule). */
|
|
20576
20650
|
async #amountFor(wei) {
|
|
20577
20651
|
return weiToTokenUnits(withMargin(wei), await this.#ethUsd(), TOKEN_DECIMALS);
|
|
@@ -20610,8 +20684,7 @@ var init_relay = __esm({
|
|
|
20610
20684
|
await (openChannel ?? ((t) => this.#buyerVault().openRelayerChannel(t)))(terms);
|
|
20611
20685
|
}
|
|
20612
20686
|
async reserve(gas, openChannel, keep = 0n, extraWei = 0n) {
|
|
20613
|
-
const
|
|
20614
|
-
const amount = maxAcceptedQuote(weiToTokenUnits(wei, await this.#ethUsd(), TOKEN_DECIMALS));
|
|
20687
|
+
const amount = await this.#reserveAmount(gas, extraWei);
|
|
20615
20688
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
20616
20689
|
const c = await this.#serial(async () => {
|
|
20617
20690
|
const found = await this.#channelFor(amount, null);
|
|
@@ -20826,6 +20899,7 @@ var init_relay = __esm({
|
|
|
20826
20899
|
}
|
|
20827
20900
|
async send(calls, options = {}) {
|
|
20828
20901
|
await this.facts();
|
|
20902
|
+
let notSent = "";
|
|
20829
20903
|
for (let resend = 0; resend < MAX_RESENDS; resend++) {
|
|
20830
20904
|
let answer = await this.#post(calls, { prepay: options.prepay === true, payer: await this.#payer(), allowFailedSwaps: options.allowFailedSwaps === true });
|
|
20831
20905
|
let again = false;
|
|
@@ -20848,6 +20922,7 @@ var init_relay = __esm({
|
|
|
20848
20922
|
continue;
|
|
20849
20923
|
}
|
|
20850
20924
|
if (answer.status === 409 && error === "not_sent") {
|
|
20925
|
+
notSent = typeof b?.message === "string" ? b.message : "";
|
|
20851
20926
|
again = true;
|
|
20852
20927
|
continue;
|
|
20853
20928
|
}
|
|
@@ -20866,7 +20941,7 @@ var init_relay = __esm({
|
|
|
20866
20941
|
}
|
|
20867
20942
|
if (!again) throw new Error(`the relayer did not relay the request after ${MAX_STEPS} answers`);
|
|
20868
20943
|
}
|
|
20869
|
-
throw
|
|
20944
|
+
throw notLandedError(MAX_RESENDS, notSent);
|
|
20870
20945
|
}
|
|
20871
20946
|
/**
|
|
20872
20947
|
* Relayer channels past SESSION_MAX_AGE_SECONDS stop paying; returns those
|
|
@@ -22035,6 +22110,21 @@ var init_borro2 = __esm({
|
|
|
22035
22110
|
}
|
|
22036
22111
|
return { buyerVault: buyer, usdgLent: { shares: usdg2.shares.toString(), value: formatUnitsAmount(usdg2.value, TOKEN_DECIMALS) }, stocks };
|
|
22037
22112
|
}
|
|
22113
|
+
/**
|
|
22114
|
+
* Per Borro stock whose vault of this agent exists: its market, the stock vault's borrow shares, and the market's
|
|
22115
|
+
* borrows and borrow shares accrued to this block, so that any number of borrow shares is valued now as
|
|
22116
|
+
* toAssetsUp(shares, borrowed, borrowedShares) (what fundFromYield takes off as the debt's interest).
|
|
22117
|
+
*/
|
|
22118
|
+
async debtBook() {
|
|
22119
|
+
const out = [];
|
|
22120
|
+
for (const s of borroStocks()) {
|
|
22121
|
+
const v = await this.#p.tokenVault(s.token).vaultAddress();
|
|
22122
|
+
if (await readVault(this.#p.client, this.#p.config.deployment, v) === null) continue;
|
|
22123
|
+
const p = await readBorroPosition(this.#p.client, v, s);
|
|
22124
|
+
out.push({ symbol: s.symbol, marketId: s.marketId, borrowShares: p.borrowShares, borrowed: p.borrowed, borrowedShares: p.borrowedShares });
|
|
22125
|
+
}
|
|
22126
|
+
return out;
|
|
22127
|
+
}
|
|
22038
22128
|
// -------------------------------------------------------------------------
|
|
22039
22129
|
// Lend and redeem
|
|
22040
22130
|
// -------------------------------------------------------------------------
|
|
@@ -23562,7 +23652,7 @@ function simulatedGas(gasUsed) {
|
|
|
23562
23652
|
const g = gasUsed * 5n / 4n + SPEND_GAS_HEADROOM2;
|
|
23563
23653
|
return g > VAULT_SPEND_GAS ? g : VAULT_SPEND_GAS;
|
|
23564
23654
|
}
|
|
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;
|
|
23655
|
+
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
23656
|
var init_launchpad = __esm({
|
|
23567
23657
|
"../core/src/launchpad.ts"() {
|
|
23568
23658
|
"use strict";
|
|
@@ -23598,6 +23688,8 @@ var init_launchpad = __esm({
|
|
|
23598
23688
|
volatility_fee: POOL_SETTING.VOLATILITY_FEE,
|
|
23599
23689
|
max_tx_move: POOL_SETTING.MAX_TX_MOVE
|
|
23600
23690
|
};
|
|
23691
|
+
WOTS_GAS_SPREAD = 100000n;
|
|
23692
|
+
STAND_IN_URI = `ipfs://bafkrei${"a".repeat(52)}`;
|
|
23601
23693
|
LaunchpadService = class {
|
|
23602
23694
|
#client;
|
|
23603
23695
|
#transport;
|
|
@@ -24503,6 +24595,32 @@ var init_launchpad = __esm({
|
|
|
24503
24595
|
if (profile.status !== "sent" || record === null) return { uri: uri2, profile, agentUri: null, pairCreators };
|
|
24504
24596
|
return { uri: uri2, profile, agentUri: await this.setAgentUri(uri2), pairCreators };
|
|
24505
24597
|
}
|
|
24598
|
+
/**
|
|
24599
|
+
* Read only: why the creator vault cannot pay for publishRegistrationFile now, or null when it can or does not pay
|
|
24600
|
+
* through the relayer. Its spends (the profile and, once the agent is registered, its agent URI) are simulated as
|
|
24601
|
+
* setProfile and setAgentUri send them, with the URI set now (or one of an ipfs:// URI's length) in place of the
|
|
24602
|
+
* file's, and each is counted at the gas it will be reserved (simulatedGas) with WOTS_GAS_SPREAD added (a simulation
|
|
24603
|
+
* signs with a throwaway key, and a WOTS signature's verification costs more or less with each message);
|
|
24604
|
+
* RelayerClient.shortfall replays their payment. A
|
|
24605
|
+
* spend the creator vault signed earlier and has not sent is refused here: its next operation would send that one
|
|
24606
|
+
* instead of the profile.
|
|
24607
|
+
*/
|
|
24608
|
+
async publishShortfall() {
|
|
24609
|
+
if (!(this.#creatorSender instanceof RelayerClient)) return null;
|
|
24610
|
+
const s = await this.#creator.state();
|
|
24611
|
+
if (!s.exists) return `the creator vault ${s.vault} does not exist yet`;
|
|
24612
|
+
if ((await this.#creator.spendSlot())?.pending != null) {
|
|
24613
|
+
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`;
|
|
24614
|
+
}
|
|
24615
|
+
const record = await this.#agentRecord();
|
|
24616
|
+
const uri2 = record?.uri ?? await this.#profileUri(s.vault) ?? STAND_IN_URI;
|
|
24617
|
+
const relayer = await this.#creatorSender.payer();
|
|
24618
|
+
const gasOf = async (action, params) => simulatedGas((await simulateVaultSpend(this.#client, this.#config.deployment, { relayer, vault: s.vault, action, params })).gasUsed + WOTS_GAS_SPREAD);
|
|
24619
|
+
const gases = [await gasOf(VAULT_ACTION.SET_PROFILE, setProfileParams(uri2))];
|
|
24620
|
+
if (record !== null) gases.push(await gasOf(VAULT_ACTION.SET_AGENT_URI, setAgentUriParams({ agentId: BigInt(record.agentId), uri: uri2 })));
|
|
24621
|
+
const short = await this.#creatorSender.shortfall(gases);
|
|
24622
|
+
return short === null ? null : `${short}; fund_creator_vault moves USDG into it`;
|
|
24623
|
+
}
|
|
24506
24624
|
/**
|
|
24507
24625
|
* Pins `file`, a registration file built from the current one (Ostrapad's listing, pad.ts), and makes it the
|
|
24508
24626
|
* agent's profile in OstraRegistry and its ERC-8004 registration file when it is registered.
|
|
@@ -24818,7 +24936,11 @@ var init_pad2 = __esm({
|
|
|
24818
24936
|
if (offers !== null) {
|
|
24819
24937
|
const entry = padServiceEntry({ provider: vault, offers }, this.#pad, this.#p.config.chainId);
|
|
24820
24938
|
const digest = padListingDigest(agentId, creatorVault, this.#pad, this.#p.config.chainId);
|
|
24821
|
-
if (!await this.#approved(vault, digest))
|
|
24939
|
+
if (!await this.#approved(vault, digest)) {
|
|
24940
|
+
const short = this.#p.publishShortfall === void 0 ? null : await this.#p.publishShortfall();
|
|
24941
|
+
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`);
|
|
24942
|
+
approval = await this.#approveAlone(digest, "Ostrapad listing approval");
|
|
24943
|
+
}
|
|
24822
24944
|
services.push(entry);
|
|
24823
24945
|
}
|
|
24824
24946
|
const out = await this.#p.publishFile({ ...current, services });
|
|
@@ -25542,6 +25664,19 @@ var init_pay = __esm({
|
|
|
25542
25664
|
|
|
25543
25665
|
// ../core/src/raeto.ts
|
|
25544
25666
|
import { getAddress as getAddress27, hashMessage, isAddress as isAddress13, parseAbi as parseAbi6 } from "viem";
|
|
25667
|
+
function netYieldSince(mark, now3, book) {
|
|
25668
|
+
if (mark.debts === void 0) return null;
|
|
25669
|
+
const high = BigInt(mark.price);
|
|
25670
|
+
const earned = now3.price > high ? BigInt(mark.shares) * (now3.price - high) / now3.unit : 0n;
|
|
25671
|
+
let interest = 0n;
|
|
25672
|
+
for (const d of mark.debts) {
|
|
25673
|
+
const m = book.find((b) => b.marketId.toLowerCase() === d.marketId.toLowerCase());
|
|
25674
|
+
if (m === void 0) return null;
|
|
25675
|
+
const owesNow = toAssetsUp(BigInt(d.borrowShares), m.borrowed, m.borrowedShares);
|
|
25676
|
+
if (owesNow > BigInt(d.debt)) interest += owesNow - BigInt(d.debt);
|
|
25677
|
+
}
|
|
25678
|
+
return { earned, interest };
|
|
25679
|
+
}
|
|
25545
25680
|
function raetoImages(answer) {
|
|
25546
25681
|
const out = [];
|
|
25547
25682
|
const choices = answer?.choices;
|
|
@@ -25788,15 +25923,20 @@ var init_raeto = __esm({
|
|
|
25788
25923
|
return this.#scrub(await this.#call("POST", "/v1/chat/completions", request, await this.#key(), COMPLETION_TIMEOUT_MS));
|
|
25789
25924
|
}
|
|
25790
25925
|
/**
|
|
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
|
|
25926
|
+
* What the vault's cash vault shares earn, net of the agent's Borro debts' interest, as credits. Kept here: a mark
|
|
25927
|
+
* (the shares, the highest share price read: a high-water mark, so a price that falls and comes back earns nothing
|
|
25928
|
+
* until it passes its high; and each Borro debt's borrow shares with what they owed), what is owed (netYieldSince,
|
|
25929
|
+
* added on every call: the shares' rise over the high less the interest the marked debts accrued; it can fall below
|
|
25930
|
+
* zero, and nothing is sent until it is back above `min`), and USDG redeemed for it and not sent yet (`ready`), with
|
|
25931
|
+
* the vault's spend slot its transfer is signed at. The interest comes off because the carry strategy borrows USDG
|
|
25932
|
+
* from Borro into this same cash vault: the shares' rise is not earned while the loan behind them owes interest.
|
|
25933
|
+
* A call adds what was earned since the mark, moves the mark to now, sends what was redeemed and not sent first, and
|
|
25934
|
+
* else, when what is owed is at least `min` USDG, redeems that from the cash vault and sends what the redeem paid (at
|
|
25935
|
+
* most what is owed) to Raeto's payTo. A transfer of `ready` that another operation of the vault sent first (it sends
|
|
25936
|
+
* a signed spend before its own) is found at its slot and not paid again. Shares and debts added or removed count
|
|
25937
|
+
* from the read after; a full exit leaves what was owed until then. A mark kept before debts were marked (MCP 0.1.10
|
|
25938
|
+
* and earlier) earns nothing for the time since it, as that time's interest cannot be read back. Raeto's terms are
|
|
25939
|
+
* checked before anything is redeemed. Calls run one after the other.
|
|
25800
25940
|
*/
|
|
25801
25941
|
fundFromYield(min2 = "1") {
|
|
25802
25942
|
return this.#serial(async () => {
|
|
@@ -25810,20 +25950,25 @@ var init_raeto = __esm({
|
|
|
25810
25950
|
return { shares, unit, price };
|
|
25811
25951
|
};
|
|
25812
25952
|
const now3 = await read();
|
|
25953
|
+
const book = await this.#p.borro.debtBook();
|
|
25954
|
+
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
25955
|
const text3 = await this.#p.folder.read(YIELD_FILE);
|
|
25814
25956
|
const kept = text3 === void 0 ? null : JSON.parse(text3);
|
|
25815
|
-
const usd4 = (x) => formatUnitsAmount(x, TOKEN_DECIMALS);
|
|
25957
|
+
const usd4 = (x) => formatUnitsAmount(x > 0n ? x : 0n, TOKEN_DECIMALS);
|
|
25816
25958
|
const write = (m) => this.#p.folder.write(YIELD_FILE, JSON.stringify(m));
|
|
25817
25959
|
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" };
|
|
25960
|
+
await write({ vault: target, shares: now3.shares.toString(), price: now3.price.toString(), owed: "0", ready: "0", debts });
|
|
25961
|
+
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
25962
|
}
|
|
25821
25963
|
const high = BigInt(kept.price);
|
|
25822
|
-
|
|
25964
|
+
const net = netYieldSince(kept, now3, book);
|
|
25965
|
+
let owed = BigInt(kept.owed) + (net === null ? 0n : net.earned - net.interest);
|
|
25823
25966
|
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() };
|
|
25967
|
+
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
25968
|
await write(mark);
|
|
25826
|
-
|
|
25969
|
+
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; " : "";
|
|
25970
|
+
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` };
|
|
25971
|
+
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
25972
|
const { payTo } = await this.terms();
|
|
25828
25973
|
if (ready > 0n && mark.readySlot !== void 0) {
|
|
25829
25974
|
const slot2 = { nonce: BigInt(mark.readySlot.nonce), keyIndex: BigInt(mark.readySlot.keyIndex) };
|
|
@@ -25859,7 +26004,7 @@ var init_raeto = __esm({
|
|
|
25859
26004
|
ready = paid <= 0n ? 0n : paid < owed ? paid : owed;
|
|
25860
26005
|
owed -= ready;
|
|
25861
26006
|
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() });
|
|
26007
|
+
await write({ vault: target, shares: after.shares.toString(), price: afterHigh.toString(), owed: owed.toString(), ready: ready.toString(), debts });
|
|
25863
26008
|
if (ready === 0n) return { vault: target, owed: usd4(owed), sent: "0", note: "the redeem paid nothing into the vault", redeem };
|
|
25864
26009
|
}
|
|
25865
26010
|
const slot = await this.#p.buyer.spendSlot();
|
|
@@ -33955,6 +34100,7 @@ var init_agent = __esm({
|
|
|
33955
34100
|
return typeof p2.profile === "object" && p2.profile !== null && !Array.isArray(p2.profile) ? p2.profile : null;
|
|
33956
34101
|
},
|
|
33957
34102
|
publishFile: (file) => lp.publishRegistrationFile(file),
|
|
34103
|
+
publishShortfall: () => lp.publishShortfall(),
|
|
33958
34104
|
upload: (file) => uploadJson(config.relayerUrl, file),
|
|
33959
34105
|
indexerUrl: config.padIndexerUrl
|
|
33960
34106
|
});
|
|
@@ -34624,7 +34770,7 @@ function registerTools(server, agent) {
|
|
|
34624
34770
|
};
|
|
34625
34771
|
tool(
|
|
34626
34772
|
"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).",
|
|
34773
|
+
"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
34774
|
{
|
|
34629
34775
|
action: z.enum(["login", "me", "models", "fund", "fund_yield", "complete"]),
|
|
34630
34776
|
name: z.string().min(1).max(64).optional(),
|
|
@@ -34683,7 +34829,7 @@ function registerTools(server, agent) {
|
|
|
34683
34829
|
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
34830
|
tool(
|
|
34685
34831
|
"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 register_agent first. 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.",
|
|
34832
|
+
"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 register_agent first, 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
34833
|
{ 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
34834
|
async (a) => {
|
|
34689
34835
|
if (a.action === "publish") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ostraagent/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Ostra Agent's MCP server (stdio): the post-quantum privacy vault for AI agents. One vault to pay, earn, work and hire on Ostrapad, and stay private on Robinhood Chain, with no ETH (the Ostra relayer sends its transactions, paid in USDG).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|