@tokenbuddy/tokenbuddy 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/src/buyer-store.d.ts +48 -1
  2. package/dist/src/buyer-store.d.ts.map +1 -1
  3. package/dist/src/buyer-store.js +144 -17
  4. package/dist/src/buyer-store.js.map +1 -1
  5. package/dist/src/cli.d.ts +17 -0
  6. package/dist/src/cli.d.ts.map +1 -1
  7. package/dist/src/cli.js +560 -63
  8. package/dist/src/cli.js.map +1 -1
  9. package/dist/src/daemon.d.ts +11 -5
  10. package/dist/src/daemon.d.ts.map +1 -1
  11. package/dist/src/daemon.js +574 -161
  12. package/dist/src/daemon.js.map +1 -1
  13. package/dist/src/doctor-clawtip-wallet.d.ts +14 -0
  14. package/dist/src/doctor-clawtip-wallet.d.ts.map +1 -0
  15. package/dist/src/doctor-clawtip-wallet.js +54 -0
  16. package/dist/src/doctor-clawtip-wallet.js.map +1 -0
  17. package/dist/src/doctor-diagnostics.d.ts +99 -0
  18. package/dist/src/doctor-diagnostics.d.ts.map +1 -0
  19. package/dist/src/doctor-diagnostics.js +552 -0
  20. package/dist/src/doctor-diagnostics.js.map +1 -0
  21. package/dist/src/init-clawtip-activation.d.ts +48 -0
  22. package/dist/src/init-clawtip-activation.d.ts.map +1 -0
  23. package/dist/src/init-clawtip-activation.js +395 -0
  24. package/dist/src/init-clawtip-activation.js.map +1 -0
  25. package/dist/src/init-payment-options.d.ts +56 -0
  26. package/dist/src/init-payment-options.d.ts.map +1 -0
  27. package/dist/src/init-payment-options.js +165 -0
  28. package/dist/src/init-payment-options.js.map +1 -0
  29. package/dist/src/provider-install.d.ts +37 -2
  30. package/dist/src/provider-install.d.ts.map +1 -1
  31. package/dist/src/provider-install.js +317 -67
  32. package/dist/src/provider-install.js.map +1 -1
  33. package/dist/src/seller-catalog.d.ts +79 -0
  34. package/dist/src/seller-catalog.d.ts.map +1 -0
  35. package/dist/src/seller-catalog.js +126 -0
  36. package/dist/src/seller-catalog.js.map +1 -0
  37. package/dist/src/tb-proxyd.js +13 -2
  38. package/dist/src/tb-proxyd.js.map +1 -1
  39. package/dist/src/terminal-image.d.ts +22 -0
  40. package/dist/src/terminal-image.d.ts.map +1 -0
  41. package/dist/src/terminal-image.js +135 -0
  42. package/dist/src/terminal-image.js.map +1 -0
  43. package/package.json +1 -1
  44. package/src/buyer-store.ts +253 -18
  45. package/src/cli.ts +709 -68
  46. package/src/daemon.ts +651 -167
  47. package/src/doctor-clawtip-wallet.ts +70 -0
  48. package/src/doctor-diagnostics.ts +861 -0
  49. package/src/init-clawtip-activation.ts +487 -0
  50. package/src/init-payment-options.ts +249 -0
  51. package/src/provider-install.ts +426 -76
  52. package/src/seller-catalog.ts +222 -0
  53. package/src/tb-proxyd.ts +14 -2
  54. package/src/terminal-image.ts +187 -0
  55. package/tests/e2e.test.ts +88 -5
  56. package/tests/tokenbuddy.test.ts +1362 -27
