@parabolicfamily/mcp 0.1.7 → 0.2.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 (80) hide show
  1. package/README.md +91 -12
  2. package/abi/ParabolicAggregatorRouter.json +2259 -0
  3. package/abi/ParabolicLaunchFactoryV2.json +2542 -0
  4. package/abi/ParabolicPairProbe.json +429 -0
  5. package/abi/ParabolicRouterV2.json +1171 -0
  6. package/abi/ParabolicSessionModule.json +1955 -0
  7. package/abi/deployments.json +258 -0
  8. package/dist/abi.d.ts +3 -1
  9. package/dist/abi.js +3 -1
  10. package/dist/abi.js.map +1 -1
  11. package/dist/chain.d.ts +12 -1
  12. package/dist/chain.js +13 -4
  13. package/dist/chain.js.map +1 -1
  14. package/dist/chains.d.ts +17 -10
  15. package/dist/chains.js +25 -13
  16. package/dist/chains.js.map +1 -1
  17. package/dist/coins.d.ts +38 -3
  18. package/dist/coins.js +54 -4
  19. package/dist/coins.js.map +1 -1
  20. package/dist/config.d.ts +36 -11
  21. package/dist/config.js +98 -20
  22. package/dist/config.js.map +1 -1
  23. package/dist/curve.d.ts +2 -1
  24. package/dist/curve.js +2 -1
  25. package/dist/curve.js.map +1 -1
  26. package/dist/deployed.d.ts +80 -0
  27. package/dist/deployed.js +95 -0
  28. package/dist/deployed.js.map +1 -0
  29. package/dist/docs.d.ts +13 -0
  30. package/dist/docs.js +75 -14
  31. package/dist/docs.js.map +1 -1
  32. package/dist/parabolic.d.ts +120 -3
  33. package/dist/parabolic.js +309 -41
  34. package/dist/parabolic.js.map +1 -1
  35. package/dist/quote-unit.d.ts +77 -0
  36. package/dist/quote-unit.js +143 -0
  37. package/dist/quote-unit.js.map +1 -0
  38. package/dist/referrals.d.ts +77 -0
  39. package/dist/referrals.js +55 -0
  40. package/dist/referrals.js.map +1 -0
  41. package/dist/restapi.d.ts +23 -0
  42. package/dist/restapi.js +60 -4
  43. package/dist/restapi.js.map +1 -1
  44. package/dist/routed.d.ts +389 -0
  45. package/dist/routed.js +413 -0
  46. package/dist/routed.js.map +1 -0
  47. package/dist/server.d.ts +1 -1
  48. package/dist/server.js +117 -10
  49. package/dist/server.js.map +1 -1
  50. package/dist/subgraph.d.ts +18 -6
  51. package/dist/subgraph.js +13 -1
  52. package/dist/subgraph.js.map +1 -1
  53. package/dist/ticker.d.ts +97 -0
  54. package/dist/ticker.js +109 -0
  55. package/dist/ticker.js.map +1 -0
  56. package/dist/tx.d.ts +6 -0
  57. package/dist/tx.js +12 -2
  58. package/dist/tx.js.map +1 -1
  59. package/dist/venues.d.ts +49 -0
  60. package/dist/venues.js +44 -0
  61. package/dist/venues.js.map +1 -0
  62. package/package.json +2 -2
  63. package/src/abi.ts +3 -1
  64. package/src/chain.ts +19 -4
  65. package/src/chains.ts +37 -17
  66. package/src/coins.ts +67 -5
  67. package/src/config.ts +112 -22
  68. package/src/curve.ts +2 -1
  69. package/src/deployed.ts +128 -0
  70. package/src/docs.ts +78 -15
  71. package/src/parabolic.ts +323 -42
  72. package/src/quote-unit.ts +194 -0
  73. package/src/referrals.ts +61 -0
  74. package/src/restapi.ts +66 -4
  75. package/src/routed.ts +499 -0
  76. package/src/server.ts +154 -10
  77. package/src/subgraph.ts +22 -4
  78. package/src/ticker.ts +148 -0
  79. package/src/tx.ts +13 -2
  80. package/src/venues.ts +93 -0
