@tokenbuddy/contracts 1.0.0 → 1.0.36
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/dist/src/crypto.d.ts +50 -4
- package/dist/src/crypto.d.ts.map +1 -1
- package/dist/src/crypto.js +26 -4
- package/dist/src/crypto.js.map +1 -1
- package/dist/src/errors.d.ts +42 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +30 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/upstream-balance-probe.d.ts +41 -0
- package/dist/src/upstream-balance-probe.d.ts.map +1 -0
- package/dist/src/upstream-balance-probe.js +384 -0
- package/dist/src/upstream-balance-probe.js.map +1 -0
- package/package.json +2 -2
- package/src/crypto.ts +50 -4
- package/src/errors.ts +42 -0
- package/src/index.ts +1 -0
- package/src/upstream-balance-probe.ts +505 -0
- package/tests/crypto.test.ts +7 -7
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultBalanceProbeCache = exports.BalanceProbeCache = void 0;
|
|
4
|
+
exports.probeUpstreamBalance = probeUpstreamBalance;
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 7000;
|
|
6
|
+
const FAILURE_CACHE_TTL_MS = 30000;
|
|
7
|
+
const DEFAULT_CNY_USD_RATE = 0.14;
|
|
8
|
+
class BalanceProbeCache {
|
|
9
|
+
entries = new Map();
|
|
10
|
+
get(key, now) {
|
|
11
|
+
const entry = this.entries.get(key);
|
|
12
|
+
if (!entry || entry.expiresAt <= now) {
|
|
13
|
+
if (entry) {
|
|
14
|
+
this.entries.delete(key);
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return entry.snapshot;
|
|
19
|
+
}
|
|
20
|
+
setFailure(key, snapshot, now) {
|
|
21
|
+
this.entries.set(key, {
|
|
22
|
+
snapshot,
|
|
23
|
+
expiresAt: now + FAILURE_CACHE_TTL_MS
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.BalanceProbeCache = BalanceProbeCache;
|
|
28
|
+
exports.defaultBalanceProbeCache = new BalanceProbeCache();
|
|
29
|
+
async function probeUpstreamBalance(config, options = {}) {
|
|
30
|
+
const now = options.now || Date.now;
|
|
31
|
+
const fetchedAt = now();
|
|
32
|
+
const key = cacheKey(config);
|
|
33
|
+
const cache = options.cache || exports.defaultBalanceProbeCache;
|
|
34
|
+
const cached = cache.get(key, fetchedAt);
|
|
35
|
+
if (cached) {
|
|
36
|
+
return cached;
|
|
37
|
+
}
|
|
38
|
+
const plan = requestPlan(config);
|
|
39
|
+
if (!plan) {
|
|
40
|
+
const snapshot = failure("unknown", fetchedAt, 0, "unsupported upstream - configure a balance parser");
|
|
41
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
42
|
+
return snapshot;
|
|
43
|
+
}
|
|
44
|
+
if (!config.upstreamApiKey) {
|
|
45
|
+
const snapshot = failure(plan.source, fetchedAt, 0, "missing upstreamApiKey for balance probe");
|
|
46
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
47
|
+
return snapshot;
|
|
48
|
+
}
|
|
49
|
+
const upstreamUserId = stringValue(config.upstreamBalanceProbe?.userId) || stringValue(config.upstreamUserId);
|
|
50
|
+
if (plan.requiresUserId && !upstreamUserId) {
|
|
51
|
+
const snapshot = failure(plan.source, fetchedAt, 0, "missing upstreamUserId for newapi upstream");
|
|
52
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
53
|
+
return snapshot;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const response = await fetchWithTimeout(plan.url, {
|
|
57
|
+
method: "GET",
|
|
58
|
+
headers: requestHeaders(config.upstreamApiKey, plan.requiresUserId ? upstreamUserId : undefined)
|
|
59
|
+
}, options.fetch || fetch, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const snapshot = failure(plan.source, fetchedAt, response.status, httpErrorMessage(response.status));
|
|
62
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
63
|
+
return snapshot;
|
|
64
|
+
}
|
|
65
|
+
const payload = await response.json();
|
|
66
|
+
const snapshot = parseBalancePayload(payload, plan, fetchedAt, cnyUsdRate(options.cnyUsdRate));
|
|
67
|
+
if (snapshot.error) {
|
|
68
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
69
|
+
}
|
|
70
|
+
return snapshot;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const snapshot = failure(plan.source, fetchedAt, 0, `network: ${err instanceof Error ? err.message : String(err)}`);
|
|
74
|
+
cache.setFailure(key, snapshot, fetchedAt);
|
|
75
|
+
return snapshot;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function requestPlan(config) {
|
|
79
|
+
const template = balanceProbeTemplateValue(config.upstreamBalanceProbe?.template);
|
|
80
|
+
if (template === "none") {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
const balanceUrl = stringValue(config.upstreamBalanceProbe?.url) || stringValue(config.upstreamBalanceUrl);
|
|
84
|
+
const upstreamUrl = stringValue(config.upstreamUrl);
|
|
85
|
+
if (template && template !== "auto") {
|
|
86
|
+
return explicitRequestPlan(template, balanceUrl, upstreamUrl);
|
|
87
|
+
}
|
|
88
|
+
const host = hostName(balanceUrl || upstreamUrl);
|
|
89
|
+
if (host === "api.deepseek.com") {
|
|
90
|
+
return { source: "deepseek", url: "https://api.deepseek.com/user/balance", currency: "CNY", requiresUserId: false };
|
|
91
|
+
}
|
|
92
|
+
if (host === "api.stepfun.ai" || host === "api.stepfun.com") {
|
|
93
|
+
return { source: "stepfun", url: "https://api.stepfun.com/v1/accounts", currency: "CNY", requiresUserId: false };
|
|
94
|
+
}
|
|
95
|
+
if (host === "api.siliconflow.cn" || host === "api.siliconflow.com") {
|
|
96
|
+
const currency = host.endsWith(".cn") ? "CNY" : "USD";
|
|
97
|
+
const url = host.endsWith(".cn") ? "https://api.siliconflow.cn/v1/user/info" : "https://api.siliconflow.com/v1/user/info";
|
|
98
|
+
return { source: "siliconflow", url, currency, requiresUserId: false };
|
|
99
|
+
}
|
|
100
|
+
if (host === "openrouter.ai") {
|
|
101
|
+
return { source: "openrouter", url: "https://openrouter.ai/api/v1/credits", currency: "USD", requiresUserId: false };
|
|
102
|
+
}
|
|
103
|
+
if (host === "api.novita.ai") {
|
|
104
|
+
return { source: "novita", url: "https://api.novita.ai/v3/user/balance", currency: "USD", requiresUserId: false };
|
|
105
|
+
}
|
|
106
|
+
if (balanceUrl && isUsageEndpoint(balanceUrl)) {
|
|
107
|
+
return { source: "usage_generic", url: balanceUrl, currency: "USD", requiresUserId: false };
|
|
108
|
+
}
|
|
109
|
+
if (balanceUrl) {
|
|
110
|
+
return { source: "newapi_generic", url: balanceUrl, currency: "USD", requiresUserId: true };
|
|
111
|
+
}
|
|
112
|
+
const genericUsageUrl = upstreamUrl ? usageUrl(upstreamUrl) : undefined;
|
|
113
|
+
if (genericUsageUrl) {
|
|
114
|
+
return { source: "usage_generic", url: genericUsageUrl, currency: "USD", requiresUserId: false };
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
function explicitRequestPlan(template, balanceUrl, upstreamUrl) {
|
|
119
|
+
if (template === "deepseek") {
|
|
120
|
+
return { source: "deepseek", url: balanceUrl || "https://api.deepseek.com/user/balance", currency: "CNY", requiresUserId: false };
|
|
121
|
+
}
|
|
122
|
+
if (template === "stepfun") {
|
|
123
|
+
return { source: "stepfun", url: balanceUrl || "https://api.stepfun.com/v1/accounts", currency: "CNY", requiresUserId: false };
|
|
124
|
+
}
|
|
125
|
+
if (template === "siliconflow") {
|
|
126
|
+
const host = hostName(balanceUrl || upstreamUrl);
|
|
127
|
+
const currency = host.endsWith(".com") ? "USD" : "CNY";
|
|
128
|
+
const url = balanceUrl || (currency === "USD" ? "https://api.siliconflow.com/v1/user/info" : "https://api.siliconflow.cn/v1/user/info");
|
|
129
|
+
return { source: "siliconflow", url, currency, requiresUserId: false };
|
|
130
|
+
}
|
|
131
|
+
if (template === "openrouter") {
|
|
132
|
+
return { source: "openrouter", url: balanceUrl || "https://openrouter.ai/api/v1/credits", currency: "USD", requiresUserId: false };
|
|
133
|
+
}
|
|
134
|
+
if (template === "novita") {
|
|
135
|
+
return { source: "novita", url: balanceUrl || "https://api.novita.ai/v3/user/balance", currency: "USD", requiresUserId: false };
|
|
136
|
+
}
|
|
137
|
+
if (template === "newapi_generic") {
|
|
138
|
+
return balanceUrl ? { source: "newapi_generic", url: balanceUrl, currency: "USD", requiresUserId: true } : undefined;
|
|
139
|
+
}
|
|
140
|
+
if (template === "usage_generic") {
|
|
141
|
+
const url = balanceUrl || (upstreamUrl ? usageUrl(upstreamUrl) : undefined);
|
|
142
|
+
return url ? { source: "usage_generic", url, currency: "USD", requiresUserId: false } : undefined;
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
function requestHeaders(upstreamApiKey, upstreamUserId) {
|
|
147
|
+
const headers = {
|
|
148
|
+
"Authorization": `Bearer ${upstreamApiKey}`
|
|
149
|
+
};
|
|
150
|
+
if (upstreamUserId) {
|
|
151
|
+
headers["New-Api-User"] = upstreamUserId;
|
|
152
|
+
}
|
|
153
|
+
return headers;
|
|
154
|
+
}
|
|
155
|
+
async function fetchWithTimeout(url, init, fetchFn, timeoutMs) {
|
|
156
|
+
const controller = new AbortController();
|
|
157
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
158
|
+
try {
|
|
159
|
+
return await fetchFn(url, { ...init, signal: controller.signal });
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
clearTimeout(timer);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function parseBalancePayload(payload, plan, fetchedAt, cnyRate) {
|
|
166
|
+
const object = objectValue(payload);
|
|
167
|
+
if (!object) {
|
|
168
|
+
return failure(plan.source, fetchedAt, 200, "balance response must be an object");
|
|
169
|
+
}
|
|
170
|
+
if (plan.source === "deepseek") {
|
|
171
|
+
return parseDeepSeek(object, fetchedAt, cnyRate);
|
|
172
|
+
}
|
|
173
|
+
if (plan.source === "stepfun") {
|
|
174
|
+
return amountSnapshot(numberFrom(object.balance), "CNY", "stepfun", fetchedAt, cnyRate);
|
|
175
|
+
}
|
|
176
|
+
if (plan.source === "siliconflow") {
|
|
177
|
+
return parseSiliconFlow(object, plan.currency, fetchedAt, cnyRate);
|
|
178
|
+
}
|
|
179
|
+
if (plan.source === "openrouter") {
|
|
180
|
+
return parseOpenRouter(object, fetchedAt, cnyRate);
|
|
181
|
+
}
|
|
182
|
+
if (plan.source === "novita") {
|
|
183
|
+
const availableBalance = numberFrom(object.availableBalance);
|
|
184
|
+
return amountSnapshot(availableBalance === null ? null : availableBalance / 10000, "USD", "novita", fetchedAt, cnyRate);
|
|
185
|
+
}
|
|
186
|
+
if (plan.source === "newapi_generic") {
|
|
187
|
+
return parseNewApi(object, fetchedAt, cnyRate);
|
|
188
|
+
}
|
|
189
|
+
if (plan.source === "usage_generic") {
|
|
190
|
+
return parseUsageGeneric(object, fetchedAt, cnyRate);
|
|
191
|
+
}
|
|
192
|
+
return failure("unknown", fetchedAt, 0, "unsupported upstream - configure a balance parser");
|
|
193
|
+
}
|
|
194
|
+
function parseDeepSeek(payload, fetchedAt, cnyRate) {
|
|
195
|
+
const infos = Array.isArray(payload.balance_infos) ? payload.balance_infos : [];
|
|
196
|
+
const first = objectValue(infos[0]);
|
|
197
|
+
const currency = currencyValue(first?.currency) || "CNY";
|
|
198
|
+
const rawAmount = numberFrom(first?.total_balance);
|
|
199
|
+
if (payload.is_available === false) {
|
|
200
|
+
return {
|
|
201
|
+
...amountSnapshot(rawAmount, currency, "deepseek", fetchedAt, cnyRate),
|
|
202
|
+
error: { httpStatus: 200, message: "Insufficient balance" }
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
if (!first) {
|
|
206
|
+
return amountSnapshot(null, currency, "deepseek", fetchedAt, cnyRate);
|
|
207
|
+
}
|
|
208
|
+
if (rawAmount === null) {
|
|
209
|
+
return failure("deepseek", fetchedAt, 200, "missing field: balance_infos[].total_balance", currency);
|
|
210
|
+
}
|
|
211
|
+
return amountSnapshot(rawAmount, currency, "deepseek", fetchedAt, cnyRate);
|
|
212
|
+
}
|
|
213
|
+
function parseSiliconFlow(payload, currency, fetchedAt, cnyRate) {
|
|
214
|
+
const code = numberFrom(payload.code);
|
|
215
|
+
if (code !== null && code !== 20000) {
|
|
216
|
+
return failure("siliconflow", fetchedAt, 200, `upstream code: ${code}`, currency);
|
|
217
|
+
}
|
|
218
|
+
const data = objectValue(payload.data);
|
|
219
|
+
if (!data) {
|
|
220
|
+
return failure("siliconflow", fetchedAt, 200, "missing field: data", currency);
|
|
221
|
+
}
|
|
222
|
+
const snapshot = amountSnapshot(numberFrom(data.totalBalance), currency, "siliconflow", fetchedAt, cnyRate);
|
|
223
|
+
const status = stringValue(data.status);
|
|
224
|
+
if (status && status !== "ok") {
|
|
225
|
+
return {
|
|
226
|
+
...snapshot,
|
|
227
|
+
error: { httpStatus: 200, message: `upstream status: ${status}` }
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return snapshot;
|
|
231
|
+
}
|
|
232
|
+
function parseOpenRouter(payload, fetchedAt, cnyRate) {
|
|
233
|
+
const data = objectValue(payload.data) || payload;
|
|
234
|
+
const totalCredits = numberFrom(data.total_credits);
|
|
235
|
+
const totalUsage = numberFrom(data.total_usage);
|
|
236
|
+
if (totalCredits === null || totalUsage === null) {
|
|
237
|
+
return failure("openrouter", fetchedAt, 200, "missing field: data.total_credits or data.total_usage", "USD");
|
|
238
|
+
}
|
|
239
|
+
return amountSnapshot(Math.max(0, totalCredits - totalUsage), "USD", "openrouter", fetchedAt, cnyRate);
|
|
240
|
+
}
|
|
241
|
+
function parseNewApi(payload, fetchedAt, cnyRate) {
|
|
242
|
+
const data = objectValue(payload.data);
|
|
243
|
+
if (!data) {
|
|
244
|
+
return failure("newapi_generic", fetchedAt, 200, "missing field: data", "USD");
|
|
245
|
+
}
|
|
246
|
+
const quota = numberFrom(data.quota);
|
|
247
|
+
const usedQuota = numberFrom(data.used_quota);
|
|
248
|
+
if (quota === null || usedQuota === null) {
|
|
249
|
+
return failure("newapi_generic", fetchedAt, 200, "missing field: data.quota or data.used_quota", "USD");
|
|
250
|
+
}
|
|
251
|
+
return amountSnapshot((quota - usedQuota) / 500000, "USD", "newapi_generic", fetchedAt, cnyRate);
|
|
252
|
+
}
|
|
253
|
+
function parseUsageGeneric(payload, fetchedAt, cnyRate) {
|
|
254
|
+
const quota = objectValue(payload.quota);
|
|
255
|
+
const rawAmount = numberFrom(payload.remaining) ?? numberFrom(quota?.remaining) ?? numberFrom(payload.balance);
|
|
256
|
+
const currency = currencyValue(payload.unit) || currencyValue(quota?.unit) || "USD";
|
|
257
|
+
if (rawAmount === null) {
|
|
258
|
+
return failure("usage_generic", fetchedAt, 200, "missing field: remaining, quota.remaining, or balance", currency);
|
|
259
|
+
}
|
|
260
|
+
const snapshot = amountSnapshot(rawAmount, currency, "usage_generic", fetchedAt, cnyRate);
|
|
261
|
+
const isValid = booleanValue(payload.is_active) ?? booleanValue(payload.isValid) ?? true;
|
|
262
|
+
if (!isValid) {
|
|
263
|
+
return {
|
|
264
|
+
...snapshot,
|
|
265
|
+
error: { httpStatus: 200, message: "upstream key is not active" }
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
return snapshot;
|
|
269
|
+
}
|
|
270
|
+
function amountSnapshot(rawAmount, currency, source, fetchedAt, cnyRate) {
|
|
271
|
+
return {
|
|
272
|
+
rawAmount,
|
|
273
|
+
amountUsdMicros: rawAmount === null ? null : Math.round(rawAmount * (currency === "CNY" ? cnyRate : 1) * 1000000),
|
|
274
|
+
currency,
|
|
275
|
+
source,
|
|
276
|
+
fetchedAt
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function failure(source, fetchedAt, httpStatus, message, currency = null) {
|
|
280
|
+
return {
|
|
281
|
+
rawAmount: null,
|
|
282
|
+
amountUsdMicros: null,
|
|
283
|
+
currency,
|
|
284
|
+
source,
|
|
285
|
+
fetchedAt,
|
|
286
|
+
error: { httpStatus, message }
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function httpErrorMessage(status) {
|
|
290
|
+
if (status === 401) {
|
|
291
|
+
return "unauthorized: check upstreamApiKey";
|
|
292
|
+
}
|
|
293
|
+
if (status === 403) {
|
|
294
|
+
return "forbidden: upstream rejected the credentials";
|
|
295
|
+
}
|
|
296
|
+
if (status === 429) {
|
|
297
|
+
return "rate limited";
|
|
298
|
+
}
|
|
299
|
+
if (status >= 500) {
|
|
300
|
+
return "upstream 5xx";
|
|
301
|
+
}
|
|
302
|
+
return `upstream http ${status}`;
|
|
303
|
+
}
|
|
304
|
+
function cnyUsdRate(value) {
|
|
305
|
+
if (value !== undefined && Number.isFinite(value) && value > 0) {
|
|
306
|
+
return value;
|
|
307
|
+
}
|
|
308
|
+
const envValue = Number(process.env.TB_CNY_USD_RATE);
|
|
309
|
+
return Number.isFinite(envValue) && envValue > 0 ? envValue : DEFAULT_CNY_USD_RATE;
|
|
310
|
+
}
|
|
311
|
+
function cacheKey(config) {
|
|
312
|
+
return [
|
|
313
|
+
stringValue(config.upstreamBalanceProbe?.template),
|
|
314
|
+
stringValue(config.upstreamBalanceProbe?.url),
|
|
315
|
+
stringValue(config.upstreamBalanceProbe?.userId),
|
|
316
|
+
stringValue(config.upstreamBalanceUrl),
|
|
317
|
+
stringValue(config.upstreamUrl),
|
|
318
|
+
stringValue(config.upstreamApiKey),
|
|
319
|
+
stringValue(config.upstreamUserId)
|
|
320
|
+
].join("|");
|
|
321
|
+
}
|
|
322
|
+
function balanceProbeTemplateValue(value) {
|
|
323
|
+
return value === "auto" ||
|
|
324
|
+
value === "deepseek" ||
|
|
325
|
+
value === "stepfun" ||
|
|
326
|
+
value === "siliconflow" ||
|
|
327
|
+
value === "openrouter" ||
|
|
328
|
+
value === "novita" ||
|
|
329
|
+
value === "newapi_generic" ||
|
|
330
|
+
value === "usage_generic" ||
|
|
331
|
+
value === "none"
|
|
332
|
+
? value
|
|
333
|
+
: undefined;
|
|
334
|
+
}
|
|
335
|
+
function hostName(value) {
|
|
336
|
+
if (!value) {
|
|
337
|
+
return "";
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
return new URL(value).hostname.replace(/^www\./, "");
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
return "";
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function usageUrl(value) {
|
|
347
|
+
try {
|
|
348
|
+
const url = new URL(value);
|
|
349
|
+
url.pathname = "/v1/usage";
|
|
350
|
+
url.search = "";
|
|
351
|
+
url.hash = "";
|
|
352
|
+
return url.toString();
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
return undefined;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function isUsageEndpoint(value) {
|
|
359
|
+
try {
|
|
360
|
+
return new URL(value).pathname.replace(/\/+$/, "") === "/v1/usage";
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function objectValue(value) {
|
|
367
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
368
|
+
? value
|
|
369
|
+
: undefined;
|
|
370
|
+
}
|
|
371
|
+
function stringValue(value) {
|
|
372
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
373
|
+
}
|
|
374
|
+
function numberFrom(value) {
|
|
375
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
|
|
376
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
377
|
+
}
|
|
378
|
+
function booleanValue(value) {
|
|
379
|
+
return typeof value === "boolean" ? value : undefined;
|
|
380
|
+
}
|
|
381
|
+
function currencyValue(value) {
|
|
382
|
+
return value === "USD" || value === "CNY" ? value : undefined;
|
|
383
|
+
}
|
|
384
|
+
//# sourceMappingURL=upstream-balance-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upstream-balance-probe.js","sourceRoot":"","sources":["../../src/upstream-balance-probe.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenbuddy/contracts",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.36",
|
|
4
4
|
"description": "Shared contract models and crypto functions",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@types/uuid": "^9.0.8"
|
|
16
16
|
}
|
|
17
|
-
}
|
|
17
|
+
}
|
package/src/crypto.ts
CHANGED
|
@@ -47,22 +47,35 @@ export function decryptSm4EcbPkcs7Base64(encryptedBase64: string, sm4KeyBase64:
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
50
|
+
* 计算资源 slug 的 MD5 摘要(hex 编码)。
|
|
51
|
+
* 用作 Clawtip 支付的 indicator 字段,seller 端用于校验资源一致性。
|
|
52
|
+
*
|
|
53
|
+
* @param slug 资源 slug
|
|
54
|
+
* @returns 小写十六进制的 MD5 摘要
|
|
51
55
|
*/
|
|
52
56
|
export function computeIndicator(slug: string): string {
|
|
53
57
|
return crypto.createHash("md5").update(slug, "utf8").digest("hex");
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
/**
|
|
57
|
-
*
|
|
61
|
+
* 生成 32 字符小写十六进制字符串作为订单号。
|
|
62
|
+
* 实现细节:UUID v4 去除中横线,保证全局唯一且 URL/日志友好。
|
|
63
|
+
*
|
|
64
|
+
* @returns 32 字符小写 hex 字符串
|
|
58
65
|
*/
|
|
59
66
|
export function generateOrderNo(): string {
|
|
60
67
|
return uuidv4().replace(/-/g, "");
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
71
|
+
* 加密 Clawtip 订单数据。
|
|
72
|
+
* 明文格式:`{"orderNo":..., "amount":..., "payTo":...}`,使用 SM4-ECB-PKCS7 加密后 base64 编码。
|
|
73
|
+
*
|
|
74
|
+
* @param orderNo 订单号
|
|
75
|
+
* @param amount 订单金额(分)
|
|
76
|
+
* @param payTo 收款方标识
|
|
77
|
+
* @param sm4KeyBase64 SM4 密钥的 base64 编码(必须解码为 16 字节)
|
|
78
|
+
* @returns base64 编码的密文
|
|
66
79
|
*/
|
|
67
80
|
export function encryptClawtipOrderData(
|
|
68
81
|
orderNo: string,
|
|
@@ -78,28 +91,61 @@ export function encryptClawtipOrderData(
|
|
|
78
91
|
return encryptSm4EcbPkcs7Base64(plaintext, sm4KeyBase64);
|
|
79
92
|
}
|
|
80
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Clawtip 支付下单所需的完整参数。
|
|
96
|
+
* 由 `buildClawtipPaymentParams` 在 buyer 端组装后下发到 seller。
|
|
97
|
+
*/
|
|
81
98
|
export interface ClawtipPaymentParams {
|
|
99
|
+
/** 32 字符小写十六进制的订单号(UUID v4 去横线),全局唯一标识一次下单 */
|
|
82
100
|
orderNo: string;
|
|
101
|
+
/** 订单金额,单位为分(人民币 1 元 = 100 分) */
|
|
83
102
|
amountFen: number;
|
|
103
|
+
/** 收款方标识,seller 校验该字段决定打款目标 */
|
|
84
104
|
payTo: string;
|
|
105
|
+
/** SM4-ECB-PKCS7 加密的 `{orderNo, amount, payTo}` JSON,base64 编码 */
|
|
85
106
|
encryptedData: string;
|
|
107
|
+
/** 资源 slug 的 MD5 摘要,用于 seller 校验资源一致性 */
|
|
86
108
|
indicator: string;
|
|
109
|
+
/** 资源 slug(人类可读 ID),与 indicator 配对使用 */
|
|
87
110
|
slug: string;
|
|
111
|
+
/** Clawtip 平台的技能 ID */
|
|
88
112
|
skillId: string;
|
|
113
|
+
/** 支付场景的人类可读描述,展示给支付方 */
|
|
89
114
|
description: string;
|
|
115
|
+
/** 资源下载/访问 URL,可用于支付完成后的资源定位 */
|
|
90
116
|
resourceUrl: string;
|
|
91
117
|
}
|
|
92
118
|
|
|
119
|
+
/**
|
|
120
|
+
* 构造 `ClawtipPaymentParams` 所需的原始输入。
|
|
121
|
+
* 调用方只需要提供业务字段;`orderNo` 和 `encryptedData` 由 builder 自动生成。
|
|
122
|
+
*/
|
|
93
123
|
export interface ClawtipPaymentParamsInput {
|
|
124
|
+
/** 收款方标识 */
|
|
94
125
|
payTo: string;
|
|
126
|
+
/** SM4 密钥的 base64 编码(解密后必须为 16 字节) */
|
|
95
127
|
sm4KeyBase64: string;
|
|
128
|
+
/** 资源 slug,会同时参与 indicator 计算 */
|
|
96
129
|
skillSlug: string;
|
|
130
|
+
/** Clawtip 平台的技能 ID */
|
|
97
131
|
skillId: string;
|
|
132
|
+
/** 支付场景描述 */
|
|
98
133
|
description: string;
|
|
134
|
+
/** 资源 URL */
|
|
99
135
|
resourceUrl: string;
|
|
136
|
+
/** 订单金额(分),必须为正整数 */
|
|
100
137
|
amountFen: number;
|
|
101
138
|
}
|
|
102
139
|
|
|
140
|
+
/**
|
|
141
|
+
* 构造 `ClawtipPaymentParams` 完整参数。
|
|
142
|
+
* 负责:生成 `orderNo`、对 `(orderNo, amount, payTo)` 做 SM4 加密、计算 `indicator`。
|
|
143
|
+
* `amountFen` 必须为正整数,否则抛错。
|
|
144
|
+
*
|
|
145
|
+
* @param input 业务字段输入
|
|
146
|
+
* @returns 包含加密数据的完整支付参数
|
|
147
|
+
* @throws Error 当 `amountFen` 不是正整数时
|
|
148
|
+
*/
|
|
103
149
|
export function buildClawtipPaymentParams(input: ClawtipPaymentParamsInput): ClawtipPaymentParams {
|
|
104
150
|
if (!Number.isInteger(input.amountFen) || input.amountFen < 1) {
|
|
105
151
|
throw new Error("amount_fen must be greater than zero");
|
package/src/errors.ts
CHANGED
|
@@ -32,6 +32,13 @@ export enum ErrorCode {
|
|
|
32
32
|
ContractVersionDrift = "contract_version_drift"
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* 错误码到重试策略分类的映射。
|
|
37
|
+
* buyer / seller 路由层根据该结果决定是否自动重试、是否触发 fail-closed。
|
|
38
|
+
*
|
|
39
|
+
* @param code 业务错误码
|
|
40
|
+
* @returns 重试分类:`RetryableWithBackoff`(建议退避重试)、`FailClosed`(关闭交易、人工介入)、`NotRetryable`(直接报错给用户)
|
|
41
|
+
*/
|
|
35
42
|
export function getRetryClass(code: ErrorCode): RetryClass {
|
|
36
43
|
switch (code) {
|
|
37
44
|
case ErrorCode.BusyCapacity:
|
|
@@ -46,6 +53,13 @@ export function getRetryClass(code: ErrorCode): RetryClass {
|
|
|
46
53
|
}
|
|
47
54
|
}
|
|
48
55
|
|
|
56
|
+
/**
|
|
57
|
+
* 错误码到 HTTP 状态码的映射。
|
|
58
|
+
* 当协议层把业务错误透传为 HTTP 响应(如 buyer → wallet-bootstrap 健康检查)时使用。
|
|
59
|
+
*
|
|
60
|
+
* @param code 业务错误码
|
|
61
|
+
* @returns 对应的 HTTP 状态码(4xx/5xx)
|
|
62
|
+
*/
|
|
49
63
|
export function getHttpStatus(code: ErrorCode): number {
|
|
50
64
|
switch (code) {
|
|
51
65
|
case ErrorCode.BusyCapacity:
|
|
@@ -87,6 +101,13 @@ export function getHttpStatus(code: ErrorCode): number {
|
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
103
|
|
|
104
|
+
/**
|
|
105
|
+
* 错误码到默认人类可读消息的映射。
|
|
106
|
+
* 用于 `createErrorEnvelope` 未传 `message` 参数时的兜底文案。
|
|
107
|
+
*
|
|
108
|
+
* @param code 业务错误码
|
|
109
|
+
* @returns 默认错误消息
|
|
110
|
+
*/
|
|
90
111
|
export function getDefaultMessage(code: ErrorCode): string {
|
|
91
112
|
switch (code) {
|
|
92
113
|
case ErrorCode.BusyCapacity:
|
|
@@ -144,18 +165,39 @@ export function getDefaultMessage(code: ErrorCode): string {
|
|
|
144
165
|
}
|
|
145
166
|
}
|
|
146
167
|
|
|
168
|
+
/**
|
|
169
|
+
* 标准错误体的字段定义。HTTP 响应或 JSON-RPC error 对象均使用该结构。
|
|
170
|
+
*/
|
|
147
171
|
export interface ErrorBody {
|
|
172
|
+
/** 机器可读的错误码,用于客户端做错误分支处理 */
|
|
148
173
|
code: ErrorCode;
|
|
174
|
+
/** 错误重试分类(fail_closed / retryable_with_backoff / not_retryable) */
|
|
149
175
|
retryClass: RetryClass;
|
|
176
|
+
/** 人类可读的错误描述 */
|
|
150
177
|
message: string;
|
|
178
|
+
/** 推荐的 HTTP 状态码,HTTP 透传场景下使用 */
|
|
151
179
|
httpStatus: number;
|
|
180
|
+
/** 退避建议秒数(仅 429/重试类错误附带) */
|
|
152
181
|
retryAfterSeconds?: number;
|
|
153
182
|
}
|
|
154
183
|
|
|
184
|
+
/**
|
|
185
|
+
* 错误响应的标准外壳。所有非 2xx 响应都以 `{ error: {...} }` 形式返回。
|
|
186
|
+
*/
|
|
155
187
|
export interface ErrorEnvelope {
|
|
188
|
+
/** 嵌套的错误体 */
|
|
156
189
|
error: ErrorBody;
|
|
157
190
|
}
|
|
158
191
|
|
|
192
|
+
/**
|
|
193
|
+
* 构造标准错误响应外壳。
|
|
194
|
+
* 自动填充 `retryClass`、`httpStatus`、默认 `message`,调用方只需提供 `code` 和可选的覆盖字段。
|
|
195
|
+
*
|
|
196
|
+
* @param code 业务错误码,决定 retryClass / httpStatus / 默认 message
|
|
197
|
+
* @param message 自定义消息;省略时使用 `getDefaultMessage(code)` 兜底文案
|
|
198
|
+
* @param retryAfterSeconds 退避秒数,仅在需要时填入(如 429)
|
|
199
|
+
* @returns 完整的 `ErrorEnvelope` 对象
|
|
200
|
+
*/
|
|
159
201
|
export function createErrorEnvelope(
|
|
160
202
|
code: ErrorCode,
|
|
161
203
|
message?: string,
|
package/src/index.ts
CHANGED