@tollbooth-dpyc/web 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -1
- package/dist/client.d.ts +13 -1
- package/dist/client.js +18 -2
- package/dist/debugLog.js +5 -2
- package/dist/errorReport.d.ts +5 -0
- package/dist/errorReport.js +14 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/inlineProof.d.ts +8 -0
- package/dist/inlineProof.js +15 -1
- package/dist/networkError.d.ts +29 -0
- package/dist/networkError.js +61 -0
- package/dist/react/CouponsPanel.d.ts +52 -0
- package/dist/react/CouponsPanel.js +98 -0
- package/dist/react/ErrorBoundary.d.ts +55 -0
- package/dist/react/ErrorBoundary.js +49 -0
- package/dist/react/PagedTable.d.ts +64 -0
- package/dist/react/PagedTable.js +28 -0
- package/dist/react/TableFilter.d.ts +93 -0
- package/dist/react/TableFilter.js +68 -0
- package/dist/react/ThemeToggle.d.ts +22 -0
- package/dist/react/ThemeToggle.js +11 -0
- package/dist/react/WalletCard.d.ts +3 -0
- package/dist/react/WalletCard.js +19 -53
- package/dist/react/WalletPage.d.ts +70 -0
- package/dist/react/WalletPage.js +104 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.js +8 -0
- package/dist/react/useSession.d.ts +2 -0
- package/dist/react/useSession.js +2 -1
- package/dist/react/useTheme.d.ts +7 -0
- package/dist/react/useTheme.js +44 -0
- package/dist/react/useTopUp.d.ts +30 -0
- package/dist/react/useTopUp.js +74 -0
- package/dist/standardTools.d.ts +325 -16
- package/dist/standardTools.js +58 -4
- package/dist/table.d.ts +52 -0
- package/dist/table.js +95 -0
- package/dist/theme.d.ts +40 -0
- package/dist/theme.js +76 -0
- package/dist/wallet.d.ts +85 -0
- package/dist/wallet.js +153 -0
- package/package.json +1 -1
- package/theme.css +22 -0
package/dist/react/useSession.js
CHANGED
|
@@ -28,6 +28,7 @@ export function useSession() {
|
|
|
28
28
|
setState(read());
|
|
29
29
|
setNotice("");
|
|
30
30
|
}, []);
|
|
31
|
+
const dismissNotice = useCallback(() => setNotice(""), []);
|
|
31
32
|
useEffect(() => onProofExpired(() => {
|
|
32
33
|
// A tab that can sign for THIS npub lost nothing.
|
|
33
34
|
if (canSignFor(currentClaim()))
|
|
@@ -35,5 +36,5 @@ export function useSession() {
|
|
|
35
36
|
setNotice("Your session lapsed while you were away. Sign in again to carry on.");
|
|
36
37
|
setState(read());
|
|
37
38
|
}), []);
|
|
38
|
-
return { ...state, notice, refresh, signOut };
|
|
39
|
+
return { ...state, notice, dismissNotice, refresh, signOut };
|
|
39
40
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The theme pick as React state: persisted under `<prefix>:theme`, applied to
|
|
3
|
+
* <html>, followed across tabs, and — in "system" — following the OS live.
|
|
4
|
+
* Call `bootstrapTheme()` in main.tsx too, so the first frame is right.
|
|
5
|
+
*/
|
|
6
|
+
import { type Theme } from "../theme.ts";
|
|
7
|
+
export declare function useTheme(fallback?: Theme): [Theme, (next: Theme) => void];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The theme pick as React state: persisted under `<prefix>:theme`, applied to
|
|
3
|
+
* <html>, followed across tabs, and — in "system" — following the OS live.
|
|
4
|
+
* Call `bootstrapTheme()` in main.tsx too, so the first frame is right.
|
|
5
|
+
*/
|
|
6
|
+
import { useCallback, useEffect, useState } from "react";
|
|
7
|
+
import { applyTheme, readTheme, themeStorageKey, writeTheme } from "../theme.js";
|
|
8
|
+
export function useTheme(fallback = "dark") {
|
|
9
|
+
const [theme, setTheme] = useState(() => readTheme(fallback));
|
|
10
|
+
// Another tab changed it.
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
let key;
|
|
13
|
+
try {
|
|
14
|
+
key = themeStorageKey();
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const onStorage = (e) => {
|
|
20
|
+
if (e.key !== key)
|
|
21
|
+
return;
|
|
22
|
+
const next = readTheme(fallback);
|
|
23
|
+
setTheme(next);
|
|
24
|
+
applyTheme(next);
|
|
25
|
+
};
|
|
26
|
+
window.addEventListener("storage", onStorage);
|
|
27
|
+
return () => window.removeEventListener("storage", onStorage);
|
|
28
|
+
}, [fallback]);
|
|
29
|
+
// In "system", the OS changed its mind.
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (theme !== "system" || !window.matchMedia)
|
|
32
|
+
return;
|
|
33
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
34
|
+
const onChange = () => applyTheme("system");
|
|
35
|
+
mq.addEventListener("change", onChange);
|
|
36
|
+
return () => mq.removeEventListener("change", onChange);
|
|
37
|
+
}, [theme]);
|
|
38
|
+
const update = useCallback((next) => {
|
|
39
|
+
writeTheme(next);
|
|
40
|
+
applyTheme(next);
|
|
41
|
+
setTheme(next);
|
|
42
|
+
}, []);
|
|
43
|
+
return [theme, update];
|
|
44
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Lightning top-up as a hook: purchase_credits → an invoice → check_payment
|
|
3
|
+
* until it settles, expires or the patron gives up.
|
|
4
|
+
*
|
|
5
|
+
* The state machine is `topUpReducer` (framework-free, tested). This adds the
|
|
6
|
+
* calls and the polling: while an invoice is out and the tab is visible,
|
|
7
|
+
* check_payment runs every `pollMs` — it is free and safe to repeat — up to
|
|
8
|
+
* `maxChecks` times, after which the patron's own "check" still works.
|
|
9
|
+
*/
|
|
10
|
+
import { type TopUpState } from "../wallet.ts";
|
|
11
|
+
export interface UseTopUpOptions {
|
|
12
|
+
/** How often to check an open invoice, in ms. 0 turns polling off. Default 5000. */
|
|
13
|
+
pollMs?: number;
|
|
14
|
+
/** Stop polling after this many checks. Default 60 (five minutes at the default rate). */
|
|
15
|
+
maxChecks?: number;
|
|
16
|
+
/** Called once when an invoice settles, with the sats credited — refresh a balance here. */
|
|
17
|
+
onSettled?: (credited: number) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface TopUp {
|
|
20
|
+
state: TopUpState;
|
|
21
|
+
/** Ask the service for an invoice of `sats`. Ignored while one is being made or is out. */
|
|
22
|
+
create: (sats: number) => void;
|
|
23
|
+
/** Check the open invoice now. */
|
|
24
|
+
check: () => void;
|
|
25
|
+
/** Drop the open invoice (it simply expires at BTCPay). */
|
|
26
|
+
cancel: () => void;
|
|
27
|
+
/** Back to idle after a settlement or failure. */
|
|
28
|
+
reset: () => void;
|
|
29
|
+
}
|
|
30
|
+
export declare function useTopUp({ pollMs, maxChecks, onSettled }?: UseTopUpOptions): TopUp;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Lightning top-up as a hook: purchase_credits → an invoice → check_payment
|
|
3
|
+
* until it settles, expires or the patron gives up.
|
|
4
|
+
*
|
|
5
|
+
* The state machine is `topUpReducer` (framework-free, tested). This adds the
|
|
6
|
+
* calls and the polling: while an invoice is out and the tab is visible,
|
|
7
|
+
* check_payment runs every `pollMs` — it is free and safe to repeat — up to
|
|
8
|
+
* `maxChecks` times, after which the patron's own "check" still works.
|
|
9
|
+
*/
|
|
10
|
+
import { useCallback, useEffect, useReducer, useRef, useState } from "react";
|
|
11
|
+
import { checkPayment, purchaseCredits } from "../standardTools.js";
|
|
12
|
+
import { shouldPoll, TOP_UP_IDLE, topUpReducer } from "../wallet.js";
|
|
13
|
+
function messageOf(e) {
|
|
14
|
+
return e instanceof Error ? e.message : String(e);
|
|
15
|
+
}
|
|
16
|
+
function tabHidden() {
|
|
17
|
+
return typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
18
|
+
}
|
|
19
|
+
export function useTopUp({ pollMs = 5000, maxChecks = 60, onSettled } = {}) {
|
|
20
|
+
const [state, dispatch] = useReducer(topUpReducer, TOP_UP_IDLE);
|
|
21
|
+
const latest = useRef(state);
|
|
22
|
+
latest.current = state;
|
|
23
|
+
const settledRef = useRef(onSettled);
|
|
24
|
+
settledRef.current = onSettled;
|
|
25
|
+
// Bumped when the tab comes back, so a poll skipped while hidden is re-armed.
|
|
26
|
+
const [wake, setWake] = useState(0);
|
|
27
|
+
const create = useCallback((sats) => {
|
|
28
|
+
const s = latest.current;
|
|
29
|
+
if (s.phase === "creating" || s.phase === "awaiting")
|
|
30
|
+
return;
|
|
31
|
+
dispatch({ type: "create", sats });
|
|
32
|
+
purchaseCredits(sats).then((result) => dispatch({ type: "created", result }), (e) => dispatch({ type: "error", message: messageOf(e) }));
|
|
33
|
+
}, []);
|
|
34
|
+
const check = useCallback(() => {
|
|
35
|
+
const s = latest.current;
|
|
36
|
+
if (s.phase !== "awaiting" || s.checking)
|
|
37
|
+
return;
|
|
38
|
+
const id = s.invoice.id;
|
|
39
|
+
dispatch({ type: "check" });
|
|
40
|
+
checkPayment(id).then((result) => {
|
|
41
|
+
// A late answer for an invoice the patron has since cancelled is dropped.
|
|
42
|
+
const now = latest.current;
|
|
43
|
+
if (now.phase === "awaiting" && now.invoice.id === id)
|
|
44
|
+
dispatch({ type: "checked", result });
|
|
45
|
+
}, (e) => dispatch({ type: "error", message: messageOf(e) }));
|
|
46
|
+
}, []);
|
|
47
|
+
const cancel = useCallback(() => dispatch({ type: "cancel" }), []);
|
|
48
|
+
const reset = useCallback(() => dispatch({ type: "reset" }), []);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (!(pollMs > 0) || !shouldPoll(state, maxChecks))
|
|
51
|
+
return;
|
|
52
|
+
const t = setTimeout(() => {
|
|
53
|
+
if (tabHidden())
|
|
54
|
+
return; // re-armed by the visibility listener below
|
|
55
|
+
check();
|
|
56
|
+
}, pollMs);
|
|
57
|
+
return () => clearTimeout(t);
|
|
58
|
+
}, [state, pollMs, maxChecks, check, wake]);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (typeof document === "undefined")
|
|
61
|
+
return;
|
|
62
|
+
const onVisible = () => {
|
|
63
|
+
if (!tabHidden())
|
|
64
|
+
setWake((n) => n + 1);
|
|
65
|
+
};
|
|
66
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
67
|
+
return () => document.removeEventListener("visibilitychange", onVisible);
|
|
68
|
+
}, []);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (state.phase === "settled")
|
|
71
|
+
settledRef.current?.(state.credited);
|
|
72
|
+
}, [state]);
|
|
73
|
+
return { state, create, check, cancel, reset };
|
|
74
|
+
}
|
package/dist/standardTools.d.ts
CHANGED
|
@@ -2,14 +2,45 @@
|
|
|
2
2
|
* Typed wrappers for the tools every operator gets from
|
|
3
3
|
* `register_standard_tools` in the tollbooth-dpyc wheel.
|
|
4
4
|
*/
|
|
5
|
+
/** What a patron must supply beyond the npub proof, per the wheel's `patron_auth_block`. */
|
|
6
|
+
export interface PatronAuth {
|
|
7
|
+
mode: "oauth" | "secure_courier" | "none";
|
|
8
|
+
patron_credentials_required: boolean;
|
|
9
|
+
/** mode "oauth": the provider's credential service. */
|
|
10
|
+
oauth_service?: string;
|
|
11
|
+
/** mode "secure_courier": the service a patron delivers secrets to. */
|
|
12
|
+
credential_service?: string;
|
|
13
|
+
}
|
|
14
|
+
/** The wheel's `service_status`: health and build facts, free and unauthenticated. */
|
|
5
15
|
export interface ServiceStatus {
|
|
16
|
+
success?: boolean;
|
|
17
|
+
service?: string;
|
|
18
|
+
slug?: string;
|
|
19
|
+
version?: string;
|
|
20
|
+
tollbooth_dpyc_version?: string;
|
|
21
|
+
vault_configured?: boolean;
|
|
22
|
+
courier_has_vault?: boolean;
|
|
6
23
|
operator_npub_hash?: string;
|
|
24
|
+
process_id?: number;
|
|
25
|
+
/** Deploy metadata from the environment (commit, build time, …), lower-cased keys. */
|
|
26
|
+
build_info?: Record<string, string> | null;
|
|
27
|
+
patron_auth?: PatronAuth;
|
|
28
|
+
/** Only on a server that runs background jobs. */
|
|
29
|
+
async_jobs?: {
|
|
30
|
+
docket_url_set: boolean;
|
|
31
|
+
backend: string;
|
|
32
|
+
durable_across_recycles: boolean;
|
|
33
|
+
};
|
|
34
|
+
durable_jobs?: {
|
|
35
|
+
modal_app: string | null;
|
|
36
|
+
detached_executor_active: boolean;
|
|
37
|
+
detached_executor_resolved: boolean;
|
|
38
|
+
detached_executor_error: string | null;
|
|
39
|
+
last_dispatch_error: string | null;
|
|
40
|
+
dispatching: boolean;
|
|
41
|
+
};
|
|
7
42
|
lifecycle?: string;
|
|
8
43
|
message?: string;
|
|
9
|
-
version?: string;
|
|
10
|
-
tollbooth_dpyc_version?: string;
|
|
11
|
-
service?: string;
|
|
12
|
-
slug?: string;
|
|
13
44
|
}
|
|
14
45
|
export declare function serviceStatus(): Promise<ServiceStatus>;
|
|
15
46
|
export interface NpubProofResult {
|
|
@@ -45,31 +76,79 @@ export interface ProofStatusResult {
|
|
|
45
76
|
error_code?: string;
|
|
46
77
|
}
|
|
47
78
|
export declare function checkProofStatus(patronNpub: string, dpopToken: string): Promise<ProofStatusResult>;
|
|
79
|
+
/** One credit tranche: a purchase (or grant) and what is left of it. */
|
|
80
|
+
export interface CreditTranche {
|
|
81
|
+
id: string;
|
|
82
|
+
amount_sats: number;
|
|
83
|
+
remaining_sats: number;
|
|
84
|
+
expires_at: string | null;
|
|
85
|
+
created_at: string | null;
|
|
86
|
+
}
|
|
48
87
|
export interface CheckBalanceResult {
|
|
49
88
|
success?: boolean;
|
|
50
89
|
balance_api_sats?: number;
|
|
51
90
|
total_deposited_api_sats?: number;
|
|
52
91
|
total_consumed_api_sats?: number;
|
|
92
|
+
total_expired_api_sats?: number;
|
|
93
|
+
pending_invoices?: number;
|
|
94
|
+
pending_invoice_ids?: string[];
|
|
95
|
+
last_deposit_at?: string | null;
|
|
53
96
|
next_expiration_iso?: string;
|
|
54
97
|
expiring_within_24h_sats?: number;
|
|
98
|
+
active_tranches?: number;
|
|
99
|
+
tranches?: CreditTranche[];
|
|
100
|
+
expired_tranches?: CreditTranche[];
|
|
101
|
+
seed_balance_granted?: boolean;
|
|
102
|
+
/** The ledger could not be read: the figures may be stale or zero. */
|
|
103
|
+
vault_unavailable?: boolean;
|
|
104
|
+
warning?: string;
|
|
105
|
+
today_usage?: Record<string, {
|
|
106
|
+
calls: number;
|
|
107
|
+
api_sats: number;
|
|
108
|
+
}>;
|
|
109
|
+
invoice_summary?: {
|
|
110
|
+
total_invoices: number;
|
|
111
|
+
settled_count: number;
|
|
112
|
+
pending_count: number;
|
|
113
|
+
total_real_sats: number;
|
|
114
|
+
total_api_sats_credited: number;
|
|
115
|
+
};
|
|
55
116
|
error?: string;
|
|
56
117
|
error_code?: string;
|
|
57
118
|
}
|
|
58
119
|
export declare function checkBalance(): Promise<CheckBalanceResult>;
|
|
120
|
+
export interface ConstraintEffect {
|
|
121
|
+
type: string;
|
|
122
|
+
message?: string;
|
|
123
|
+
[key: string]: unknown;
|
|
124
|
+
}
|
|
125
|
+
/** The wheel's `check_price` preview. */
|
|
59
126
|
export interface CheckPriceResult {
|
|
60
127
|
success: boolean;
|
|
61
128
|
tool_id?: string;
|
|
62
|
-
|
|
63
|
-
|
|
129
|
+
tool_name?: string;
|
|
130
|
+
/** "flat" | "flat+multipliers" | "percent" */
|
|
131
|
+
pricing_type?: string;
|
|
132
|
+
base_cost_api_sats?: number | null;
|
|
133
|
+
effective_cost_api_sats?: number | null;
|
|
134
|
+
rate_percent?: number;
|
|
135
|
+
rate_param?: string;
|
|
136
|
+
min_cost_sats?: number;
|
|
137
|
+
multipliers?: Record<string, unknown>;
|
|
138
|
+
constraints_enabled?: boolean;
|
|
139
|
+
constraint_effects?: ConstraintEffect[];
|
|
140
|
+
hint?: string;
|
|
64
141
|
error?: string;
|
|
65
142
|
error_code?: string;
|
|
66
143
|
}
|
|
67
144
|
/**
|
|
68
145
|
* The fare for one tool in api_sats, as the live pricing model resolves it,
|
|
69
|
-
* constraints included — keyed by the tool's frozen UUID
|
|
70
|
-
*
|
|
146
|
+
* constraints included — keyed by the tool's frozen UUID (or its capability
|
|
147
|
+
* name). `toolKwargs` are the call's own parameters, for a tool priced by
|
|
148
|
+
* them (ad valorem, or a multiplier on a categorical argument). Null when
|
|
149
|
+
* unreadable: show the answer without a price rather than invent one.
|
|
71
150
|
*/
|
|
72
|
-
export declare function checkPrice(toolId: string): Promise<number | null>;
|
|
151
|
+
export declare function checkPrice(toolId: string, toolKwargs?: Record<string, unknown>): Promise<number | null>;
|
|
73
152
|
export interface PurchaseCreditsResult {
|
|
74
153
|
success?: boolean;
|
|
75
154
|
invoice_id?: string;
|
|
@@ -89,23 +168,107 @@ export interface CheckPaymentResult {
|
|
|
89
168
|
invoice_id?: string;
|
|
90
169
|
credits_granted?: number;
|
|
91
170
|
balance_api_sats?: number;
|
|
171
|
+
amount_sats?: number;
|
|
172
|
+
/** false: the credit could not be written; nothing was granted. */
|
|
173
|
+
persisted?: boolean;
|
|
174
|
+
source?: string;
|
|
92
175
|
error?: string;
|
|
93
176
|
error_code?: string;
|
|
94
177
|
}
|
|
95
178
|
export declare function checkPayment(invoiceId: string): Promise<CheckPaymentResult>;
|
|
96
|
-
export interface
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
179
|
+
export interface StatementInvoice {
|
|
180
|
+
invoice_id: string;
|
|
181
|
+
status: string;
|
|
182
|
+
amount_sats: number;
|
|
183
|
+
api_sats_credited: number;
|
|
184
|
+
multiplier?: number;
|
|
185
|
+
created_at: string | null;
|
|
186
|
+
settled_at?: string;
|
|
187
|
+
}
|
|
188
|
+
export interface StatementTranche {
|
|
189
|
+
granted_at: string | null;
|
|
190
|
+
original_sats: number;
|
|
191
|
+
remaining_sats: number;
|
|
192
|
+
invoice_id: string | null;
|
|
193
|
+
expires_at?: string;
|
|
194
|
+
}
|
|
195
|
+
export interface StatementToolUsage {
|
|
196
|
+
tool: string;
|
|
197
|
+
calls: number;
|
|
198
|
+
api_sats: number;
|
|
199
|
+
}
|
|
200
|
+
export interface StatementDay {
|
|
201
|
+
date: string;
|
|
202
|
+
total_calls: number;
|
|
203
|
+
total_api_sats: number;
|
|
204
|
+
tools: Record<string, {
|
|
103
205
|
calls: number;
|
|
104
206
|
api_sats: number;
|
|
105
207
|
}>;
|
|
208
|
+
}
|
|
209
|
+
/** The wheel's `account_statement`: history, tranches and usage, newest first. */
|
|
210
|
+
export interface AccountStatementResult {
|
|
211
|
+
success?: boolean;
|
|
212
|
+
generated_at?: string;
|
|
213
|
+
statement_period_days?: number;
|
|
214
|
+
account_summary?: {
|
|
215
|
+
balance_api_sats: number;
|
|
216
|
+
total_deposited_api_sats: number;
|
|
217
|
+
total_consumed_api_sats: number;
|
|
218
|
+
total_expired_api_sats: number;
|
|
219
|
+
};
|
|
220
|
+
purchase_history?: StatementInvoice[];
|
|
221
|
+
active_tranches?: StatementTranche[];
|
|
222
|
+
tool_usage_all_time?: StatementToolUsage[];
|
|
223
|
+
daily_usage?: StatementDay[];
|
|
106
224
|
error?: string;
|
|
225
|
+
error_code?: string;
|
|
107
226
|
}
|
|
108
227
|
export declare function getAccountStatement(days?: number): Promise<AccountStatementResult>;
|
|
228
|
+
export interface PatronCoupon {
|
|
229
|
+
coupon_id: string;
|
|
230
|
+
name: string;
|
|
231
|
+
discount_percent: number;
|
|
232
|
+
valid_from: string;
|
|
233
|
+
valid_until: string;
|
|
234
|
+
uses_per_patron: number | null;
|
|
235
|
+
use_count: number;
|
|
236
|
+
uses_remaining: number | null;
|
|
237
|
+
total_uses: number | null;
|
|
238
|
+
total_remaining: number | null;
|
|
239
|
+
/** active | window_closed | window_not_started | patron_limit | total_limit */
|
|
240
|
+
status: string;
|
|
241
|
+
}
|
|
242
|
+
export interface ListMyCouponsResult {
|
|
243
|
+
success?: boolean;
|
|
244
|
+
count?: number;
|
|
245
|
+
coupons?: PatronCoupon[];
|
|
246
|
+
error?: string;
|
|
247
|
+
error_code?: string;
|
|
248
|
+
}
|
|
249
|
+
export interface RedeemCouponResult {
|
|
250
|
+
success?: boolean;
|
|
251
|
+
coupon_id?: string;
|
|
252
|
+
name?: string;
|
|
253
|
+
discount_percent?: number;
|
|
254
|
+
valid_until?: string;
|
|
255
|
+
uses_remaining?: number | null;
|
|
256
|
+
uses_per_patron?: number | null;
|
|
257
|
+
error?: string;
|
|
258
|
+
error_code?: string;
|
|
259
|
+
}
|
|
260
|
+
export interface ForgetCouponResult {
|
|
261
|
+
success?: boolean;
|
|
262
|
+
coupon_id?: string;
|
|
263
|
+
error?: string;
|
|
264
|
+
error_code?: string;
|
|
265
|
+
}
|
|
266
|
+
/** The coupons this patron has redeemed here. Free. */
|
|
267
|
+
export declare function listMyCoupons(): Promise<ListMyCouponsResult>;
|
|
268
|
+
/** Redeem an operator's code once; the discount then applies on its own. Free. */
|
|
269
|
+
export declare function redeemCoupon(code: string): Promise<RedeemCouponResult>;
|
|
270
|
+
/** Take a coupon off the patron's list. The code stays re-redeemable while its window allows. */
|
|
271
|
+
export declare function forgetCoupon(couponId: string): Promise<ForgetCouponResult>;
|
|
109
272
|
export interface Kind0 {
|
|
110
273
|
name?: string;
|
|
111
274
|
display_name?: string;
|
|
@@ -132,3 +295,149 @@ export interface PublishNostrProfileResult {
|
|
|
132
295
|
}
|
|
133
296
|
/** Relay a kind-0 the BROWSER signed. The wheel verifies it and fans it out. */
|
|
134
297
|
export declare function publishNostrProfile(npub: string, signedEvent: string): Promise<PublishNostrProfileResult>;
|
|
298
|
+
/** Every lifecycle `session_status` reports. */
|
|
299
|
+
export type SessionLifecycle = "ready" | "warming_up" | "misconfigured" | "quota_exceeded" | "not_registered" | "no_identity";
|
|
300
|
+
/** The patron's stored upstream OAuth token, when the operator has a provider. */
|
|
301
|
+
export interface UpstreamOAuth {
|
|
302
|
+
service: string;
|
|
303
|
+
has_access_token: boolean;
|
|
304
|
+
has_refresh_token: boolean;
|
|
305
|
+
refresh_enabled: boolean;
|
|
306
|
+
access_token_expires_at?: number;
|
|
307
|
+
access_token_expires_in_seconds?: number;
|
|
308
|
+
}
|
|
309
|
+
export interface SessionStatusResult {
|
|
310
|
+
success?: boolean;
|
|
311
|
+
lifecycle?: SessionLifecycle;
|
|
312
|
+
message?: string;
|
|
313
|
+
operator_npub?: string;
|
|
314
|
+
/** Why it is not ready, from the failing layer. */
|
|
315
|
+
detail?: string;
|
|
316
|
+
operator_credential_service?: string;
|
|
317
|
+
patron_credential_service?: string;
|
|
318
|
+
upstream_oauth?: UpstreamOAuth;
|
|
319
|
+
/** The vault could not answer — not the same as "never authorized". */
|
|
320
|
+
upstream_oauth_unreadable?: string;
|
|
321
|
+
error?: string;
|
|
322
|
+
error_code?: string;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Is the operator ready to serve? Free, no proof. With `patronNpub`, also the
|
|
326
|
+
* patron's upstream OAuth token expiry, so a page can refresh ahead of time.
|
|
327
|
+
*/
|
|
328
|
+
export declare function sessionStatus(patronNpub?: string): Promise<SessionStatusResult>;
|
|
329
|
+
export interface OnboardingItem {
|
|
330
|
+
field: string;
|
|
331
|
+
/** "identity" | "authority" | "secret" */
|
|
332
|
+
category: string;
|
|
333
|
+
/** "configured" | "missing" | "unknown" */
|
|
334
|
+
status: string;
|
|
335
|
+
how?: string;
|
|
336
|
+
lifecycle?: string;
|
|
337
|
+
delivered_at?: string | null;
|
|
338
|
+
}
|
|
339
|
+
/** The wheel's `get_operator_onboarding_status`: what the operator still has to set up. */
|
|
340
|
+
export interface OperatorOnboardingStatus {
|
|
341
|
+
ready?: boolean;
|
|
342
|
+
configured?: OnboardingItem[];
|
|
343
|
+
missing?: OnboardingItem[];
|
|
344
|
+
optional_missing?: OnboardingItem[];
|
|
345
|
+
summary?: string;
|
|
346
|
+
bootstrap_error?: string;
|
|
347
|
+
vault_ok?: boolean;
|
|
348
|
+
/** Set when the credential vault could not be read: nothing is known either way. */
|
|
349
|
+
vault_situation?: string;
|
|
350
|
+
credential_greeting?: string | null;
|
|
351
|
+
credential_service?: string | null;
|
|
352
|
+
operator_name?: string;
|
|
353
|
+
error?: string;
|
|
354
|
+
error_code?: string;
|
|
355
|
+
}
|
|
356
|
+
export declare function getOperatorOnboardingStatus(): Promise<OperatorOnboardingStatus>;
|
|
357
|
+
/**
|
|
358
|
+
* The operator's own balance at its Authority — what certifies patron top-ups.
|
|
359
|
+
* The Authority's ledger, in the same shape as a patron's `check_balance`.
|
|
360
|
+
*/
|
|
361
|
+
export declare function checkAuthorityBalance(): Promise<CheckBalanceResult>;
|
|
362
|
+
export interface PricingStep {
|
|
363
|
+
id: string;
|
|
364
|
+
type: string;
|
|
365
|
+
params?: Record<string, unknown>;
|
|
366
|
+
patron_npubs?: string[];
|
|
367
|
+
}
|
|
368
|
+
export interface ToolPrice {
|
|
369
|
+
tool_id: string;
|
|
370
|
+
tool_name: string;
|
|
371
|
+
price_sats: number;
|
|
372
|
+
category: string;
|
|
373
|
+
intent: string;
|
|
374
|
+
priced: boolean;
|
|
375
|
+
price_type?: string;
|
|
376
|
+
price_formula?: unknown;
|
|
377
|
+
min_cost?: number;
|
|
378
|
+
max_cost?: number;
|
|
379
|
+
multipliers?: Record<string, unknown>;
|
|
380
|
+
chain?: PricingStep[];
|
|
381
|
+
}
|
|
382
|
+
/** The wheel's `get_pricing_model`. `status` is "ok" or "error". */
|
|
383
|
+
export interface PricingModelResult {
|
|
384
|
+
status?: string;
|
|
385
|
+
model_id?: string | null;
|
|
386
|
+
name?: string | null;
|
|
387
|
+
is_active?: boolean | null;
|
|
388
|
+
tools?: ToolPrice[] | null;
|
|
389
|
+
tranche_lifetime?: {
|
|
390
|
+
target_usage_pct: number;
|
|
391
|
+
ttl_days?: number;
|
|
392
|
+
min_days?: number;
|
|
393
|
+
max_days?: number;
|
|
394
|
+
};
|
|
395
|
+
error?: string;
|
|
396
|
+
}
|
|
397
|
+
/** The operator's active pricing model. Free, no proof. */
|
|
398
|
+
export declare function getPricingModel(): Promise<PricingModelResult>;
|
|
399
|
+
export interface CanonicalIdentity {
|
|
400
|
+
tool_id: string;
|
|
401
|
+
mcp_name: string;
|
|
402
|
+
category: string;
|
|
403
|
+
intent: string;
|
|
404
|
+
capability: string;
|
|
405
|
+
registered: boolean;
|
|
406
|
+
reason?: string;
|
|
407
|
+
}
|
|
408
|
+
/** The wheel's `list_canonical_identities`: every tool's frozen UUID and wire name. */
|
|
409
|
+
export interface CanonicalIdentitiesResult {
|
|
410
|
+
success?: boolean;
|
|
411
|
+
operator_npub?: string;
|
|
412
|
+
count?: number;
|
|
413
|
+
unregistered_count?: number;
|
|
414
|
+
tools?: CanonicalIdentity[];
|
|
415
|
+
unregistered?: Array<{
|
|
416
|
+
mcp_name: string;
|
|
417
|
+
reason: string;
|
|
418
|
+
[key: string]: unknown;
|
|
419
|
+
}>;
|
|
420
|
+
error?: string;
|
|
421
|
+
}
|
|
422
|
+
export declare function listCanonicalIdentities(): Promise<CanonicalIdentitiesResult>;
|
|
423
|
+
export interface PatronCredentialFieldsResult {
|
|
424
|
+
success?: boolean;
|
|
425
|
+
fields?: string[];
|
|
426
|
+
/** Per field, when it was delivered; null for secrets vaulted before stamps. */
|
|
427
|
+
delivered_at?: Record<string, string | null>;
|
|
428
|
+
count?: number;
|
|
429
|
+
error?: string;
|
|
430
|
+
error_code?: string;
|
|
431
|
+
}
|
|
432
|
+
export interface PatronCredentialWriteResult {
|
|
433
|
+
success?: boolean;
|
|
434
|
+
message?: string;
|
|
435
|
+
error?: string;
|
|
436
|
+
error_code?: string;
|
|
437
|
+
}
|
|
438
|
+
/** The names of the patron's stored credential fields — never their values. */
|
|
439
|
+
export declare function getPatronCredentialFields(): Promise<PatronCredentialFieldsResult>;
|
|
440
|
+
/** Set one credential field, leaving the others as they are. */
|
|
441
|
+
export declare function updatePatronCredential(field: string, value: string): Promise<PatronCredentialWriteResult>;
|
|
442
|
+
/** Remove one credential field, leaving the others as they are. */
|
|
443
|
+
export declare function deletePatronCredential(field: string): Promise<PatronCredentialWriteResult>;
|
package/dist/standardTools.js
CHANGED
|
@@ -39,11 +39,16 @@ export function checkBalance() {
|
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* The fare for one tool in api_sats, as the live pricing model resolves it,
|
|
42
|
-
* constraints included — keyed by the tool's frozen UUID
|
|
43
|
-
*
|
|
42
|
+
* constraints included — keyed by the tool's frozen UUID (or its capability
|
|
43
|
+
* name). `toolKwargs` are the call's own parameters, for a tool priced by
|
|
44
|
+
* them (ad valorem, or a multiplier on a categorical argument). Null when
|
|
45
|
+
* unreadable: show the answer without a price rather than invent one.
|
|
44
46
|
*/
|
|
45
|
-
export async function checkPrice(toolId) {
|
|
46
|
-
const r = await callTool("check_price", {
|
|
47
|
+
export async function checkPrice(toolId, toolKwargs) {
|
|
48
|
+
const r = await callTool("check_price", {
|
|
49
|
+
tool_id: toolId,
|
|
50
|
+
...(toolKwargs ? { tool_kwargs: JSON.stringify(toolKwargs) } : {}),
|
|
51
|
+
});
|
|
47
52
|
const v = r.effective_cost_api_sats ?? r.base_cost_api_sats;
|
|
48
53
|
return typeof v === "number" ? v : null;
|
|
49
54
|
}
|
|
@@ -56,6 +61,18 @@ export function checkPayment(invoiceId) {
|
|
|
56
61
|
export function getAccountStatement(days = 30) {
|
|
57
62
|
return callTool("account_statement", { days });
|
|
58
63
|
}
|
|
64
|
+
/** The coupons this patron has redeemed here. Free. */
|
|
65
|
+
export function listMyCoupons() {
|
|
66
|
+
return callTool("list_my_coupons", {});
|
|
67
|
+
}
|
|
68
|
+
/** Redeem an operator's code once; the discount then applies on its own. Free. */
|
|
69
|
+
export function redeemCoupon(code) {
|
|
70
|
+
return callTool("redeem_coupon", { code });
|
|
71
|
+
}
|
|
72
|
+
/** Take a coupon off the patron's list. The code stays re-redeemable while its window allows. */
|
|
73
|
+
export function forgetCoupon(couponId) {
|
|
74
|
+
return callTool("forget_coupon", { coupon_id: couponId });
|
|
75
|
+
}
|
|
59
76
|
export function getNostrProfile(npub) {
|
|
60
77
|
return callTool("get_nostr_profile", { npub });
|
|
61
78
|
}
|
|
@@ -66,3 +83,40 @@ export function publishNostrProfile(npub, signedEvent) {
|
|
|
66
83
|
signed_event: signedEvent,
|
|
67
84
|
});
|
|
68
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Is the operator ready to serve? Free, no proof. With `patronNpub`, also the
|
|
88
|
+
* patron's upstream OAuth token expiry, so a page can refresh ahead of time.
|
|
89
|
+
*/
|
|
90
|
+
export function sessionStatus(patronNpub) {
|
|
91
|
+
return callTool("session_status", patronNpub ? { patron_npub: patronNpub } : {}, { bestEffort: true });
|
|
92
|
+
}
|
|
93
|
+
export function getOperatorOnboardingStatus() {
|
|
94
|
+
return callTool("get_operator_onboarding_status", {}, { bestEffort: true });
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The operator's own balance at its Authority — what certifies patron top-ups.
|
|
98
|
+
* The Authority's ledger, in the same shape as a patron's `check_balance`.
|
|
99
|
+
*/
|
|
100
|
+
export function checkAuthorityBalance() {
|
|
101
|
+
return callTool("check_authority_balance", {}, { bestEffort: true });
|
|
102
|
+
}
|
|
103
|
+
/** The operator's active pricing model. Free, no proof. */
|
|
104
|
+
export function getPricingModel() {
|
|
105
|
+
return callTool("get_pricing_model", {});
|
|
106
|
+
}
|
|
107
|
+
export function listCanonicalIdentities() {
|
|
108
|
+
return callTool("list_canonical_identities", {});
|
|
109
|
+
}
|
|
110
|
+
/** The names of the patron's stored credential fields — never their values. */
|
|
111
|
+
export function getPatronCredentialFields() {
|
|
112
|
+
return callTool("get_patron_credential_fields", {});
|
|
113
|
+
}
|
|
114
|
+
/** Set one credential field, leaving the others as they are. */
|
|
115
|
+
export function updatePatronCredential(field, value) {
|
|
116
|
+
// `field` first: the log's scrubber keys on it to hide `value`.
|
|
117
|
+
return callTool("update_patron_credential", { field, value });
|
|
118
|
+
}
|
|
119
|
+
/** Remove one credential field, leaving the others as they are. */
|
|
120
|
+
export function deletePatronCredential(field) {
|
|
121
|
+
return callTool("delete_patron_credential", { field });
|
|
122
|
+
}
|