@tabai/sdk 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,23 +1,59 @@
1
- SPDX-License-Identifier: MIT
2
-
3
- MIT License
4
-
5
- Copyright (c) 2026 Tab Project Contributors
6
-
7
- Permission is hereby granted, free of charge, to any person obtaining a copy
8
- of this software and associated documentation files (the "Software"), to deal
9
- in the Software without restriction, including without limitation the rights
10
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- copies of the Software, and to permit persons to whom the Software is
12
- furnished to do so, subject to the following conditions:
13
-
14
- The above copyright notice and this permission notice shall be included in all
15
- copies or substantial portions of the Software.
16
-
17
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
- SOFTWARE.
1
+ Tab Source-Available License
2
+
3
+ Copyright (c) 2026 Emad Qureshi. All rights reserved.
4
+
5
+ This repository is published so that it can be read, run and evaluated.
6
+ It is not open source, and no licence is granted except as written below.
7
+
8
+ 1. What you may do without asking
9
+
10
+ You may view, clone, build and run this software, locally or against its
11
+ public deployments, for the sole purpose of evaluating it. Evaluating
12
+ includes judging it in a competition, reviewing it, and auditing it. You
13
+ may make the copies that such an evaluation needs, and must delete them
14
+ once it is over.
15
+
16
+ 2. What needs written permission first
17
+
18
+ Any other use needs prior written permission from the copyright holder.
19
+ That includes, without limitation: using the software in production or
20
+ for any commercial purpose; operating your own deployment of it;
21
+ modifying it for anything beyond an evaluation; creating derivative
22
+ works; and redistributing, publishing, sublicensing or selling it or any
23
+ part of it.
24
+
25
+ To ask for permission, contact Emad Qureshi through GitHub at
26
+ https://github.com/EmadQureshiKhi. Permission counts only when it is
27
+ given in writing.
28
+
29
+ 3. What stays under its own licence
30
+
31
+ (a) Solidity source files in this repository that carry the header
32
+ `SPDX-License-Identifier: MIT` remain available under the MIT
33
+ License. They include the contracts deployed and verified on Monad,
34
+ whose published source must match what is on chain.
35
+ (b) Versions of `@tabai/sdk` up to and including 0.2.0, and of
36
+ `@tabai/agent-wallet-plugin` up to and including 0.1.1, were
37
+ published to npm under the MIT License and remain under it. Later
38
+ versions are released under this licence.
39
+ (c) Third-party code, including everything under
40
+ `packages/contracts/lib` and `apps/registry/vendor`, remains under
41
+ the licence its authors chose.
42
+
43
+ 4. Contributions
44
+
45
+ By submitting a contribution to this repository, you agree that the
46
+ copyright holder may use, modify and license it under any terms,
47
+ including this licence.
48
+
49
+ 5. No warranty, no trademark
50
+
51
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
52
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
53
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
54
+ NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR
55
+ OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
56
+ OR ITS USE.
57
+
58
+ This licence grants no right to use the name "Tab", its logo or any
59
+ other mark of the copyright holder.
package/README.md CHANGED
@@ -142,7 +142,7 @@ export default {
142
142
  {
143
143
  serviceId: "0x7461622e64656d6f000000000000000000000000000000000000000000000000",
144
144
  name: "tab.demo",
145
- endpoint: "http://localhost:8788",
145
+ endpoint: "https://gateway-testnet-production-a657.up.railway.app",
146
146
  },
147
147
  ],
148
148
 
@@ -187,7 +187,8 @@ The key is read at the moment a Settlement is built, and never from this file. `
187
187
  | `MONAD_RPC_URL` | every read. The MCP server and `doctor` need only this |
188
188
  | `MONAD_CHAIN_ID` | `143` for Mainnet, `10143` for Testnet. Defaults to Testnet |
189
189
  | `TAB_BOOK_ADDRESS`, `TAB_SETTLEMENT_ADDRESS`, `SERVICE_REGISTRY_ADDRESS`, `BOND_ADDRESS` | resolving credit, Services and Bond |
190
- | `NEXT_PUBLIC_REGISTRY_API_URL` | the Service directory and an agent's history, if you use the read API rather than the chain |
190
+ | `NEXT_PUBLIC_REGISTRY_API_URL` | the Service directory and an agent's history. Defaults to the project's hosted registry for the chosen network |
191
+ | `TAB_HOSTED_DEFAULTS` | `off` stops the hosted registry and demo Service from filling in what you did not configure |
191
192
  | `AGENT_PRIVATE_KEY` | broadcasting a Settlement, and nothing else. Never written to a configuration file |
192
193
 
193
194
  ---
@@ -390,12 +391,21 @@ A Settlement is final when its block is. **Nothing in an agent's request path wa
390
391
 
391
392
  ## Status
392
393
 
393
- The contracts are live on Mainnet and Testnet, and everything in this package runs against them today.
394
- A hosted read API, a public demo Service endpoint and a Dashboard are coming soon on Monad.
395
- Until then, `tab_discover` and `tab_status` need a Tab registry you point `registryUrl` at, and a Service's `endpoint` is wherever that Service runs.
394
+ Live on Monad Mainnet and Monad Testnet.
395
+
396
+ | | Mainnet (`143`) | Testnet (`10143`) |
397
+ | --- | --- | --- |
398
+ | Registry read API | `https://registry-mainnet-production.up.railway.app` | `https://registry-testnet-production.up.railway.app` |
399
+ | Demo Service `tab.demo` | `https://gateway-mainnet-production.up.railway.app` | `https://gateway-testnet-production-a657.up.railway.app` |
400
+
401
+ **With nothing configured, this package uses them.** `tab_discover` and `tab_status` read the hosted registry for the chosen network, and `tab_call` can reach the demo Service, so a fresh `npx -y @tabai/sdk connect` works before you set anything.
402
+ Anything you configure wins, and `TAB_HOSTED_DEFAULTS=off` switches the defaults off entirely.
403
+ They are exported as `TAB_HOSTED`.
404
+
405
+ The Dashboard, which shows either network, is at `https://trytabai.vercel.app`, and the documentation at `https://trytabai-docs.vercel.app`.
396
406
 
397
407
  ---
398
408
 
399
409
  ## Built by
400
410
 
401
- Emad Qureshi. MIT licensed.
411
+ Emad Qureshi. Source-available: free to read, run and evaluate, and any other use needs permission. Versions up to 0.2.0 were published under MIT and stay under it. See LICENSE.
@@ -9,7 +9,7 @@
9
9
  * Addresses of Tab's own contracts are deployment output and live in
10
10
  * `deployments.json`, never here.
11
11
  */
12
- import type { Address } from "./hex.js";
12
+ import type { Address, Bytes32 } from "./hex.js";
13
13
  /** A Monad network a Tab deployment can target. */
