@arcnow/mcp 0.1.0

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.
Files changed (71) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +624 -0
  3. package/dist/client-options.d.ts +16 -0
  4. package/dist/client-options.d.ts.map +1 -0
  5. package/dist/client-options.js +22 -0
  6. package/dist/client-options.js.map +1 -0
  7. package/dist/config.d.ts +223 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +516 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/format.d.ts +79 -0
  12. package/dist/format.d.ts.map +1 -0
  13. package/dist/format.js +164 -0
  14. package/dist/format.js.map +1 -0
  15. package/dist/index.d.ts +17 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +50 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/sdk-port.d.ts +227 -0
  20. package/dist/sdk-port.d.ts.map +1 -0
  21. package/dist/sdk-port.js +144 -0
  22. package/dist/sdk-port.js.map +1 -0
  23. package/dist/server.d.ts +25 -0
  24. package/dist/server.d.ts.map +1 -0
  25. package/dist/server.js +103 -0
  26. package/dist/server.js.map +1 -0
  27. package/dist/tools/errors.d.ts +44 -0
  28. package/dist/tools/errors.d.ts.map +1 -0
  29. package/dist/tools/errors.js +231 -0
  30. package/dist/tools/errors.js.map +1 -0
  31. package/dist/tools/index.d.ts +35 -0
  32. package/dist/tools/index.d.ts.map +1 -0
  33. package/dist/tools/index.js +59 -0
  34. package/dist/tools/index.js.map +1 -0
  35. package/dist/tools/launch-params.d.ts +27 -0
  36. package/dist/tools/launch-params.d.ts.map +1 -0
  37. package/dist/tools/launch-params.js +29 -0
  38. package/dist/tools/launch-params.js.map +1 -0
  39. package/dist/tools/pool.d.ts +84 -0
  40. package/dist/tools/pool.d.ts.map +1 -0
  41. package/dist/tools/pool.js +249 -0
  42. package/dist/tools/pool.js.map +1 -0
  43. package/dist/tools/quote.d.ts +53 -0
  44. package/dist/tools/quote.d.ts.map +1 -0
  45. package/dist/tools/quote.js +85 -0
  46. package/dist/tools/quote.js.map +1 -0
  47. package/dist/tools/read.d.ts +26 -0
  48. package/dist/tools/read.d.ts.map +1 -0
  49. package/dist/tools/read.js +920 -0
  50. package/dist/tools/read.js.map +1 -0
  51. package/dist/tools/resolve.d.ts +45 -0
  52. package/dist/tools/resolve.d.ts.map +1 -0
  53. package/dist/tools/resolve.js +75 -0
  54. package/dist/tools/resolve.js.map +1 -0
  55. package/dist/tools/schema.d.ts +98 -0
  56. package/dist/tools/schema.d.ts.map +1 -0
  57. package/dist/tools/schema.js +143 -0
  58. package/dist/tools/schema.js.map +1 -0
  59. package/dist/tools/spend.d.ts +45 -0
  60. package/dist/tools/spend.d.ts.map +1 -0
  61. package/dist/tools/spend.js +99 -0
  62. package/dist/tools/spend.js.map +1 -0
  63. package/dist/tools/venue.d.ts +67 -0
  64. package/dist/tools/venue.d.ts.map +1 -0
  65. package/dist/tools/venue.js +110 -0
  66. package/dist/tools/venue.js.map +1 -0
  67. package/dist/tools/write.d.ts +56 -0
  68. package/dist/tools/write.d.ts.map +1 -0
  69. package/dist/tools/write.js +950 -0
  70. package/dist/tools/write.js.map +1 -0
  71. package/package.json +55 -0