@@ -0,0 +1,249 @@
1
+ import * as p from "@clack/prompts";
2
+ import * as fs from "fs";
3
+ import * as os from "os";
4
+ import * as path from "path";
5
+ import type { PaymentConfig } from "./buyer-store.js";
6
+ import type { ProviderCandidate } from "./provider-install.js";
7
+
8
+ export type InitPaymentMethod = "clawtip";
9
+
10
+ export interface InitPaymentOption {
11
+ value: InitPaymentMethod;
12
+ label: string;
13
+ hint?: string;
14
+ }
15
+
16
+ export interface ComingSoonPaymentOption {
17
+ id: string;
18
+ label: string;
19
+ }
20
+
21
+ export interface ExistingClawtipBinding {
22
+ config: Record<string, unknown>;
23
+ resourceUrl?: string;
24
+ orderNo?: string;
25
+ }
26
+
27
+ export interface InitTerminalOption {
28
+ value: string;
29
+ label: string;
30
+ hint?: string;
31
+ }
32
+
33
+ export interface InitTerminalSelectionState {
34
+ installed: InitTerminalOption[];
35
+ options: InitTerminalOption[];
36
+ }
37
+
38
+ export interface OpenClawWalletConfigState {
39
+ expectedPath: string;
40
+ configsDirExists: boolean;
41
+ exists: boolean;
42
+ alternatePaths: string[];
43
+ }
44
+
45
+ export type ClawtipWalletStatus =
46
+ | "ready"
47
+ | "metadata_missing_wallet"
48
+ | "wallet_missing_metadata"
49
+ | "missing";
50
+
51
+ export interface ClawtipWalletReadiness {
52
+ status: ClawtipWalletStatus;
53
+ walletConfig: OpenClawWalletConfigState;
54
+ savedBinding?: ExistingClawtipBinding;
55
+ reusableBinding?: ExistingClawtipBinding;
56
+ message: string;
57
+ }
58
+
59
+ export const OTHER_TERMINAL_OPTION: InitTerminalOption = {
60
+ value: "other",
61
+ label: "Other",
62
+ hint: "I will configure my own terminal using the TokenBuddy proxy endpoints."
63
+ };
64
+
65
+ export const INIT_PAYMENT_OPTIONS: InitPaymentOption[] = [
66
+ {
67
+ value: "clawtip",
68
+ label: "JD ClawTip Pay (Scan QR Code to activate)",
69
+ hint: "1 Fen activation fee"
70
+ }
71
+ ];
72
+
73
+ export const INIT_COMING_SOON_PAYMENT_OPTIONS = [
74
+ {
75
+ id: "wechat-pay",
76
+ label: "WeChat Pay"
77
+ },
78
+ {
79
+ id: "alipay-agent-payment",
80
+ label: "Alipay Agent Payment"
81
+ },
82
+ {
83
+ id: "coinbase-smart-wallet",
84
+ label: "Coinbase Smart Wallet"
85
+ }
86
+ ] satisfies ReadonlyArray<ComingSoonPaymentOption>;
87
+
88
+ export function noteInitComingSoonPayments(
89
+ note: (message?: string, title?: string) => void = p.note
90
+ ): void {
91
+ note(
92
+ INIT_COMING_SOON_PAYMENT_OPTIONS.map((entry) => `- ${entry.label}(接入中)`).join("\n"),
93
+ "更多支付方式"
94
+ );
95
+ }
96
+
97
+ export function buildInitTerminalSelectionState(providers: ProviderCandidate[]): InitTerminalSelectionState {
98
+ const installed = providers
99
+ .filter((provider) => provider.detected && provider.status === "configured")
100
+ .map((provider) => ({
101
+ value: provider.id,
102
+ label: `${provider.name}(已安装)`,
103
+ hint: provider.reason
104
+ }));
105
+
106
+ const options = providers
107
+ .filter((provider) => provider.detected && provider.status !== "configured")
108
+ .map((provider) => ({
109
+ value: provider.id,
110
+ label: provider.name,
111
+ hint: provider.reason
112
+ }));
113
+
114
+ return {
115
+ installed,
116
+ options: [...options, OTHER_TERMINAL_OPTION]
117
+ };
118
+ }
119
+
120
+ export function validateInitTerminalSelection(selected: string[] | undefined): string | undefined {
121
+ if (!selected || selected.length === 0) {
122
+ return "Select at least one terminal or choose Other.";
123
+ }
124
+ return undefined;
125
+ }
126
+
127
+ export function buildInstalledTerminalMessage(installed: InitTerminalOption[]): string | undefined {
128
+ if (installed.length === 0) {
129
+ return undefined;
130
+ }
131
+ return installed
132
+ .map((entry) => `- ${entry.label}${entry.hint ? `\n ${entry.hint}` : ""}`)
133
+ .join("\n");
134
+ }
135
+
136
+ function defaultHomeDir(): string {
137
+ return process.env.HOME || os.homedir();
138
+ }
139
+
140
+ export function inspectOpenClawWalletConfig(home: string = defaultHomeDir()): OpenClawWalletConfigState {
141
+ const configsDir = path.join(home, ".openclaw", "configs");
142
+ const expectedPath = path.join(configsDir, "config.json");
143
+ const configsDirExists = fs.existsSync(configsDir);
144
+ const alternatePaths: string[] = [];
145
+
146
+ if (configsDirExists) {
147
+ try {
148
+ const entries = fs.readdirSync(configsDir)
149
+ .filter((entry) => entry !== "config.json" && !entry.startsWith("."))
150
+ .sort();
151
+ for (const entry of entries) {
152
+ alternatePaths.push(path.join(configsDir, entry));
153
+ }
154
+ } catch {
155
+ // Ignore directory read failures and treat as no alternates.
156
+ }
157
+ }
158
+
159
+ return {
160
+ expectedPath,
161
+ configsDirExists,
162
+ exists: fs.existsSync(expectedPath),
163
+ alternatePaths
164
+ };
165
+ }
166
+
167
+ function stringField(value: unknown): string | undefined {
168
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
169
+ }
170
+
171
+ export function detectExistingClawtipBinding(payment: PaymentConfig | undefined): ExistingClawtipBinding | undefined {
172
+ if (!payment || payment.method !== "clawtip" || !payment.config || typeof payment.config !== "object") {
173
+ return undefined;
174
+ }
175
+ const config = payment.config as Record<string, unknown>;
176
+ const resourceUrl = stringField(config.resourceUrl);
177
+ const orderNo = stringField(config.orderNo);
178
+ if (!resourceUrl && !orderNo) {
179
+ return undefined;
180
+ }
181
+ return {
182
+ config,
183
+ resourceUrl,
184
+ orderNo,
185
+ };
186
+ }
187
+
188
+ export function detectReusableClawtipBinding(
189
+ payment: PaymentConfig | undefined,
190
+ walletConfig: OpenClawWalletConfigState
191
+ ): ExistingClawtipBinding | undefined {
192
+ if (!walletConfig.exists) {
193
+ return undefined;
194
+ }
195
+ return detectExistingClawtipBinding(payment);
196
+ }
197
+
198
+ export function inspectClawtipWalletReadiness(
199
+ payment: PaymentConfig | undefined,
200
+ walletConfig: OpenClawWalletConfigState = inspectOpenClawWalletConfig(),
201
+ ): ClawtipWalletReadiness {
202
+ const savedBinding = detectExistingClawtipBinding(payment);
203
+ const reusableBinding = detectReusableClawtipBinding(payment, walletConfig);
204
+
205
+ if (reusableBinding) {
206
+ return {
207
+ status: "ready",
208
+ walletConfig,
209
+ savedBinding,
210
+ reusableBinding,
211
+ message: "ClawTip payment metadata and local OpenClaw wallet config are both present.",
212
+ };
213
+ }
214
+
215
+ if (savedBinding) {
216
+ return {
217
+ status: "metadata_missing_wallet",
218
+ walletConfig,
219
+ savedBinding,
220
+ message: "Saved ClawTip payment metadata exists, but the local OpenClaw wallet config is missing.",
221
+ };
222
+ }
223
+
224
+ if (walletConfig.exists) {
225
+ return {
226
+ status: "wallet_missing_metadata",
227
+ walletConfig,
228
+ message: "Local OpenClaw wallet config exists, but TokenBuddy ClawTip payment metadata is not saved.",
229
+ };
230
+ }
231
+
232
+ return {
233
+ status: "missing",
234
+ walletConfig,
235
+ message: "ClawTip payment metadata and local OpenClaw wallet config are not configured.",
236
+ };
237
+ }
238
+
239
+ export function buildInitSuccessMessage(summaryLines: string[] = []): string {
240
+ const lines = ["✅ TokenBuddy setup completed successfully."];
241
+ for (const line of summaryLines) {
242
+ const trimmed = line.trim();
243
+ if (trimmed) {
244
+ lines.push(`- ${trimmed}`);
245
+ }
246
+ }
247
+ lines.push("Run `tb doctor` to audit status anytime.");
248
+ return lines.join("\n");
249
+ }