14
14
  export interface ChainDescriptor {
15
15
  readonly name: string;
@@ -93,6 +93,46 @@ export declare const TESTNET_ASSETS: {
93
93
  export declare const PERMIT2_ADDRESS: "0x000000000022D473030F116dDEE9F6B43aC78BA3";
94
94
  /** The x402 facilitator that verifies and settles `exact` payments on Monad. */
95
95
  export declare const X402_FACILITATOR_URL: "https://x402-facilitator.molandak.org";
96
+ /** A Service this project hosts, and where it is reached. */
97
+ export interface HostedService {
98
+ readonly serviceId: Bytes32;
99
+ readonly name: string;
100
+ readonly endpoint: string;
101
+ }
102
+ /** What this project hosts on one network: the read API and the demo Service. */
103
+ export interface TabHosted {
104
+ readonly registryUrl: string;
105
+ readonly demoService: HostedService;
106
+ /** The test token the hosted deployment prices in, where it ships one: `mUSDC`, 6 decimals. */
107
+ readonly testAsset?: Address;
108
+ }
109
+ /**
110
+ * The read API and the demo Service this project runs, per network.
111
+ *
112
+ * Defaults, never authority: the chain is the authority on every figure, and a
113
+ * configured `registryUrl` or `services` entry always wins over these. They are
114
+ * here so that a fresh install can discover and call something before its owner
115
+ * has configured anything, which is the first thing anyone tries.
116
+ */
117
+ export declare const TAB_HOSTED: {
118
+ readonly 143: {
119
+ readonly registryUrl: "https://registry-mainnet-production.up.railway.app";
120
+ readonly demoService: {
121
+ readonly serviceId: "0x7461622e64656d6f000000000000000000000000000000000000000000000000";
122
+ readonly name: "tab.demo";
123
+ readonly endpoint: "https://gateway-mainnet-production.up.railway.app";
124
+ };
125
+ };
126
+ readonly 10143: {
127
+ readonly registryUrl: "https://registry-testnet-production.up.railway.app";
128
+ readonly demoService: {
129
+ readonly serviceId: "0x7461622e64656d6f000000000000000000000000000000000000000000000000";
130
+ readonly name: "tab.demo";
131
+ readonly endpoint: "https://gateway-testnet-production-a657.up.railway.app";
132
+ };
133
+ readonly testAsset: "0x480209747417f5c830fDA188a9b9AcFa70Bc4083";
134
+ };
135
+ };
96
136
  /** The two ERC-8004 registries a Tab deployment reads and writes. */
97
137
  export interface Erc8004Registries {
98
138
  /** Agent identities: an ERC-721 whose token id is the agentId and whose URI is the registration file. */
@@ -1 +1 @@
1
- {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../src/chains.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oCAAoC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,aAAa;;;;;CAKU,CAAC;AAErC,eAAO,MAAM,aAAa;;;;;;CAMU,CAAC;AAErC,eAAO,MAAM,MAAM;;;;;;;;;;;;;;CAGT,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,MAAM,CAAC;AAE/C,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,GAAG,SAAS,CAG9E;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjG;AAED,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,8CAA8C;AAC9C,eAAO,MAAM,cAAc;;;;;;;;;;;CAWmC,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;;;;;CAMmC,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,eAAe,8CAA0E,CAAC;AAEvG,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,EAAG,uCAAgD,CAAC;AAErF,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,yGAAyG;IACzG,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB;;;;;;;;;CASuC,CAAC;AAEvE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAG5F;AAED,eAAO,MAAM,mBAAmB,EAAG,4CAAqD,CAAC;AAEzF,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOxE"}
1
+ {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../src/chains.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEjD,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oCAAoC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,aAAa;;;;;CAKU,CAAC;AAErC,eAAO,MAAM,aAAa;;;;;;CAMU,CAAC;AAErC,eAAO,MAAM,MAAM;;;;;;;;;;;;;;CAGT,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,MAAM,CAAC;AAE/C,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,GAAG,SAAS,CAG9E;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjG;AAED,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,8CAA8C;AAC9C,eAAO,MAAM,cAAc;;;;;;;;;;;CAWmC,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;;;;;CAMmC,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,eAAe,8CAA0E,CAAC;AAEvG,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,EAAG,uCAAgD,CAAC;AAErF,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC;IACpC,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;CAkBuC,CAAC;AAE/D,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,yGAAyG;IACzG,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB;;;;;;;;;CASuC,CAAC;AAEvE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAG5F;AAED,eAAO,MAAM,mBAAmB,EAAG,4CAAqD,CAAC;AAEzF,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOxE"}
@@ -61,6 +61,33 @@ export const TESTNET_ASSETS = {
61
61
  export const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
62
62
  /** The x402 facilitator that verifies and settles `exact` payments on Monad. */
63
63
  export const X402_FACILITATOR_URL = "https://x402-facilitator.molandak.org";
64
+ /**
65
+ * The read API and the demo Service this project runs, per network.
66
+ *
67
+ * Defaults, never authority: the chain is the authority on every figure, and a
68
+ * configured `registryUrl` or `services` entry always wins over these. They are
69
+ * here so that a fresh install can discover and call something before its owner
70
+ * has configured anything, which is the first thing anyone tries.
71
+ */
72
+ export const TAB_HOSTED = {
73
+ [MONAD_MAINNET.chainId]: {
74
+ registryUrl: "https://registry-mainnet-production.up.railway.app",
75
+ demoService: {
76
+ serviceId: "0x7461622e64656d6f000000000000000000000000000000000000000000000000",
77
+ name: "tab.demo",
78
+ endpoint: "https://gateway-mainnet-production.up.railway.app",
79
+ },
80
+ },
81
+ [MONAD_TESTNET.chainId]: {
82
+ registryUrl: "https://registry-testnet-production.up.railway.app",
83
+ demoService: {
84
+ serviceId: "0x7461622e64656d6f000000000000000000000000000000000000000000000000",
85
+ name: "tab.demo",
86
+ endpoint: "https://gateway-testnet-production-a657.up.railway.app",
87
+ },
88
+ testAsset: "0x480209747417f5c830fDA188a9b9AcFa70Bc4083",
89
+ },
90
+ };
64
91
  /** The canonical ERC-8004 registries, keyed by chain id. */
65
92
  export const ERC8004_REGISTRIES = {
66
93
  [MONAD_MAINNET.chainId]: {
@@ -1 +1 @@
1
- {"version":3,"file":"chains.js","sourceRoot":"","sources":["../src/chains.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Chain and Asset constants for Tab on Monad.\n *\n * Tab runs on one chain. The Agent's payment and the ledger entry happen in the\n * same Monad transaction, so nothing in the system refers to any other chain.\n * What this module carries is which Monad network a deployment targets and\n * which Assets it settles in.\n *\n * Addresses of Tab's own contracts are deployment output and live in\n * `deployments.json`, never here.\n */\nimport type { Address } from \"./hex.js\";\n\n/** A Monad network a Tab deployment can target. */\nexport interface ChainDescriptor {\n readonly name: string;\n readonly chainId: number;\n readonly rpcUrl: string;\n readonly explorerUrl: string;\n /** The MON faucet, testnet only. */\n readonly faucetUrl?: string;\n}\n\nexport const MONAD_MAINNET = {\n name: \"Monad Mainnet\",\n chainId: 143,\n rpcUrl: \"https://rpc.monad.xyz\",\n explorerUrl: \"https://monadvision.com\",\n} as const satisfies ChainDescriptor;\n\nexport const MONAD_TESTNET = {\n name: \"Monad Testnet\",\n chainId: 10143,\n rpcUrl: \"https://testnet-rpc.monad.xyz\",\n explorerUrl: \"https://testnet.monadvision.com\",\n faucetUrl: \"https://faucet.monad.xyz\",\n} as const satisfies ChainDescriptor;\n\nexport const CHAINS = {\n [MONAD_MAINNET.chainId]: MONAD_MAINNET,\n [MONAD_TESTNET.chainId]: MONAD_TESTNET,\n} as const;\n\nexport type MonadChainId = keyof typeof CHAINS;\n\nexport function isMonadChainId(value: unknown): value is MonadChainId {\n return value === MONAD_MAINNET.chainId || value === MONAD_TESTNET.chainId;\n}\n\nexport function chainFor(chainId: number | bigint): ChainDescriptor | undefined {\n const narrowed = typeof chainId === \"bigint\" ? Number(chainId) : chainId;\n return isMonadChainId(narrowed) ? CHAINS[narrowed] : undefined;\n}\n\n/** Link to an address or a transaction on the explorer for a chain. */\nexport function explorerLink(chain: ChainDescriptor, kind: \"address\" | \"tx\", hash: string): string {\n return `${chain.explorerUrl}/${kind}/${hash}`;\n}\n\n/** A stablecoin Tab settles in. Amounts everywhere are integer base units. */\nexport interface AssetDescriptor {\n readonly symbol: string;\n readonly decimals: number;\n readonly address: Address;\n}\n\n/** Canonical stablecoins on Monad Mainnet. */\nexport const MAINNET_ASSETS = {\n USDC: {\n symbol: \"USDC\",\n decimals: 6,\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n },\n AUSD: {\n symbol: \"AUSD\",\n decimals: 6,\n address: \"0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a\",\n },\n} as const satisfies Readonly<Record<string, AssetDescriptor>>;\n\n/**\n * Stablecoins on Monad Testnet. `USDC` is Circle's own testnet deployment\n * (`name` \"USDC\", EIP-712 version \"2\", 20 USDC per address every two hours from\n * https://faucet.circle.com). `MockUsdc`, the mintable test double the deploy\n * script ships, is a deployment output and lives in `deployments.json`.\n */\nexport const TESTNET_ASSETS = {\n USDC: {\n symbol: \"USDC\",\n decimals: 6,\n address: \"0x534b2f3A21130d7a60830c2Df862319e593943A3\",\n },\n} as const satisfies Readonly<Record<string, AssetDescriptor>>;\n\n/**\n * Uniswap's Permit2, at its canonical address on every chain it was deployed\n * to, Monad Mainnet and Testnet included. `TabSettlement.settleWithPermit2`\n * verifies an Agent's signature against it, so an Agent approves Permit2 once\n * and signs thereafter.\n */\nexport const PERMIT2_ADDRESS = \"0x000000000022D473030F116dDEE9F6B43aC78BA3\" as const satisfies Address;\n\n/** The x402 facilitator that verifies and settles `exact` payments on Monad. */\nexport const X402_FACILITATOR_URL = \"https://x402-facilitator.molandak.org\" as const;\n\n/** The two ERC-8004 registries a Tab deployment reads and writes. */\nexport interface Erc8004Registries {\n /** Agent identities: an ERC-721 whose token id is the agentId and whose URI is the registration file. */\n readonly identity: Address;\n /** Feedback about agents, keyed by agentId and client. */\n readonly reputation: Address;\n}\n\n/** The canonical ERC-8004 registries, keyed by chain id. */\nexport const ERC8004_REGISTRIES = {\n [MONAD_MAINNET.chainId]: {\n identity: \"0x8004A169FB4a3325136EB29fA0ceB6D2e539a432\",\n reputation: \"0x8004BAa17C55a88189AE136b182e5fdA19dE9b63\",\n },\n [MONAD_TESTNET.chainId]: {\n identity: \"0x8004A818BFB912233c491871b3d84c89A494BD9e\",\n reputation: \"0x8004B663056A597Dffe9eCcC1965A193B7388713\",\n },\n} as const satisfies Readonly<Record<MonadChainId, Erc8004Registries>>;\n\nexport function erc8004RegistriesFor(chainId: number | bigint): Erc8004Registries | undefined {\n const narrowed = typeof chainId === \"bigint\" ? Number(chainId) : chainId;\n return isMonadChainId(narrowed) ? ERC8004_REGISTRIES[narrowed] : undefined;\n}\n\nexport const PLACEHOLDER_ADDRESS = \"0x0000000000000000000000000000000000000000\" as const;\n\n/** Formats base units of a six-decimal Asset for display, without floating point. */\nexport function formatBaseUnits(amount: bigint, decimals: number): string {\n const negative = amount < 0n;\n const abs = negative ? -amount : amount;\n const scale = 10n ** BigInt(decimals);\n const whole = abs / scale;\n const fraction = (abs % scale).toString().padStart(decimals, \"0\").replace(/0+$/, \"\");\n return `${negative ? \"-\" : \"\"}${whole}${fraction ? `.${fraction}` : \"\"}`;\n}\n"]}
1
+ {"version":3,"file":"chains.js","sourceRoot":"","sources":["../src/chains.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Chain and Asset constants for Tab on Monad.\n *\n * Tab runs on one chain. The Agent's payment and the ledger entry happen in the\n * same Monad transaction, so nothing in the system refers to any other chain.\n * What this module carries is which Monad network a deployment targets and\n * which Assets it settles in.\n *\n * Addresses of Tab's own contracts are deployment output and live in\n * `deployments.json`, never here.\n */\nimport type { Address, Bytes32 } from \"./hex.js\";\n\n/** A Monad network a Tab deployment can target. */\nexport interface ChainDescriptor {\n readonly name: string;\n readonly chainId: number;\n readonly rpcUrl: string;\n readonly explorerUrl: string;\n /** The MON faucet, testnet only. */\n readonly faucetUrl?: string;\n}\n\nexport const MONAD_MAINNET = {\n name: \"Monad Mainnet\",\n chainId: 143,\n rpcUrl: \"https://rpc.monad.xyz\",\n explorerUrl: \"https://monadvision.com\",\n} as const satisfies ChainDescriptor;\n\nexport const MONAD_TESTNET = {\n name: \"Monad Testnet\",\n chainId: 10143,\n rpcUrl: \"https://testnet-rpc.monad.xyz\",\n explorerUrl: \"https://testnet.monadvision.com\",\n faucetUrl: \"https://faucet.monad.xyz\",\n} as const satisfies ChainDescriptor;\n\nexport const CHAINS = {\n [MONAD_MAINNET.chainId]: MONAD_MAINNET,\n [MONAD_TESTNET.chainId]: MONAD_TESTNET,\n} as const;\n\nexport type MonadChainId = keyof typeof CHAINS;\n\nexport function isMonadChainId(value: unknown): value is MonadChainId {\n return value === MONAD_MAINNET.chainId || value === MONAD_TESTNET.chainId;\n}\n\nexport function chainFor(chainId: number | bigint): ChainDescriptor | undefined {\n const narrowed = typeof chainId === \"bigint\" ? Number(chainId) : chainId;\n return isMonadChainId(narrowed) ? CHAINS[narrowed] : undefined;\n}\n\n/** Link to an address or a transaction on the explorer for a chain. */\nexport function explorerLink(chain: ChainDescriptor, kind: \"address\" | \"tx\", hash: string): string {\n return `${chain.explorerUrl}/${kind}/${hash}`;\n}\n\n/** A stablecoin Tab settles in. Amounts everywhere are integer base units. */\nexport interface AssetDescriptor {\n readonly symbol: string;\n readonly decimals: number;\n readonly address: Address;\n}\n\n/** Canonical stablecoins on Monad Mainnet. */\nexport const MAINNET_ASSETS = {\n USDC: {\n symbol: \"USDC\",\n decimals: 6,\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n },\n AUSD: {\n symbol: \"AUSD\",\n decimals: 6,\n address: \"0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a\",\n },\n} as const satisfies Readonly<Record<string, AssetDescriptor>>;\n\n/**\n * Stablecoins on Monad Testnet. `USDC` is Circle's own testnet deployment\n * (`name` \"USDC\", EIP-712 version \"2\", 20 USDC per address every two hours from\n * https://faucet.circle.com). `MockUsdc`, the mintable test double the deploy\n * script ships, is a deployment output and lives in `deployments.json`.\n */\nexport const TESTNET_ASSETS = {\n USDC: {\n symbol: \"USDC\",\n decimals: 6,\n address: \"0x534b2f3A21130d7a60830c2Df862319e593943A3\",\n },\n} as const satisfies Readonly<Record<string, AssetDescriptor>>;\n\n/**\n * Uniswap's Permit2, at its canonical address on every chain it was deployed\n * to, Monad Mainnet and Testnet included. `TabSettlement.settleWithPermit2`\n * verifies an Agent's signature against it, so an Agent approves Permit2 once\n * and signs thereafter.\n */\nexport const PERMIT2_ADDRESS = \"0x000000000022D473030F116dDEE9F6B43aC78BA3\" as const satisfies Address;\n\n/** The x402 facilitator that verifies and settles `exact` payments on Monad. */\nexport const X402_FACILITATOR_URL = \"https://x402-facilitator.molandak.org\" as const;\n\n/** A Service this project hosts, and where it is reached. */\nexport interface HostedService {\n readonly serviceId: Bytes32;\n readonly name: string;\n readonly endpoint: string;\n}\n\n/** What this project hosts on one network: the read API and the demo Service. */\nexport interface TabHosted {\n readonly registryUrl: string;\n readonly demoService: HostedService;\n /** The test token the hosted deployment prices in, where it ships one: `mUSDC`, 6 decimals. */\n readonly testAsset?: Address;\n}\n\n/**\n * The read API and the demo Service this project runs, per network.\n *\n * Defaults, never authority: the chain is the authority on every figure, and a\n * configured `registryUrl` or `services` entry always wins over these. They are\n * here so that a fresh install can discover and call something before its owner\n * has configured anything, which is the first thing anyone tries.\n */\nexport const TAB_HOSTED = {\n [MONAD_MAINNET.chainId]: {\n registryUrl: \"https://registry-mainnet-production.up.railway.app\",\n demoService: {\n serviceId: \"0x7461622e64656d6f000000000000000000000000000000000000000000000000\",\n name: \"tab.demo\",\n endpoint: \"https://gateway-mainnet-production.up.railway.app\",\n },\n },\n [MONAD_TESTNET.chainId]: {\n registryUrl: \"https://registry-testnet-production.up.railway.app\",\n demoService: {\n serviceId: \"0x7461622e64656d6f000000000000000000000000000000000000000000000000\",\n name: \"tab.demo\",\n endpoint: \"https://gateway-testnet-production-a657.up.railway.app\",\n },\n testAsset: \"0x480209747417f5c830fDA188a9b9AcFa70Bc4083\",\n },\n} as const satisfies Readonly<Record<MonadChainId, TabHosted>>;\n\n/** The two ERC-8004 registries a Tab deployment reads and writes. */\nexport interface Erc8004Registries {\n /** Agent identities: an ERC-721 whose token id is the agentId and whose URI is the registration file. */\n readonly identity: Address;\n /** Feedback about agents, keyed by agentId and client. */\n readonly reputation: Address;\n}\n\n/** The canonical ERC-8004 registries, keyed by chain id. */\nexport const ERC8004_REGISTRIES = {\n [MONAD_MAINNET.chainId]: {\n identity: \"0x8004A169FB4a3325136EB29fA0ceB6D2e539a432\",\n reputation: \"0x8004BAa17C55a88189AE136b182e5fdA19dE9b63\",\n },\n [MONAD_TESTNET.chainId]: {\n identity: \"0x8004A818BFB912233c491871b3d84c89A494BD9e\",\n reputation: \"0x8004B663056A597Dffe9eCcC1965A193B7388713\",\n },\n} as const satisfies Readonly<Record<MonadChainId, Erc8004Registries>>;\n\nexport function erc8004RegistriesFor(chainId: number | bigint): Erc8004Registries | undefined {\n const narrowed = typeof chainId === \"bigint\" ? Number(chainId) : chainId;\n return isMonadChainId(narrowed) ? ERC8004_REGISTRIES[narrowed] : undefined;\n}\n\nexport const PLACEHOLDER_ADDRESS = \"0x0000000000000000000000000000000000000000\" as const;\n\n/** Formats base units of a six-decimal Asset for display, without floating point. */\nexport function formatBaseUnits(amount: bigint, decimals: number): string {\n const negative = amount < 0n;\n const abs = negative ? -amount : amount;\n const scale = 10n ** BigInt(decimals);\n const whole = abs / scale;\n const fraction = (abs % scale).toString().padStart(decimals, \"0\").replace(/0+$/, \"\");\n return `${negative ? \"-\" : \"\"}${whole}${fraction ? `.${fraction}` : \"\"}`;\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -36,6 +36,8 @@ export declare const WORKSPACE_ID_SDK: "@tabai/sdk";
36
36
  export declare const SHARED_WORKSPACE_ID: "./_shared/index.js";
37
37
  export { ok, err, wrap, causeOf } from "./_shared/index.js";
38
38
  export type { Result, TabError, ErrorCategory, Address, Bytes32, Hex } from "./_shared/index.js";
39
+ export { TAB_HOSTED } from "./_shared/index.js";
40
+ export type { TabHosted, HostedService } from "./_shared/index.js";
39
41
  export * from "./logger.js";
40
42
  export * from "./errors.js";
41
43
  export * from "./payments/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,eAAO,MAAM,gBAAgB,EAAG,YAAqB,CAAC;AAEtD,eAAO,MAAM,mBAAmB,iBAAe,CAAC;AAKhD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAE5F,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,eAAO,MAAM,gBAAgB,EAAG,YAAqB,CAAC;AAEtD,eAAO,MAAM,mBAAmB,iBAAe,CAAC;AAKhD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAI5F,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9D,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -39,6 +39,9 @@ export const SHARED_WORKSPACE_ID = WORKSPACE_ID;
39
39
  // constructors from the package it installed; `./_shared/index.js` is inlined at pack
40
40
  // time and has no name on npm to import them from.
41
41
  export { ok, err, wrap, causeOf } from "./_shared/index.js";
42
+ // Where this project hosts its read API and demo Service on each network, which
43
+ // the MCP server falls back to when nothing else is configured.
44
+ export { TAB_HOSTED } from "./_shared/index.js";
42
45
  export * from "./logger.js";
43
46
  export * from "./errors.js";
44
47
  export * from "./payments/index.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAqB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAY,CAAC;AAEhD,+EAA+E;AAC/E,iFAAiF;AACjF,mDAAmD;AACnD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGvD,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC","sourcesContent":["/**\n * `@tabai/sdk` is the published client surface. It may draw on `./_shared/index.js`\n * and on nothing else inside the workspace.\n *\n * Three surfaces, and the shape of the product is visible in how they relate:\n *\n * - **`payments/`** - the strategy seam. The interface a Settlement goes through,\n * the Monad strategy this package ships, and the three ways a consumer adds a\n * strategy of their own without editing a file in here (R23.1, R23.6).\n * - **`http/`**, the wire contract and the Agent's side of it. `headers.ts` is the\n * single definition of the `Tab-*` format, and `client-402.ts` is the post-paid\n * 402 client that reads it (R23.2).\n * - **`server/`**, the Service's side. `tabPostPaid` accrues after a delivery and\n * never withholds a response, with adapters for Hono, Express, and Next.js\n * (R23.3).\n * - **`proxy/`** - the Service's front door. `createTabProxy` forwards a request\n * upstream under the metering plugin and runs hooks around it (R23.4), and a\n * hook can attach the Settlement that covers a proxied request (R23.5).\n * - **`x402/`** - the prepaid protocol beside the credit one. A Tab `402` can\n * offer an x402 payment for the one call it refused, an Agent with an x402\n * signer can take it, and a Service can front an x402 upstream and meter the\n * Agent for what it paid.\n *\n * **`http/headers.ts` is deliberately the only place the wire format exists.** The\n * client parses with it and the server formats with it, so the two halves cannot\n * drift apart without a test failing in one file, rather than mis-parsing silently\n * between two.\n *\n * Nothing exported from this package throws. Every fallible call returns a\n * `Result` from `./_shared/index.js` (R21.5). The one exception is named and deliberate:\n * the Hono and Next.js adapters re-raise a handler's own thrown value, because a\n * framework's contract for a failed handler is an exception and the adapter is the\n * boundary where a `Result` becomes whatever the host expects.\n */\n\nimport { WORKSPACE_ID } from \"./_shared/index.js\";\n\nexport const WORKSPACE_ID_SDK = \"@tabai/sdk\" as const;\n\nexport const SHARED_WORKSPACE_ID = WORKSPACE_ID;\n\n// Every fallible call returns a `Result`, so a consumer needs its type and its\n// constructors from the package it installed; `./_shared/index.js` is inlined at pack\n// time and has no name on npm to import them from.\nexport { ok, err, wrap, causeOf } from \"./_shared/index.js\";\nexport type { Result, TabError, ErrorCategory, Address, Bytes32, Hex } from \"./_shared/index.js\";\n\nexport * from \"./logger.js\";\nexport * from \"./errors.js\";\nexport * from \"./payments/index.js\";\nexport * from \"./http/index.js\";\nexport * from \"./server/index.js\";\nexport * from \"./proxy/index.js\";\nexport * from \"./x402/index.js\";\nexport * from \"./mcp/index.js\";\nexport * from \"./cli/index.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAqB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAY,CAAC;AAEhD,+EAA+E;AAC/E,iFAAiF;AACjF,mDAAmD;AACnD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGvD,gFAAgF;AAChF,gEAAgE;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC","sourcesContent":["/**\n * `@tabai/sdk` is the published client surface. It may draw on `./_shared/index.js`\n * and on nothing else inside the workspace.\n *\n * Three surfaces, and the shape of the product is visible in how they relate:\n *\n * - **`payments/`** - the strategy seam. The interface a Settlement goes through,\n * the Monad strategy this package ships, and the three ways a consumer adds a\n * strategy of their own without editing a file in here (R23.1, R23.6).\n * - **`http/`**, the wire contract and the Agent's side of it. `headers.ts` is the\n * single definition of the `Tab-*` format, and `client-402.ts` is the post-paid\n * 402 client that reads it (R23.2).\n * - **`server/`**, the Service's side. `tabPostPaid` accrues after a delivery and\n * never withholds a response, with adapters for Hono, Express, and Next.js\n * (R23.3).\n * - **`proxy/`** - the Service's front door. `createTabProxy` forwards a request\n * upstream under the metering plugin and runs hooks around it (R23.4), and a\n * hook can attach the Settlement that covers a proxied request (R23.5).\n * - **`x402/`** - the prepaid protocol beside the credit one. A Tab `402` can\n * offer an x402 payment for the one call it refused, an Agent with an x402\n * signer can take it, and a Service can front an x402 upstream and meter the\n * Agent for what it paid.\n *\n * **`http/headers.ts` is deliberately the only place the wire format exists.** The\n * client parses with it and the server formats with it, so the two halves cannot\n * drift apart without a test failing in one file, rather than mis-parsing silently\n * between two.\n *\n * Nothing exported from this package throws. Every fallible call returns a\n * `Result` from `./_shared/index.js` (R21.5). The one exception is named and deliberate:\n * the Hono and Next.js adapters re-raise a handler's own thrown value, because a\n * framework's contract for a failed handler is an exception and the adapter is the\n * boundary where a `Result` becomes whatever the host expects.\n */\n\nimport { WORKSPACE_ID } from \"./_shared/index.js\";\n\nexport const WORKSPACE_ID_SDK = \"@tabai/sdk\" as const;\n\nexport const SHARED_WORKSPACE_ID = WORKSPACE_ID;\n\n// Every fallible call returns a `Result`, so a consumer needs its type and its\n// constructors from the package it installed; `./_shared/index.js` is inlined at pack\n// time and has no name on npm to import them from.\nexport { ok, err, wrap, causeOf } from \"./_shared/index.js\";\nexport type { Result, TabError, ErrorCategory, Address, Bytes32, Hex } from \"./_shared/index.js\";\n\n// Where this project hosts its read API and demo Service on each network, which\n// the MCP server falls back to when nothing else is configured.\nexport { TAB_HOSTED } from \"./_shared/index.js\";\nexport type { TabHosted, HostedService } from \"./_shared/index.js\";\n\nexport * from \"./logger.js\";\nexport * from \"./errors.js\";\nexport * from \"./payments/index.js\";\nexport * from \"./http/index.js\";\nexport * from \"./server/index.js\";\nexport * from \"./proxy/index.js\";\nexport * from \"./x402/index.js\";\nexport * from \"./mcp/index.js\";\nexport * from \"./cli/index.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/mcp/assets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAGrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iGAAiG;IACjG,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC;AAED,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,GAAG,MAAM,EAAE,SAAS,MAAM,KAAG,WACzB,CAAC;AAEhD,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,KAAG,WAAwD,CAAC;AAEzG,oDAAoD;AACpD,eAAO,MAAM,eAAe,uBAA0D,CAAC;AA6BvF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAU,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,QAAQ,CAAC,CA2ClH;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,UAAU,CAQtH"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/mcp/assets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAGrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iGAAiG;IACjG,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC;AAED,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,GAAG,MAAM,EAAE,SAAS,MAAM,KAAG,WACzB,CAAC;AAEhD,eAAO,MAAM,aAAa,GAAI,OAAO,QAAQ,KAAG,WAAwD,CAAC;AAEzG,oDAAoD;AACpD,eAAO,MAAM,eAAe,uBAA0D,CAAC;AAiCvF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAU,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,QAAQ,CAAC,CA2ClH;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,UAAU,CAQtH"}
@@ -1,4 +1,4 @@
1
- import { MAINNET_ASSETS, MONAD_MAINNET, MONAD_TESTNET, TESTNET_ASSETS, isAddress, ok } from "../_shared/index.js";
1
+ import { MAINNET_ASSETS, MONAD_MAINNET, MONAD_TESTNET, TAB_HOSTED, TESTNET_ASSETS, isAddress, ok } from "../_shared/index.js";
2
2
  import { validationError } from "../errors.js";
3
3
  export const formatAsset = (chainId, address) => `${String(chainId)}:${address.toLowerCase()}`;
4
4
  export const assetStringOf = (asset) => formatAsset(asset.chainId, asset.address);
@@ -7,7 +7,7 @@ export const KNOWN_CHAIN_IDS = [MONAD_MAINNET.chainId, MONAD_TESTNET.chainId];
7
7
  /**
8
8
  * The stablecoins this SDK can name, per chain. On Testnet that is Circle's
9
9
  * USDC from the shared table plus the mock token the deployment shipped, read
10
- * from `MOCK_USDC_ADDRESS`. The mock is named `mUSDC` here although its own
10
+ * from `MOCK_USDC_ADDRESS` or, failing that, the hosted deployment's. The mock is named `mUSDC` here although its own
11
11
  * `symbol()` says `USDC`, because a Service that accepts both must show two
12
12
  * Assets and not one word twice.
13
13
  */
@@ -25,8 +25,12 @@ function knownAssets(chainId, env) {
25
25
  symbol: asset.symbol,
26
26
  decimals: asset.decimals,
27
27
  }));
28
- const mock = env["MOCK_USDC_ADDRESS"];
29
- return mock !== undefined && isAddress(mock) ? [...known, { address: mock.toLowerCase(), symbol: "mUSDC", decimals: 6 }] : known;
28
+ // The environment names the test token for a deployment of its own; the
29
+ // hosted Testnet deployment's is known without it, so a fresh install
30
+ // shows `mUSDC` rather than an address with no symbol.
31
+ const configured = env["MOCK_USDC_ADDRESS"];
32
+ const mock = configured !== undefined && isAddress(configured) ? configured : TAB_HOSTED[MONAD_TESTNET.chainId].testAsset;
33
+ return mock !== undefined ? [...known, { address: mock.toLowerCase(), symbol: "mUSDC", decimals: 6 }] : known;
30
34
  }
31
35
  return [];
32
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/mcp/assets.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Assets at the MCP boundary.\n *\n * An Asset is named to a model as `<chainId>:<address>`, the same shape the\n * `Tab-Charge-Asset` header carries, so the string a tool result shows is the\n * string a tool argument accepts. `TabBook` keys an Asset by token address alone;\n * the chain id travels with it here because the SDK can be pointed at Monad\n * Mainnet or Monad Testnet and a bare address is ambiguous between the two.\n *\n * The canonical stablecoins are known by symbol and decimals. Any other address\n * is still a valid Asset, it is just one this SDK has no facts about, and the\n * tool results say so rather than guessing.\n */\nimport type { Address, Result } from \"../_shared/index.js\";\nimport { MAINNET_ASSETS, MONAD_MAINNET, MONAD_TESTNET, TESTNET_ASSETS, isAddress, ok } from \"../_shared/index.js\";\nimport { validationError } from \"../errors.js\";\nimport type { AssetRef } from \"../payments/strategy.js\";\n\nexport type AssetString = string;\n\nexport interface AssetFacts {\n readonly chainId: number;\n readonly address: Address;\n readonly symbol: string | null;\n readonly decimals: number | null;\n /** True when the address is a canonical stablecoin on that chain, or a configured test token. */\n readonly curatedAsset: boolean;\n}\n\nexport const formatAsset = (chainId: bigint | number, address: string): AssetString =>\n `${String(chainId)}:${address.toLowerCase()}`;\n\nexport const assetStringOf = (asset: AssetRef): AssetString => formatAsset(asset.chainId, asset.address);\n\n/** The chain ids this SDK knows how to describe. */\nexport const KNOWN_CHAIN_IDS = [MONAD_MAINNET.chainId, MONAD_TESTNET.chainId] as const;\n\n/**\n * The stablecoins this SDK can name, per chain. On Testnet that is Circle's\n * USDC from the shared table plus the mock token the deployment shipped, read\n * from `MOCK_USDC_ADDRESS`. The mock is named `mUSDC` here although its own\n * `symbol()` says `USDC`, because a Service that accepts both must show two\n * Assets and not one word twice.\n */\nfunction knownAssets(chainId: number, env: NodeJS.ProcessEnv): readonly { address: string; symbol: string; decimals: number }[] {\n if (chainId === MONAD_MAINNET.chainId) {\n return Object.values(MAINNET_ASSETS).map((asset) => ({\n address: asset.address.toLowerCase(),\n symbol: asset.symbol,\n decimals: asset.decimals,\n }));\n }\n if (chainId === MONAD_TESTNET.chainId) {\n const known = Object.values(TESTNET_ASSETS).map((asset) => ({\n address: asset.address.toLowerCase(),\n symbol: asset.symbol,\n decimals: asset.decimals,\n }));\n const mock = env[\"MOCK_USDC_ADDRESS\"];\n return mock !== undefined && isAddress(mock) ? [...known, { address: mock.toLowerCase(), symbol: \"mUSDC\", decimals: 6 }] : known;\n }\n return [];\n}\n\nexport function parseAsset(value: unknown, label = \"asset\", env: NodeJS.ProcessEnv = process.env): Result<AssetRef> {\n if (typeof value !== \"string\") {\n return validationError(\"ASSET_MALFORMED\", `${label} must be a string of the form chainId:tokenAddress, received ${typeof value}`, {\n details: { label },\n });\n }\n const colon = value.indexOf(\":\");\n if (colon <= 0) {\n return validationError(\n \"ASSET_MALFORMED\",\n `${label} must be chainId:tokenAddress, for example 143:${MAINNET_ASSETS.USDC.address.toLowerCase()}, received \\`${value}\\``,\n { details: { label, value } },\n );\n }\n const rawChainId = value.slice(0, colon);\n const rawAddress = value.slice(colon + 1);\n if (!/^[0-9]+$/.test(rawChainId)) {\n return validationError(\"ASSET_CHAIN_ID_MALFORMED\", `${label} must start with a decimal chain id, received \\`${rawChainId}\\``, {\n details: { label, chainId: rawChainId },\n });\n }\n if (!isAddress(rawAddress)) {\n return validationError(\"ASSET_ADDRESS_MALFORMED\", `${label} must end in a 20-byte 0x address, received \\`${rawAddress}\\``, {\n details: { label, address: rawAddress },\n });\n }\n const chainId = Number(rawChainId);\n if (!(KNOWN_CHAIN_IDS as readonly number[]).includes(chainId)) {\n return validationError(\n \"ASSET_CHAIN_UNSUPPORTED\",\n `chain id ${rawChainId} is not a Monad network; the supported ids are ${KNOWN_CHAIN_IDS.join(\" and \")}`,\n { details: { label, chainId: rawChainId, supported: KNOWN_CHAIN_IDS.join(\", \") } },\n );\n }\n const facts = assetFacts(chainId, rawAddress, env);\n return ok({\n chainId: BigInt(chainId),\n address: rawAddress.toLowerCase() as Address,\n // An unknown token is assumed to be a six-decimal stablecoin, which is what\n // every Asset Tab settles in. The facts say when that is a guess.\n decimals: facts.decimals ?? 6,\n symbol: facts.symbol ?? \"TOKEN\",\n });\n}\n\nexport function assetFacts(chainId: bigint | number, address: string, env: NodeJS.ProcessEnv = process.env): AssetFacts {\n const lowered = address.toLowerCase() as Address;\n const numeric = typeof chainId === \"bigint\" ? Number(chainId) : chainId;\n const known = knownAssets(numeric, env).find((asset) => asset.address === lowered);\n if (known !== undefined) {\n return { chainId: numeric, address: lowered, symbol: known.symbol, decimals: known.decimals, curatedAsset: true };\n }\n return { chainId: numeric, address: lowered, symbol: null, decimals: null, curatedAsset: false };\n}\n"]}
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/mcp/assets.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Assets at the MCP boundary.\n *\n * An Asset is named to a model as `<chainId>:<address>`, the same shape the\n * `Tab-Charge-Asset` header carries, so the string a tool result shows is the\n * string a tool argument accepts. `TabBook` keys an Asset by token address alone;\n * the chain id travels with it here because the SDK can be pointed at Monad\n * Mainnet or Monad Testnet and a bare address is ambiguous between the two.\n *\n * The canonical stablecoins are known by symbol and decimals. Any other address\n * is still a valid Asset, it is just one this SDK has no facts about, and the\n * tool results say so rather than guessing.\n */\nimport type { Address, Result } from \"../_shared/index.js\";\nimport { MAINNET_ASSETS, MONAD_MAINNET, MONAD_TESTNET, TAB_HOSTED, TESTNET_ASSETS, isAddress, ok } from \"../_shared/index.js\";\nimport { validationError } from \"../errors.js\";\nimport type { AssetRef } from \"../payments/strategy.js\";\n\nexport type AssetString = string;\n\nexport interface AssetFacts {\n readonly chainId: number;\n readonly address: Address;\n readonly symbol: string | null;\n readonly decimals: number | null;\n /** True when the address is a canonical stablecoin on that chain, or a configured test token. */\n readonly curatedAsset: boolean;\n}\n\nexport const formatAsset = (chainId: bigint | number, address: string): AssetString =>\n `${String(chainId)}:${address.toLowerCase()}`;\n\nexport const assetStringOf = (asset: AssetRef): AssetString => formatAsset(asset.chainId, asset.address);\n\n/** The chain ids this SDK knows how to describe. */\nexport const KNOWN_CHAIN_IDS = [MONAD_MAINNET.chainId, MONAD_TESTNET.chainId] as const;\n\n/**\n * The stablecoins this SDK can name, per chain. On Testnet that is Circle's\n * USDC from the shared table plus the mock token the deployment shipped, read\n * from `MOCK_USDC_ADDRESS` or, failing that, the hosted deployment's. The mock is named `mUSDC` here although its own\n * `symbol()` says `USDC`, because a Service that accepts both must show two\n * Assets and not one word twice.\n */\nfunction knownAssets(chainId: number, env: NodeJS.ProcessEnv): readonly { address: string; symbol: string; decimals: number }[] {\n if (chainId === MONAD_MAINNET.chainId) {\n return Object.values(MAINNET_ASSETS).map((asset) => ({\n address: asset.address.toLowerCase(),\n symbol: asset.symbol,\n decimals: asset.decimals,\n }));\n }\n if (chainId === MONAD_TESTNET.chainId) {\n const known = Object.values(TESTNET_ASSETS).map((asset) => ({\n address: asset.address.toLowerCase(),\n symbol: asset.symbol,\n decimals: asset.decimals,\n }));\n // The environment names the test token for a deployment of its own; the\n // hosted Testnet deployment's is known without it, so a fresh install\n // shows `mUSDC` rather than an address with no symbol.\n const configured = env[\"MOCK_USDC_ADDRESS\"];\n const mock = configured !== undefined && isAddress(configured) ? configured : TAB_HOSTED[MONAD_TESTNET.chainId].testAsset;\n return mock !== undefined ? [...known, { address: mock.toLowerCase(), symbol: \"mUSDC\", decimals: 6 }] : known;\n }\n return [];\n}\n\nexport function parseAsset(value: unknown, label = \"asset\", env: NodeJS.ProcessEnv = process.env): Result<AssetRef> {\n if (typeof value !== \"string\") {\n return validationError(\"ASSET_MALFORMED\", `${label} must be a string of the form chainId:tokenAddress, received ${typeof value}`, {\n details: { label },\n });\n }\n const colon = value.indexOf(\":\");\n if (colon <= 0) {\n return validationError(\n \"ASSET_MALFORMED\",\n `${label} must be chainId:tokenAddress, for example 143:${MAINNET_ASSETS.USDC.address.toLowerCase()}, received \\`${value}\\``,\n { details: { label, value } },\n );\n }\n const rawChainId = value.slice(0, colon);\n const rawAddress = value.slice(colon + 1);\n if (!/^[0-9]+$/.test(rawChainId)) {\n return validationError(\"ASSET_CHAIN_ID_MALFORMED\", `${label} must start with a decimal chain id, received \\`${rawChainId}\\``, {\n details: { label, chainId: rawChainId },\n });\n }\n if (!isAddress(rawAddress)) {\n return validationError(\"ASSET_ADDRESS_MALFORMED\", `${label} must end in a 20-byte 0x address, received \\`${rawAddress}\\``, {\n details: { label, address: rawAddress },\n });\n }\n const chainId = Number(rawChainId);\n if (!(KNOWN_CHAIN_IDS as readonly number[]).includes(chainId)) {\n return validationError(\n \"ASSET_CHAIN_UNSUPPORTED\",\n `chain id ${rawChainId} is not a Monad network; the supported ids are ${KNOWN_CHAIN_IDS.join(\" and \")}`,\n { details: { label, chainId: rawChainId, supported: KNOWN_CHAIN_IDS.join(\", \") } },\n );\n }\n const facts = assetFacts(chainId, rawAddress, env);\n return ok({\n chainId: BigInt(chainId),\n address: rawAddress.toLowerCase() as Address,\n // An unknown token is assumed to be a six-decimal stablecoin, which is what\n // every Asset Tab settles in. The facts say when that is a guess.\n decimals: facts.decimals ?? 6,\n symbol: facts.symbol ?? \"TOKEN\",\n });\n}\n\nexport function assetFacts(chainId: bigint | number, address: string, env: NodeJS.ProcessEnv = process.env): AssetFacts {\n const lowered = address.toLowerCase() as Address;\n const numeric = typeof chainId === \"bigint\" ? Number(chainId) : chainId;\n const known = knownAssets(numeric, env).find((asset) => asset.address === lowered);\n if (known !== undefined) {\n return { chainId: numeric, address: lowered, symbol: known.symbol, decimals: known.decimals, curatedAsset: true };\n }\n return { chainId: numeric, address: lowered, symbol: null, decimals: null, curatedAsset: false };\n}\n"]}
@@ -62,6 +62,12 @@ export interface TabMcpSettingsOptions {
62
62
  readonly agent?: string;
63
63
  readonly chainId?: number;
64
64
  readonly registryUrl?: string;
65
+ /**
66
+ * Whether the project's hosted read API and demo Service fill in what nothing
67
+ * else names. Default true; `TAB_HOSTED_DEFAULTS=off` in the environment
68
+ * turns them off as well.
69
+ */
70
+ readonly hostedDefaults?: boolean;
65
71
  readonly rpcUrl?: string;
66
72
  readonly explorerUrl?: string;
67
73
  readonly services?: readonly TabServiceEntry[];
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/mcp/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,wFAAwF;IACxF,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,yFAAyF;IACzF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC7C,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED,8EAA8E;AAC9E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,oCAAoC,CAAC;AAEtE,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAsCtC;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,cAAc,CAAC,CA4GzB"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/mcp/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,wFAAwF;IACxF,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,yFAAyF;IACzF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,0FAA0F;IAC1F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC7C,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED,8EAA8E;AAC9E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,oCAAoC,CAAC;AAEtE,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAsCtC;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,cAAc,CAAC,CA6HzB"}
@@ -28,7 +28,7 @@
28
28
  *
29
29
  * Requirements: 25.3, 25.5, 28.6
30
30
  */
31
- import { isAddress } from "../_shared/index.js";
31
+ import { CHAINS, TAB_HOSTED, isAddress, isMonadChainId } from "../_shared/index.js";
32
32
  import { loadTabConfig } from "../payments/config.js";
33
33
  import { defaultLogger } from "../logger.js";
34
34
  /** The public Monad Testnet explorer, used when nothing names one. */
@@ -127,18 +127,34 @@ export async function resolveTabMcpSettings(options = {}) {
127
127
  logger.warn("the configured agent is not a 20-byte address and was ignored", { agent: rawAgent });
128
128
  delete sources["agent"];
129
129
  }
130
- const envRegistry = registryUrlFromEnv(env);
131
- const registryUrl = pick("registryUrl", options.registryUrl, config.registryUrl, envRegistry === undefined ? undefined : { value: envRegistry.url, source: envRegistry.source });
132
130
  const envRpc = trimmed(env["MONAD_RPC_URL"]);
133
131
  const rpcUrl = pick("rpcUrl", options.rpcUrl, undefined, envRpc === undefined ? undefined : { value: envRpc, source: "env MONAD_RPC_URL" });
134
132
  const envChain = trimmed(env["MONAD_CHAIN_ID"]);
135
133
  const chainIdText = pick("chainId", options.chainId === undefined ? undefined : String(options.chainId), undefined, envChain === undefined ? undefined : { value: envChain, source: "env MONAD_CHAIN_ID" });
136
134
  const chainId = chainIdText !== undefined && /^[0-9]+$/.test(chainIdText) ? Number(chainIdText) : DEFAULT_CHAIN_ID;
135
+ /*
136
+ What this project hosts on the chosen network: its read API and its demo
137
+ Service. The lowest-priority source for both, so anything configured wins,
138
+ and switched off with TAB_HOSTED_DEFAULTS=off for a setup that must reach
139
+ nothing it did not name.
140
+ */
141
+ const hosted = options.hostedDefaults !== false && trimmed(env["TAB_HOSTED_DEFAULTS"]) !== "off" && isMonadChainId(chainId)
142
+ ? TAB_HOSTED[chainId]
143
+ : undefined;
144
+ const envRegistry = registryUrlFromEnv(env);
145
+ let registryUrl = pick("registryUrl", options.registryUrl, config.registryUrl, envRegistry === undefined ? undefined : { value: envRegistry.url, source: envRegistry.source });
146
+ if (registryUrl === undefined && hosted !== undefined) {
147
+ registryUrl = hosted.registryUrl;
148
+ sources["registryUrl"] = "default (the project's hosted read API)";
149
+ }
137
150
  const envExplorer = trimmed(env["MONAD_EXPLORER_URL"]);
138
- const explorerUrl = pick("explorerUrl", options.explorerUrl, undefined, envExplorer === undefined ? undefined : { value: envExplorer, source: "env MONAD_EXPLORER_URL" }) ?? DEFAULT_EXPLORER_URL;
139
- const services = mergeServices(options.services ?? [], config.services ?? []);
140
- if (services.length > 0)
151
+ const explorerUrl = pick("explorerUrl", options.explorerUrl, undefined, envExplorer === undefined ? undefined : { value: envExplorer, source: "env MONAD_EXPLORER_URL" }) ?? (isMonadChainId(chainId) ? CHAINS[chainId].explorerUrl : DEFAULT_EXPLORER_URL);
152
+ const configured = mergeServices(options.services ?? [], config.services ?? []);
153
+ if (configured.length > 0)
141
154
  sources["services"] = options.services === undefined ? "tab.config" : "options";
155
+ const services = hosted === undefined ? configured : mergeServices(configured, [hosted.demoService]);
156
+ if (configured.length === 0 && services.length > 0)
157
+ sources["services"] = "default (the project's hosted demo Service)";
142
158
  const strategyId = trimmed(options.strategyId);
143
159
  if (strategyId !== undefined)
144
160
  sources["strategyId"] = "options";
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/mcp/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,EAAE,aAAa,EAAkB,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAe,MAAM,cAAc,CAAC;AA8C1D,sEAAsE;AACtE,MAAM,CAAC,MAAM,oBAAoB,GAAG,iCAAiC,CAAC;AAEtE,sDAAsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAEtC,MAAM,OAAO,GAAG,CAAC,KAAyB,EAAsB,EAAE;IAChE,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC3B,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9D,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,kBAAkB,GAAG,CAAC,GAAsB,EAA+C,EAAE;IACjG,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;IAC9D,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC;IACjG,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC;IAC3C,IAAI,IAAI,KAAK,SAAS,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,GAAG,EAAE,oBAAoB,IAAI,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC1E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,gFAAgF;AAChF,SAAS,aAAa,CAAC,GAAG,MAA+C;IACvE,MAAM,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAC;IAChD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,OAAO,KAAK,EAAE,SAAS,KAAK,QAAQ,IAAI,OAAO,KAAK,EAAE,QAAQ,KAAK,QAAQ;gBAAE,SAAS;YAC1F,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;YAC1C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,UAAiC,EAAE;IAEnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;IAC/C,MAAM,OAAO,GAA2B,EAAE,CAAC;IAE3C,IAAI,MAAM,GAAc,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;YAC1D,QAAQ,EAAE,KAAK;YACf,MAAM;SACP,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;YAC7B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS;gBAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,uDAAuD,EAAE;gBACnE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;gBACvB,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO;aAC9B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QACpC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC;IACjC,CAAC;IAED,MAAM,IAAI,GAAG,CACX,GAAW,EACX,QAA4B,EAC5B,UAA8B,EAC9B,OAAsD,EAClC,EAAE;QACtB,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;YACzB,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC;YAC5B,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9B,OAAO,OAAO,CAAC,KAAK,CAAC;QACvB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,QAAQ,KAAK,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,QAAQ,CAAC,WAAW,EAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9G,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,+DAA+D,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClG,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,IAAI,CACtB,aAAa,EACb,OAAO,CAAC,WAAW,EACnB,MAAM,CAAC,WAAW,EAClB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAC/F,CAAC;IAEF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CACjB,QAAQ,EACR,OAAO,CAAC,MAAM,EACd,SAAS,EACT,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAClF,CAAC;IAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,CACtB,SAAS,EACT,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EACnE,SAAS,EACT,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB,EAAE,CACvF,CAAC;IACF,MAAM,OAAO,GAAG,WAAW,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAEnH,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACvD,MAAM,WAAW,GACf,IAAI,CACF,aAAa,EACb,OAAO,CAAC,WAAW,EACnB,SAAS,EACT,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,wBAAwB,EAAE,CACjG,IAAI,oBAAoB,CAAC;IAE5B,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC9E,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAEzG,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IAEhE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3F,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAEhG,OAAO;QACL,KAAK;QACL,WAAW;QACX,MAAM;QACN,OAAO;QACP,WAAW;QACX,QAAQ;QACR,UAAU;QACV,IAAI;QACJ,OAAO;KACR,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Where the MCP server gets its settings, and the order it prefers them in.\n *\n * Three sources, most specific first:\n *\n * 1. the options handed to {@link resolveTabMcpSettings}, which is what a test\n * and an embedding host use;\n * 2. `tab.config.{ts,mts,mjs,js,cjs}`, discovered by walking up from the working\n * directory -- the mechanism this package already has for consumer\n * configuration, so the MCP surface adds no second one;\n * 3. the environment, which is what the `mcpServers` stanza `tab connect` writes\n * actually carries.\n *\n * Every environment variable read here is already declared in the tracked\n * `.env.example` contract. That is not incidental: the repository's environment\n * gate extracts every `process.env` read in the tree and fails the build when\n * one has no declaration, so a new name would be a new line in a contract this\n * surface has no business changing. The RPC endpoint is `MONAD_RPC_URL`, in the\n * stanza and here.\n *\n * ## No key is a setting\n *\n * Nothing in this module reads a private key and nothing returns one. The\n * settlement signing key is read from the environment at the moment a Settlement\n * is signed, by the strategy that signs it, and never travels through a config\n * file or an MCP client's `mcpServers` stanza. That is what makes `tab connect`\n * safe to run against a file the client software rewrites.\n *\n * Requirements: 25.3, 25.5, 28.6\n */\n\nimport type { Address } from \"../_shared/index.js\";\nimport { isAddress } from \"../_shared/index.js\";\n\nimport type { TabServiceEntry } from \"../payments/config.js\";\nimport { loadTabConfig, type TabConfig } from \"../payments/config.js\";\nimport { defaultLogger, type Logger } from \"../logger.js\";\nimport type { X402SignerFactory } from \"../x402/client.js\";\n\n/** The settings every tool reads. Each field is resolved or explicitly absent. */\nexport interface TabMcpSettings {\n /** Whose Open Tab a metered call lands on. Undefined until one is configured. */\n readonly agent: Address | undefined;\n /** Absolute base URL of the registry read API, or undefined when none is configured. */\n readonly registryUrl: string | undefined;\n /** The Monad JSON-RPC endpoint, used by `doctor` and by nothing that signs. */\n readonly rpcUrl: string | undefined;\n /** The EVM chain id every Asset is named against: 143 for Mainnet, 10143 for Testnet. */\n readonly chainId: number;\n /** Where a Monad transaction is linked. Always resolved; a default is fine for a link. */\n readonly explorerUrl: string;\n /** The endpoint directory, keyed by lower-case serviceId. */\n readonly services: readonly TabServiceEntry[];\n /** Which strategy `tab_settle` settles through when the call names none. */\n readonly strategyId: string | undefined;\n /**\n * The x402 signer factory, for `tab_call`'s prepaid fallback. Never called\n * while settings are resolved; only when a refused call carries an offer.\n */\n readonly x402: X402SignerFactory | undefined;\n /** Where each setting came from, so `doctor` can print it. */\n readonly sources: Readonly<Record<string, string>>;\n}\n\n/** Explicit settings, which beat both the config file and the environment. */\nexport interface TabMcpSettingsOptions {\n readonly agent?: string;\n readonly chainId?: number;\n readonly registryUrl?: string;\n readonly rpcUrl?: string;\n readonly explorerUrl?: string;\n readonly services?: readonly TabServiceEntry[];\n readonly strategyId?: string;\n readonly x402?: X402SignerFactory;\n /** Where the `tab.config` walk starts. Defaults to the working directory. */\n readonly cwd?: string;\n /** `false` skips config discovery entirely, which is what a hermetic test wants. */\n readonly config?: TabConfig | false;\n readonly env?: NodeJS.ProcessEnv;\n readonly logger?: Logger;\n}\n\n/** The public Monad Testnet explorer, used when nothing names one. */\nexport const DEFAULT_EXPLORER_URL = \"https://testnet.monadvision.com\";\n\n/** Monad Testnet, used when nothing names a chain. */\nexport const DEFAULT_CHAIN_ID = 10143;\n\nconst trimmed = (value: string | undefined): string | undefined => {\n const text = value?.trim();\n return text === undefined || text === \"\" ? undefined : text;\n};\n\n/**\n * The registry read API the environment names.\n *\n * `NEXT_PUBLIC_REGISTRY_API_URL` is the deployment's own name for this value and\n * is already in the environment contract, so it is what is read. When only\n * `REGISTRY_PORT` is set the read API is taken to be local, which is exactly the\n * developer case and saves a second variable that would say the same thing.\n */\nconst registryUrlFromEnv = (env: NodeJS.ProcessEnv): { url: string; source: string } | undefined => {\n const declared = trimmed(env[\"NEXT_PUBLIC_REGISTRY_API_URL\"]);\n if (declared !== undefined) return { url: declared, source: \"env NEXT_PUBLIC_REGISTRY_API_URL\" };\n const port = trimmed(env[\"REGISTRY_PORT\"]);\n if (port !== undefined && /^[0-9]{1,5}$/.test(port)) {\n return { url: `http://127.0.0.1:${port}`, source: \"env REGISTRY_PORT\" };\n }\n return undefined;\n};\n\n/** Keeps the first entry for each serviceId, so a more specific source wins. */\nfunction mergeServices(...groups: readonly (readonly TabServiceEntry[])[]): readonly TabServiceEntry[] {\n const byId = new Map<string, TabServiceEntry>();\n for (const group of groups) {\n for (const entry of group) {\n if (typeof entry?.serviceId !== \"string\" || typeof entry?.endpoint !== \"string\") continue;\n const key = entry.serviceId.toLowerCase();\n if (!byId.has(key)) byId.set(key, { ...entry, serviceId: key });\n }\n }\n return [...byId.values()];\n}\n\n/**\n * Resolves the settings, loading `tab.config` unless one was handed in.\n *\n * Never fails. A config file that cannot be imported is logged and skipped\n * rather than taking the server down: the tools each report their own missing\n * settings by name, which is a better message than a startup failure that names\n * a file the caller may not have known existed.\n */\nexport async function resolveTabMcpSettings(\n options: TabMcpSettingsOptions = {},\n): Promise<TabMcpSettings> {\n const env = options.env ?? process.env;\n const logger = options.logger ?? defaultLogger;\n const sources: Record<string, string> = {};\n\n let config: TabConfig = {};\n if (options.config === undefined) {\n const loaded = await loadTabConfig({\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n registry: false,\n logger,\n });\n if (loaded.ok) {\n config = loaded.value.config;\n if (loaded.value.path !== undefined) sources[\"config\"] = loaded.value.path;\n } else {\n logger.warn(\"tab config could not be loaded; continuing without it\", {\n code: loaded.error.code,\n message: loaded.error.message,\n });\n }\n } else if (options.config !== false) {\n config = options.config;\n sources[\"config\"] = \"supplied\";\n }\n\n const pick = (\n key: string,\n explicit: string | undefined,\n fromConfig: string | undefined,\n fromEnv: { value: string; source: string } | undefined,\n ): string | undefined => {\n if (trimmed(explicit) !== undefined) {\n sources[key] = \"options\";\n return trimmed(explicit);\n }\n if (trimmed(fromConfig) !== undefined) {\n sources[key] = \"tab.config\";\n return trimmed(fromConfig);\n }\n if (fromEnv !== undefined) {\n sources[key] = fromEnv.source;\n return fromEnv.value;\n }\n return undefined;\n };\n\n const rawAgent = pick(\"agent\", options.agent, config.agent, undefined);\n const agent = rawAgent !== undefined && isAddress(rawAgent) ? (rawAgent.toLowerCase() as Address) : undefined;\n if (rawAgent !== undefined && agent === undefined) {\n logger.warn(\"the configured agent is not a 20-byte address and was ignored\", { agent: rawAgent });\n delete sources[\"agent\"];\n }\n\n const envRegistry = registryUrlFromEnv(env);\n const registryUrl = pick(\n \"registryUrl\",\n options.registryUrl,\n config.registryUrl,\n envRegistry === undefined ? undefined : { value: envRegistry.url, source: envRegistry.source },\n );\n\n const envRpc = trimmed(env[\"MONAD_RPC_URL\"]);\n const rpcUrl = pick(\n \"rpcUrl\",\n options.rpcUrl,\n undefined,\n envRpc === undefined ? undefined : { value: envRpc, source: \"env MONAD_RPC_URL\" },\n );\n\n const envChain = trimmed(env[\"MONAD_CHAIN_ID\"]);\n const chainIdText = pick(\n \"chainId\",\n options.chainId === undefined ? undefined : String(options.chainId),\n undefined,\n envChain === undefined ? undefined : { value: envChain, source: \"env MONAD_CHAIN_ID\" },\n );\n const chainId = chainIdText !== undefined && /^[0-9]+$/.test(chainIdText) ? Number(chainIdText) : DEFAULT_CHAIN_ID;\n\n const envExplorer = trimmed(env[\"MONAD_EXPLORER_URL\"]);\n const explorerUrl =\n pick(\n \"explorerUrl\",\n options.explorerUrl,\n undefined,\n envExplorer === undefined ? undefined : { value: envExplorer, source: \"env MONAD_EXPLORER_URL\" },\n ) ?? DEFAULT_EXPLORER_URL;\n\n const services = mergeServices(options.services ?? [], config.services ?? []);\n if (services.length > 0) sources[\"services\"] = options.services === undefined ? \"tab.config\" : \"options\";\n\n const strategyId = trimmed(options.strategyId);\n if (strategyId !== undefined) sources[\"strategyId\"] = \"options\";\n\n const x402 = options.x402 ?? (typeof config.x402 === \"function\" ? config.x402 : undefined);\n if (x402 !== undefined) sources[\"x402\"] = options.x402 === undefined ? \"tab.config\" : \"options\";\n\n return {\n agent,\n registryUrl,\n rpcUrl,\n chainId,\n explorerUrl,\n services,\n strategyId,\n x402,\n sources,\n };\n}\n"]}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/mcp/settings.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Where the MCP server gets its settings, and the order it prefers them in.\n *\n * Three sources, most specific first:\n *\n * 1. the options handed to {@link resolveTabMcpSettings}, which is what a test\n * and an embedding host use;\n * 2. `tab.config.{ts,mts,mjs,js,cjs}`, discovered by walking up from the working\n * directory -- the mechanism this package already has for consumer\n * configuration, so the MCP surface adds no second one;\n * 3. the environment, which is what the `mcpServers` stanza `tab connect` writes\n * actually carries.\n *\n * Every environment variable read here is already declared in the tracked\n * `.env.example` contract. That is not incidental: the repository's environment\n * gate extracts every `process.env` read in the tree and fails the build when\n * one has no declaration, so a new name would be a new line in a contract this\n * surface has no business changing. The RPC endpoint is `MONAD_RPC_URL`, in the\n * stanza and here.\n *\n * ## No key is a setting\n *\n * Nothing in this module reads a private key and nothing returns one. The\n * settlement signing key is read from the environment at the moment a Settlement\n * is signed, by the strategy that signs it, and never travels through a config\n * file or an MCP client's `mcpServers` stanza. That is what makes `tab connect`\n * safe to run against a file the client software rewrites.\n *\n * Requirements: 25.3, 25.5, 28.6\n */\n\nimport type { Address } from \"../_shared/index.js\";\nimport { CHAINS, TAB_HOSTED, isAddress, isMonadChainId } from \"../_shared/index.js\";\n\nimport type { TabServiceEntry } from \"../payments/config.js\";\nimport { loadTabConfig, type TabConfig } from \"../payments/config.js\";\nimport { defaultLogger, type Logger } from \"../logger.js\";\nimport type { X402SignerFactory } from \"../x402/client.js\";\n\n/** The settings every tool reads. Each field is resolved or explicitly absent. */\nexport interface TabMcpSettings {\n /** Whose Open Tab a metered call lands on. Undefined until one is configured. */\n readonly agent: Address | undefined;\n /** Absolute base URL of the registry read API, or undefined when none is configured. */\n readonly registryUrl: string | undefined;\n /** The Monad JSON-RPC endpoint, used by `doctor` and by nothing that signs. */\n readonly rpcUrl: string | undefined;\n /** The EVM chain id every Asset is named against: 143 for Mainnet, 10143 for Testnet. */\n readonly chainId: number;\n /** Where a Monad transaction is linked. Always resolved; a default is fine for a link. */\n readonly explorerUrl: string;\n /** The endpoint directory, keyed by lower-case serviceId. */\n readonly services: readonly TabServiceEntry[];\n /** Which strategy `tab_settle` settles through when the call names none. */\n readonly strategyId: string | undefined;\n /**\n * The x402 signer factory, for `tab_call`'s prepaid fallback. Never called\n * while settings are resolved; only when a refused call carries an offer.\n */\n readonly x402: X402SignerFactory | undefined;\n /** Where each setting came from, so `doctor` can print it. */\n readonly sources: Readonly<Record<string, string>>;\n}\n\n/** Explicit settings, which beat both the config file and the environment. */\nexport interface TabMcpSettingsOptions {\n readonly agent?: string;\n readonly chainId?: number;\n readonly registryUrl?: string;\n /**\n * Whether the project's hosted read API and demo Service fill in what nothing\n * else names. Default true; `TAB_HOSTED_DEFAULTS=off` in the environment\n * turns them off as well.\n */\n readonly hostedDefaults?: boolean;\n readonly rpcUrl?: string;\n readonly explorerUrl?: string;\n readonly services?: readonly TabServiceEntry[];\n readonly strategyId?: string;\n readonly x402?: X402SignerFactory;\n /** Where the `tab.config` walk starts. Defaults to the working directory. */\n readonly cwd?: string;\n /** `false` skips config discovery entirely, which is what a hermetic test wants. */\n readonly config?: TabConfig | false;\n readonly env?: NodeJS.ProcessEnv;\n readonly logger?: Logger;\n}\n\n/** The public Monad Testnet explorer, used when nothing names one. */\nexport const DEFAULT_EXPLORER_URL = \"https://testnet.monadvision.com\";\n\n/** Monad Testnet, used when nothing names a chain. */\nexport const DEFAULT_CHAIN_ID = 10143;\n\nconst trimmed = (value: string | undefined): string | undefined => {\n const text = value?.trim();\n return text === undefined || text === \"\" ? undefined : text;\n};\n\n/**\n * The registry read API the environment names.\n *\n * `NEXT_PUBLIC_REGISTRY_API_URL` is the deployment's own name for this value and\n * is already in the environment contract, so it is what is read. When only\n * `REGISTRY_PORT` is set the read API is taken to be local, which is exactly the\n * developer case and saves a second variable that would say the same thing.\n */\nconst registryUrlFromEnv = (env: NodeJS.ProcessEnv): { url: string; source: string } | undefined => {\n const declared = trimmed(env[\"NEXT_PUBLIC_REGISTRY_API_URL\"]);\n if (declared !== undefined) return { url: declared, source: \"env NEXT_PUBLIC_REGISTRY_API_URL\" };\n const port = trimmed(env[\"REGISTRY_PORT\"]);\n if (port !== undefined && /^[0-9]{1,5}$/.test(port)) {\n return { url: `http://127.0.0.1:${port}`, source: \"env REGISTRY_PORT\" };\n }\n return undefined;\n};\n\n/** Keeps the first entry for each serviceId, so a more specific source wins. */\nfunction mergeServices(...groups: readonly (readonly TabServiceEntry[])[]): readonly TabServiceEntry[] {\n const byId = new Map<string, TabServiceEntry>();\n for (const group of groups) {\n for (const entry of group) {\n if (typeof entry?.serviceId !== \"string\" || typeof entry?.endpoint !== \"string\") continue;\n const key = entry.serviceId.toLowerCase();\n if (!byId.has(key)) byId.set(key, { ...entry, serviceId: key });\n }\n }\n return [...byId.values()];\n}\n\n/**\n * Resolves the settings, loading `tab.config` unless one was handed in.\n *\n * Never fails. A config file that cannot be imported is logged and skipped\n * rather than taking the server down: the tools each report their own missing\n * settings by name, which is a better message than a startup failure that names\n * a file the caller may not have known existed.\n */\nexport async function resolveTabMcpSettings(\n options: TabMcpSettingsOptions = {},\n): Promise<TabMcpSettings> {\n const env = options.env ?? process.env;\n const logger = options.logger ?? defaultLogger;\n const sources: Record<string, string> = {};\n\n let config: TabConfig = {};\n if (options.config === undefined) {\n const loaded = await loadTabConfig({\n ...(options.cwd === undefined ? {} : { cwd: options.cwd }),\n registry: false,\n logger,\n });\n if (loaded.ok) {\n config = loaded.value.config;\n if (loaded.value.path !== undefined) sources[\"config\"] = loaded.value.path;\n } else {\n logger.warn(\"tab config could not be loaded; continuing without it\", {\n code: loaded.error.code,\n message: loaded.error.message,\n });\n }\n } else if (options.config !== false) {\n config = options.config;\n sources[\"config\"] = \"supplied\";\n }\n\n const pick = (\n key: string,\n explicit: string | undefined,\n fromConfig: string | undefined,\n fromEnv: { value: string; source: string } | undefined,\n ): string | undefined => {\n if (trimmed(explicit) !== undefined) {\n sources[key] = \"options\";\n return trimmed(explicit);\n }\n if (trimmed(fromConfig) !== undefined) {\n sources[key] = \"tab.config\";\n return trimmed(fromConfig);\n }\n if (fromEnv !== undefined) {\n sources[key] = fromEnv.source;\n return fromEnv.value;\n }\n return undefined;\n };\n\n const rawAgent = pick(\"agent\", options.agent, config.agent, undefined);\n const agent = rawAgent !== undefined && isAddress(rawAgent) ? (rawAgent.toLowerCase() as Address) : undefined;\n if (rawAgent !== undefined && agent === undefined) {\n logger.warn(\"the configured agent is not a 20-byte address and was ignored\", { agent: rawAgent });\n delete sources[\"agent\"];\n }\n\n const envRpc = trimmed(env[\"MONAD_RPC_URL\"]);\n const rpcUrl = pick(\n \"rpcUrl\",\n options.rpcUrl,\n undefined,\n envRpc === undefined ? undefined : { value: envRpc, source: \"env MONAD_RPC_URL\" },\n );\n\n const envChain = trimmed(env[\"MONAD_CHAIN_ID\"]);\n const chainIdText = pick(\n \"chainId\",\n options.chainId === undefined ? undefined : String(options.chainId),\n undefined,\n envChain === undefined ? undefined : { value: envChain, source: \"env MONAD_CHAIN_ID\" },\n );\n const chainId = chainIdText !== undefined && /^[0-9]+$/.test(chainIdText) ? Number(chainIdText) : DEFAULT_CHAIN_ID;\n\n /*\n What this project hosts on the chosen network: its read API and its demo\n Service. The lowest-priority source for both, so anything configured wins,\n and switched off with TAB_HOSTED_DEFAULTS=off for a setup that must reach\n nothing it did not name.\n */\n const hosted =\n options.hostedDefaults !== false && trimmed(env[\"TAB_HOSTED_DEFAULTS\"]) !== \"off\" && isMonadChainId(chainId)\n ? TAB_HOSTED[chainId]\n : undefined;\n\n const envRegistry = registryUrlFromEnv(env);\n let registryUrl = pick(\n \"registryUrl\",\n options.registryUrl,\n config.registryUrl,\n envRegistry === undefined ? undefined : { value: envRegistry.url, source: envRegistry.source },\n );\n if (registryUrl === undefined && hosted !== undefined) {\n registryUrl = hosted.registryUrl;\n sources[\"registryUrl\"] = \"default (the project's hosted read API)\";\n }\n\n const envExplorer = trimmed(env[\"MONAD_EXPLORER_URL\"]);\n const explorerUrl =\n pick(\n \"explorerUrl\",\n options.explorerUrl,\n undefined,\n envExplorer === undefined ? undefined : { value: envExplorer, source: \"env MONAD_EXPLORER_URL\" },\n ) ?? (isMonadChainId(chainId) ? CHAINS[chainId].explorerUrl : DEFAULT_EXPLORER_URL);\n\n const configured = mergeServices(options.services ?? [], config.services ?? []);\n if (configured.length > 0) sources[\"services\"] = options.services === undefined ? \"tab.config\" : \"options\";\n const services = hosted === undefined ? configured : mergeServices(configured, [hosted.demoService]);\n if (configured.length === 0 && services.length > 0) sources[\"services\"] = \"default (the project's hosted demo Service)\";\n\n const strategyId = trimmed(options.strategyId);\n if (strategyId !== undefined) sources[\"strategyId\"] = \"options\";\n\n const x402 = options.x402 ?? (typeof config.x402 === \"function\" ? config.x402 : undefined);\n if (x402 !== undefined) sources[\"x402\"] = options.x402 === undefined ? \"tab.config\" : \"options\";\n\n return {\n agent,\n registryUrl,\n rpcUrl,\n chainId,\n explorerUrl,\n services,\n strategyId,\n x402,\n sources,\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tabai/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Post-paid billing for autonomous agents on Monad. MCP server, CLI and TypeScript SDK: call a priced tool now, settle in USDC later, and let TabSettlement apply the payment to the tab in the same transaction.",
5
5
  "keywords": [
6
6
  "monad",
@@ -17,7 +17,7 @@
17
17
  "sdk",
18
18
  "cli"
19
19
  ],
20
- "license": "MIT",
20
+ "license": "SEE LICENSE IN LICENSE",
21
21
  "author": "Emad Qureshi",
22
22
  "type": "module",
23
23
  "engines": {
@@ -27,6 +27,14 @@
27
27
  ".": {
28
28
  "types": "./dist/index.d.ts",
29
29
  "default": "./dist/index.js"
30
+ },
31
+ "./hub": {
32
+ "types": "./dist/x402/hub.d.ts",
33
+ "default": "./dist/x402/hub.js"
34
+ },
35
+ "./metering": {
36
+ "types": "./dist/http/metering-claim.d.ts",
37
+ "default": "./dist/http/metering-claim.js"
30
38
  }
31
39
  },
32
40
  "bin": {