@@ -0,0 +1,84 @@
1
+ /**
2
+ * A graduated token's Uniswap v4 pool, as a quote presents it.
3
+ *
4
+ * # What a pool quote contains
5
+ *
6
+ * The SDK prices a pool trade by `eth_call`-ing the real swap through
7
+ * arcnow.io's router and reading back the trader's own balance delta. So the
8
+ * figures it returns — the quote in or out, tokens out or in — are the real
9
+ * fill, with **two** charges already inside them, and this module's job is to
10
+ * take them back out and name each one:
11
+ *
12
+ * - **arcnow.io's 1%**, the same flat fee the curve took, charged in the pool's
13
+ * quote token by `ArcNowFeeHook` inside the swap — off the input on a buy,
14
+ * out of the payout on a sell. The SDK reports it as `feeQuote`.
15
+ * - **The pool's own LP fee**, which is Uniswap's and not arcnow.io's: the
16
+ * `fee` field of the pool key, in hundredths of a bip (3000 is 0.3%), charged
17
+ * by the pool on the amount it swaps and kept by its liquidity. The SDK does
18
+ * not report it as an amount; its rate is read from `pool.key()` and the
19
+ * amount follows from the rate.
20
+ *
21
+ * # The quote is the SDK's, whichever currency of the key it is
22
+ *
23
+ * A v4 key orders its two currencies by address. Native USDC is `address(0)` and
24
+ * always `currency0`; an ERC-20 quote such as EURC may be either. Nothing here
25
+ * reads `currency0` as the quote: the amounts are the SDK's `QuoteAmount`s,
26
+ * already oriented and scaled, and where a report names the pair it asks the
27
+ * SDK which side the quote is on.
28
+ *
29
+ * # The spot price comes from a probe, because the SDK has no reader for one
30
+ *
31
+ * `@arcnow/sdk` exposes no pool price — no `slot0`, no `sqrtPriceX96`. Reading
32
+ * the PoolManager's storage here would be exactly the second, unpinned copy of
33
+ * chain code that `src/sdk-port.ts` exists to prevent. So the spot price is the
34
+ * SDK's own quote of a buy too small to move the price ({@link spotProbe}),
35
+ * with both fees taken back out, and every report that shows one says so. The
36
+ * price impact is the order's own fill, fees out, against that.
37
+ *
38
+ * @module
39
+ */
40
+ import type { QuoteTokenInfo } from "@arcnow/sdk";
41
+ import { QuoteAmount, Tokens } from "@arcnow/sdk";
42
+ import type { PoolHandle } from "../sdk-port.js";
43
+ import type { ToolContext, ToolOutput } from "./schema.js";
44
+ import type { Market } from "./venue.js";
45
+ /**
46
+ * The buy a spot price is read from: a millionth of a whole unit of the quote,
47
+ * or 10,000 of its raw units if that is more.
48
+ *
49
+ * Small enough that it moves no pool's price by anything a report can show.
50
+ * Large enough that the hook and the pool, which charge their fees on RAW
51
+ * units, round by at most one part in ten thousand: for 18-decimal native USDC
52
+ * that is 0.000001 USDC, and for 6-decimal EURC it is 0.01 EURC — a millionth
53
+ * of a EURC is one raw unit, on which a 1% fee floors to nothing.
54
+ */
55
+ export declare function spotProbe(quote: QuoteTokenInfo): QuoteAmount;
56
+ /** A v4 LP fee, in hundredths of a bip, said both ways. */
57
+ export declare function lpFee(fee: number): string;
58
+ /** The LP fee on a buy, in the quote: charged on what reaches the pool. */
59
+ export declare function buyLpFee(quoteIn: QuoteAmount, fee: number): QuoteAmount;
60
+ /** The LP fee on a sell, in tokens: charged on the tokens the pool takes in. */
61
+ export declare function sellLpFee(tokensIn: Tokens, fee: number): Tokens;
62
+ /** The quote per token a buy filled at, with both fees taken back out. */
63
+ export declare function buyFillExFees(quoteIn: QuoteAmount, tokensOut: Tokens, fee: number): QuoteAmount | undefined;
64
+ /** The quote per token a sell filled at, with both fees taken back out. */
65
+ export declare function sellFillExFees(tokensIn: Tokens, quoteOut: QuoteAmount, fee: number): QuoteAmount | undefined;
66
+ /** The pool's spot price, fees out, from the SDK's quote of {@link spotProbe}. */
67
+ export declare function poolSpotPrice(pool: PoolHandle, quote: QuoteTokenInfo, fee: number): Promise<QuoteAmount | undefined>;
68
+ /**
69
+ * How the quote leaves the buyer: `msg.value` for native USDC, an ERC-20 pull
70
+ * after an exact approval for anything else.
71
+ */
72
+ export declare function buyPaymentLine(amount: QuoteAmount, puller: string): string;
73
+ export declare function quotePoolBuy(args: {
74
+ quoteIn: string;
75
+ referrer?: string | undefined;
76
+ developer?: string | undefined;
77
+ }, ctx: ToolContext, market: Market, symbol: string): Promise<ToolOutput>;
78
+ export declare function quotePoolSell(args: {
79
+ tokensIn: string;
80
+ holder?: string | undefined;
81
+ referrer?: string | undefined;
82
+ developer?: string | undefined;
83
+ }, ctx: ToolContext, market: Market, symbol: string): Promise<ToolOutput>;
84
+ //# sourceMappingURL=pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/tools/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAiC,MAAM,aAAa,CAAC;AACjF,OAAO,EAIL,WAAW,EACX,MAAM,EAGP,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AASzC;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,WAAW,CAE5D;AAED,2DAA2D;AAC3D,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzC;AAOD,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAGvE;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,WAAW,GAAG,SAAS,CAIzB;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,WAAW,EACrB,GAAG,EAAE,MAAM,GACV,WAAW,GAAG,SAAS,CAKzB;AAED,kFAAkF;AAClF,wBAAsB,aAAa,CACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAQlC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO1E;AA4BD,wBAAsB,YAAY,CAChC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EACxF,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,CAAC,CAoDrB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,EACD,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,CAAC,CA+ErB"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * A graduated token's Uniswap v4 pool, as a quote presents it.
3
+ *
4
+ * # What a pool quote contains
5
+ *
6
+ * The SDK prices a pool trade by `eth_call`-ing the real swap through
7
+ * arcnow.io's router and reading back the trader's own balance delta. So the
8
+ * figures it returns — the quote in or out, tokens out or in — are the real
9
+ * fill, with **two** charges already inside them, and this module's job is to
10
+ * take them back out and name each one:
11
+ *
12
+ * - **arcnow.io's 1%**, the same flat fee the curve took, charged in the pool's
13
+ * quote token by `ArcNowFeeHook` inside the swap — off the input on a buy,
14
+ * out of the payout on a sell. The SDK reports it as `feeQuote`.
15
+ * - **The pool's own LP fee**, which is Uniswap's and not arcnow.io's: the
16
+ * `fee` field of the pool key, in hundredths of a bip (3000 is 0.3%), charged
17
+ * by the pool on the amount it swaps and kept by its liquidity. The SDK does
18
+ * not report it as an amount; its rate is read from `pool.key()` and the
19
+ * amount follows from the rate.
20
+ *
21
+ * # The quote is the SDK's, whichever currency of the key it is
22
+ *
23
+ * A v4 key orders its two currencies by address. Native USDC is `address(0)` and
24
+ * always `currency0`; an ERC-20 quote such as EURC may be either. Nothing here
25
+ * reads `currency0` as the quote: the amounts are the SDK's `QuoteAmount`s,
26
+ * already oriented and scaled, and where a report names the pair it asks the
27
+ * SDK which side the quote is on.
28
+ *
29
+ * # The spot price comes from a probe, because the SDK has no reader for one
30
+ *
31
+ * `@arcnow/sdk` exposes no pool price — no `slot0`, no `sqrtPriceX96`. Reading
32
+ * the PoolManager's storage here would be exactly the second, unpinned copy of
33
+ * chain code that `src/sdk-port.ts` exists to prevent. So the spot price is the
34
+ * SDK's own quote of a buy too small to move the price ({@link spotProbe}),
35
+ * with both fees taken back out, and every report that shows one says so. The
36
+ * price impact is the order's own fill, fees out, against that.
37
+ *
38
+ * @module
39
+ */
40
+ import { Bps, minQuoteOutFromQuote, minTokensOutFromQuote, QuoteAmount, Tokens, TRADE_FEE_BPS, WAD, } from "@arcnow/sdk";
41
+ import { addr, effectivePrice, money, note, price, priceMove, qty, report, section } from "../format.js";
42
+ import { renderPoolError } from "./errors.js";
43
+ import { parseQuoteAmount } from "./quote.js";
44
+ import { refuseCurveOnly, routerName, venueMovedText } from "./venue.js";
45
+ const BPS = 10000n;
46
+ const LP_FEE_DENOMINATOR = 1000000n;
47
+ /** The tolerances a quote is shown at, so a floor is a choice and not a guess. */
48
+ const TOLERANCES = [50n, 100n, 300n, 1000n];
49
+ /**
50
+ * The buy a spot price is read from: a millionth of a whole unit of the quote,
51
+ * or 10,000 of its raw units if that is more.
52
+ *
53
+ * Small enough that it moves no pool's price by anything a report can show.
54
+ * Large enough that the hook and the pool, which charge their fees on RAW
55
+ * units, round by at most one part in ten thousand: for 18-decimal native USDC
56
+ * that is 0.000001 USDC, and for 6-decimal EURC it is 0.01 EURC — a millionth
57
+ * of a EURC is one raw unit, on which a 1% fee floors to nothing.
58
+ */
59
+ export function spotProbe(quote) {
60
+ return QuoteAmount.fromRaw(quote, 10n ** BigInt(Math.max(4, quote.decimals - 6)));
61
+ }
62
+ /** A v4 LP fee, in hundredths of a bip, said both ways. */
63
+ export function lpFee(fee) {
64
+ return `${fee / 10_000}% (${fee} hundredths of a bip)`;
65
+ }
66
+ /** What reaches the pool on a buy: the input after arcnow.io's 1%. */
67
+ function afterHookFee(quoteIn) {
68
+ return (quoteIn.wad * (BPS - TRADE_FEE_BPS)) / BPS;
69
+ }
70
+ /** The LP fee on a buy, in the quote: charged on what reaches the pool. */
71
+ export function buyLpFee(quoteIn, fee) {
72
+ const lp = (afterHookFee(quoteIn) * BigInt(fee)) / LP_FEE_DENOMINATOR;
73
+ return QuoteAmount.fromWad(quoteIn.token, lp);
74
+ }
75
+ /** The LP fee on a sell, in tokens: charged on the tokens the pool takes in. */
76
+ export function sellLpFee(tokensIn, fee) {
77
+ return Tokens.fromWad((tokensIn.wad * BigInt(fee)) / LP_FEE_DENOMINATOR);
78
+ }
79
+ /** The quote per token a buy filled at, with both fees taken back out. */
80
+ export function buyFillExFees(quoteIn, tokensOut, fee) {
81
+ if (tokensOut.wad === 0n)
82
+ return undefined;
83
+ const swapped = (afterHookFee(quoteIn) * (LP_FEE_DENOMINATOR - BigInt(fee))) / LP_FEE_DENOMINATOR;
84
+ return QuoteAmount.fromWad(quoteIn.token, (swapped * WAD) / tokensOut.wad);
85
+ }
86
+ /** The quote per token a sell filled at, with both fees taken back out. */
87
+ export function sellFillExFees(tokensIn, quoteOut, fee) {
88
+ const swapped = (tokensIn.wad * (LP_FEE_DENOMINATOR - BigInt(fee))) / LP_FEE_DENOMINATOR;
89
+ if (swapped === 0n)
90
+ return undefined;
91
+ const gross = (quoteOut.wad * BPS) / (BPS - TRADE_FEE_BPS);
92
+ return QuoteAmount.fromWad(quoteOut.token, (gross * WAD) / swapped);
93
+ }
94
+ /** The pool's spot price, fees out, from the SDK's quote of {@link spotProbe}. */
95
+ export async function poolSpotPrice(pool, quote, fee) {
96
+ const probe = spotProbe(quote);
97
+ try {
98
+ const quoted = await pool.quoteBuy(probe);
99
+ return buyFillExFees(probe, quoted.tokensOut, fee);
100
+ }
101
+ catch {
102
+ return undefined;
103
+ }
104
+ }
105
+ /**
106
+ * How the quote leaves the buyer: `msg.value` for native USDC, an ERC-20 pull
107
+ * after an exact approval for anything else.
108
+ */
109
+ export function buyPaymentLine(amount, puller) {
110
+ return amount.token.isNative
111
+ ? `${money(amount)} — as msg.value; native USDC needs no approval and has no ERC-20 leg`
112
+ : `${money(amount)} — pulled by ${puller} from the buyer's ${amount.token.symbol}, with no value `
113
+ + `sent: it needs an exact ERC-20 approval of this amount first — a separate transaction, `
114
+ + "sent by the buying tool only when the existing allowance falls short, never for more, "
115
+ + "and reported";
116
+ }
117
+ function againstSpot(spot, fill, side) {
118
+ return section("against the pool's own price", [
119
+ ["pool spot price", spot === undefined
120
+ ? "could not be read — the probe quote it comes from failed"
121
+ : `${price(spot)} — the pool's marginal price before this order, fees out`],
122
+ ["fill, fees out", fill === undefined ? "n/a" : price(fill)],
123
+ ["price impact", spot === undefined || fill === undefined
124
+ ? "n/a"
125
+ : `${priceMove(spot, fill)} — how far from the spot price this order fills from its `
126
+ + `own size alone (a ${side} fills ${side === "buy" ? "above" : "below"} spot)`],
127
+ ]);
128
+ }
129
+ function spotNote(quote) {
130
+ return `How the spot price is read: @arcnow/sdk has no reader for a pool's price, so it is the `
131
+ + `SDK's own quote of a ${spotProbe(quote).format()} probe buy with both fees taken back `
132
+ + "out — an order too small to move the price. A pool swap names no referrer and no "
133
+ + "developer: arcnow.io's fee hook pays those two shares of its 1% to the platform recipient.";
134
+ }
135
+ function curveOnlyNamed(args) {
136
+ return ["referrer", "developer"].filter((field) => args[field] !== undefined);
137
+ }
138
+ // ─────────────────────────────────────────────────────────────────────────────
139
+ export async function quotePoolBuy(args, ctx, market, symbol) {
140
+ const refused = curveOnlyNamed(args);
141
+ if (refused.length > 0) {
142
+ return { isError: true, text: refuseCurveOnly("arcnow_quote_buy", refused, "quoted") };
143
+ }
144
+ const quoteToken = market.state.quoteToken;
145
+ const quoteIn = parseQuoteAmount(quoteToken, args.quoteIn, "quoteIn");
146
+ const pool = market.trade.pool;
147
+ let quote;
148
+ try {
149
+ quote = await market.trade.quoteBuy(quoteIn);
150
+ }
151
+ catch (error) {
152
+ return { isError: true, text: renderPoolError("arcnow_quote_buy", "buy", error) };
153
+ }
154
+ if (quote.venue !== "pool")
155
+ return { isError: true, text: venueMovedText("arcnow_quote_buy") };
156
+ const key = await pool.key();
157
+ const spot = await poolSpotPrice(pool, quoteToken, key.fee);
158
+ const avg = effectivePrice(quote.quoteIn, quote.tokensOut);
159
+ const fill = buyFillExFees(quote.quoteIn, quote.tokensOut, key.fee);
160
+ const router = routerName(ctx.port.config);
161
+ return {
162
+ text: report(`Buy quote — POOL — ${money(quoteIn)} into ${symbol}, in its Uniswap v4 pool`, note(`This is a Uniswap v4 pool quote, not a bonding-curve quote. ${symbol} graduated and `
163
+ + "migrated, its curve no longer trades, and this price comes from simulating the real "
164
+ + `swap through arcnow.io's router at ${router} against the pool as it is now.`), section("what you pay and get", [
165
+ ["venue", `Uniswap v4 pool, through arcnow.io's router ${router}`],
166
+ ["you send", buyPaymentLine(quote.quoteIn, `arcnow.io's router ${router}`)],
167
+ ["arcnow.io fee", `${money(quote.feeQuote)} — the same flat 1% the curve charged, taken in `
168
+ + `${quoteToken.symbol} by arcnow.io's fee hook inside the swap`],
169
+ ["pool fee", `${lpFee(key.fee)} — Uniswap's LP fee, charged by the pool on top of `
170
+ + `arcnow.io's 1% and kept by its liquidity: about ${money(buyLpFee(quote.quoteIn, key.fee))} `
171
+ + "of this order"],
172
+ ["tokens out", qty(quote.tokensOut, symbol)],
173
+ ["average fill price", avg === undefined
174
+ ? "n/a"
175
+ : `${price(avg)} — everything you pay, both fees in, over everything you get`],
176
+ ]), againstSpot(spot, fill, "buy"), section("minimum tokens out, by tolerance", TOLERANCES.map((bps) => [
177
+ `${bps} bps (${Number(bps) / 100}%)`,
178
+ qty(minTokensOutFromQuote(quote, Bps.of(bps)), symbol),
179
+ ])), note(spotNote(quoteToken)), note("This quote is one block old the moment it is returned. Anybody's trade in this pool "
180
+ + "moves it, which is what the minimum-out floor is for.")),
181
+ };
182
+ }
183
+ export async function quotePoolSell(args, ctx, market, symbol) {
184
+ const refused = curveOnlyNamed(args);
185
+ if (refused.length > 0) {
186
+ return { isError: true, text: refuseCurveOnly("arcnow_quote_sell", refused, "quoted") };
187
+ }
188
+ const holder = (args.holder ?? ctx.port.signerAddress);
189
+ if (holder === undefined) {
190
+ return {
191
+ isError: true,
192
+ text: report("arcnow_quote_sell: a sell in a Uniswap v4 pool is priced for a particular holder, and "
193
+ + "this call named none and this server has no signing address to default to. Nothing "
194
+ + "was quoted.", note("The SDK prices a pool sell by simulating the real swap as that holder. The router "
195
+ + "pulls the tokens with transferFrom; the simulation stands in for the approval but "
196
+ + "deliberately not for the balance, because a price for tokens nobody has is a "
197
+ + "number, not a quote. Call again with `holder` set to an address that actually "
198
+ + "holds at least this many tokens.")),
199
+ };
200
+ }
201
+ const quoteToken = market.state.quoteToken;
202
+ const tokensIn = Tokens.parse(args.tokensIn);
203
+ const pool = market.trade.pool;
204
+ let quote;
205
+ try {
206
+ quote = await market.trade.quoteSell(tokensIn, { from: holder });
207
+ }
208
+ catch (error) {
209
+ return { isError: true, text: renderPoolError("arcnow_quote_sell", "sell", error) };
210
+ }
211
+ if (quote.venue !== "pool")
212
+ return { isError: true, text: venueMovedText("arcnow_quote_sell") };
213
+ const [key, approved] = await Promise.all([pool.key(), pool.routerAllowance(holder)]);
214
+ const spot = await poolSpotPrice(pool, quoteToken, key.fee);
215
+ const avg = effectivePrice(quote.quoteOut, quote.tokensIn);
216
+ const fill = sellFillExFees(quote.tokensIn, quote.quoteOut, key.fee);
217
+ const router = routerName(ctx.port.config);
218
+ return {
219
+ text: report(`Sell quote — POOL — ${qty(tokensIn, symbol)}, in its Uniswap v4 pool`, note(`This is a Uniswap v4 pool quote, not a bonding-curve quote. ${symbol} graduated and `
220
+ + "migrated, its curve no longer trades, and this price comes from simulating the real "
221
+ + `swap as ${addr(holder)} through arcnow.io's router at ${router}.`), section("what you give and get", [
222
+ ["venue", `Uniswap v4 pool, through arcnow.io's router ${router}`],
223
+ ["you send", `${qty(quote.tokensIn, symbol)} — pulled by the router, which needs an `
224
+ + "ERC-20 approval first (below)"],
225
+ ["pool fee", `${lpFee(key.fee)} — Uniswap's LP fee, taken by the pool from the tokens `
226
+ + `you sell and kept by its liquidity: about ${qty(sellLpFee(quote.tokensIn, key.fee), symbol)}`],
227
+ ["arcnow.io fee", `${money(quote.feeQuote)} — the same flat 1% the curve charged, taken `
228
+ + `by arcnow.io's fee hook out of the ${quoteToken.symbol} the pool pays`],
229
+ ["you receive", `${money(quote.quoteOut)} — net of both fees`],
230
+ ["average fill price", avg === undefined
231
+ ? "n/a"
232
+ : `${price(avg)} — what you receive, net of both fees, over what you give`],
233
+ ]), againstSpot(spot, fill, "sell"), section("the approval a pool sell needs", [
234
+ ["spender", `${router} — arcnow.io's v4 router`],
235
+ ["holder", addr(holder)],
236
+ ["approved now", qty(approved, symbol)],
237
+ ["this sell needs", approved.lt(tokensIn)
238
+ ? `an ERC-20 approval of ${qty(tokensIn, symbol)} first — a SEPARATE transaction that `
239
+ + "grants the router the right to move that many tokens. arcnow_sell sends it only "
240
+ + "when told to (approveRouter: true), for exactly the amount sold, and reports it."
241
+ : "nothing more — the existing allowance already covers it"],
242
+ ]), section(`minimum ${quoteToken.symbol} out, by tolerance`, TOLERANCES.map((bps) => [
243
+ `${bps} bps (${Number(bps) / 100}%)`,
244
+ money(minQuoteOutFromQuote(quote, Bps.of(bps)).ceilToRepresentable()),
245
+ ])), note(spotNote(quoteToken)), note("A bonding-curve sell never needed an approval; a pool sell always does, because the "
246
+ + "router has no privileged path. This quote is a snapshot of one block.")),
247
+ };
248
+ }
249
+ //# sourceMappingURL=pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/tools/pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Amounts in a quote token, and which quote token a launch is in.
3
+ *
4
+ * # An amount is parsed exactly, in its own quote's decimals
5
+ *
6
+ * Every amount a tool takes — `quoteIn`, `initialBuy`, `maxTotalCost` — is a
7
+ * decimal string in the quote the token is priced in, and is parsed with the
8
+ * SDK's `QuoteAmount.parse` in THAT quote's decimals. EURC has 6: `"1.0000001"`
9
+ * is not an amount of EURC, and it is refused, naming the decimals, rather than
10
+ * rounded to something nobody typed. A parsed amount is therefore always a whole
11
+ * number of the quote's raw units, which is what an ERC-20 transfer moves.
12
+ *
13
+ * # A launch names its quote by symbol or address
14
+ *
15
+ * A symbol is looked up in the network's own `quoteTokens` (the SDK's
16
+ * `networks.json`, or `ARCNOW_MCP_NETWORK_FILE`) and nowhere else. An address is
17
+ * taken as given; one the network does not list is metadata the SDK can read,
18
+ * but no spend cap can name it, so a launch in it is refused (see `./spend.ts`).
19
+ *
20
+ * @module
21
+ */
22
+ import type { Address } from "viem";
23
+ import type { NetworkConfig, QuoteTokenInfo } from "@arcnow/sdk";
24
+ import { QuoteAmount } from "@arcnow/sdk";
25
+ /** An argument that is not an amount of its quote, or names no quote. The message is the report. */
26
+ export declare class QuoteInputError extends Error {
27
+ readonly name = "QuoteInputError";
28
+ }
29
+ /**
30
+ * `QuoteAmount.parse(token, value)`, with a refusal that names the field, the
31
+ * quote and its decimals.
32
+ *
33
+ * @throws {QuoteInputError}
34
+ */
35
+ export declare function parseQuoteAmount(token: QuoteTokenInfo, value: string, field: string): QuoteAmount;
36
+ /** The network's native quote: native USDC. */
37
+ export declare function nativeQuote(config: NetworkConfig): QuoteTokenInfo;
38
+ /** What a launch's `quote` argument named. */
39
+ export type QuoteChoice = {
40
+ readonly listed: true;
41
+ readonly token: QuoteTokenInfo;
42
+ } | {
43
+ readonly listed: false;
44
+ readonly address: Address;
45
+ };
46
+ /**
47
+ * Resolve a `quote` argument — a symbol of the network's quote tokens, or an
48
+ * address — with no RPC. Omitted, it is native USDC.
49
+ *
50
+ * @throws {QuoteInputError} for a symbol the network does not list, or one two of its tokens share.
51
+ */
52
+ export declare function chooseQuote(config: NetworkConfig, raw: string | undefined): QuoteChoice;
53
+ //# sourceMappingURL=quote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.d.ts","sourceRoot":"","sources":["../../src/tools/quote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAiD,WAAW,EAAE,MAAM,aAAa,CAAC;AAIzF,oGAAoG;AACpG,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAkB,IAAI,qBAAqB;CAC5C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAwBjG;AAED,+CAA+C;AAC/C,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CAEjE;AAED,8CAA8C;AAC9C,MAAM,MAAM,WAAW,GACjB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAI5D;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAoBvF"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Amounts in a quote token, and which quote token a launch is in.
3
+ *
4
+ * # An amount is parsed exactly, in its own quote's decimals
5
+ *
6
+ * Every amount a tool takes — `quoteIn`, `initialBuy`, `maxTotalCost` — is a
7
+ * decimal string in the quote the token is priced in, and is parsed with the
8
+ * SDK's `QuoteAmount.parse` in THAT quote's decimals. EURC has 6: `"1.0000001"`
9
+ * is not an amount of EURC, and it is refused, naming the decimals, rather than
10
+ * rounded to something nobody typed. A parsed amount is therefore always a whole
11
+ * number of the quote's raw units, which is what an ERC-20 transfer moves.
12
+ *
13
+ * # A launch names its quote by symbol or address
14
+ *
15
+ * A symbol is looked up in the network's own `quoteTokens` (the SDK's
16
+ * `networks.json`, or `ARCNOW_MCP_NETWORK_FILE`) and nowhere else. An address is
17
+ * taken as given; one the network does not list is metadata the SDK can read,
18
+ * but no spend cap can name it, so a launch in it is refused (see `./spend.ts`).
19
+ *
20
+ * @module
21
+ */
22
+ import { AmountParseError, findQuoteToken, NATIVE_USDC, QuoteAmount } from "@arcnow/sdk";
23
+ import { note, report } from "../format.js";
24
+ /** An argument that is not an amount of its quote, or names no quote. The message is the report. */
25
+ export class QuoteInputError extends Error {
26
+ name = "QuoteInputError";
27
+ }
28
+ /**
29
+ * `QuoteAmount.parse(token, value)`, with a refusal that names the field, the
30
+ * quote and its decimals.
31
+ *
32
+ * @throws {QuoteInputError}
33
+ */
34
+ export function parseQuoteAmount(token, value, field) {
35
+ try {
36
+ return QuoteAmount.parse(token, value);
37
+ }
38
+ catch (error) {
39
+ if (!(error instanceof AmountParseError))
40
+ throw error;
41
+ const [whole = "", fraction = ""] = value.split(".");
42
+ if (fraction.length > token.decimals) {
43
+ const nearest = token.decimals === 0 ? whole : `${whole}.${fraction.slice(0, token.decimals)}`;
44
+ throw new QuoteInputError(report(`${field} "${value}" is not an amount of ${token.symbol}: ${token.symbol} has `
45
+ + `${token.decimals} decimals, and this has ${fraction.length} decimal places.`, note(`Nothing was quoted and nothing was sent. An amount is read exactly, in the decimals `
46
+ + `of the quote it is in, and never rounded: ${token.symbol} cannot hold a smaller unit `
47
+ + `than 1e-${token.decimals}, so there is no such amount to send. The nearest amount below `
48
+ + `it is "${nearest}"; ask the user which amount they mean rather than choosing one.`)), { cause: error });
49
+ }
50
+ throw new QuoteInputError(report(`${field} "${value}" could not be read as an amount of ${token.symbol}.`, error.message, note("Nothing was quoted and nothing was sent. Amounts are decimal strings in whole units "
51
+ + `of the quote — "25", "1.5" — with at most ${token.decimals} decimals for ${token.symbol}.`)), { cause: error });
52
+ }
53
+ }
54
+ /** The network's native quote: native USDC. */
55
+ export function nativeQuote(config) {
56
+ return config.quoteTokens.find((token) => token.isNative) ?? NATIVE_USDC;
57
+ }
58
+ const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
59
+ /**
60
+ * Resolve a `quote` argument — a symbol of the network's quote tokens, or an
61
+ * address — with no RPC. Omitted, it is native USDC.
62
+ *
63
+ * @throws {QuoteInputError} for a symbol the network does not list, or one two of its tokens share.
64
+ */
65
+ export function chooseQuote(config, raw) {
66
+ if (raw === undefined)
67
+ return { listed: true, token: nativeQuote(config) };
68
+ if (ADDRESS.test(raw)) {
69
+ const token = findQuoteToken(config, raw);
70
+ return token === undefined
71
+ ? { listed: false, address: raw.toLowerCase() }
72
+ : { listed: true, token };
73
+ }
74
+ const wanted = raw.toUpperCase();
75
+ const matches = config.quoteTokens.filter((token) => token.symbol.toUpperCase() === wanted);
76
+ const symbols = config.quoteTokens.map((token) => token.symbol).join(", ");
77
+ if (matches.length === 1 && matches[0] !== undefined)
78
+ return { listed: true, token: matches[0] };
79
+ throw new QuoteInputError(report(matches.length === 0
80
+ ? `${raw} is not a quote token of ${config.name}. Its quote tokens are ${symbols}.`
81
+ : `${raw} names ${matches.length} quote tokens of ${config.name}; pass the address instead.`, note("Nothing was quoted and nothing was sent. A quote is named by a symbol from this "
82
+ + "network's own quote tokens, or by its address. arcnow_quote_tokens lists them, with "
83
+ + "which ones the quote registry currently accepts for a launch.")));
84
+ }
85
+ //# sourceMappingURL=quote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../src/tools/quote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The read-only tools: everything that cannot cost anybody anything.
3
+ *
4
+ * These are always published, on every server, in every mode, and they are the
5
+ * part worth getting excellent. An assistant that can answer "what is this
6
+ * token, what would 50 USDC buy me, and how close is it to graduating" without
7
+ * being able to sign anything is useful to far more people than one that can
8
+ * trade, and it is useful with no key anywhere near it.
9
+ *
10
+ * A quote answers for wherever the token trades now: its bonding curve before
11
+ * graduation, its Uniswap v4 pool after migration (see `./pool.ts`), and
12
+ * nowhere in between — which is said, not glossed.
13
+ *
14
+ * @module
15
+ */
16
+ import type { FeeSplit } from "@arcnow/sdk";
17
+ import { QuoteAmount } from "@arcnow/sdk";
18
+ import { z } from "./schema.js";
19
+ import type { AnyTool } from "./schema.js";
20
+ /** The launch tools' `quote` argument. */
21
+ export declare function quoteArg(): z.ZodOptional<z.ZodString>;
22
+ export declare const GRADUATING_BUY_WARNING: string;
23
+ export declare function statusLine(graduated: boolean, migrated: boolean): string;
24
+ export declare function feeSplitSection(fee: QuoteAmount, split: FeeSplit, referrer: string | undefined, developer: string | undefined): string;
25
+ export declare const READ_TOOLS: readonly AnyTool[];
26
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAsC,MAAM,aAAa,CAAC;AAChF,OAAO,EAGL,WAAW,EAGZ,MAAM,aAAa,CAAC;AAoBrB,OAAO,EAAgF,CAAC,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,aAAa,CAAC;AAgwBxD,0CAA0C;AAC1C,wBAAgB,QAAQ,+BAOvB;AAkOD,eAAO,MAAM,sBAAsB,QAUoD,CAAC;AAExF,wBAAgB,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAQxE;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,MAAM,CAaR;AAMD,eAAO,MAAM,UAAU,EAAE,SAAS,OAAO,EAUxC,CAAC"}