@0xdivyanshh/tab-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @0xdivyanshh/tab-sdk
2
+
3
+ **Tier 3 · PUBLISHED to npm · thin HTTP client · browser-safe**
4
+
5
+ The TypeScript client every other surface is built on: `agentkit-plugin`, `mcp`, `cli`,
6
+ `dashboard`, and both demo agents.
7
+
8
+ ## Thin on purpose
9
+
10
+ `boundaries.json` forbids `@hiero-ledger/sdk`, `ioredis` and `drizzle-orm` here. This package
11
+ speaks HTTP to the gateway and nothing else.
12
+
13
+ That constraint carries the product claim. The agent holds no key and signs nothing — so the
14
+ library it installs should not even be *able* to sign. If the SDK bundled the Hedera SDK, the
15
+ claim would rest on us not having used it. This way it rests on a check anyone can run.
16
+
17
+ Browser-safe matters too: `apps/web` imports this, and a browser bundle must not be able to
18
+ reach a signing path or a database driver.
19
+
20
+ ## Surface
21
+
22
+ `spend` · `quote` · `balance` · `ceiling` · `receipts` · `register`
23
+
24
+ The same five verbs appear in the Agent Kit plugin and the MCP server. Define them once here.
25
+
26
+ ## Contents
27
+
28
+ | File | Holds |
29
+ |---|---|
30
+ | `src/client.ts` | constructor, auth, retry, timeouts |
31
+ | `src/spend.ts` | the spend call, including the refusal shape |
32
+ | `src/quote.ts` | pre-flight quote without reserving |
33
+ | `src/state.ts` | balance, ceiling, available, pending holds, window countdown |
34
+ | `src/receipts.ts` | receipt history and the SSE stream the dashboard consumes |
35
+ | `src/errors.ts` | typed errors — refusal, unavailable, invalid |
36
+ | `src/types.ts` | re-exported from `@0xdivyanshh/tab-protocol`. One definition, not two |
37
+
38
+ ## Invariants
39
+
40
+ - **A refusal is a value, not an exception.** `spend()` returns a discriminated result carrying
41
+ the rule that fired. Throwing on refusal pushes every consumer into `try/catch` and makes the
42
+ Refusals view harder to build — and refusal is the demo, so it deserves a first-class type.
43
+ Throw only for transport and protocol failures.
44
+ - **Amounts cross the wire as decimal strings**, parsed to `MicroUsdc` on the way in. `bigint`
45
+ does not survive `JSON.stringify`.
46
+ - **Types are re-exported from `@0xdivyanshh/tab-protocol`, never redefined.** A second copy will drift.
47
+ - **Retries are safe.** `spend` carries an idempotency key so a network retry cannot double-spend.
48
+ - **No key material in the constructor.** If the SDK ever accepts a private key, the whole claim
49
+ is gone.
50
+
51
+ ## Publishing
52
+
53
+ Versioned with changesets. Once an agent depends on this, breaking changes cost someone a
54
+ redeploy — so treat exports as a contract from the first release.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The HTTP client.
3
+ *
4
+ * Thin on purpose. `boundaries.json` forbids `@hiero-ledger/sdk`, `ioredis` and
5
+ * `drizzle-orm` here, and that constraint carries the product claim: the agent
6
+ * holds no key and signs nothing, so the library it installs should not even be
7
+ * ABLE to sign. If this bundled the Hedera SDK the claim would rest on us not
8
+ * having used it; this way it rests on a check anyone can run.
9
+ *
10
+ * Browser-safe for the same reason — `apps/web` imports this, and a browser
11
+ * bundle must not be able to reach a signing path or a database driver.
12
+ */
13
+ export interface TabClientConfig {
14
+ /** The gateway's base URL. */
15
+ baseUrl: string;
16
+ /**
17
+ * Bearer token, if the deployment requires one.
18
+ *
19
+ * NOT a private key, and there is deliberately no way to pass one. If this
20
+ * constructor ever accepts key material the whole claim is gone.
21
+ */
22
+ token?: string;
23
+ /** Per-request timeout. Default 120s — a spend waits on x402 settlement. */
24
+ timeoutMs?: number;
25
+ /** Retries for transport failures only. Default 2. */
26
+ maxRetries?: number;
27
+ /** Injectable for tests and for runtimes with a non-global fetch. */
28
+ fetch?: typeof globalThis.fetch;
29
+ }
30
+ export declare class TabClient {
31
+ private readonly baseUrl;
32
+ private readonly token?;
33
+ private readonly timeoutMs;
34
+ private readonly maxRetries;
35
+ private readonly doFetch;
36
+ constructor(config: TabClientConfig);
37
+ /**
38
+ * One request, with retries for transport failures only.
39
+ *
40
+ * A 4xx or 5xx is NOT retried. The gateway answered — retrying an answer we
41
+ * did not like is how a refused spend becomes six refused spends, and how a
42
+ * 500 mid-settlement becomes a double payment. Only a thrown fetch (DNS,
43
+ * connection reset, timeout) is retried, and only because in that case the
44
+ * caller has no answer at all.
45
+ */
46
+ request<T>(method: 'GET' | 'POST', path: string, body?: unknown): Promise<T>;
47
+ }
48
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;CAChC;AAeD,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAErC,MAAM,EAAE,eAAe;IA4BnC;;;;;;;;OAQG;IACG,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;CA+FnF"}
package/dist/client.js ADDED
@@ -0,0 +1,140 @@
1
+ import { TabProtocolError, TabUnavailableError } from "./errors.js";
2
+ const DEFAULTS = {
3
+ /*
4
+ * 120 seconds, which looks absurd for an HTTP client and is not.
5
+ *
6
+ * A spend waits on an x402 HTS settlement, measured at 25-39s end to end,
7
+ * plus a hold write awaiting consensus. A 30s default would time out on
8
+ * perfectly healthy spends and the caller would retry — against a gateway
9
+ * that had already taken the hold.
10
+ */
11
+ timeoutMs: 120_000,
12
+ maxRetries: 2,
13
+ };
14
+ export class TabClient {
15
+ baseUrl;
16
+ token;
17
+ timeoutMs;
18
+ maxRetries;
19
+ doFetch;
20
+ constructor(config) {
21
+ // Trailing slash removed once, here, so every path can be written `/v1/...`
22
+ // without a caller having to know whether it will be doubled.
23
+ this.baseUrl = config.baseUrl.replace(/\/+$/, '');
24
+ if (config.token)
25
+ this.token = config.token;
26
+ this.timeoutMs = config.timeoutMs ?? DEFAULTS.timeoutMs;
27
+ this.maxRetries = config.maxRetries ?? DEFAULTS.maxRetries;
28
+ /*
29
+ * BOUND to globalThis, and that bind is load-bearing in a browser.
30
+ *
31
+ * `fetch` is a method on Window, and the spec requires it to be called with
32
+ * a Window receiver. Stored bare and invoked as `this.doFetch(...)`, the
33
+ * receiver becomes this client instance and the browser throws
34
+ *
35
+ * TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
36
+ *
37
+ * before a single byte leaves the machine. Node's fetch has no such
38
+ * requirement, so every test here and every server-side caller passed while
39
+ * the console failed on EVERY request — and failed as a transport error,
40
+ * which reads exactly like an unreachable gateway. It cost hours of
41
+ * chasing CORS and cold starts that were never involved.
42
+ *
43
+ * An INJECTED fetch is used as given: it is the caller's function and
44
+ * binding it to globalThis would be us rewriting their receiver.
45
+ */
46
+ this.doFetch = config.fetch ?? globalThis.fetch.bind(globalThis);
47
+ }
48
+ /**
49
+ * One request, with retries for transport failures only.
50
+ *
51
+ * A 4xx or 5xx is NOT retried. The gateway answered — retrying an answer we
52
+ * did not like is how a refused spend becomes six refused spends, and how a
53
+ * 500 mid-settlement becomes a double payment. Only a thrown fetch (DNS,
54
+ * connection reset, timeout) is retried, and only because in that case the
55
+ * caller has no answer at all.
56
+ */
57
+ async request(method, path, body) {
58
+ const url = `${this.baseUrl}${path}`;
59
+ let lastError;
60
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
61
+ const controller = new AbortController();
62
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
63
+ try {
64
+ const response = await this.doFetch(url, {
65
+ method,
66
+ headers: {
67
+ 'content-type': 'application/json',
68
+ ...(this.token ? { authorization: `Bearer ${this.token}` } : {}),
69
+ },
70
+ ...(body === undefined ? {} : { body: JSON.stringify(body) }),
71
+ signal: controller.signal,
72
+ });
73
+ const text = await response.text();
74
+ let parsed;
75
+ try {
76
+ parsed = text.length > 0 ? JSON.parse(text) : null;
77
+ }
78
+ catch {
79
+ throw new TabProtocolError(`The gateway returned ${response.status} with a body that is not JSON`, response.status, text.slice(0, 512));
80
+ }
81
+ /*
82
+ * A REFUSAL comes back 200 with `{ refused: ... }`, so it lands here as
83
+ * a normal response and the caller gets a value. A non-2xx really is a
84
+ * protocol failure — the gateway could not answer the question.
85
+ */
86
+ if (!response.ok) {
87
+ throw new TabProtocolError(`The gateway returned ${response.status}`, response.status, parsed);
88
+ }
89
+ return parsed;
90
+ }
91
+ catch (error) {
92
+ if (error instanceof TabProtocolError)
93
+ throw error;
94
+ lastError = error;
95
+ // Backoff only between attempts, never after the last one.
96
+ if (attempt < this.maxRetries) {
97
+ await new Promise((resolve) => setTimeout(resolve, 250 * 2 ** attempt));
98
+ }
99
+ }
100
+ finally {
101
+ clearTimeout(timer);
102
+ }
103
+ }
104
+ /*
105
+ * The outcome is UNKNOWN, and saying so is the whole point of this message.
106
+ *
107
+ * The first draft said "nothing was spent", which is false and dangerously
108
+ * reassuring: a timeout can mean the gateway took the hold, paid the seller,
109
+ * and the RESPONSE was lost. A client that tells a caller it is safe to
110
+ * retry blindly is how one spend becomes two.
111
+ *
112
+ * The idempotency key is what makes a retry safe, so the caller is told to
113
+ * reuse it rather than told not to worry.
114
+ */
115
+ /*
116
+ * The CAUSE is named in the message, not only attached as `cause`.
117
+ *
118
+ * "Could not reach the gateway" is true of a CORS rejection, a DNS
119
+ * failure, a refused connection and a timeout alike — and those have
120
+ * completely different fixes. The distinguishing detail was being carried
121
+ * on a property nothing displays, so a console showing this error sent us
122
+ * hunting the wrong problem more than once.
123
+ *
124
+ * An AbortError here is always OUR timeout firing, so it is named as one:
125
+ * "aborted" reads like a cancelled request and hides the fact that a
126
+ * deadline was exceeded.
127
+ */
128
+ const because = lastError instanceof Error
129
+ ? lastError.name === 'AbortError' || lastError.name === 'TimeoutError'
130
+ ? `timed out after ${this.timeoutMs}ms`
131
+ : `${lastError.name}: ${lastError.message}`
132
+ : String(lastError);
133
+ throw new TabUnavailableError(`Could not reach the Tab gateway at ${url} after ${this.maxRetries + 1} attempt(s) ` +
134
+ `(${because}). ` +
135
+ 'The outcome is UNKNOWN — a transport failure cannot distinguish "never arrived" from ' +
136
+ '"succeeded and the response was lost". Retry with the SAME idempotencyKey: the gateway ' +
137
+ 'treats it as the hold id, so a repeat cannot double-spend. Do not retry with a new key.', lastError);
138
+ }
139
+ }
140
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Typed errors — and the one thing that is deliberately NOT an error.
3
+ *
4
+ * **A refusal is a value, not an exception.** `spend()` returns a discriminated
5
+ * result carrying the rule that fired. Throwing on refusal would push every
6
+ * consumer into `try/catch`, and refusal is the product demonstrating that
7
+ * underwriting works — it deserves a first-class type, not a control-flow
8
+ * escape.
9
+ *
10
+ * These throw only for transport and protocol failures: the gateway was
11
+ * unreachable, or it answered something this client cannot interpret.
12
+ */
13
+ /** The gateway could not be reached, or did not answer in time. */
14
+ export declare class TabUnavailableError extends Error {
15
+ readonly kind: "unavailable";
16
+ readonly reason: unknown;
17
+ constructor(message: string, reason?: unknown);
18
+ }
19
+ /**
20
+ * The gateway answered, but not with something this client understands.
21
+ *
22
+ * Carries the status and the raw body. A caller debugging a version mismatch
23
+ * needs to see what actually came back — "invalid response" with the evidence
24
+ * discarded is the least useful error a client can raise.
25
+ */
26
+ export declare class TabProtocolError extends Error {
27
+ readonly kind: "protocol";
28
+ readonly status: number;
29
+ readonly body: unknown;
30
+ constructor(message: string, status: number, body: unknown);
31
+ }
32
+ /** A caller mistake — a malformed amount, a missing tab id. */
33
+ export declare class TabInvalidError extends Error {
34
+ readonly kind: "invalid";
35
+ constructor(message: string);
36
+ }
37
+ export type TabError = TabUnavailableError | TabProtocolError | TabInvalidError;
38
+ export declare function isTabError(error: unknown): error is TabError;
39
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,mEAAmE;AACnE,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAG,aAAa,CAAS;IAStC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;gBACZ,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO;CAK9C;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAS;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;gBACV,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO;CAM3D;AAED,+DAA+D;AAC/D,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAS;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,MAAM,QAAQ,GAAG,mBAAmB,GAAG,gBAAgB,GAAG,eAAe,CAAA;AAE/E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAM5D"}
package/dist/errors.js ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Typed errors — and the one thing that is deliberately NOT an error.
3
+ *
4
+ * **A refusal is a value, not an exception.** `spend()` returns a discriminated
5
+ * result carrying the rule that fired. Throwing on refusal would push every
6
+ * consumer into `try/catch`, and refusal is the product demonstrating that
7
+ * underwriting works — it deserves a first-class type, not a control-flow
8
+ * escape.
9
+ *
10
+ * These throw only for transport and protocol failures: the gateway was
11
+ * unreachable, or it answered something this client cannot interpret.
12
+ */
13
+ /** The gateway could not be reached, or did not answer in time. */
14
+ export class TabUnavailableError extends Error {
15
+ kind = 'unavailable';
16
+ /*
17
+ * Fields declared and assigned, not TS parameter properties.
18
+ *
19
+ * `erasableSyntaxOnly` is on across the repo so Node can run the TypeScript
20
+ * directly with `--experimental-strip-types`, and parameter properties are
21
+ * not erasable — they generate assignments. The constraint is repo-wide; see
22
+ * HANDOFF.
23
+ */
24
+ reason;
25
+ constructor(message, reason) {
26
+ super(message);
27
+ this.name = 'TabUnavailableError';
28
+ this.reason = reason;
29
+ }
30
+ }
31
+ /**
32
+ * The gateway answered, but not with something this client understands.
33
+ *
34
+ * Carries the status and the raw body. A caller debugging a version mismatch
35
+ * needs to see what actually came back — "invalid response" with the evidence
36
+ * discarded is the least useful error a client can raise.
37
+ */
38
+ export class TabProtocolError extends Error {
39
+ kind = 'protocol';
40
+ status;
41
+ body;
42
+ constructor(message, status, body) {
43
+ super(message);
44
+ this.name = 'TabProtocolError';
45
+ this.status = status;
46
+ this.body = body;
47
+ }
48
+ }
49
+ /** A caller mistake — a malformed amount, a missing tab id. */
50
+ export class TabInvalidError extends Error {
51
+ kind = 'invalid';
52
+ constructor(message) {
53
+ super(message);
54
+ this.name = 'TabInvalidError';
55
+ }
56
+ }
57
+ export function isTabError(error) {
58
+ return (error instanceof TabUnavailableError ||
59
+ error instanceof TabProtocolError ||
60
+ error instanceof TabInvalidError);
61
+ }
62
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,mEAAmE;AACnE,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,GAAG,aAAsB,CAAA;IACtC;;;;;;;OAOG;IACM,MAAM,CAAS;IACxB,YAAY,OAAe,EAAE,MAAgB;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAA;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,GAAG,UAAmB,CAAA;IAC1B,MAAM,CAAQ;IACd,IAAI,CAAS;IACtB,YAAY,OAAe,EAAE,MAAc,EAAE,IAAa;QACxD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAA;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAED,+DAA+D;AAC/D,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,GAAG,SAAkB,CAAA;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF;AAID,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,CACL,KAAK,YAAY,mBAAmB;QACpC,KAAK,YAAY,gBAAgB;QACjC,KAAK,YAAY,eAAe,CACjC,CAAA;AACH,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @0xdivyanshh/tab-sdk — the client every other surface is built on.
3
+ *
4
+ * Tier 3. Published, thin, browser-safe. `boundaries.json` forbids
5
+ * `@hiero-ledger/sdk`, `ioredis` and `drizzle-orm` here, and that constraint
6
+ * carries the product claim: the agent holds no key and signs nothing, so the
7
+ * library it installs should not even be ABLE to sign.
8
+ *
9
+ * ```ts
10
+ * const tab = createTab({ baseUrl: 'http://localhost:8080' })
11
+ * const result = await tab.spend({ tab: '0.0.x', url: seller, max: usdc('0.040000') })
12
+ * if (result.outcome === 'refused') console.log(result.rule, result.guidance)
13
+ * ```
14
+ *
15
+ * **A refusal is a value, not an exception.** That is the one thing to know
16
+ * before using this.
17
+ */
18
+ import type { MicroUsdc } from '@0xdivyanshh/tab-money';
19
+ import { type TabClientConfig } from './client.ts';
20
+ import { health } from './receipts.ts';
21
+ import type { CeilingView, CounterpartyWeight, Hold, Quote, ReceiptRow, SettlementView, SpendRequest, SpendResult, TabList, TabState } from './types.ts';
22
+ export interface Tab {
23
+ spend(request: SpendRequest): Promise<SpendResult>;
24
+ quote(params: {
25
+ tab: string;
26
+ max: MicroUsdc;
27
+ }): Promise<Quote>;
28
+ state(tab: string): Promise<TabState>;
29
+ holds(tab: string): Promise<Hold[]>;
30
+ receipts(tab: string): Promise<ReceiptRow[]>;
31
+ counterparties(tab: string): Promise<CounterpartyWeight[]>;
32
+ /** The ceiling in force, its arithmetic, and the series behind it. */
33
+ ceiling(tab: string): Promise<CeilingView>;
34
+ /** Settled windows, ascending by window. */
35
+ settlements(tab: string): Promise<SettlementView[]>;
36
+ /** The tabs this gateway knows about. NOT a registry — see `TabList`. */
37
+ tabs(): Promise<TabList>;
38
+ health(): Promise<Awaited<ReturnType<typeof health>>>;
39
+ }
40
+ /**
41
+ * The ten verbs, bound to one client.
42
+ *
43
+ * Object-with-methods rather than loose functions because the same surface
44
+ * appears in the Agent Kit plugin, the MCP server and the CLI — defining it
45
+ * once, here, is what stops those three drifting apart.
46
+ *
47
+ * Two of the ten (`spend`, `quote`) act. The other eight only read, and every
48
+ * one of them reads what was PUBLISHED rather than recomputing it: this package
49
+ * cannot import `@0xdivyanshh/tab-scoring` or `@0xdivyanshh/tab-graph`, so it is structurally incapable
50
+ * of offering a second opinion about a ceiling or a weight. That is the point.
51
+ */
52
+ export declare function createTab(config: TabClientConfig): Tab;
53
+ export type { WeightReason } from '@0xdivyanshh/tab-protocol';
54
+ export { TabClient, type TabClientConfig } from './client.ts';
55
+ export { isTabError, type TabError, TabInvalidError, TabProtocolError, TabUnavailableError, } from './errors.ts';
56
+ export { ceiling, counterparties, health, holds, receipts, settlements, tabs } from './receipts.ts';
57
+ export { parseAmount, quote, spend, state } from './spend.ts';
58
+ export type { CeilingInputsView, CeilingView, CounterpartyWeight, Hold, PublishedCeilingView, Quote, ReceiptLeg, ReceiptRow, RefusalCode, SettlementView, SpendFailed, SpendPaid, SpendRefused, SpendRequest, SpendResult, TabList, TabState, TabSummary, } from './types.ts';
59
+ export { BLOCKING_REASONS, isBlocking, isRetryable, REFUSAL_CODES, REFUSAL_GUIDANCE, WEIGHT_REASON_DETAIL, WEIGHT_REASONS, } from './types.ts';
60
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EAA2B,MAAM,EAAsC,MAAM,eAAe,CAAA;AAEnG,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,IAAI,EACJ,KAAK,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,WAAW,EACX,OAAO,EACP,QAAQ,EACT,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,GAAG;IAClB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IAClD,KAAK,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IAC9D,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACrC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IAC5C,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAA;IAC1D,sEAAsE;IACtE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1C,4CAA4C;IAC5C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;IACnD,yEAAyE;IACzE,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAA;CACtD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,GAAG,CActD;AAID,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EACL,UAAU,EACV,KAAK,QAAQ,EACb,eAAe,EACf,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACnG,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAC7D,YAAY,EACV,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,IAAI,EACJ,oBAAoB,EACpB,KAAK,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,WAAW,EACX,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,OAAO,EACP,QAAQ,EACR,UAAU,GACX,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,GACf,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @0xdivyanshh/tab-sdk — the client every other surface is built on.
3
+ *
4
+ * Tier 3. Published, thin, browser-safe. `boundaries.json` forbids
5
+ * `@hiero-ledger/sdk`, `ioredis` and `drizzle-orm` here, and that constraint
6
+ * carries the product claim: the agent holds no key and signs nothing, so the
7
+ * library it installs should not even be ABLE to sign.
8
+ *
9
+ * ```ts
10
+ * const tab = createTab({ baseUrl: 'http://localhost:8080' })
11
+ * const result = await tab.spend({ tab: '0.0.x', url: seller, max: usdc('0.040000') })
12
+ * if (result.outcome === 'refused') console.log(result.rule, result.guidance)
13
+ * ```
14
+ *
15
+ * **A refusal is a value, not an exception.** That is the one thing to know
16
+ * before using this.
17
+ */
18
+ import { TabClient } from "./client.js";
19
+ import { ceiling, counterparties, health, holds, receipts, settlements, tabs } from "./receipts.js";
20
+ import { quote, spend, state } from "./spend.js";
21
+ /**
22
+ * The ten verbs, bound to one client.
23
+ *
24
+ * Object-with-methods rather than loose functions because the same surface
25
+ * appears in the Agent Kit plugin, the MCP server and the CLI — defining it
26
+ * once, here, is what stops those three drifting apart.
27
+ *
28
+ * Two of the ten (`spend`, `quote`) act. The other eight only read, and every
29
+ * one of them reads what was PUBLISHED rather than recomputing it: this package
30
+ * cannot import `@0xdivyanshh/tab-scoring` or `@0xdivyanshh/tab-graph`, so it is structurally incapable
31
+ * of offering a second opinion about a ceiling or a weight. That is the point.
32
+ */
33
+ export function createTab(config) {
34
+ const client = new TabClient(config);
35
+ return {
36
+ spend: (request) => spend(client, request),
37
+ quote: (params) => quote(client, params),
38
+ state: (tab) => state(client, tab),
39
+ holds: (tab) => holds(client, tab),
40
+ receipts: (tab) => receipts(client, tab),
41
+ counterparties: (tab) => counterparties(client, tab),
42
+ ceiling: (tab) => ceiling(client, tab),
43
+ settlements: (tab) => settlements(client, tab),
44
+ tabs: () => tabs(client),
45
+ health: () => health(client),
46
+ };
47
+ }
48
+ export { TabClient } from "./client.js";
49
+ export { isTabError, TabInvalidError, TabProtocolError, TabUnavailableError, } from "./errors.js";
50
+ export { ceiling, counterparties, health, holds, receipts, settlements, tabs } from "./receipts.js";
51
+ export { parseAmount, quote, spend, state } from "./spend.js";
52
+ export { BLOCKING_REASONS, isBlocking, isRetryable, REFUSAL_CODES, REFUSAL_GUIDANCE, WEIGHT_REASON_DETAIL, WEIGHT_REASONS, } from "./types.js";
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,SAAS,EAAwB,MAAM,aAAa,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACnG,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AA8BhD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,MAAuB;IAC/C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;IACpC,OAAO;QACL,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;QAC1C,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC;QACxC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC;QAClC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC;QAClC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;QACxC,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC;QACpD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;QACtC,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC;QAC9C,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;QACxB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;KAC7B,CAAA;AACH,CAAC;AAKD,OAAO,EAAE,SAAS,EAAwB,MAAM,aAAa,CAAA;AAC7D,OAAO,EACL,UAAU,EAEV,eAAe,EACf,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACnG,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAqB7D,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,GACf,MAAM,YAAY,CAAA"}
@@ -0,0 +1,81 @@
1
+ import type { TabClient } from './client.ts';
2
+ import type { CeilingView, CounterpartyWeight, Hold, ReceiptRow, SettlementView, TabList } from './types.ts';
3
+ /**
4
+ * Receipt history and pending holds.
5
+ *
6
+ * Both read the gateway's projection rather than HCS directly, because this
7
+ * package must stay browser-safe and a browser has no business walking a topic.
8
+ * A consumer that wants to verify rather than display should run
9
+ * `pnpm verify-tab`, which replays the topic itself and trusts nothing we say.
10
+ */
11
+ export declare function holds(client: TabClient, tab: string): Promise<Hold[]>;
12
+ export declare function receipts(client: TabClient, tab: string): Promise<ReceiptRow[]>;
13
+ /** Is the gateway up, and which network and window is it on? */
14
+ export declare function health(client: TabClient): Promise<{
15
+ ok: boolean;
16
+ network: string;
17
+ token: string;
18
+ window: number;
19
+ demoMode: boolean;
20
+ /**
21
+ * The HCS topics this gateway is actually reading.
22
+ *
23
+ * Served so a reader can go and check for themselves, and taken from the
24
+ * gateway rather than from the consumer's own config so the two cannot
25
+ * disagree — a "view on HashScan" link that points somewhere other than the
26
+ * data it sits beside is worse than no link.
27
+ *
28
+ * Absent from an older gateway that did not serve them, in which case a
29
+ * caller should show no link rather than guess at one.
30
+ */
31
+ topics?: {
32
+ receipts: string;
33
+ ceilings: string;
34
+ settlements: string;
35
+ };
36
+ }>;
37
+ /**
38
+ * Published independence weights for a tab's counterparties.
39
+ *
40
+ * Reason codes are VALIDATED against `WEIGHT_REASONS`, not cast — an unknown
41
+ * reason from a newer server is dropped rather than typed as a real one, for
42
+ * the same reason an unknown refusal code is: the console would otherwise
43
+ * render a rule that does not exist, and `isBlocking` would answer confidently
44
+ * about it.
45
+ */
46
+ export declare function counterparties(client: TabClient, tab: string): Promise<CounterpartyWeight[]>;
47
+ /**
48
+ * The ceiling in force, its arithmetic, and the series behind it.
49
+ *
50
+ * Read from what the ENGINE published, never recomputed — the SDK is
51
+ * browser-safe and cannot import `@0xdivyanshh/tab-scoring`, and that is the right
52
+ * constraint. A client that recomputed the ceiling would hand a viewer a second
53
+ * answer to compare against the topic, and two answers is worse than one even
54
+ * when they agree.
55
+ *
56
+ * `published: false` is not an error. It means the engine has not run for this
57
+ * tab yet and the starter ceiling is in force — `enforced` says what that is.
58
+ */
59
+ export declare function ceiling(client: TabClient, tab: string): Promise<CeilingView>;
60
+ /**
61
+ * Settled windows, ascending by window.
62
+ *
63
+ * Ordered by WINDOW rather than by arrival: a repaired or late settlement lands
64
+ * on the topic after the windows that follow it, and a table sorted by
65
+ * timestamp would put window 41 above window 39 with no explanation.
66
+ *
67
+ * The gross legs come through as absent when the topic did not carry them. A
68
+ * caller must render that as "not published", never as zero.
69
+ */
70
+ export declare function settlements(client: TabClient, tab: string): Promise<SettlementView[]>;
71
+ /**
72
+ * The tabs this gateway knows about.
73
+ *
74
+ * Named `tabs`, not `registry`, and the response carries
75
+ * `registrationEnforced: false` so a caller cannot mistake it for one. Nothing
76
+ * writes a `register` message yet — one Starter Tab per funding root is
77
+ * unenforced and the README labels it OPEN — so a tab appears here the first
78
+ * time it spends or earns, and there is no registration time to report.
79
+ */
80
+ export declare function tabs(client: TabClient): Promise<TabList>;
81
+ //# sourceMappingURL=receipts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipts.d.ts","sourceRoot":"","sources":["../src/receipts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAG5C,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,IAAI,EAEJ,UAAU,EACV,cAAc,EACd,OAAO,EAER,MAAM,YAAY,CAAA;AAenB;;;;;;;GAOG;AAEH,wBAAsB,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAW3E;AAED,wBAAsB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA+BpF;AAED,gEAAgE;AAChE,wBAAsB,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IACvD,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,OAAO,CAAA;IACjB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;CACrE,CAAC,CAmBD;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA0C/B;AAqDD;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBlF;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA6B3F;AAED;;;;;;;;GAQG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CA8C9D"}