@@ -0,0 +1,95 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { getAddress, isAddress } from "viem";
5
+ /**
6
+ * What this package ships addresses for, read from the deployment records rather than typed out.
7
+ *
8
+ * `scripts/sync-abis.mjs` reduces `contracts/deployments/<chainId>.json` into `abi/deployments.json`;
9
+ * this module reads it at import time, the way src/abi.ts reads the ABIs, and it is the only place in
10
+ * the package a deployed address comes from.
11
+ *
12
+ * ## Why it exists (23 September 2026, finding F50)
13
+ *
14
+ * `DEPLOYMENTS` in src/config.ts was three chains written by hand and chain two was never written. So
15
+ * the published 0.1.8 told every model "Parabolic is not deployed on Robinhood Chain yet" — four days
16
+ * after nine contracts were deployed there and twenty-three coins launched — and an operator who did
17
+ * what that message says (`PARABOLIC_CHAIN_ID=4663`) got Arc's RPC, no factory and an empty list. A
18
+ * table somebody has to remember to update is a table that goes stale silently, and this one went stale
19
+ * on the surface whose whole job is to be a model's system prompt.
20
+ *
21
+ * So a chain is served here **because its record says so**: `live` in src/chains.ts and the entry in
22
+ * `DEPLOYMENTS` are both derived from this file, and syncing a new chain's record is the whole of
23
+ * turning it on. The same rule web/lib/chains.ts follows through web/abi/deployments.json.
24
+ */
25
+ /** One level above src/ (tests) and dist/ (build), as src/abi.ts resolves it, and the same override. */
26
+ const DIR = process.env.PARABOLIC_ABI_DIR ?? resolve(dirname(fileURLToPath(import.meta.url)), "..", "abi");
27
+ const file = join(DIR, "deployments.json");
28
+ let records;
29
+ try {
30
+ records = JSON.parse(readFileSync(file, "utf8"));
31
+ }
32
+ catch (e) {
33
+ // Loud rather than silent, and for the same reason src/abi.ts is: a missing record would take every
34
+ // chain's addresses with it and the server would come up looking configured and reading nothing.
35
+ throw new Error(`Cannot read the bundled deployment records ${file}. The package ships abi/deployments.json; a missing file means a damaged install, so reinstall @parabolicfamily/mcp (${e.message})`);
36
+ }
37
+ const addr = (v) => (typeof v === "string" && isAddress(v, { strict: false }) ? getAddress(v) : undefined);
38
+ /** The record for a chain, or undefined where this package ships none. */
39
+ export const recordFor = (chainId) => records[String(chainId)];
40
+ /** A deployed contract's address by its Solidity name, or undefined where that chain's record has none. */
41
+ export const deployedAt = (chainId, name) => addr(recordFor(chainId)?.contracts?.[name]?.address);
42
+ /**
43
+ * The block the factory itself was deployed at, which is where a `TokenLaunched` scan starts.
44
+ *
45
+ * The factory's own block rather than the record's `startBlock`: the record's is the first transaction of
46
+ * the whole deploy, and no coin can exist before the contract that launches them does.
47
+ */
48
+ export const factoryBlock = (chainId) => {
49
+ const b = recordFor(chainId)?.contracts?.ParabolicLaunchFactory?.block;
50
+ return typeof b === "number" && b >= 0 ? b : undefined;
51
+ };
52
+ /** EURC where a chain's deploy recorded one, undefined otherwise. Arc mainnet's record names none. */
53
+ export const recordedEurc = (chainId) => addr(recordFor(chainId)?.config?.eurc);
54
+ /**
55
+ * Every quote asset a chain's deployment record names, checksummed. `config.quoteAssets` since the 4663 record
56
+ * (USDG and the three shares approved on 21 Sep 2026); Arc's record predates the field and names its ERC-20
57
+ * quote in `config.eurc` alone, null on mainnet, which is what "EURC pairs off at launch" looks like in a record.
58
+ * Read, never typed: a share named by hand here is the copy that goes stale (23 Sep 2026, the bot had exactly
59
+ * that gap and this package had it too, answering a 4663 share by its address alone).
60
+ */
61
+ export function recordedQuoteAssets(chainId) {
62
+ const config = recordFor(chainId)?.config;
63
+ if (!config)
64
+ return [];
65
+ const listed = Array.isArray(config.quoteAssets) ? config.quoteAssets : [];
66
+ const out = [];
67
+ for (const a of listed) {
68
+ const address = addr(a?.address);
69
+ if (address !== undefined && typeof a?.symbol === "string" && a.symbol.trim() !== "")
70
+ out.push({ address, symbol: a.symbol.trim() });
71
+ }
72
+ if (out.length > 0)
73
+ return out;
74
+ const eurc = addr(config.eurc);
75
+ return eurc === undefined ? [] : [{ address: eurc, symbol: "EURC" }];
76
+ }
77
+ export const deployedChainIds = () => Object.keys(records).map(Number).filter(Number.isFinite).sort((a, b) => a - b);
78
+ /**
79
+ * Whether Parabolic is deployed on this chain, which is what `live` means in src/chains.ts: a factory
80
+ * this package can read with no configuration at all, not merely a chain a reference can name.
81
+ */
82
+ export const isDeployedOn = (chainId) => deployedAt(chainId, "ParabolicLaunchFactory") !== undefined;
83
+ /**
84
+ * The ParabolicAggregatorRouter a chain's deployment record names under `aggregator`, or undefined. Undefined is the
85
+ * ordinary state until the founder deploys it (docs/33 §A11), and every routed tool then refuses by name: nothing in
86
+ * this package builds a routed trade against an address the record does not carry (src/routed.ts).
87
+ */
88
+ export const recordedAggregator = (chainId) => {
89
+ const a = recordFor(chainId)?.aggregator;
90
+ const address = addr(a?.address ?? undefined);
91
+ return address === undefined || /^0x0{40}$/i.test(address) ? undefined : { address, block: typeof a?.block === "number" ? a.block : null };
92
+ };
93
+ /** One v4 periphery contract by the record's own key (`v4Quoter`, `stateView`, `permit2`, `universalRouter`). */
94
+ export const recordedV4 = (chainId, name) => addr(recordFor(chainId)?.v4?.[name]?.address ?? undefined);
95
+ //# sourceMappingURL=deployed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployed.js","sourceRoot":"","sources":["../src/deployed.ts"],"names":[],"mappings":"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"}
package/dist/docs.d.ts CHANGED
@@ -1,4 +1,17 @@
1
1
  import { type Config } from "./config.js";
