chia-explorer 0.1.2 → 0.1.4

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 (43) hide show
  1. package/README.md +8 -1
  2. package/dist/coingecko/cache.d.ts +6 -0
  3. package/dist/coingecko/cache.js +27 -0
  4. package/dist/coingecko/cache.js.map +1 -0
  5. package/dist/coingecko/client.d.ts +1 -0
  6. package/dist/coingecko/client.js +45 -0
  7. package/dist/coingecko/client.js.map +1 -0
  8. package/dist/coingecko/index.d.ts +2 -0
  9. package/dist/coingecko/index.js +12 -0
  10. package/dist/coingecko/index.js.map +1 -0
  11. package/dist/coinset/pagination.d.ts +3 -0
  12. package/dist/coinset/pagination.js +19 -1
  13. package/dist/coinset/pagination.js.map +1 -1
  14. package/dist/prefarm/registry.d.ts +33 -0
  15. package/dist/prefarm/registry.js +121 -0
  16. package/dist/prefarm/registry.js.map +1 -0
  17. package/dist/prefarm/spends.d.ts +29 -0
  18. package/dist/prefarm/spends.js +113 -0
  19. package/dist/prefarm/spends.js.map +1 -0
  20. package/dist/prompts/prefarm-summary.d.ts +2 -0
  21. package/dist/prompts/prefarm-summary.js +27 -0
  22. package/dist/prompts/prefarm-summary.js.map +1 -0
  23. package/dist/schemas/price.d.ts +3 -0
  24. package/dist/schemas/price.js +16 -0
  25. package/dist/schemas/price.js.map +1 -0
  26. package/dist/server.js +17 -3
  27. package/dist/server.js.map +1 -1
  28. package/dist/tools/prefarm/get-prefarm-spends.d.ts +2 -0
  29. package/dist/tools/prefarm/get-prefarm-spends.js +68 -0
  30. package/dist/tools/prefarm/get-prefarm-spends.js.map +1 -0
  31. package/dist/tools/prefarm/get-prefarm-status.d.ts +2 -0
  32. package/dist/tools/prefarm/get-prefarm-status.js +72 -0
  33. package/dist/tools/prefarm/get-prefarm-status.js.map +1 -0
  34. package/dist/tools/prefarm/list-prefarm-addresses.d.ts +2 -0
  35. package/dist/tools/prefarm/list-prefarm-addresses.js +33 -0
  36. package/dist/tools/prefarm/list-prefarm-addresses.js.map +1 -0
  37. package/dist/tools/price/convert-xch-to-fiat.d.ts +2 -0
  38. package/dist/tools/price/convert-xch-to-fiat.js +42 -0
  39. package/dist/tools/price/convert-xch-to-fiat.js.map +1 -0
  40. package/dist/tools/price/get-xch-price.d.ts +2 -0
  41. package/dist/tools/price/get-xch-price.js +26 -0
  42. package/dist/tools/price/get-xch-price.js.map +1 -0
  43. package/package.json +1 -1
package/README.md CHANGED
@@ -11,6 +11,7 @@ Backed by the public [coinset.org](https://www.coinset.org) full-node API. Suppo
11
11
  - What is the balance of `xch1...` (or `txch1...`, or a raw puzzle hash)?
12
12
  - Look up a coin by name. Calculate a coin name from its fields.
13
13
  - Convert between addresses and puzzle hashes in either direction.
14
+ - What is XCH worth in USD (or EUR, GBP, BTC, ...) right now? What's this balance worth?
14
15
 
15
16
  ## Install
16
17
 
@@ -61,8 +62,14 @@ Add to your `claude_desktop_config.json`:
61
62
  | `calculate_coin_name` | sha256(parent_coin_info \|\| puzzle_hash \|\| amount) — no RPC |
62
63
  | `address_to_puzzle_hash` | bech32m decode — no RPC |
63
64
  | `puzzle_hash_to_address` | bech32m encode — no RPC |
65
+ | `get_xch_price` | Current XCH spot price in one or more currencies (CoinGecko) |
66
+ | `convert_xch_to_fiat` | Convert a mojo amount to fiat using the current XCH price |
64
67
 
65
- All tools take an optional `network: "mainnet" | "testnet11"` (default `mainnet`).
68
+ Blockchain tools take an optional `network: "mainnet" | "testnet11"` (default `mainnet`). The price tools don't take a network arg.
69
+
70
+ ## Optional config
71
+
72
+ - `COINGECKO_API_KEY` — if set, sent as `x-cg-demo-api-key` to lift the free-tier rate limit. The price tools work without it.
66
73
 
67
74
  ## Prompts
68
75
 
@@ -0,0 +1,6 @@
1
+ export declare function getCachedPrices(currencies: string[]): {
2
+ cached: Record<string, number>;
3
+ missing: string[];
4
+ };
5
+ export declare function setCachedPrices(prices: Record<string, number>): void;
6
+ export declare function resetCache(): void;
@@ -0,0 +1,27 @@
1
+ const TTL_MS = 60_000;
2
+ const cache = new Map();
3
+ export function getCachedPrices(currencies) {
4
+ const now = Date.now();
5
+ const cached = {};
6
+ const missing = [];
7
+ for (const currency of currencies) {
8
+ const entry = cache.get(currency);
9
+ if (entry && entry.expiresAt > now) {
10
+ cached[currency] = entry.price;
11
+ }
12
+ else {
13
+ missing.push(currency);
14
+ }
15
+ }
16
+ return { cached, missing };
17
+ }
18
+ export function setCachedPrices(prices) {
19
+ const expiresAt = Date.now() + TTL_MS;
20
+ for (const [currency, price] of Object.entries(prices)) {
21
+ cache.set(currency, { price, expiresAt });
22
+ }
23
+ }
24
+ export function resetCache() {
25
+ cache.clear();
26
+ }
27
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/coingecko/cache.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,MAAM,CAAC;AAOtB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;AAEvC,MAAM,UAAU,eAAe,CAAC,UAAoB;IAIlD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,KAAK,IAAI,KAAK,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;YACnC,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAA8B;IAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC;IACtC,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function fetchXchPrices(currencies: string[]): Promise<Record<string, number>>;
@@ -0,0 +1,45 @@
1
+ const COINGECKO_URL = 'https://api.coingecko.com/api/v3/simple/price';
2
+ const REQUEST_TIMEOUT_MS = 10_000;
3
+ export async function fetchXchPrices(currencies) {
4
+ if (currencies.length === 0) {
5
+ throw new Error('at least one currency is required');
6
+ }
7
+ const params = new URLSearchParams({
8
+ ids: 'chia',
9
+ vs_currencies: currencies.join(','),
10
+ });
11
+ const headers = { accept: 'application/json' };
12
+ const apiKey = process.env.COINGECKO_API_KEY;
13
+ if (apiKey)
14
+ headers['x-cg-demo-api-key'] = apiKey;
15
+ const res = await fetch(`${COINGECKO_URL}?${params.toString()}`, {
16
+ headers,
17
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
18
+ });
19
+ if (!res.ok) {
20
+ const body = await res.text().catch(() => '');
21
+ const detail = body ? `: ${body.slice(0, 200)}` : '';
22
+ throw new Error(`coingecko ${res.status} ${res.statusText}${detail}`);
23
+ }
24
+ const data = (await res.json());
25
+ if (!data || typeof data !== 'object' || !('chia' in data)) {
26
+ throw new Error('coingecko response missing `chia` field');
27
+ }
28
+ const chia = data.chia;
29
+ if (!chia || typeof chia !== 'object') {
30
+ throw new Error('coingecko response `chia` field is not an object');
31
+ }
32
+ const out = {};
33
+ for (const [currency, value] of Object.entries(chia)) {
34
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
35
+ throw new Error(`coingecko returned non-numeric price for ${currency}`);
36
+ }
37
+ out[currency.toLowerCase()] = value;
38
+ }
39
+ const missing = currencies.filter((c) => !(c in out));
40
+ if (missing.length > 0) {
41
+ throw new Error(`coingecko returned no price for: ${missing.join(', ')}`);
42
+ }
43
+ return out;
44
+ }
45
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/coingecko/client.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,+CAA+C,CAAC;AACtE,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAoB;IACvD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,GAAG,EAAE,MAAM;QACX,aAAa,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;KACpC,CAAC,CAAC;IAEH,MAAM,OAAO,GAA2B,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC7C,IAAI,MAAM;QAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC;IAElD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE;QAC/D,OAAO;QACP,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC;KAChD,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,GAAG,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAY,CAAC;IAC3C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACvB,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,4CAA4C,QAAQ,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC;IACtC,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACtD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oCAAoC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function getXchPrices(currencies: string[]): Promise<Record<string, number>>;
2
+ export { resetCache } from './cache.js';
@@ -0,0 +1,12 @@
1
+ import { fetchXchPrices } from './client.js';
2
+ import { getCachedPrices, setCachedPrices } from './cache.js';
3
+ export async function getXchPrices(currencies) {
4
+ const { cached, missing } = getCachedPrices(currencies);
5
+ if (missing.length === 0)
6
+ return cached;
7
+ const fetched = await fetchXchPrices(missing);
8
+ setCachedPrices(fetched);
9
+ return { ...cached, ...fetched };
10
+ }
11
+ export { resetCache } from './cache.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/coingecko/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAoB;IACrD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IACxD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9C,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
@@ -27,3 +27,6 @@ export declare function fetchCoinRecordsByPuzzleHash(agent: RPCAgent, puzzleHash
27
27
  startHeight?: number;
28
28
  endHeight?: number;
29
29
  }): Promise<CoinRecordLike[]>;