2
+ /**
3
+ * The referral's share of a trade fee, in basis points of the whole fee, which is the unit the ledger that
4
+ * actually credits it is folded in (`REFERRAL_OF_FEE_BPS` in indexer/src/memo-payload.ts; decided 12 Sep 2026,
5
+ * curve buys only, paid out of Parabolic's own half of the fee).
6
+ *
7
+ * The line below wrote the percentage as a figure until 23 Sep 2026 (F60). Three packages state this rate and
8
+ * only the site's copy was pinned to a constant, so moving the indexer's would have left this file quoting a
9
+ * share nobody is paid at, on the one surface that is a model's system prompt rather than a page somebody
10
+ * skims. web/test/review-web-api-contract.test.ts reads the percentage out of THIS file and fails when it
11
+ * stops agreeing with web/lib/data.ts and the indexer, which holds the figures in this comment to those two
12
+ * as well: 1,000 bps is 10% of the fee, which is 0.10% of a referred buy.
13
+ */
14
+ export declare const REFERRAL_OF_FEE_BPS = 1000;
2
15
  /**
3
16
  * Adopted product parameters (adopted 2026-09-06, graduation threshold revised to $8,000 on 2026-09-16; published
4
17
  * at https://www.parabolic.family/docs#parameters) and the chain's own facts, as text.
package/dist/docs.js CHANGED
@@ -1,6 +1,22 @@
1
- import { ARC_MEMO_DEFAULT, ENV_VARS, USDC_VIEW, chainName } from "./config.js";
1
+ import { ARC_MEMO_DEFAULT, DEPLOYMENTS, ENV_VARS, USDC_VIEW, chainName } from "./config.js";
2
2
  import { chainFor } from "./chains.js";
3
+ import { deployedAt, recordedAggregator } from "./deployed.js";
4
+ import { VENUES, VENUE_KEYS, venueOn } from "./venues.js";
5
+ import { defaultQuoteOf } from "./quote-unit.js";
3
6
  import { endpointHost } from "./format.js";
7
+ /**
8
+ * The referral's share of a trade fee, in basis points of the whole fee, which is the unit the ledger that
9
+ * actually credits it is folded in (`REFERRAL_OF_FEE_BPS` in indexer/src/memo-payload.ts; decided 12 Sep 2026,
10
+ * curve buys only, paid out of Parabolic's own half of the fee).
11
+ *
12
+ * The line below wrote the percentage as a figure until 23 Sep 2026 (F60). Three packages state this rate and
13
+ * only the site's copy was pinned to a constant, so moving the indexer's would have left this file quoting a
14
+ * share nobody is paid at, on the one surface that is a model's system prompt rather than a page somebody
15
+ * skims. web/test/review-web-api-contract.test.ts reads the percentage out of THIS file and fails when it
16
+ * stops agreeing with web/lib/data.ts and the indexer, which holds the figures in this comment to those two
17
+ * as well: 1,000 bps is 10% of the fee, which is 0.10% of a referred buy.
18
+ */
19
+ export const REFERRAL_OF_FEE_BPS = 1_000;
4
20
  /**
5
21
  * Adopted product parameters (adopted 2026-09-06, graduation threshold revised to $8,000 on 2026-09-16; published
6
22
  * at https://www.parabolic.family/docs#parameters) and the chain's own facts, as text.
@@ -18,11 +34,14 @@ export function docsText(config) {
18
34
  // Which chain family, from the registry rather than from a pair of written ids: everything in the Arc block
19
35
  // below is Arc's own, and an id comparison here is the same kind of hardcoded chain fact this file is losing.
20
36
  const onArc = chain?.key === "arc" || chain?.key === "arc-testnet";
37
+ const quote = defaultQuoteOf(config.chainId);
21
38
  const gas = chain?.native ? `${chain.native.symbol}${chain.native.dollar ? " (itself a dollar, so a figure in it is a figure in dollars)" : " (not a dollar: a figure in it is not a figure in dollars)"}` : "not read from this chain in this repo, so nothing here prices it";
22
39
  return [
23
- `PARABOLIC — bonding-curve token launchpad on ${chainName(config.chainId)}; curves priced in dollars${chain?.native?.dollar === true
24
- ? ", which on this chain is also the gas asset"
25
- : ", not in the gas token"}`,
40
+ // "curves priced in dollars" was written in both branches until 20 Sep 2026, which is true of every asset
41
+ // Parabolic has ever been quoted in and is not a property of a curve. The chain's own default asset says it.
42
+ `PARABOLIC · bonding-curve token launchpad on ${chainName(config.chainId)}; each curve is priced in one quote asset${quote === undefined
43
+ ? ", read it from the coin's curve (`pairToken`)"
44
+ : `, which on this chain is ${quote.symbol}${quote.dollar ? " (a dollar)" : " (NOT a dollar: never put a $ in front of a figure counted in it)"}${chain?.native?.symbol === quote.symbol ? " and is also the gas asset" : ", not the gas token"}`}`,
26
45
  "parabolic.family · contact@parabolic.family · the people's launchpad; the goal is the betterment of the community.",
27
46
  "Category: bonding-curve launchpad (pump.fun / fomo.family), not a fundraising venue. Non-custodial: every launch and trade is a wallet-signed transaction; no custody, no warranties, no advice; coins are user-created and experimental.",
28
47
  "",
@@ -30,18 +49,27 @@ export function docsText(config) {
30
49
  "- Supply: 1,000,000,000 tokens (18 decimals), all minted to the curve.",
31
50
  onArc
32
51
  ? "- Quote asset: native USDC (Arc's gas token; 18-decimal native accounting). EURC (6-decimal ERC-20) pairs when approved on the factory."
33
- : `- Quote asset: read it from the coin's curve (\`pairToken\`) and the factory's \`pairTokenEconomics\`. A chain's dollar is its own — never assume USDC, and never assume decimals: a token's symbol() is not the name of the money. Gas on this chain: ${gas}.`,
52
+ : `- Quote asset: read it from the coin's curve (\`pairToken\`) and the factory's \`pairTokenEconomics\`. A chain's dollar is its own. Never assume USDC, and never assume decimals: a token's symbol() is not the name of the money. Gas on this chain: ${gas}.`,
34
53
  "- Opening: phantom quote reserve $5,000 against the full supply → ≈ $0.000005 per token, ≈ $5,000 opening market cap.",
35
54
  "- Graduation: when the curve's real quote reserve reaches $8,000. Terminal curve price = (5,000 + 8,000) / reservedTokens → fully diluted market cap at graduation = 13,000² / 5,000 = $33,800 (constant product over the whole 1e9 supply). Both figures are the launch config's, so read `getLaunchConfig(launchConfigId)` rather than taking them from here: Arc Testnet's factory still answers 12,500.",
36
55
  "- Reserved tokens: supply × phantom / (phantom + threshold) = 5,000 / 13,000 ≈ 38.46% of supply is never sold on the curve and is still held by it at graduation. Of that, ≈ 23.7% of supply (reserved × 8,000 / 13,000) seeds the Uniswap v4 full-range position together with the $8,000 raised, at the same terminal price, and the remaining ≈ 14.8% of supply is permanently locked (GraduationTokensPermanentlyLocked). The position itself is locked forever in ParabolicLaunchLocker.",
37
- "- Launch fee: whatever `launchFee()` on the factory answers. It is charged as `msg.value` on launchToken, so it is denominated in the chain's gas asset and is a dollar only where that asset is one. Read the figure and never assume it: the intended direction is zero everywhere (docs/20 §4), but Arc's factory still answers 1e18 as of 18 Sep 2026, so the intent is not the state of any chain. `parabolic.protocol_stats` reports it as `launchFee` with `launchFeeAsset` and `launchFeeSource`, and `build_launch_tx` puts the read value into the transaction.",
56
+ "- Launch fee: whatever `launchFee()` on the factory answers. It is charged as `msg.value` on launchToken, so it is denominated in the chain's gas asset and is a dollar only where that asset is one. Read the figure and never assume it, including from this line: Arc answered 1e18 until `setLaunchFee(0)` on 19 Sep 2026 and answers 0 now, Robinhood Chain has been 0 since its deploy, and a figure written down is a figure that can be stale while a transaction pays the one the factory holds. `parabolic.protocol_stats` reports it as `launchFee` with `launchFeeAsset` and `launchFeeSource`, and `build_launch_tx` puts the read value into the transaction.",
38
57
  "- Agents page: parabolic.family/agents lists coins launched by wallets holding an ERC-8004 identity where the chain publishes a registry (Arc Testnet today), and, on every chain, coins whose launch memo carries the note \"mcp\": build_launch_tx returns that variant as `memo` (EOA-only). Sign it to be listed.",
39
- "- Trade fee: 1.00% (100 bps) on the quote leg, before and after graduation (ParabolicHook takes it on the pool). The split is a per-chain parameter, not a constant: read `protocolFeeShareBps` and `buybackBurnBps` on the hook for the next launch, and the coin's own curve for an existing one, which carries the terms it copied at launch. On Arc the hook has answered 5,000 / 0 — creator 50 / protocol 50 — since 17 Sep 2026.",
58
+ "- Trade fee: 1.00% (100 bps) on the quote leg, before and after graduation (ParabolicHook takes it on the pool). The split is a per-chain parameter, not a constant: read `protocolFeeShareBps` and `buybackBurnBps` on the hook for the next launch, and the coin's own curve for an existing one, which carries the terms it copied at launch. On Arc the hook has answered 5,000 / 0 (creator 50 / protocol 50) since 17 Sep 2026.",
40
59
  "- Creator tax: optional 0–5% (0–500 bps), fixed at launch, charged like the fee on buys and sells, paid entirely to the creator.",
41
60
  "- Snipe tax: 93% (9,300 bps) at launch decaying to 0 over 5 s along a quadratic ease-out (remaining² / window²); capped at 10,000 − fee − creatorTax − 1 bps, which 9,300 stays below at every legal creator tax, so it is charged as written. Buys only. Only the creator's own address is exempt, and it stays exempt for every buy inside the window, not just the opening one; there is no other exemption pathway. Snipe revenue is split like the base fee.",
61
+ // Three cases, not two (found by the second review of 23 September 2026). The non-Arc branch said
62
+ // "it exists on Arc only; a chain without that precompile has no referral attribution", which became a
63
+ // false statement about money the moment this server started serving Robinhood Chain the same day:
64
+ // `ParabolicRouter` takes the referral code as an argument there, the indexer credits it through the
65
+ // same ledger as Arc's memo (indexer/src/memo-payload.ts), and the site prints referral links on that
66
+ // chain. What is true off Arc is narrower and is said here instead: the share is paid, and this package
67
+ // cannot build the call that carries it.
42
68
  onArc
43
- ? "- Referral: a bytes8 referral code (first 8 bytes of the referrer's address) carried in the Arc memo of a routed buy earns 10% of the fee."
44
- : "- Referral: carried in an Arc transaction memo, so it exists on Arc only; a chain without that precompile has no referral attribution.",
69
+ ? `- Referral: a bytes8 referral code (first 8 bytes of the referrer's address) carried in the Arc memo of a routed buy earns ${REFERRAL_OF_FEE_BPS / 100}% of the fee.`
70
+ : deployedAt(config.chainId, "ParabolicRouter")
71
+ ? `- Referral: a bytes8 referral code (first 8 bytes of the referrer's address) earns ${REFERRAL_OF_FEE_BPS / 100}% of the fee on this chain as it does on Arc, credited through the same ledger; it rides as an argument on \`ParabolicRouter\` rather than in an Arc memo. This server carries no encoder for that router, so a buy built here goes straight to the curve and earns nobody a referral.`
72
+ : "- Referral: a bytes8 referral code earns a share of the fee where a routed buy can carry one, which is Arc's memo or a chain that deploys `ParabolicRouter`. This chain's record names neither, so there is no referral attribution on it.",
45
73
  "- Dev buy (fair launch): the creator's opening buy is snipe-tax exempt. ParabolicMemoRouter.launchAndBuy (native quote; value = launch fee + buy) and launchAndBuyWithToken (ERC-20 quote; value = launch fee, buy pulled after an approval) place it inside the launch transaction, before anyone else can trade. The router forwards no exemption list and requires creatorFeeRecipient to be zero or the signer (FeeRecipientMustBeCreator); buyQuoteIn must be non-zero (ZeroBuyAmount). Without the router the buy is a second transaction to the new curve right after launch.",
46
74
  "",
47
75
  "CURVE MECHANICS (what the tools compute)",
@@ -53,8 +81,11 @@ export function docsText(config) {
53
81
  "",
54
82
  ...(onArc
55
83
  ? [
56
- "ARC NETWORK FACTS (verified against Arc Testnet)",
57
- "- Testnet: chain id 5042002, RPC https://rpc.testnet.arc.io, explorer https://testnet.arcscan.app. Mainnet: chain id 5042 (unofficial until Circle publishes it), public launch 16 Sep 2026.",
84
+ "ARC NETWORK FACTS",
85
+ // Read from the registry and the deployment table rather than written again (23 Sep 2026, F36):
86
+ // this line said mainnet's id was "unofficial until Circle publishes it" for a week after the
87
+ // public launch, on the one surface whose whole job is to be a model's system prompt.
88
+ `- Mainnet: chain id 5042, RPC ${DEPLOYMENTS[5042].rpcUrl}, explorer ${chainFor(5042)?.explorer}, live since 16 Sep 2026 (nine contracts, source verified on Sourcify). Testnet: chain id 5042002, RPC ${DEPLOYMENTS[5042002].rpcUrl}, explorer ${chainFor(5042002)?.explorer}.`,
58
89
  `- USDC is the native gas asset (18-decimal native accounting); its 6-decimal ERC-20 view is ${USDC_VIEW}. Base fee target ≈ $0.01, floor 20 Gwei, ceiling 20,000 Gwei (EWMA-smoothed).`,
59
90
  "- Malachite BFT consensus, deterministic finality < 1 s, proof of authority with 12 institutional validators. Osaka EVM on Reth. PREVRANDAO = 0 (no on-chain randomness). Mempool not observable.",
60
91
  `- System contracts on testnet: Memo (${ARC_MEMO_DEFAULT}; EOA-only, no value forwarding), Multicall3From, Permit2 (canonical), CREATE2, CCTP v2 (domain 26), Gateway, EURC, USYC, StableFX FxEscrow.`,
@@ -65,20 +96,50 @@ export function docsText(config) {
65
96
  ]
66
97
  : [
67
98
  `${chainName(config.chainId).toUpperCase()} NETWORK FACTS`,
68
- `- Nothing about this chain is written down here. Gas asset: ${gas}. Read the chain for anything else, and treat an unread figure as unknown rather than as Arc's.`,
69
- "- The Arc `Memo` precompile does not exist off Arc, so buy notes, on-chain forum posts and referral attribution are Arc-only features.",
99
+ `- Gas asset: ${gas}. Read the chain for anything else, and treat an unread figure as unknown rather than as Arc's.`,
100
+ // Reachable since 23 Sep 2026, when Robinhood Chain became a chain this server serves (F50). The
101
+ // routed sentence is conditional because it is a fact about the chain's own deployment record,
102
+ // not about every chain that is not Arc.
103
+ deployedAt(config.chainId, "ParabolicRouter")
104
+ ? "- Arc's `Memo` precompile exists on Arc alone. This chain deploys `ParabolicRouter`, which takes the referral code and the note as arguments and emits its own event; this server carries no encoder for it, so buy notes and referral attribution cannot be built here. `build_buy_tx` goes straight to the curve, which is the same call on every chain."
105
+ : "- The Arc `Memo` precompile does not exist off Arc, so buy notes, on-chain forum posts and referral attribution are Arc-only features.",
70
106
  "",
71
107
  ]),
72
108
  "THIS SERVER",
73
109
  `- Chain: ${chainName(config.chainId)} (${config.chainId}), RPC ${endpointHost(config.rpcUrl)}.`,
74
110
  `- Factory: ${set(config.factory)} · Memo router: ${set(config.memoRouter)} · Subgraph: ${config.subgraphUrl ? endpointHost(config.subgraphUrl) : "(not configured)"} · EURC: ${set(config.eurc)} · Hook: ${config.hook ?? "(read from factory)"} · Launch config id: ${config.launchConfigId}.`,
75
- "- Tools: parabolic.list_coins, parabolic.get_coin, parabolic.quote_buy, parabolic.quote_sell, parabolic.build_buy_tx, parabolic.build_sell_tx, parabolic.build_launch_tx, parabolic.protocol_stats, parabolic.agent_status, parabolic.build_register_agent_tx, parabolic.docs. Resources: parabolic://docs/parameters, parabolic://coins/{address}.",
111
+ "- Tools: parabolic.list_coins, parabolic.get_coin, parabolic.quote_buy, parabolic.quote_sell, parabolic.build_buy_tx, parabolic.build_sell_tx, parabolic.build_launch_tx, parabolic.protocol_stats, parabolic.agent_status, parabolic.build_register_agent_tx, parabolic.check_ticker, parabolic.referral_status, parabolic.list_venue_coins, parabolic.quote_routed_buy, parabolic.quote_routed_sell, parabolic.build_routed_buy_tx, parabolic.build_routed_sell_tx, parabolic.docs. Resources: parabolic://docs/parameters, parabolic://coins/{address}.",
112
+ "- check_ticker asks the Parabolic site (PARABOLIC_API_URL's site, route /api/v1/studio/ticker) whether a coin already carries a symbol on any chain the site serves and whether <ticker>.parabolic.family is free. Advice, not a gate: nothing on chain enforces a unique symbol. The hostname is the one exclusive thing and belongs to the oldest coin with the ticker.",
113
+ "- referral_status reads one wallet's referral payouts from the Parabolic site (route /api/v1/referrals/{account}): credited, published in the latest weekly root, claimed and claimable per asset, never summed, and the claim(asset, account, cumulative, proof) arguments. The referral distributor pays the account and nobody else. Read-only.",
76
114
  "- It never holds keys, signs, sends or broadcasts. build_* tools return unsigned { to, data, value, chainId } for the caller's wallet. Quotes are read from chain at call time and can move before a transaction lands.",
77
115
  `- build_launch_tx: with PARABOLIC_MEMO_ROUTER set and devBuy > 0 it returns one ParabolicMemoRouter.launchAndBuy transaction (creatorFeeRecipient zero, minTokensOut from the curve math on the launch config's phantom quote, value = launch fee + devBuy)${config.memoRouter ? " (router configured)" : " (router not configured here)"}; otherwise factory.launchToken plus, for a devBuy, the two-step plan (buy calldata to send to the new curve).`,
78
116
  "- The factory ABI has no enumeration function; listing uses the subgraph when set, otherwise Parabolic's public read API (PARABOLIC_API_URL), and a TokenLaunched log scan of the factory only when both are unavailable.",
79
117
  "",
118
+ ...routedSection(config),
119
+ "",
80
120
  "ENVIRONMENT",
81
121
  ...ENV_VARS.map(([k, v]) => `- ${k}: ${v}`),
82
122
  ].join("\n");
83
123
  }
124
+ /**
125
+ * Coins made on other launchpads, traded through ParabolicAggregatorRouter (src/routed.ts). Said per chain from the
126
+ * chain's own record: whether a router is deployed here, and which launchpads run here and are proven through it.
127
+ */
128
+ function routedSection(config) {
129
+ const recorded = recordedAggregator(config.chainId);
130
+ const router = config.aggregatorRouter;
131
+ const here = VENUE_KEYS.flatMap((k) => {
132
+ const on = venueOn(k, config.chainId);
133
+ return on ? [`${VENUES[k].name} (factory ${on.factory}, ${on.proven.path === "lineage" ? `proven through the router by ${on.proven.method === "fork" ? "a fork execution" : "a live-node simulation, not an execution"} at block ${on.proven.block.toLocaleString("en-US")}` : "proven on its pools, which this server does not build"}; subgraph ${config.venueSubgraphs?.[k] ? endpointHost(config.venueSubgraphs[k]) : `not configured, set ${on.subgraphEnv}`})`] : [];
134
+ });
135
+ return [
136
+ "OTHER LAUNCHPADS' COINS (routed through Parabolic)",
137
+ "- list_venue_coins lists coins made on another launchpad from that launchpad's subgraph; quote_routed_buy / quote_routed_sell and build_routed_buy_tx / build_routed_sell_tx trade them through ParabolicAggregatorRouter.",
138
+ "- Such a coin lives on the other launchpad's contracts, not Parabolic's: its curve or pool, its own fee and creator tax, and its snipe tax (keyed on the RECIPIENT on pons) are that launchpad's. Parabolic's own coins never go through the router.",
139
+ "- The routed fee: the router takes Parabolic's fee on top of the launchpad's own, from the input of a buy and from the venue's payout on a sell, and pushes it to the treasury in the same call. It is the router's `defaultFeeBps`, read at every call: 60 bps (0.6%) at deploy, the Free tier's; Pro (30) and Hyper (10) are vouchers the Parabolic site signs for one wallet, and this server sends none. No owner call can raise it above 100 bps.",
140
+ "- A build sends minOut from a fresh quote less slippage, maxSnipeTaxBps 0 unless raised to the tax the launchpad charges now, recipient = from, and a deadline five minutes past the chain's head block. An ERC-20 input (a USDG-quoted buy, every sell) comes with an approval of the router for exactly the amount, because the site's one-shot Permit2 transfer is a signature this server cannot make.",
141
+ `- Router on this chain: ${router ? `${router} (${config.aggregatorSource === "env" ? "PARABOLIC_AGGREGATOR_ROUTER, not in the deployment record: a rehearsal" : "from the deployment record"})` : recorded ? recorded.address : "none. This chain's deployment record carries no `aggregator` key yet, so every routed tool refuses rather than build against a guessed address"}.`,
142
+ `- Launchpads on this chain: ${here.length ? here.join("; ") : "none this server knows"}.`,
143
+ ];
144
+ }
84
145
  //# sourceMappingURL=docs.js.map
package/dist/docs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,9 @@ import { type Address, type Hex } from "viem";
2
2
  import { type Rpc } from "./chain.js";
3
3
  import { type SortKey, type StatusKey } from "./coins.js";
4
4
  import { type Config } from "./config.js";
5
+ import { type QuoteBlock } from "./quote-unit.js";
5
6
  import { RestApi, type PairFilter } from "./restapi.js";
7
+ import { RoutedTrades } from "./routed.js";
6
8
  import { Subgraph, type Fetch } from "./subgraph.js";
7
9
  import { type Socials, type TokenParams } from "./tx.js";
8
10
  export declare const PHASES: readonly ["NotGraduated", "Swept", "PoolCreated", "Rescued"];
@@ -50,6 +52,9 @@ export type ListInput = {
50
52
  export type AgentStatusInput = {
51
53
  address: string;
52
54
  };
55
+ export type CheckTickerInput = {
56
+ ticker: string;
57
+ };
53
58
  export type BuildRegisterAgentInput = {
54
59
  metadataURI?: string;
55
60
  from: string;
@@ -102,7 +107,11 @@ export declare class Parabolic {
102
107
  readonly rpc: Rpc;
103
108
  readonly subgraph: Subgraph | undefined;
104
109
  readonly api: RestApi | undefined;
110
+ /** Routed trades on another launchpad's coin through ParabolicAggregatorRouter (src/routed.ts). */
111
+ readonly routed: RoutedTrades;
105
112
  private hookPromise;
113
+ /** Resolved quote assets by address: one or two per server, read once each. */
114
+ private readonly quoteCache;
106
115
  constructor(config: Config, deps?: {
107
116
  rpc?: Rpc;
108
117
  fetch?: Fetch;
@@ -135,6 +144,27 @@ export declare class Parabolic {
135
144
  assertChain(value: string | number | undefined): void;
136
145
  /** Finds a launch by token address (or curve address) through the factory, falling back to the subgraph. */
137
146
  resolveLaunch(input: string): Promise<Launch>;
147
+ /**
148
+ * The quote asset a curve is priced in: what it is called, the scale its amounts are written at, and whether
149
+ * it is a dollar. Cached per address, because every tool call reads the same one or two assets.
150
+ *
151
+ * This replaces `quoteDecimals: native ? 18 : 6`, which appeared at four places in this file and once in
152
+ * src/coins.ts. It is Arc's two answers typed out: 18 is right only where the gas token is an 18-decimal
153
+ * dollar, and 6 is right only for EURC on Arc. USDC is a **6-decimal ERC-20** on Base, Ethereum and BNB, so
154
+ * on any of them `build_buy_tx` encoded a buy a **trillion times too small** and reported it as correct.
155
+ *
156
+ * So nothing is derived from the boolean. A gas-asset quote takes the chain registry's figures, which were
157
+ * read off that chain before they were written down; an ERC-20 answers for itself, with the same
158
+ * `decimals()` call the factory makes at every launch. An asset that will not say **stops the tool**: a
159
+ * scale that is wrong by a million prices a trade an agent then signs.
160
+ */
161
+ private quoteAsset;
162
+ private readQuoteAsset;
163
+ /**
164
+ * `l` rather than a bare curve address: the launch already carries `pairToken`, so a native-quoted curve —
165
+ * every coin on Arc — costs exactly the reads it has always cost, and an ERC-20 quote costs two more the
166
+ * first time that asset is seen and none after.
167
+ */
138
168
  private liveTerms;
139
169
  private assertOpen;
140
170
  listCoins(input?: ListInput): Promise<{
@@ -157,9 +187,10 @@ export declare class Parabolic {
157
187
  name: string;
158
188
  ticker: string;
159
189
  creator: Address;
160
- pair: "USDC" | "EURC";
190
+ pair: string;
161
191
  pairToken: Address;
162
192
  quoteDecimals: number;
193
+ quote: QuoteBlock;
163
194
  status: StatusKey;
164
195
  raised: string;
165
196
  raisedRaw: bigint;
@@ -243,6 +274,7 @@ export declare class Parabolic {
243
274
  pair: string;
244
275
  pairToken: `0x${string}`;
245
276
  quoteDecimals: number;
277
+ quote: QuoteBlock;
246
278
  status: string;
247
279
  phase: "NotGraduated" | "Swept" | "PoolCreated" | "Rescued";
248
280
  readyToGraduate: boolean;
@@ -338,6 +370,7 @@ export declare class Parabolic {
338
370
  coin: `0x${string}`;
339
371
  curve: `0x${string}`;
340
372
  pair: string;
373
+ quote: QuoteBlock;
341
374
  quoteIn: {
342
375
  amount: string;
343
376
  raw: string;
@@ -413,6 +446,7 @@ export declare class Parabolic {
413
446
  coin: `0x${string}`;
414
447
  curve: `0x${string}`;
415
448
  pair: string;
449
+ quote: QuoteBlock;
416
450
  tokensIn: {
417
451
  amount: string;
418
452
  raw: string;
@@ -462,6 +496,20 @@ export declare class Parabolic {
462
496
  };
463
497
  notes: string[];
464
498
  }>;
499
+ /**
500
+ * What this server can truthfully say about a routed buy on the chain it serves.
501
+ *
502
+ * Found by the second review of 23 September 2026. The buy payload's second note read "A memo-routed
503
+ * variant (ParabolicMemoRouter through Arc's Memo contract, carrying a referral code) exists: pass
504
+ * `memo: { referral }`" with no condition on anything, so the day this server started serving Robinhood
505
+ * Chain a model was told to pass `memo` and got back "Memo-routed buys need PARABOLIC_MEMO_ROUTER" — the
506
+ * one variable src/config.ts's 4663 entry says must stay absent, because `ParabolicRouter` and
507
+ * `ParabolicMemoRouter` share no function selector and filling it would encode calldata for functions that
508
+ * address does not have. The case is read from the chain's own record, never from a written chain id.
509
+ */
510
+ private routedBuyNote;
511
+ /** Why `memo` cannot be honoured here, in the terms of the chain's own record rather than a variable name. */
512
+ private noMemoRouterReason;
465
513
  buildBuyTx(input: BuildBuyInput): Promise<{
466
514
  kind: string;
467
515
  chain: {
@@ -471,6 +519,7 @@ export declare class Parabolic {
471
519
  };
472
520
  coin: `0x${string}`;
473
521
  curve: `0x${string}`;
522
+ quoteAsset: QuoteBlock;
474
523
  eoaOnly: boolean;
475
524
  steps: string[];
476
525
  approval: import("./tx.js").UnsignedTx;
@@ -537,6 +586,7 @@ export declare class Parabolic {
537
586
  };
538
587
  coin: `0x${string}`;
539
588
  curve: `0x${string}`;
589
+ quoteAsset: QuoteBlock;
540
590
  steps: string[];
541
591
  approval: import("./tx.js").UnsignedTx | null;
542
592
  tx: import("./tx.js").UnsignedTx;
@@ -591,6 +641,7 @@ export declare class Parabolic {
591
641
  };
592
642
  coin: `0x${string}`;
593
643
  curve: `0x${string}`;
644
+ quoteAsset: QuoteBlock;
594
645
  steps: string[];
595
646
  approval: import("./tx.js").UnsignedTx;
596
647
  tx: import("./tx.js").UnsignedTx;
@@ -661,9 +712,13 @@ export declare class Parabolic {
661
712
  } | null;
662
713
  params: TokenParams;
663
714
  launchConfigId: string;
664
- pair: "USDC" | "EURC";
715
+ pair: string;
665
716
  pairToken: `0x${string}`;
717
+ quoteAsset: QuoteBlock;
666
718
  launchFee: {
719
+ symbol: string;
720
+ dollar: boolean;
721
+ note: string;
667
722
  amount: string;
668
723
  raw: string;
669
724
  };
@@ -762,9 +817,13 @@ export declare class Parabolic {
762
817
  } | null;
763
818
  params: TokenParams;
764
819
  launchConfigId: string;
765
- pair: "USDC" | "EURC";
820
+ pair: string;
766
821
  pairToken: `0x${string}`;
822
+ quoteAsset: QuoteBlock;
767
823
  launchFee: {
824
+ symbol: string;
825
+ dollar: boolean;
826
+ note: string;
768
827
  amount: string;
769
828
  raw: string;
770
829
  };
@@ -892,6 +951,43 @@ export declare class Parabolic {
892
951
  warnings: string[];
893
952
  notes: string[];
894
953
  }>;
954
+ /**
955
+ * Whether a coin already carries this ticker on any chain the site serves, and whether
956
+ * `<ticker>.parabolic.family` is free — read from the Parabolic site's own route, which is the only party
957
+ * that can answer the hostname half.
958
+ *
959
+ * Advice and not a gate: nothing on chain enforces a unique symbol, so `free: false` names what exists and
960
+ * leaves the choice with the caller. The hostname is the one exclusive thing, and it belongs to the oldest
961
+ * coin carrying the ticker. The result says both, in `message` and in `notes`, because a model reading
962
+ * `free: false` as "cannot launch" would be wrong in one direction and one reading `free: true` as "the
963
+ * name is mine" would be wrong in the other.
964
+ *
965
+ * The normalisation is checked HERE first (src/ticker.ts mirrors the site's rule), so an impossible ticker
966
+ * is refused with the reason before a request is spent. The site is asked whatever `PARABOLIC_FACTORY` or
967
+ * `PARABOLIC_RPC_URL` say, unlike the listing: a fork holds its own coins, but the hostnames and the public
968
+ * board are the site's, and those are what the question is about.
969
+ */
970
+ checkTicker(input: CheckTickerInput): Promise<{
971
+ ticker: string;
972
+ asked: string;
973
+ chain: {
974
+ id: number;
975
+ key: string;
976
+ name: string;
977
+ };
978
+ scope: string;
979
+ free: boolean;
980
+ taken: import("./ticker.js").TakenRow[];
981
+ reserved: {
982
+ name: string;
983
+ } | null;
984
+ host: string | null;
985
+ hostFree: boolean;
986
+ hostRule: string;
987
+ message: string;
988
+ source: string;
989
+ notes: string[];
990
+ }>;
895
991
  protocolStats(): Promise<{
896
992
  chain: {
897
993
  rpcHost: string;
@@ -908,10 +1004,16 @@ export declare class Parabolic {
908
1004
  volume: {
909
1005
  amount: string;
910
1006
  raw: string;
1007
+ } | {
1008
+ amount: null;
1009
+ raw: string;
911
1010
  };
912
1011
  fees: {
913
1012
  amount: string;
914
1013
  raw: string;
1014
+ } | {
1015
+ amount: null;
1016
+ raw: string;
915
1017
  };
916
1018
  today: {
917
1019
  day: number;
@@ -922,10 +1024,16 @@ export declare class Parabolic {
922
1024
  volume: {
923
1025
  amount: string;
924
1026
  raw: string;
1027
+ } | {
1028
+ amount: null;
1029
+ raw: string;
925
1030
  };
926
1031
  fees: {
927
1032
  amount: string;
928
1033
  raw: string;
1034
+ } | {
1035
+ amount: null;
1036
+ raw: string;
929
1037
  };
930
1038
  } | null;
931
1039
  daily: {
@@ -937,10 +1045,16 @@ export declare class Parabolic {
937
1045
  volume: {
938
1046
  amount: string;
939
1047
  raw: string;
1048
+ } | {
1049
+ amount: null;
1050
+ raw: string;
940
1051
  };
941
1052
  fees: {
942
1053
  amount: string;
943
1054
  raw: string;
1055
+ } | {
1056
+ amount: null;
1057
+ raw: string;
944
1058
  };
945
1059
  }[];
946
1060
  units: string;
@@ -950,6 +1064,8 @@ export declare class Parabolic {
950
1064
  factory: {
951
1065
  address: `0x${string}`;
952
1066
  launchFee: {
1067
+ symbol: string;
1068
+ dollar: boolean;
953
1069
  amount: string;
954
1070
  raw: string;
955
1071
  };
@@ -995,6 +1111,7 @@ export declare class Parabolic {
995
1111
  graduationMarketCap: number;
996
1112
  poolFee: number;
997
1113
  tickSpacing: number;
1114
+ quoteNote: string;
998
1115
  };
999
1116
  contracts: {
1000
1117
  feeEscrow: `0x${string}`;