30
+ export declare function fetchCoinRecordsByParentIds(agent: RPCAgent, parentIds: readonly string[], options?: {
31
+ includeSpent?: boolean;
32
+ }): Promise<CoinRecordLike[]>;
@@ -1,4 +1,4 @@
1
- import { get_coin_records_by_puzzle_hash } from 'chia-agent/api/rpc/full_node/index.js';
1
+ import { get_coin_records_by_parent_ids, get_coin_records_by_puzzle_hash, } from 'chia-agent/api/rpc/full_node/index.js';
2
2
  const PAGE_SIZE_LIMIT = 5_000;
3
3
  /**
4
4
  * Fetch coin records by puzzle hash, paginating by height window if the response
@@ -48,4 +48,22 @@ export async function fetchCoinRecordsByPuzzleHash(agent, puzzleHashHex, options
48
48
  }
49
49
  return all;
50
50
  }
51
+ const PARENT_IDS_BATCH = 200;
52
+ export async function fetchCoinRecordsByParentIds(agent, parentIds, options = {}) {
53
+ if (parentIds.length === 0)
54
+ return [];
55
+ const includeSpent = options.includeSpent ?? true;
56
+ const all = [];
57
+ for (let i = 0; i < parentIds.length; i += PARENT_IDS_BATCH) {
58
+ const batch = parentIds.slice(i, i + PARENT_IDS_BATCH);
59
+ const payload = {
60
+ parent_ids: batch,
61
+ include_spent_coins: includeSpent,
62
+ };
63
+ const res = await get_coin_records_by_parent_ids(agent, payload);
64
+ const records = (res.coin_records ?? []);
65
+ all.push(...records);
66
+ }
67
+ return all;
68
+ }
51
69
  //# sourceMappingURL=pagination.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/coinset/pagination.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,uCAAuC,CAAC;AAiBxF,MAAM,eAAe,GAAG,KAAK,CAAC;AAE9B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,KAAe,EACf,aAAqB,EACrB,UAAgF,EAAE;IAElF,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,KAAK,CAAC;IACnD,IAAI,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC;IAC9B,MAAM,GAAG,GAAqB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,GAAG;YAAE,MAAM;QACnE,MAAM,OAAO,GAA+B;YAC1C,WAAW,EAAE,aAAa;YAC1B,mBAAmB,EAAE,YAAY;SAClC,CAAC;QACF,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,YAAY,GAAG,KAAK,CAAC;QACtD,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,CAAC,UAAU,GAAG,GAAG,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,+BAA+B,CAAC,KAAK,EAAE,OAA4B,CAAC,CAAC;QACvF,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAqB,CAAC;QAC7D,IAAI,SAAS,GAAG,KAAK,IAAI,CAAC,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC3F,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACZ,IAAI,CAAC,CAAC,qBAAqB,GAAG,SAAS;gBAAE,SAAS,GAAG,CAAC,CAAC,qBAAqB,CAAC;QAC/E,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,GAAG,eAAe;YAAE,MAAM;QAC5C,IAAI,KAAK,KAAK,SAAS,IAAI,SAAS,IAAI,KAAK;YAAE,MAAM;QACrD,KAAK,GAAG,SAAS,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/coinset/pagination.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export type WalletId = 'us-cold' | 'us-warm' | 'ch-cold' | 'ch-warm';
2
+ export type Region = 'us' | 'ch';
3
+ export type Temperature = 'cold' | 'warm';
4
+ export type DestinationCategory = 'partner' | 'market-maker' | 'exchange' | 'other';
5
+ export interface PrefarmWallet {
6
+ id: WalletId;
7
+ label: string;
8
+ region: Region;
9
+ temperature: Temperature;
10
+ /**
11
+ * Current on-chain p2 addresses for this custody singleton. Warm wallets carry
12
+ * more than one because outgoing spends sit at a clawback intermediate before
13
+ * settling. Empty array = pending population.
14
+ */
15
+ addresses: readonly string[];
16
+ /** Lower-case hex puzzle hashes derived from `addresses`. Same length, same order. */
17
+ puzzleHashes: readonly string[];
18
+ }
19
+ export interface KnownDestination {
20
+ address: string;
21
+ puzzleHash: string;
22
+ entity: string;
23
+ label: string;
24
+ category: DestinationCategory;
25
+ }
26
+ /** Genesis total of the Chia strategic reserve. The only amount we hardcode; everything else is live. */
27
+ export declare const TOTAL_PREFARM_ALLOCATION_MOJO: bigint;
28
+ export declare const PREFARM_WALLETS: readonly PrefarmWallet[];
29
+ export declare const KNOWN_DESTINATIONS: readonly KnownDestination[];
30
+ export declare function lookupDestination(puzzleHashHex: string): KnownDestination | undefined;
31
+ export declare function lookupPrefarmWallet(puzzleHashHex: string): PrefarmWallet | undefined;
32
+ export declare function getWalletById(id: WalletId): PrefarmWallet | undefined;
33
+ export declare function isPopulated(wallet: PrefarmWallet): boolean;
@@ -0,0 +1,121 @@
1
+ import { MOJOS_PER_XCH } from '../chia/amounts.js';
2
+ import { addressToPuzzleHash } from '../chia/bech32.js';
3
+ /** Genesis total of the Chia strategic reserve. The only amount we hardcode; everything else is live. */
4
+ export const TOTAL_PREFARM_ALLOCATION_MOJO = 21000000n * MOJOS_PER_XCH;
5
+ const WALLET_INPUTS = [
6
+ {
7
+ id: 'us-cold',
8
+ label: 'Strategic Reserve — US Cold',
9
+ region: 'us',
10
+ temperature: 'cold',
11
+ addresses: ['xch1yxqsmyuyjdlgxw4sqjg4vqlqv5ms2qzex00586nu643jqemmarwslh08yl'],
12
+ },
13
+ {
14
+ id: 'us-warm',
15
+ label: 'Strategic Reserve — US Warm',
16
+ region: 'us',
17
+ temperature: 'warm',
18
+ addresses: [
19
+ 'xch12pc7qk46t8aktdsd7ss96pctdp0236sexakfsdvsqefuqyyll3hqzhnldc',
20
+ 'xch1aukdy3djga7j8ckaw06lwjew9pnnv5hugqyx9lu9l2utaxjtgj5snuuwkc',
21
+ ],
22
+ },
23
+ {
24
+ id: 'ch-cold',
25
+ label: 'Strategic Reserve — Swiss Cold',
26
+ region: 'ch',
27
+ temperature: 'cold',
28
+ addresses: ['xch1y6krqgs2cjz6mjgz5wy4dd5zqghm3a5pgueccjtudchn2xzcajtsnyzvgy'],
29
+ },
30
+ {
31
+ id: 'ch-warm',
32
+ label: 'Strategic Reserve — Swiss Warm',
33
+ region: 'ch',
34
+ temperature: 'warm',
35
+ addresses: [
36
+ 'xch18hp0afeqmcvn675dqpnxfhk7gggwcpjaa0huc45huu79tkaa28dsuse43w',
37
+ 'xch1xhghtsdqdtt5eqr307lcacg49nt72zmeuq2qfwu7ymmqvqf0ej0qsruh0w',
38
+ ],
39
+ },
40
+ ];
41
+ const DESTINATION_INPUTS = [
42
+ {
43
+ address: 'xch1drz2ufckxz7dtlaajsw3gwtyd6ztss08vwxyfcr4rz0z0t77ufrq8qqe09',
44
+ entity: 'silicon',
45
+ label: 'Silicon.net',
46
+ category: 'partner',
47
+ },
48
+ {
49
+ address: 'xch1mhw0vz0jl8etxqar0se73excayq2e4jg3g5zegzumyzm2u4htzusjfk8q4',
50
+ entity: 'koba42',
51
+ label: 'Koba42 Gaming RFP Grant',
52
+ category: 'partner',
53
+ },
54
+ {
55
+ address: 'xch1plthft5ykcnnaxvpydzlmu2nlslzcevn3vv4s43rkm908d95nd5sv22nqr',
56
+ entity: 'nossd',
57
+ label: 'Purchase Agreement with NoSSD',
58
+ category: 'partner',
59
+ },
60
+ {
61
+ address: 'xch1hy7r0hcq4xymv2d944dtsn7rw8tv8pntc7adr36u45zhmmh3ad4seh48zz',
62
+ entity: 'market-maker-primary',
63
+ label: 'Market Maker (primary)',
64
+ category: 'market-maker',
65
+ },
66
+ {
67
+ address: 'xch1g8wl32qjyquzx6rnzn0rpj5l2q5acykawzped7nl5kdsfp3drpqqfavwnf',
68
+ entity: 'market-maker-secondary',
69
+ label: 'Market Maker (secondary)',
70
+ category: 'market-maker',
71
+ },
72
+ {
73
+ address: 'xch1d6w3ctu8pqtkkmsa3hjmqam9fuy7q9u4fzy5hqw08rx36whpg3hs4xpjeu',
74
+ entity: 'market-maker-tertiary',
75
+ label: 'Market Maker (tertiary)',
76
+ category: 'market-maker',
77
+ },
78
+ ];
79
+ function buildWallets() {
80
+ return WALLET_INPUTS.map((w) => {
81
+ const puzzleHashes = w.addresses.map((addr) => {
82
+ const { puzzleHash, network } = addressToPuzzleHash(addr);
83
+ if (network !== 'mainnet') {
84
+ throw new Error(`prefarm wallet ${w.id} must use mainnet addresses`);
85
+ }
86
+ return puzzleHash;
87
+ });
88
+ return { ...w, puzzleHashes };
89
+ });
90
+ }
91
+ function buildDestinations() {
92
+ return DESTINATION_INPUTS.map((d) => {
93
+ const { puzzleHash, network } = addressToPuzzleHash(d.address);
94
+ if (network !== 'mainnet') {
95
+ throw new Error(`destination ${d.entity} must use a mainnet address`);
96
+ }
97
+ return { ...d, puzzleHash };
98
+ });
99
+ }
100
+ export const PREFARM_WALLETS = buildWallets();
101
+ export const KNOWN_DESTINATIONS = buildDestinations();
102
+ const DESTINATION_INDEX = new Map(KNOWN_DESTINATIONS.map((d) => [d.puzzleHash, d]));
103
+ const WALLET_BY_PUZZLE_HASH = new Map();
104
+ for (const w of PREFARM_WALLETS) {
105
+ for (const ph of w.puzzleHashes)
106
+ WALLET_BY_PUZZLE_HASH.set(ph, w);
107
+ }
108
+ const WALLET_BY_ID = new Map(PREFARM_WALLETS.map((w) => [w.id, w]));
109
+ export function lookupDestination(puzzleHashHex) {
110
+ return DESTINATION_INDEX.get(puzzleHashHex.toLowerCase());
111
+ }
112
+ export function lookupPrefarmWallet(puzzleHashHex) {
113
+ return WALLET_BY_PUZZLE_HASH.get(puzzleHashHex.toLowerCase());
114
+ }
115
+ export function getWalletById(id) {
116
+ return WALLET_BY_ID.get(id);
117
+ }
118
+ export function isPopulated(wallet) {
119
+ return wallet.addresses.length > 0;
120
+ }
121
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/prefarm/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { RPCAgent } from 'chia-agent';
2
+ import { KnownDestination, PrefarmWallet } from './registry.js';
3
+ export interface DestinationOutflow {
4
+ puzzle_hash: string;
5
+ address: string;
6
+ amount_mojo: string;
7
+ amount_xch: string;
8
+ entity: string | null;
9
+ label: string | null;
10
+ category: KnownDestination['category'] | 'internal-rotation' | 'unknown';
11
+ internal_wallet_id?: PrefarmWallet['id'];
12
+ }
13
+ export interface PrefarmSpend {
14
+ wallet_id: PrefarmWallet['id'];
15
+ source_address: string;
16
+ source_puzzle_hash: string;
17
+ parent_coin_name: string;
18
+ spent_amount_mojo: string;
19
+ spent_amount_xch: string;
20
+ spent_height: number;
21
+ confirmed_height: number;
22
+ timestamp: number;
23
+ destinations: DestinationOutflow[];
24
+ outflow_mojo: string;
25
+ outflow_xch: string;
26
+ }
27
+ export declare function getWalletSpends(agent: RPCAgent, wallet: PrefarmWallet, options?: {
28
+ sinceHeight?: number;
29
+ }): Promise<PrefarmSpend[]>;
@@ -0,0 +1,113 @@
1
+ import { mojoToXch, toBigInt } from '../chia/amounts.js';
2
+ import { puzzleHashToAddress } from '../chia/bech32.js';
3
+ import { coinName } from '../chia/coin-name.js';
4
+ import { fetchCoinRecordsByParentIds, fetchCoinRecordsByPuzzleHash, } from '../coinset/pagination.js';
5
+ import { isPopulated, lookupDestination, lookupPrefarmWallet, } from './registry.js';
6
+ function labelDestination(puzzleHash, address, amountMojo) {
7
+ const internal = lookupPrefarmWallet(puzzleHash);
8
+ if (internal) {
9
+ return {
10
+ puzzle_hash: puzzleHash,
11
+ address,
12
+ amount_mojo: amountMojo.toString(),
13
+ amount_xch: mojoToXch(amountMojo),
14
+ entity: 'prefarm',
15
+ label: internal.label,
16
+ category: 'internal-rotation',
17
+ internal_wallet_id: internal.id,
18
+ };
19
+ }
20
+ const known = lookupDestination(puzzleHash);
21
+ if (known) {
22
+ return {
23
+ puzzle_hash: puzzleHash,
24
+ address,
25
+ amount_mojo: amountMojo.toString(),
26
+ amount_xch: mojoToXch(amountMojo),
27
+ entity: known.entity,
28
+ label: known.label,
29
+ category: known.category,
30
+ };
31
+ }
32
+ return {
33
+ puzzle_hash: puzzleHash,
34
+ address,
35
+ amount_mojo: amountMojo.toString(),
36
+ amount_xch: mojoToXch(amountMojo),
37
+ entity: null,
38
+ label: null,
39
+ category: 'unknown',
40
+ };
41
+ }
42
+ export async function getWalletSpends(agent, wallet, options = {}) {
43
+ if (!isPopulated(wallet))
44
+ return [];
45
+ const ownPuzzleHashes = new Set(wallet.puzzleHashes.map((ph) => ph.toLowerCase()));
46
+ const recordGroups = await Promise.all(wallet.puzzleHashes.map((ph) => fetchCoinRecordsByPuzzleHash(agent, ph, {
47
+ includeSpent: true,
48
+ ...(options.sinceHeight !== undefined ? { startHeight: options.sinceHeight } : {}),
49
+ })));
50
+ const records = recordGroups.flat();
51
+ const spent = records.filter((r) => r.spent_block_index > 0);
52
+ if (spent.length === 0)
53
+ return [];
54
+ const parentByName = new Map();
55
+ for (const r of spent) {
56
+ const name = coinName({
57
+ parent_coin_info: r.coin.parent_coin_info,
58
+ puzzle_hash: r.coin.puzzle_hash,
59
+ amount: toBigInt(r.coin.amount),
60
+ });
61
+ parentByName.set(name, r);
62
+ }
63
+ const children = await fetchCoinRecordsByParentIds(agent, [...parentByName.keys()], {
64
+ includeSpent: true,
65
+ });
66
+ const childrenByParent = new Map();
67
+ for (const child of children) {
68
+ const key = child.coin.parent_coin_info.toLowerCase().replace(/^0x/, '');
69
+ const list = childrenByParent.get(key) ?? [];
70
+ list.push(child);
71
+ childrenByParent.set(key, list);
72
+ }
73
+ const out = [];
74
+ for (const [parentName, parent] of parentByName) {
75
+ const childCoins = childrenByParent.get(parentName) ?? [];
76
+ // Filter out children that land back on one of *this* wallet's own puzzle hashes:
77
+ // those are singleton bookkeeping (e.g. the singleton recreating itself, or
78
+ // moving between a wallet's primary p2 and its clawback intermediate). Children
79
+ // landing on a different prefarm wallet are real inter-custody rotations.
80
+ const meaningful = childCoins.filter((c) => {
81
+ const ph = c.coin.puzzle_hash.toLowerCase().replace(/^0x/, '');
82
+ return !ownPuzzleHashes.has(ph);
83
+ });
84
+ if (meaningful.length === 0)
85
+ continue;
86
+ const destinations = meaningful.map((c) => {
87
+ const ph = c.coin.puzzle_hash.toLowerCase().replace(/^0x/, '');
88
+ const addr = puzzleHashToAddress(ph, 'mainnet');
89
+ return labelDestination(ph, addr, toBigInt(c.coin.amount));
90
+ });
91
+ const outflow = destinations
92
+ .filter((d) => d.category !== 'internal-rotation')
93
+ .reduce((acc, d) => acc + BigInt(d.amount_mojo), 0n);
94
+ const sourcePh = parent.coin.puzzle_hash.toLowerCase().replace(/^0x/, '');
95
+ out.push({
96
+ wallet_id: wallet.id,
97
+ source_puzzle_hash: sourcePh,
98
+ source_address: puzzleHashToAddress(sourcePh, 'mainnet'),
99
+ parent_coin_name: parentName,
100
+ spent_amount_mojo: toBigInt(parent.coin.amount).toString(),
101
+ spent_amount_xch: mojoToXch(toBigInt(parent.coin.amount)),
102
+ spent_height: parent.spent_block_index,
103
+ confirmed_height: parent.confirmed_block_index,
104
+ timestamp: Number(parent.timestamp),
105
+ destinations,
106
+ outflow_mojo: outflow.toString(),
107
+ outflow_xch: mojoToXch(outflow),
108
+ });
109
+ }
110
+ out.sort((a, b) => b.spent_height - a.spent_height);
111
+ return out;
112
+ }
113
+ //# sourceMappingURL=spends.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spends.js","sourceRoot":"","sources":["../../src/prefarm/spends.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,27 @@
1
+ export function register(server) {
2
+ server.registerPrompt('prefarm_summary', {
3
+ title: 'Chia strategic-reserve summary',
4
+ description: 'Summarise the Chia strategic reserve: how much pre-farm has been spent, how much remains, and where it has gone.',
5
+ argsSchema: {},
6
+ }, () => {
7
+ const text = [
8
+ `Summarise the state of the Chia strategic reserve (the 21M XCH pre-farm).`,
9
+ ``,
10
+ `Steps:`,
11
+ `1. Call \`get_prefarm_status\` to get headline numbers and per-wallet balances.`,
12
+ `2. Call \`get_prefarm_spends\` with \`limit: 10\` to get the most recent outflows.`,
13
+ `3. Call \`get_xch_price\` to convert spent and remaining amounts to USD.`,
14
+ ``,
15
+ `Present, in this order:`,
16
+ `- Total spent vs remaining as both XCH and USD, with the percentage of the 21M reserve spent so far. If some wallets are pending population, say so explicitly and base the percentage only on tracked wallets.`,
17
+ `- Per-wallet breakdown: id, balance in XCH, percent of its allocation spent. Skip wallets marked \`pending\`.`,
18
+ `- Last few outflows: height, amount in XCH, destination label (or "unknown" if unlabelled). Skip internal rotations between custody wallets.`,
19
+ ``,
20
+ `Keep it tight. Plain prose, no tables unless asked.`,
21
+ ].join('\n');
22
+ return {
23
+ messages: [{ role: 'user', content: { type: 'text', text } }],
24
+ };
25
+ });
26
+ }
27
+ //# sourceMappingURL=prefarm-summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefarm-summary.js","sourceRoot":"","sources":["../../src/prompts/prefarm-summary.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,cAAc,CACnB,iBAAiB,EACjB;QACE,KAAK,EAAE,gCAAgC;QACvC,WAAW,EACT,kHAAkH;QACpH,UAAU,EAAE,EAAE;KACf,EACD,GAAG,EAAE;QACH,MAAM,IAAI,GAAG;YACX,2EAA2E;YAC3E,EAAE;YACF,QAAQ;YACR,iFAAiF;YACjF,oFAAoF;YACpF,0EAA0E;YAC1E,EAAE;YACF,yBAAyB;YACzB,iNAAiN;YACjN,+GAA+G;YAC/G,8IAA8I;YAC9I,EAAE;YACF,qDAAqD;SACtD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO;YACL,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;SAC9D,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { z } from 'zod';
2
+ export declare const currenciesSchema: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
3
+ export declare const mojoAmountSchema: z.ZodString;
@@ -0,0 +1,16 @@
1
+ import { z } from 'zod';
2
+ export const currenciesSchema = z
3
+ .array(z
4
+ .string()
5
+ .min(2)
6
+ .max(10)
7
+ .regex(/^[a-zA-Z]+$/))
8
+ .min(1)
9
+ .max(20)
10
+ .default(['usd'])
11
+ .describe("Fiat or crypto currency codes accepted by CoinGecko (e.g. 'usd', 'eur', 'gbp', 'jpy', 'btc', 'eth'). Case-insensitive. Defaults to ['usd'].");
12
+ export const mojoAmountSchema = z
13
+ .string()
14
+ .regex(/^\d+$/)
15
+ .describe('Non-negative integer mojo amount as a decimal string. 1 XCH = 1,000,000,000,000 mojo. Convert XCH amounts to mojo before passing.');
16
+ //# sourceMappingURL=price.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price.js","sourceRoot":"","sources":["../../src/schemas/price.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC;KAC9B,KAAK,CACJ,CAAC;KACE,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,EAAE,CAAC;KACP,KAAK,CAAC,aAAa,CAAC,CACxB;KACA,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,EAAE,CAAC;KACP,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;KAChB,QAAQ,CACP,6IAA6I,CAC9I,CAAC;AAEJ,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC;KAC9B,MAAM,EAAE;KACR,KAAK,CAAC,OAAO,CAAC;KACd,QAAQ,CACP,mIAAmI,CACpI,CAAC"}
package/dist/server.js CHANGED
@@ -12,15 +12,23 @@ import { register as registerGetCoinByName } from './tools/coins/get-coin-by-nam
12
12
  import { register as registerCalculateCoinName } from './tools/coins/calculate-coin-name.js';
13
13
  import { register as registerAddressToPuzzleHash } from './tools/addresses/address-to-puzzle-hash.js';
14
14
  import { register as registerPuzzleHashToAddress } from './tools/addresses/puzzle-hash-to-address.js';
15
+ import { register as registerGetXchPrice } from './tools/price/get-xch-price.js';
16
+ import { register as registerConvertXchToFiat } from './tools/price/convert-xch-to-fiat.js';
17
+ import { register as registerGetPrefarmStatus } from './tools/prefarm/get-prefarm-status.js';
18
+ import { register as registerGetPrefarmSpends } from './tools/prefarm/get-prefarm-spends.js';
19
+ import { register as registerListPrefarmAddresses } from './tools/prefarm/list-prefarm-addresses.js';
15
20
  import { register as registerNetworkStatusPrompt } from './prompts/network-status.js';
16
21
  import { register as registerAddressSummaryPrompt } from './prompts/address-summary.js';
17
22
  import { register as registerBlockSummaryPrompt } from './prompts/block-summary.js';
23
+ import { register as registerPrefarmSummaryPrompt } from './prompts/prefarm-summary.js';
18
24
  export function createServer() {
19
25
  const server = new McpServer({ name: 'chia-explorer', version: VERSION }, {
20
- instructions: 'chia-explorer answers questions about the Chia blockchain via the public coinset.org API. ' +
26
+ instructions: 'chia-explorer answers questions about the Chia blockchain via the public coinset.org API, ' +
27
+ 'plus XCH spot price and fiat conversion via the public CoinGecko API. ' +
21
28
  'Read-only: no signing, no key material, no push_tx. ' +
22
- "All tools accept an optional `network: 'mainnet' | 'testnet11'` argument; mainnet is the default. " +
23
- 'When an address is provided, the network is auto-detected from the prefix (xch / txch).',
29
+ "Blockchain tools accept an optional `network: 'mainnet' | 'testnet11'` argument; mainnet is the default. " +
30
+ 'When an address is provided, the network is auto-detected from the prefix (xch / txch). ' +
31
+ 'Price tools take no network argument.',
24
32
  });
25
33
  registerGetBlockchainState(server);
26
34
  registerGetNetspace(server);
@@ -34,9 +42,15 @@ export function createServer() {
34
42
  registerCalculateCoinName(server);
35
43
  registerAddressToPuzzleHash(server);
36
44
  registerPuzzleHashToAddress(server);
45
+ registerGetXchPrice(server);
46
+ registerConvertXchToFiat(server);
47
+ registerGetPrefarmStatus(server);
48
+ registerGetPrefarmSpends(server);
49
+ registerListPrefarmAddresses(server);
37
50
  registerNetworkStatusPrompt(server);
38
51
  registerAddressSummaryPrompt(server);
39
52
  registerBlockSummaryPrompt(server);
53
+ registerPrefarmSummaryPrompt(server);
40
54
  return server;
41
55
  }
42
56
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,QAAQ,IAAI,0BAA0B,EAAE,MAAM,4CAA4C,CAAC;AACpG,OAAO,EAAE,QAAQ,IAAI,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,EAAE,QAAQ,IAAI,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC1F,OAAO,EAAE,QAAQ,IAAI,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACjG,OAAO,EAAE,QAAQ,IAAI,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AAC7F,OAAO,EAAE,QAAQ,IAAI,8BAA8B,EAAE,MAAM,gDAAgD,CAAC;AAE5G,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,QAAQ,IAAI,kCAAkC,EAAE,MAAM,kDAAkD,CAAC;AAClH,OAAO,EAAE,QAAQ,IAAI,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,EAAE,QAAQ,IAAI,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAE7F,OAAO,EAAE,QAAQ,IAAI,2BAA2B,EAAE,MAAM,6CAA6C,CAAC;AACtG,OAAO,EAAE,QAAQ,IAAI,2BAA2B,EAAE,MAAM,6CAA6C,CAAC;AAEtG,OAAO,EAAE,QAAQ,IAAI,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAE,QAAQ,IAAI,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AACxF,OAAO,EAAE,QAAQ,IAAI,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAEpF,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,EAC3C;QACE,YAAY,EACV,4FAA4F;YAC5F,sDAAsD;YACtD,oGAAoG;YACpG,yFAAyF;KAC5F,CACF,CAAC;IAEF,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,8BAA8B,CAAC,MAAM,CAAC,CAAC;IAEvC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,kCAAkC,CAAC,MAAM,CAAC,CAAC;IAC3C,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAElC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAEpC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACrC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IAEnC,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,QAAQ,IAAI,0BAA0B,EAAE,MAAM,4CAA4C,CAAC;AACpG,OAAO,EAAE,QAAQ,IAAI,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,EAAE,QAAQ,IAAI,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC1F,OAAO,EAAE,QAAQ,IAAI,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACjG,OAAO,EAAE,QAAQ,IAAI,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AAC7F,OAAO,EAAE,QAAQ,IAAI,8BAA8B,EAAE,MAAM,gDAAgD,CAAC;AAE5G,OAAO,EAAE,QAAQ,IAAI,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,QAAQ,IAAI,kCAAkC,EAAE,MAAM,kDAAkD,CAAC;AAClH,OAAO,EAAE,QAAQ,IAAI,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AACtF,OAAO,EAAE,QAAQ,IAAI,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAE7F,OAAO,EAAE,QAAQ,IAAI,2BAA2B,EAAE,MAAM,6CAA6C,CAAC;AACtG,OAAO,EAAE,QAAQ,IAAI,2BAA2B,EAAE,MAAM,6CAA6C,CAAC;AAEtG,OAAO,EAAE,QAAQ,IAAI,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACjF,OAAO,EAAE,QAAQ,IAAI,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAE5F,OAAO,EAAE,QAAQ,IAAI,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAC7F,OAAO,EAAE,QAAQ,IAAI,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AAC7F,OAAO,EAAE,QAAQ,IAAI,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AAErG,OAAO,EAAE,QAAQ,IAAI,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAE,QAAQ,IAAI,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AACxF,OAAO,EAAE,QAAQ,IAAI,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,QAAQ,IAAI,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAExF,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,EAC3C;QACE,YAAY,EACV,4FAA4F;YAC5F,wEAAwE;YACxE,sDAAsD;YACtD,2GAA2G;YAC3G,0FAA0F;YAC1F,uCAAuC;KAC1C,CACF,CAAC;IAEF,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,8BAA8B,CAAC,MAAM,CAAC,CAAC;IAEvC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,kCAAkC,CAAC,MAAM,CAAC,CAAC;IAC3C,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAElC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAEpC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAEjC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IAErC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IACrC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,4BAA4B,CAAC,MAAM,CAAC,CAAC;IAErC,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ import { mojoToXch } from '../../chia/amounts.js';
3
+ import { getAgent } from '../../coinset/agent.js';
4
+ import { PREFARM_WALLETS, getWalletById, isPopulated } from '../../prefarm/registry.js';
5
+ import { getWalletSpends } from '../../prefarm/spends.js';
6
+ import { errorText, jsonText } from '../shared/response.js';
7
+ const WALLET_IDS = [
8
+ 'us-cold',
9
+ 'us-warm',
10
+ 'ch-cold',
11
+ 'ch-warm',
12
+ ];
13
+ export function register(server) {
14
+ server.tool('get_prefarm_spends', 'List outflows from the Chia strategic reserve. For each spent coin: the source wallet, the destination addresses (labelled when they map to a known partner / market maker / exchange), and amounts. Internal rotations between custody wallets are flagged and excluded from total outflow. Mainnet only.', {
15
+ wallet_id: z
16
+ .enum(WALLET_IDS)
17
+ .optional()
18
+ .describe('Restrict to one wallet. Omit to query all four.'),
19
+ limit: z
20
+ .number()
21
+ .int()
22
+ .positive()
23
+ .max(500)
24
+ .optional()
25
+ .describe('Maximum spends to return, sorted newest first. Default 50.'),
26
+ since_height: z
27
+ .number()
28
+ .int()
29
+ .nonnegative()
30
+ .optional()
31
+ .describe('Only include spends at or after this block height.'),
32
+ }, async ({ wallet_id, limit, since_height }) => {
33
+ try {
34
+ const targets = wallet_id
35
+ ? (() => {
36
+ const w = getWalletById(wallet_id);
37
+ if (!w)
38
+ throw new Error(`unknown wallet_id: ${wallet_id}`);
39
+ return [w];
40
+ })()
41
+ : [...PREFARM_WALLETS];
42
+ const populated = targets.filter(isPopulated);
43
+ const pending = targets.filter((w) => !isPopulated(w)).map((w) => w.id);
44
+ const agent = getAgent('mainnet');
45
+ const grouped = await Promise.all(populated.map((w) => getWalletSpends(agent, w, {
46
+ ...(since_height !== undefined ? { sinceHeight: since_height } : {}),
47
+ })));
48
+ const all = grouped.flat();
49
+ all.sort((a, b) => b.spent_height - a.spent_height);
50
+ const cap = limit ?? 50;
51
+ const trimmed = all.slice(0, cap);
52
+ const totalOutflow = all.reduce((acc, s) => acc + BigInt(s.outflow_mojo), 0n);
53
+ return jsonText({
54
+ spends: trimmed,
55
+ total_spend_count: all.length,
56
+ returned_count: trimmed.length,
57
+ total_outflow_mojo: totalOutflow.toString(),
58
+ total_outflow_xch: mojoToXch(totalOutflow),
59
+ wallets_queried: populated.map((w) => w.id),
60
+ wallets_pending: pending,
61
+ });
62
+ }
63
+ catch (err) {
64
+ return errorText(err);
65
+ }
66
+ });
67
+ }
68
+ //# sourceMappingURL=get-prefarm-spends.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-prefarm-spends.js","sourceRoot":"","sources":["../../../src/tools/prefarm/get-prefarm-spends.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,72 @@
1
+ import { mojoToXch, toBigInt } from '../../chia/amounts.js';
2
+ import { getAgent } from '../../coinset/agent.js';
3
+ import { fetchCoinRecordsByPuzzleHash } from '../../coinset/pagination.js';
4
+ import { PREFARM_WALLETS, TOTAL_PREFARM_ALLOCATION_MOJO, isPopulated, } from '../../prefarm/registry.js';
5
+ import { errorText, jsonText } from '../shared/response.js';
6
+ async function statusForWallet(wallet) {
7
+ const base = {
8
+ id: wallet.id,
9
+ label: wallet.label,
10
+ region: wallet.region,
11
+ temperature: wallet.temperature,
12
+ addresses: wallet.addresses,
13
+ puzzle_hashes: wallet.puzzleHashes,
14
+ };
15
+ if (!isPopulated(wallet)) {
16
+ return {
17
+ ...base,
18
+ balance_mojo: null,
19
+ balance_xch: null,
20
+ unspent_coin_count: null,
21
+ pending: true,
22
+ };
23
+ }
24
+ const agent = getAgent('mainnet');
25
+ const groups = await Promise.all(wallet.puzzleHashes.map((ph) => fetchCoinRecordsByPuzzleHash(agent, ph, { includeSpent: false })));
26
+ let balance = 0n;
27
+ let coinCount = 0;
28
+ for (const records of groups) {
29
+ coinCount += records.length;
30
+ for (const r of records)
31
+ balance += toBigInt(r.coin.amount);
32
+ }
33
+ return {
34
+ ...base,
35
+ balance_mojo: balance.toString(),
36
+ balance_xch: mojoToXch(balance),
37
+ unspent_coin_count: coinCount,
38
+ pending: false,
39
+ };
40
+ }
41
+ export function register(server) {
42
+ server.tool('get_prefarm_status', 'Aggregate status of the Chia strategic reserve (21M XCH across four custody wallets: US/CH × cold/warm). Per-wallet balances are read live from coinset.org; the only hardcoded amount is the 21M XCH genesis total. Mainnet only.', {}, async () => {
43
+ try {
44
+ const wallets = await Promise.all(PREFARM_WALLETS.map(statusForWallet));
45
+ const trackedBalance = wallets
46
+ .filter((w) => !w.pending)
47
+ .reduce((acc, w) => acc + BigInt(w.balance_mojo ?? '0'), 0n);
48
+ const walletsPending = wallets.filter((w) => w.pending).length;
49
+ const totalAllocation = TOTAL_PREFARM_ALLOCATION_MOJO;
50
+ const trackedSpent = totalAllocation - trackedBalance;
51
+ const spentPct = walletsPending > 0 ? null : Number((trackedSpent * 10000n) / totalAllocation) / 100;
52
+ return jsonText({
53
+ wallets,
54
+ totals: {
55
+ allocation_mojo: totalAllocation.toString(),
56
+ allocation_xch: mojoToXch(totalAllocation),
57
+ tracked_balance_mojo: trackedBalance.toString(),
58
+ tracked_balance_xch: mojoToXch(trackedBalance),
59
+ tracked_spent_mojo: trackedSpent.toString(),
60
+ tracked_spent_xch: mojoToXch(trackedSpent),
61
+ tracked_spent_pct: spentPct,
62
+ },
63
+ wallets_configured: wallets.filter((w) => !w.pending).length,
64
+ wallets_pending: walletsPending,
65
+ });
66
+ }
67
+ catch (err) {
68
+ return errorText(err);
69
+ }
70
+ });
71
+ }
72
+ //# sourceMappingURL=get-prefarm-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-prefarm-status.js","sourceRoot":"","sources":["../../../src/tools/prefarm/get-prefarm-status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,33 @@
1
+ import { mojoToXch } from '../../chia/amounts.js';
2
+ import { KNOWN_DESTINATIONS, PREFARM_WALLETS, TOTAL_PREFARM_ALLOCATION_MOJO, } from '../../prefarm/registry.js';
3
+ import { jsonText } from '../shared/response.js';
4
+ export function register(server) {
5
+ server.tool('list_prefarm_addresses', 'Return the hardcoded registry of Chia strategic-reserve custody wallets and labelled destination addresses (partners, market makers, exchanges). Identities only — balances are not returned here; call `get_prefarm_status` for live amounts. Pure local data, no network call.', {}, async () => {
6
+ const wallets = PREFARM_WALLETS.map((w) => ({
7
+ id: w.id,
8
+ label: w.label,
9
+ region: w.region,
10
+ temperature: w.temperature,
11
+ addresses: w.addresses,
12
+ puzzle_hashes: w.puzzleHashes,
13
+ pending: w.addresses.length === 0,
14
+ }));
15
+ const destinations = KNOWN_DESTINATIONS.map((d) => ({
16
+ address: d.address,
17
+ puzzle_hash: d.puzzleHash,
18
+ entity: d.entity,
19
+ label: d.label,
20
+ category: d.category,
21
+ }));
22
+ return jsonText({
23
+ wallets,
24
+ destinations,
25
+ total_allocation_mojo: TOTAL_PREFARM_ALLOCATION_MOJO.toString(),
26
+ total_allocation_xch: mojoToXch(TOTAL_PREFARM_ALLOCATION_MOJO),
27
+ wallets_configured: wallets.filter((w) => !w.pending).length,
28
+ wallets_pending: wallets.filter((w) => w.pending).length,
29
+ destinations_configured: destinations.length,
30
+ });
31
+ });
32
+ }
33
+ //# sourceMappingURL=list-prefarm-addresses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-prefarm-addresses.js","sourceRoot":"","sources":["../../../src/tools/prefarm/list-prefarm-addresses.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,6BAA6B,GAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,wBAAwB,EACxB,kRAAkR,EAClR,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC1C,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,aAAa,EAAE,CAAC,CAAC,YAAY;YAC7B,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;SAClC,CAAC,CAAC,CAAC;QACJ,MAAM,YAAY,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClD,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,WAAW,EAAE,CAAC,CAAC,UAAU;YACzB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACrB,CAAC,CAAC,CAAC;QACJ,OAAO,QAAQ,CAAC;YACd,OAAO;YACP,YAAY;YACZ,qBAAqB,EAAE,6BAA6B,CAAC,QAAQ,EAAE;YAC/D,oBAAoB,EAAE,SAAS,CAAC,6BAA6B,CAAC;YAC9D,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM;YAC5D,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM;YACxD,uBAAuB,EAAE,YAAY,CAAC,MAAM;SAC7C,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,42 @@
1
+ import { getXchPrices } from '../../coingecko/index.js';
2
+ import { mojoToXch, toBigInt } from '../../chia/amounts.js';
3
+ import { currenciesSchema, mojoAmountSchema } from '../../schemas/price.js';
4
+ import { errorText, jsonText } from '../shared/response.js';
5
+ function normalize(currencies) {
6
+ return Array.from(new Set(currencies.map((c) => c.toLowerCase())));
7
+ }
8
+ export function register(server) {
9
+ server.tool('convert_xch_to_fiat', 'Convert a mojo amount to its current fiat (or other CoinGecko-supported currency) value. 1 XCH = 1,000,000,000,000 mojo — convert XCH to mojo before calling. Prices come from CoinGecko (cached 60s). Returned values use JS floating-point; precise to far more decimals than any realistic balance.', {
10
+ mojo: mojoAmountSchema,
11
+ currencies: currenciesSchema,
12
+ }, async ({ mojo, currencies }) => {
13
+ try {
14
+ const mojoBig = toBigInt(mojo);
15
+ if (mojoBig < 0n)
16
+ throw new Error('mojo must be non-negative');
17
+ const xchString = mojoToXch(mojoBig);
18
+ const xchNumber = Number(xchString);
19
+ const normalized = normalize(currencies);
20
+ const prices = await getXchPrices(normalized);
21
+ const values = {};
22
+ for (const currency of normalized) {
23
+ const price = prices[currency];
24
+ if (price === undefined)
25
+ throw new Error(`missing price for ${currency}`);
26
+ values[currency] = xchNumber * price;
27
+ }
28
+ return jsonText({
29
+ source: 'coingecko',
30
+ mojo: mojoBig.toString(),
31
+ amount_xch: xchString,
32
+ prices_per_xch: prices,
33
+ values,
34
+ fetched_at: new Date().toISOString(),
35
+ });
36
+ }
37
+ catch (err) {
38
+ return errorText(err);
39
+ }
40
+ });
41
+ }
42
+ //# sourceMappingURL=convert-xch-to-fiat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert-xch-to-fiat.js","sourceRoot":"","sources":["../../../src/tools/price/convert-xch-to-fiat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,SAAS,SAAS,CAAC,UAAoB;IACrC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,wSAAwS,EACxS;QACE,IAAI,EAAE,gBAAgB;QACtB,UAAU,EAAE,gBAAgB;KAC7B,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,OAAO,GAAG,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC/D,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;YAEpC,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;YAE9C,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC/B,IAAI,KAAK,KAAK,SAAS;oBAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;gBAC1E,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,KAAK,CAAC;YACvC,CAAC;YAED,OAAO,QAAQ,CAAC;gBACd,MAAM,EAAE,WAAW;gBACnB,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE;gBACxB,UAAU,EAAE,SAAS;gBACrB,cAAc,EAAE,MAAM;gBACtB,MAAM;gBACN,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACrC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function register(server: McpServer): void;
@@ -0,0 +1,26 @@
1
+ import { getXchPrices } from '../../coingecko/index.js';
2
+ import { currenciesSchema } from '../../schemas/price.js';
3
+ import { errorText, jsonText } from '../shared/response.js';
4
+ function normalize(currencies) {
5
+ return Array.from(new Set(currencies.map((c) => c.toLowerCase())));
6
+ }
7
+ export function register(server) {
8
+ server.tool('get_xch_price', "Current XCH spot price via CoinGecko. Accepts any currency CoinGecko supports (e.g. 'usd', 'eur', 'gbp', 'jpy', 'btc', 'eth'); defaults to ['usd']. Free-tier API is rate-limited; results are cached for 60 seconds.", {
9
+ currencies: currenciesSchema,
10
+ }, async ({ currencies }) => {
11
+ try {
12
+ const normalized = normalize(currencies);
13
+ const prices = await getXchPrices(normalized);
14
+ return jsonText({
15
+ source: 'coingecko',
16
+ asset: 'chia',
17
+ prices,
18
+ fetched_at: new Date().toISOString(),
19
+ });
20
+ }
21
+ catch (err) {
22
+ return errorText(err);
23
+ }
24
+ });
25
+ }
26
+ //# sourceMappingURL=get-xch-price.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-xch-price.js","sourceRoot":"","sources":["../../../src/tools/price/get-xch-price.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,SAAS,SAAS,CAAC,UAAoB;IACrC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAiB;IACxC,MAAM,CAAC,IAAI,CACT,eAAe,EACf,uNAAuN,EACvN;QACE,UAAU,EAAE,gBAAgB;KAC7B,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;YAC9C,OAAO,QAAQ,CAAC;gBACd,MAAM,EAAE,WAAW;gBACnB,KAAK,EAAE,MAAM;gBACb,MAAM;gBACN,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACrC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chia-explorer",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "MCP server that answers questions about the Chia blockchain via the public coinset.org API",
5
5
  "mcpName": "io.github.Spacetime-Technology/chia-explorer",
6
6
  "type": "module",