@keelcodes/sdk 0.0.0-stage → 2.0.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/dist/account.d.ts +50 -0
- package/dist/account.js +26 -0
- package/dist/data.d.ts +217 -0
- package/dist/data.js +253 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.js +22 -0
- package/dist/http.d.ts +17 -0
- package/dist/http.js +76 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +29 -0
- package/dist/payment.d.ts +230 -0
- package/dist/payment.js +160 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.js +5 -0
- package/dist/wallet.d.ts +490 -0
- package/dist/wallet.js +142 -0
- package/package.json +53 -4
- package/README.md +0 -3
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { HttpClient } from './http';
|
|
2
|
+
import type { KeelModule } from './types';
|
|
3
|
+
export interface TenantCreateParams {
|
|
4
|
+
name: string;
|
|
5
|
+
metadata?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export interface TenantResult {
|
|
8
|
+
tenantId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
apiKey: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ApikeyCreateParams {
|
|
13
|
+
tenantId: string;
|
|
14
|
+
module: KeelModule;
|
|
15
|
+
/** 幂等键(同 reference 不重复签发)。 */
|
|
16
|
+
reference?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ApikeyResult {
|
|
19
|
+
apiKey: string;
|
|
20
|
+
module: KeelModule;
|
|
21
|
+
}
|
|
22
|
+
export interface SubscriptionParams {
|
|
23
|
+
module: KeelModule;
|
|
24
|
+
planId: string;
|
|
25
|
+
/** 幂等键(同 reference 不重复订阅)。 */
|
|
26
|
+
reference?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface SubscriptionResult {
|
|
29
|
+
module: KeelModule;
|
|
30
|
+
planId: string;
|
|
31
|
+
status: string;
|
|
32
|
+
}
|
|
33
|
+
export declare class AccountAPI {
|
|
34
|
+
private http;
|
|
35
|
+
constructor(http: HttpClient);
|
|
36
|
+
tenant: {
|
|
37
|
+
create: (p: TenantCreateParams) => Promise<TenantResult>;
|
|
38
|
+
get: (tenantId: string) => Promise<TenantResult>;
|
|
39
|
+
};
|
|
40
|
+
/** 按模块签发 key(用户订阅哪个模块,就为哪个模块签发)。 */
|
|
41
|
+
apikey: {
|
|
42
|
+
create: (p: ApikeyCreateParams) => Promise<ApikeyResult>;
|
|
43
|
+
revoke: (apiKey: string) => Promise<unknown>;
|
|
44
|
+
};
|
|
45
|
+
subscription: {
|
|
46
|
+
get: (module: KeelModule) => Promise<SubscriptionResult>;
|
|
47
|
+
subscribe: (p: SubscriptionParams) => Promise<SubscriptionResult>;
|
|
48
|
+
cancel: (module: KeelModule) => Promise<unknown>;
|
|
49
|
+
};
|
|
50
|
+
}
|
package/dist/account.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// @keelcodes/sdk — account 模块(3 动作)
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AccountAPI = void 0;
|
|
7
|
+
class AccountAPI {
|
|
8
|
+
constructor(http) {
|
|
9
|
+
this.http = http;
|
|
10
|
+
this.tenant = {
|
|
11
|
+
create: (p) => this.http.post('/v1/account/tenant', p),
|
|
12
|
+
get: (tenantId) => this.http.get('/v1/account/tenant/' + encodeURIComponent(tenantId)),
|
|
13
|
+
};
|
|
14
|
+
/** 按模块签发 key(用户订阅哪个模块,就为哪个模块签发)。 */
|
|
15
|
+
this.apikey = {
|
|
16
|
+
create: (p) => this.http.post('/v1/account/apikey', p),
|
|
17
|
+
revoke: (apiKey) => this.http.post('/v1/account/apikey/revoke', { apiKey }),
|
|
18
|
+
};
|
|
19
|
+
this.subscription = {
|
|
20
|
+
get: (module) => this.http.get('/v1/account/subscription?module=' + module),
|
|
21
|
+
subscribe: (p) => this.http.post('/v1/account/subscription', p),
|
|
22
|
+
cancel: (module) => this.http.post('/v1/account/subscription/cancel', { module }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.AccountAPI = AccountAPI;
|
package/dist/data.d.ts
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { HttpClient } from './http';
|
|
2
|
+
export interface BarsParams {
|
|
3
|
+
symbol: string;
|
|
4
|
+
timeframe?: string;
|
|
5
|
+
marketType?: 'spot' | 'swap';
|
|
6
|
+
start?: number;
|
|
7
|
+
end?: number;
|
|
8
|
+
limit?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface BarsResult {
|
|
11
|
+
symbol: string;
|
|
12
|
+
bars: Record<string, unknown>[];
|
|
13
|
+
}
|
|
14
|
+
export interface TickersParams {
|
|
15
|
+
symbols: string | string[];
|
|
16
|
+
marketType?: 'spot' | 'swap';
|
|
17
|
+
}
|
|
18
|
+
export interface TickersResult {
|
|
19
|
+
items: Record<string, unknown>[];
|
|
20
|
+
missing: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface FactorsParams {
|
|
23
|
+
symbols?: string;
|
|
24
|
+
category?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface FactorsResult {
|
|
27
|
+
factors: Record<string, unknown>;
|
|
28
|
+
values: Record<string, Record<string, number>>;
|
|
29
|
+
}
|
|
30
|
+
export interface GraphParams {
|
|
31
|
+
symbol?: string;
|
|
32
|
+
entity?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface GraphResult {
|
|
35
|
+
entities: unknown[];
|
|
36
|
+
edges: unknown[];
|
|
37
|
+
}
|
|
38
|
+
export interface PredictParams {
|
|
39
|
+
model: 'bolt' | 'moirai' | 'timesfm';
|
|
40
|
+
symbol: string;
|
|
41
|
+
start?: number;
|
|
42
|
+
end?: number;
|
|
43
|
+
limit?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface PredictResult {
|
|
46
|
+
predictions: unknown[];
|
|
47
|
+
}
|
|
48
|
+
export interface EventsParams {
|
|
49
|
+
chain?: string;
|
|
50
|
+
address?: string;
|
|
51
|
+
contract?: string;
|
|
52
|
+
eventType?: string;
|
|
53
|
+
category?: string;
|
|
54
|
+
fromBlock?: string;
|
|
55
|
+
toBlock?: string;
|
|
56
|
+
limit?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface EventsResult {
|
|
59
|
+
events: unknown[];
|
|
60
|
+
}
|
|
61
|
+
export interface RagParams {
|
|
62
|
+
query: string;
|
|
63
|
+
topK?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface RagResult {
|
|
66
|
+
results: unknown[];
|
|
67
|
+
}
|
|
68
|
+
export declare class DataAPI {
|
|
69
|
+
private http;
|
|
70
|
+
constructor(http: HttpClient);
|
|
71
|
+
bars(params: BarsParams): Promise<BarsResult>;
|
|
72
|
+
tickers(params: TickersParams): Promise<TickersResult>;
|
|
73
|
+
factors(params?: FactorsParams): Promise<FactorsResult>;
|
|
74
|
+
graph(params?: GraphParams): Promise<GraphResult>;
|
|
75
|
+
predictions(params: PredictParams): Promise<PredictResult>;
|
|
76
|
+
events(params?: EventsParams): Promise<EventsResult>;
|
|
77
|
+
rag(params: RagParams): Promise<RagResult>;
|
|
78
|
+
/** 取单符号最新行情(ticker)。 */
|
|
79
|
+
ticker(symbol: string): Promise<Record<string, unknown>>;
|
|
80
|
+
/** 列出受支持交易符号(可按市场 / 关键词过滤)。 */
|
|
81
|
+
symbols(params?: {
|
|
82
|
+
market?: string;
|
|
83
|
+
limit?: number;
|
|
84
|
+
}): Promise<Record<string, unknown>>;
|
|
85
|
+
/** 模糊搜索符号(跨市场)。 */
|
|
86
|
+
symbolSearch(p: {
|
|
87
|
+
keyword: string;
|
|
88
|
+
market?: string;
|
|
89
|
+
limit?: number;
|
|
90
|
+
}): Promise<Record<string, unknown>>;
|
|
91
|
+
/** 解析原始符号关键词为规范交易符号。 */
|
|
92
|
+
symbolResolve(p: {
|
|
93
|
+
symbol: string;
|
|
94
|
+
market?: string;
|
|
95
|
+
}): Promise<Record<string, unknown>>;
|
|
96
|
+
/** 券商市场策略(各市场主交易场所)。 */
|
|
97
|
+
brokerPolicy(): Promise<Record<string, unknown>>;
|
|
98
|
+
/** 取因子历史序列(按符号 + 因子 id + 时间窗)。 */
|
|
99
|
+
factorsHistory(p: {
|
|
100
|
+
symbol: string;
|
|
101
|
+
factor: string;
|
|
102
|
+
start?: number;
|
|
103
|
+
end?: number;
|
|
104
|
+
limit?: number;
|
|
105
|
+
}): Promise<Record<string, unknown>>;
|
|
106
|
+
/** 取快照数据(macro / onchain / defi_tvl / indices…)。 */
|
|
107
|
+
snapshots(p?: {
|
|
108
|
+
type?: string;
|
|
109
|
+
date?: string;
|
|
110
|
+
limit?: number;
|
|
111
|
+
}): Promise<Record<string, unknown>>;
|
|
112
|
+
/** DC 统计(事件总数 / 活跃链)。 */
|
|
113
|
+
stats(): Promise<Record<string, unknown>>;
|
|
114
|
+
/** 各链区块索引检查点。 */
|
|
115
|
+
checkpoints(chain?: string): Promise<Record<string, unknown>>;
|
|
116
|
+
/** DC 订阅套餐价目(公开)。 */
|
|
117
|
+
plans(): Promise<Record<string, unknown>>;
|
|
118
|
+
/** 支持的代币列表(含元数据)。 */
|
|
119
|
+
tokens(chain?: string): Promise<Record<string, unknown>>;
|
|
120
|
+
/** 支持的区块链网络列表。 */
|
|
121
|
+
chains(): Promise<Record<string, unknown>>;
|
|
122
|
+
/** 事件业务分类目录(category_id + label_id)。 */
|
|
123
|
+
eventCategories(): Promise<Record<string, unknown>>;
|
|
124
|
+
/** 按业务分类聚合的事件计数(可按链过滤)。 */
|
|
125
|
+
eventStats(chain?: string): Promise<Record<string, unknown>>;
|
|
126
|
+
/** 订阅 DC 套餐(x-wallet-address 鉴权;免费即时生效返 dcApiKey,付费返支付意图)。 */
|
|
127
|
+
subscriptionSubscribe(p: {
|
|
128
|
+
planId: string;
|
|
129
|
+
rail?: string;
|
|
130
|
+
walletAddress: string;
|
|
131
|
+
}): Promise<Record<string, unknown>>;
|
|
132
|
+
/** 轮询 DC 订阅支付状态(x-wallet-address 鉴权)。 */
|
|
133
|
+
subscriptionPaymentCheck(walletAddress: string): Promise<Record<string, unknown>>;
|
|
134
|
+
/** 确认 DC 订阅的 x402 支付(提交 txHash;付款钱包须匹配)。 */
|
|
135
|
+
subscriptionVerify(p: {
|
|
136
|
+
txHash: string;
|
|
137
|
+
walletAddress: string;
|
|
138
|
+
}): Promise<Record<string, unknown>>;
|
|
139
|
+
/** 读取 DC 订阅用量(套餐 / key / 月配额 / 当前用量 / 日明细)。 */
|
|
140
|
+
subscriptionUsage(walletAddress: string): Promise<Record<string, unknown>>;
|
|
141
|
+
market: {
|
|
142
|
+
/** 按名称/符号搜索 DEX 代币(DexScreener)。 */
|
|
143
|
+
search: (p: {
|
|
144
|
+
keyword: string;
|
|
145
|
+
chainIndex?: string;
|
|
146
|
+
limit?: string;
|
|
147
|
+
}) => Promise<unknown>;
|
|
148
|
+
/** 热门 DEX 池(GeckoTerminal trending)。 */
|
|
149
|
+
hot: (p?: {
|
|
150
|
+
chainIndex?: string;
|
|
151
|
+
limit?: string;
|
|
152
|
+
}) => Promise<unknown>;
|
|
153
|
+
/** K 线(OHLCV)。 */
|
|
154
|
+
candles: (p: {
|
|
155
|
+
chainIndex: string;
|
|
156
|
+
tokenAddress: string;
|
|
157
|
+
period?: string;
|
|
158
|
+
limit?: string;
|
|
159
|
+
}) => Promise<unknown>;
|
|
160
|
+
/** 实时 DEX 价。 */
|
|
161
|
+
price: (p: {
|
|
162
|
+
chainIndex: string;
|
|
163
|
+
tokenAddress: string;
|
|
164
|
+
}) => Promise<unknown>;
|
|
165
|
+
/** 加入监控列表(自动采集 K 线 / 快照)。 */
|
|
166
|
+
trackToken: (p: {
|
|
167
|
+
chain: string;
|
|
168
|
+
tokenAddress: string;
|
|
169
|
+
label?: string;
|
|
170
|
+
}) => Promise<unknown>;
|
|
171
|
+
/** 列出监控中的代币。 */
|
|
172
|
+
listTracked: (chain?: string) => Promise<unknown>;
|
|
173
|
+
/** 注册自定义事件签名(topicHash + eventType,可选 ABI)。 */
|
|
174
|
+
registerEvent: (p: {
|
|
175
|
+
chain: string;
|
|
176
|
+
topicHash: string;
|
|
177
|
+
eventType: string;
|
|
178
|
+
eventName?: string;
|
|
179
|
+
abi?: unknown;
|
|
180
|
+
}) => Promise<unknown>;
|
|
181
|
+
/** Market 订阅套餐价目(公开)。 */
|
|
182
|
+
subscriptionPlans: () => Promise<unknown>;
|
|
183
|
+
/** 发起 Market 订阅支付(免费即时生效;付费返支付意图)。 */
|
|
184
|
+
subscriptionCheckout: (p: {
|
|
185
|
+
plan_id: string;
|
|
186
|
+
rail?: string;
|
|
187
|
+
subscriber?: string;
|
|
188
|
+
}) => Promise<unknown>;
|
|
189
|
+
/** 轮询 Market 订阅支付状态。 */
|
|
190
|
+
subscriptionPaymentCheck: (p?: {
|
|
191
|
+
subscriber?: string;
|
|
192
|
+
}) => Promise<unknown>;
|
|
193
|
+
/** 确认 Market 订阅的 x402 支付(提交 txHash)。 */
|
|
194
|
+
subscriptionVerify: (p: {
|
|
195
|
+
txHash: string;
|
|
196
|
+
}) => Promise<unknown>;
|
|
197
|
+
/** 读取 Market 订阅用量。 */
|
|
198
|
+
subscriptionUsage: () => Promise<unknown>;
|
|
199
|
+
};
|
|
200
|
+
factorFactory: {
|
|
201
|
+
/** 创建因子挖掘任务(结构化 preferences/constraints/formulas;intent 走 LLM 解析)。返回 job_id。 */
|
|
202
|
+
start: (p?: {
|
|
203
|
+
preferences?: Record<string, unknown>;
|
|
204
|
+
constraints?: Record<string, unknown>;
|
|
205
|
+
formulas?: string[];
|
|
206
|
+
intent?: string;
|
|
207
|
+
}) => Promise<unknown>;
|
|
208
|
+
/** 查询挖掘任务状态(含 stage 细分:pool/eval/select/persist)。 */
|
|
209
|
+
status: (jobId: string) => Promise<unknown>;
|
|
210
|
+
/** 查询挖掘任务结果(合格因子列表 + 统计)。 */
|
|
211
|
+
result: (jobId: string) => Promise<unknown>;
|
|
212
|
+
/** 最近挖掘任务列表。 */
|
|
213
|
+
list: (limit?: number) => Promise<unknown>;
|
|
214
|
+
/** 取消挖掘任务(排队/运行中可取消)。 */
|
|
215
|
+
cancel: (jobId: string) => Promise<unknown>;
|
|
216
|
+
};
|
|
217
|
+
}
|
package/dist/data.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// @keelcodes/sdk — data 模块(7 动作)
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DataAPI = void 0;
|
|
7
|
+
class DataAPI {
|
|
8
|
+
constructor(http) {
|
|
9
|
+
this.http = http;
|
|
10
|
+
// ── Market 子域(DEX 行情 / 监控 / 订阅):canonical `/v1/data/market*` ──
|
|
11
|
+
this.market = {
|
|
12
|
+
/** 按名称/符号搜索 DEX 代币(DexScreener)。 */
|
|
13
|
+
search: (p) => {
|
|
14
|
+
const q = new URLSearchParams({ keyword: p.keyword });
|
|
15
|
+
if (p.chainIndex)
|
|
16
|
+
q.set('chainIndex', p.chainIndex);
|
|
17
|
+
if (p.limit)
|
|
18
|
+
q.set('limit', p.limit);
|
|
19
|
+
return this.http.get('/v1/data/market/token-search?' + q.toString());
|
|
20
|
+
},
|
|
21
|
+
/** 热门 DEX 池(GeckoTerminal trending)。 */
|
|
22
|
+
hot: (p = {}) => {
|
|
23
|
+
const q = new URLSearchParams();
|
|
24
|
+
if (p.chainIndex)
|
|
25
|
+
q.set('chainIndex', p.chainIndex);
|
|
26
|
+
if (p.limit)
|
|
27
|
+
q.set('limit', p.limit);
|
|
28
|
+
return this.http.get('/v1/data/market/hot-tokens?' + q.toString());
|
|
29
|
+
},
|
|
30
|
+
/** K 线(OHLCV)。 */
|
|
31
|
+
candles: (p) => {
|
|
32
|
+
const q = new URLSearchParams({ chainIndex: p.chainIndex, tokenAddress: p.tokenAddress });
|
|
33
|
+
if (p.period)
|
|
34
|
+
q.set('period', p.period);
|
|
35
|
+
if (p.limit)
|
|
36
|
+
q.set('limit', p.limit);
|
|
37
|
+
return this.http.get('/v1/data/market/candles?' + q.toString());
|
|
38
|
+
},
|
|
39
|
+
/** 实时 DEX 价。 */
|
|
40
|
+
price: (p) => this.http.get('/v1/data/market/price?' + new URLSearchParams({ chainIndex: p.chainIndex, tokenAddress: p.tokenAddress }).toString()),
|
|
41
|
+
/** 加入监控列表(自动采集 K 线 / 快照)。 */
|
|
42
|
+
trackToken: (p) => this.http.post('/v1/data/market/tracked-tokens', p),
|
|
43
|
+
/** 列出监控中的代币。 */
|
|
44
|
+
listTracked: (chain) => this.http.get('/v1/data/market/tracked-tokens' + (chain ? '?chain=' + encodeURIComponent(chain) : '')),
|
|
45
|
+
/** 注册自定义事件签名(topicHash + eventType,可选 ABI)。 */
|
|
46
|
+
registerEvent: (p) => this.http.post('/v1/data/market/custom-sigs', p),
|
|
47
|
+
/** Market 订阅套餐价目(公开)。 */
|
|
48
|
+
subscriptionPlans: () => this.http.get('/v1/data/market-subscription/plans'),
|
|
49
|
+
/** 发起 Market 订阅支付(免费即时生效;付费返支付意图)。 */
|
|
50
|
+
subscriptionCheckout: (p) => this.http.post('/v1/data/market-subscription/checkout', p),
|
|
51
|
+
/** 轮询 Market 订阅支付状态。 */
|
|
52
|
+
subscriptionPaymentCheck: (p = {}) => this.http.post('/v1/data/market-subscription/payment-check', p),
|
|
53
|
+
/** 确认 Market 订阅的 x402 支付(提交 txHash)。 */
|
|
54
|
+
subscriptionVerify: (p) => this.http.post('/v1/data/market-subscription/verify', p),
|
|
55
|
+
/** 读取 Market 订阅用量。 */
|
|
56
|
+
subscriptionUsage: () => this.http.get('/v1/data/market-subscription/usage'),
|
|
57
|
+
};
|
|
58
|
+
// ── Factor 工厂(因子挖掘):canonical `/v1/data/factor-factory/*`(由 ml-service 承载)──
|
|
59
|
+
this.factorFactory = {
|
|
60
|
+
/** 创建因子挖掘任务(结构化 preferences/constraints/formulas;intent 走 LLM 解析)。返回 job_id。 */
|
|
61
|
+
start: (p = {}) => {
|
|
62
|
+
const body = { preferences: p.preferences ?? {}, constraints: p.constraints ?? {} };
|
|
63
|
+
if (p.formulas?.length)
|
|
64
|
+
body.formulas = p.formulas;
|
|
65
|
+
return p.intent
|
|
66
|
+
? this.http.post('/v1/data/factor-factory/mine', { ...body, intent: p.intent })
|
|
67
|
+
: this.http.post('/v1/data/factor-factory/start', body);
|
|
68
|
+
},
|
|
69
|
+
/** 查询挖掘任务状态(含 stage 细分:pool/eval/select/persist)。 */
|
|
70
|
+
status: (jobId) => this.http.get('/v1/data/factor-factory/status?job_id=' + encodeURIComponent(jobId)),
|
|
71
|
+
/** 查询挖掘任务结果(合格因子列表 + 统计)。 */
|
|
72
|
+
result: (jobId) => this.http.get('/v1/data/factor-factory/result?job_id=' + encodeURIComponent(jobId)),
|
|
73
|
+
/** 最近挖掘任务列表。 */
|
|
74
|
+
list: (limit) => this.http.get('/v1/data/factor-factory/list' + (limit ? '?limit=' + limit : '')),
|
|
75
|
+
/** 取消挖掘任务(排队/运行中可取消)。 */
|
|
76
|
+
cancel: (jobId) => this.http.post('/v1/data/factor-factory/cancel?job_id=' + encodeURIComponent(jobId)),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
bars(params) {
|
|
80
|
+
const q = new URLSearchParams({ symbol: params.symbol });
|
|
81
|
+
if (params.timeframe)
|
|
82
|
+
q.set('timeframe', params.timeframe);
|
|
83
|
+
if (params.marketType)
|
|
84
|
+
q.set('market_type', params.marketType);
|
|
85
|
+
if (params.start)
|
|
86
|
+
q.set('start', String(params.start));
|
|
87
|
+
if (params.end)
|
|
88
|
+
q.set('end', String(params.end));
|
|
89
|
+
if (params.limit)
|
|
90
|
+
q.set('limit', String(params.limit));
|
|
91
|
+
return this.http.get('/v1/data/bars?' + q.toString());
|
|
92
|
+
}
|
|
93
|
+
tickers(params) {
|
|
94
|
+
const symbols = Array.isArray(params.symbols) ? params.symbols.join(',') : params.symbols;
|
|
95
|
+
const q = new URLSearchParams({ symbols });
|
|
96
|
+
if (params.marketType)
|
|
97
|
+
q.set('market_type', params.marketType);
|
|
98
|
+
return this.http.get('/v1/data/tickers?' + q.toString());
|
|
99
|
+
}
|
|
100
|
+
factors(params = {}) {
|
|
101
|
+
const q = new URLSearchParams();
|
|
102
|
+
if (params.symbols)
|
|
103
|
+
q.set('symbols', params.symbols);
|
|
104
|
+
if (params.category)
|
|
105
|
+
q.set('category', params.category);
|
|
106
|
+
return this.http.get('/v1/data/factors?' + q.toString());
|
|
107
|
+
}
|
|
108
|
+
graph(params = {}) {
|
|
109
|
+
const q = new URLSearchParams();
|
|
110
|
+
if (params.symbol)
|
|
111
|
+
q.set('symbol', params.symbol);
|
|
112
|
+
if (params.entity)
|
|
113
|
+
q.set('entity', params.entity);
|
|
114
|
+
return this.http.get('/v1/data/graph?' + q.toString());
|
|
115
|
+
}
|
|
116
|
+
predictions(params) {
|
|
117
|
+
const q = new URLSearchParams({ model: params.model, symbol: params.symbol });
|
|
118
|
+
if (params.start)
|
|
119
|
+
q.set('start', String(params.start));
|
|
120
|
+
if (params.end)
|
|
121
|
+
q.set('end', String(params.end));
|
|
122
|
+
if (params.limit)
|
|
123
|
+
q.set('limit', String(params.limit));
|
|
124
|
+
return this.http.get('/v1/data/predictions?' + q.toString());
|
|
125
|
+
}
|
|
126
|
+
events(params = {}) {
|
|
127
|
+
const q = new URLSearchParams();
|
|
128
|
+
if (params.chain)
|
|
129
|
+
q.set('chain', params.chain);
|
|
130
|
+
if (params.address)
|
|
131
|
+
q.set('address', params.address);
|
|
132
|
+
if (params.contract)
|
|
133
|
+
q.set('contract', params.contract);
|
|
134
|
+
if (params.eventType)
|
|
135
|
+
q.set('event_type', params.eventType);
|
|
136
|
+
if (params.category)
|
|
137
|
+
q.set('category', params.category);
|
|
138
|
+
if (params.fromBlock)
|
|
139
|
+
q.set('from_block', params.fromBlock);
|
|
140
|
+
if (params.toBlock)
|
|
141
|
+
q.set('to_block', params.toBlock);
|
|
142
|
+
if (params.limit)
|
|
143
|
+
q.set('limit', String(params.limit));
|
|
144
|
+
return this.http.get('/v1/data/events?' + q.toString());
|
|
145
|
+
}
|
|
146
|
+
rag(params) {
|
|
147
|
+
return this.http.post('/v1/data/rag', params);
|
|
148
|
+
}
|
|
149
|
+
// ── 行情 / 符号 / 快照(旧 hub MCP 能力)──
|
|
150
|
+
/** 取单符号最新行情(ticker)。 */
|
|
151
|
+
ticker(symbol) {
|
|
152
|
+
return this.http.get('/v1/data/ticker?symbol=' + encodeURIComponent(symbol));
|
|
153
|
+
}
|
|
154
|
+
/** 列出受支持交易符号(可按市场 / 关键词过滤)。 */
|
|
155
|
+
symbols(params = {}) {
|
|
156
|
+
const q = new URLSearchParams();
|
|
157
|
+
if (params.market)
|
|
158
|
+
q.set('market', params.market);
|
|
159
|
+
if (params.limit)
|
|
160
|
+
q.set('limit', String(params.limit));
|
|
161
|
+
const qs = q.toString();
|
|
162
|
+
return this.http.get('/v1/data/symbols' + (qs ? '?' + qs : ''));
|
|
163
|
+
}
|
|
164
|
+
/** 模糊搜索符号(跨市场)。 */
|
|
165
|
+
symbolSearch(p) {
|
|
166
|
+
const q = new URLSearchParams({ keyword: p.keyword });
|
|
167
|
+
if (p.market)
|
|
168
|
+
q.set('market', p.market);
|
|
169
|
+
if (p.limit)
|
|
170
|
+
q.set('limit', String(p.limit));
|
|
171
|
+
return this.http.get('/v1/data/symbols/search?' + q.toString());
|
|
172
|
+
}
|
|
173
|
+
/** 解析原始符号关键词为规范交易符号。 */
|
|
174
|
+
symbolResolve(p) {
|
|
175
|
+
const q = new URLSearchParams({ symbol: p.symbol });
|
|
176
|
+
if (p.market)
|
|
177
|
+
q.set('market', p.market);
|
|
178
|
+
return this.http.get('/v1/data/symbol/resolve?' + q.toString());
|
|
179
|
+
}
|
|
180
|
+
/** 券商市场策略(各市场主交易场所)。 */
|
|
181
|
+
brokerPolicy() {
|
|
182
|
+
return this.http.get('/v1/data/policy/broker-market');
|
|
183
|
+
}
|
|
184
|
+
/** 取因子历史序列(按符号 + 因子 id + 时间窗)。 */
|
|
185
|
+
factorsHistory(p) {
|
|
186
|
+
const q = new URLSearchParams({ symbol: p.symbol, factor: p.factor });
|
|
187
|
+
if (p.start)
|
|
188
|
+
q.set('start', String(p.start));
|
|
189
|
+
if (p.end)
|
|
190
|
+
q.set('end', String(p.end));
|
|
191
|
+
if (p.limit)
|
|
192
|
+
q.set('limit', String(p.limit));
|
|
193
|
+
return this.http.get('/v1/data/factors/history?' + q.toString());
|
|
194
|
+
}
|
|
195
|
+
/** 取快照数据(macro / onchain / defi_tvl / indices…)。 */
|
|
196
|
+
snapshots(p = {}) {
|
|
197
|
+
const q = new URLSearchParams();
|
|
198
|
+
if (p.type)
|
|
199
|
+
q.set('type', p.type);
|
|
200
|
+
if (p.date)
|
|
201
|
+
q.set('date', p.date);
|
|
202
|
+
if (p.limit)
|
|
203
|
+
q.set('limit', String(p.limit));
|
|
204
|
+
const qs = q.toString();
|
|
205
|
+
return this.http.get('/v1/data/snapshots' + (qs ? '?' + qs : ''));
|
|
206
|
+
}
|
|
207
|
+
// ── DC(数据中心)面:统计 / 链 / 代币 / 事件分类 / 订阅 ──
|
|
208
|
+
/** DC 统计(事件总数 / 活跃链)。 */
|
|
209
|
+
stats() {
|
|
210
|
+
return this.http.get('/v1/data/stats');
|
|
211
|
+
}
|
|
212
|
+
/** 各链区块索引检查点。 */
|
|
213
|
+
checkpoints(chain) {
|
|
214
|
+
return this.http.get('/v1/data/checkpoints' + (chain ? '?chain=' + encodeURIComponent(chain) : ''));
|
|
215
|
+
}
|
|
216
|
+
/** DC 订阅套餐价目(公开)。 */
|
|
217
|
+
plans() {
|
|
218
|
+
return this.http.get('/v1/data/plans');
|
|
219
|
+
}
|
|
220
|
+
/** 支持的代币列表(含元数据)。 */
|
|
221
|
+
tokens(chain) {
|
|
222
|
+
return this.http.get('/v1/data/tokens' + (chain ? '?chain=' + encodeURIComponent(chain) : ''));
|
|
223
|
+
}
|
|
224
|
+
/** 支持的区块链网络列表。 */
|
|
225
|
+
chains() {
|
|
226
|
+
return this.http.get('/v1/data/chains');
|
|
227
|
+
}
|
|
228
|
+
/** 事件业务分类目录(category_id + label_id)。 */
|
|
229
|
+
eventCategories() {
|
|
230
|
+
return this.http.get('/v1/data/event-categories');
|
|
231
|
+
}
|
|
232
|
+
/** 按业务分类聚合的事件计数(可按链过滤)。 */
|
|
233
|
+
eventStats(chain) {
|
|
234
|
+
return this.http.get('/v1/data/event-stats' + (chain ? '?chain=' + encodeURIComponent(chain) : ''));
|
|
235
|
+
}
|
|
236
|
+
/** 订阅 DC 套餐(x-wallet-address 鉴权;免费即时生效返 dcApiKey,付费返支付意图)。 */
|
|
237
|
+
subscriptionSubscribe(p) {
|
|
238
|
+
return this.http.post('/v1/data/subscribe', { planId: p.planId, rail: p.rail }, { 'x-wallet-address': p.walletAddress });
|
|
239
|
+
}
|
|
240
|
+
/** 轮询 DC 订阅支付状态(x-wallet-address 鉴权)。 */
|
|
241
|
+
subscriptionPaymentCheck(walletAddress) {
|
|
242
|
+
return this.http.post('/v1/data/payment-check', {}, { 'x-wallet-address': walletAddress });
|
|
243
|
+
}
|
|
244
|
+
/** 确认 DC 订阅的 x402 支付(提交 txHash;付款钱包须匹配)。 */
|
|
245
|
+
subscriptionVerify(p) {
|
|
246
|
+
return this.http.post('/v1/data/verify', { txHash: p.txHash }, { 'x-wallet-address': p.walletAddress });
|
|
247
|
+
}
|
|
248
|
+
/** 读取 DC 订阅用量(套餐 / key / 月配额 / 当前用量 / 日明细)。 */
|
|
249
|
+
subscriptionUsage(walletAddress) {
|
|
250
|
+
return this.http.get('/v1/data/usage', { 'x-wallet-address': walletAddress });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
exports.DataAPI = DataAPI;
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** 引擎返回非 2xx 时抛出。`status` 为 HTTP 状态码,`code` 为契约错误码。 */
|
|
2
|
+
export declare class KeelApiError extends Error {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly status: number;
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly body: unknown;
|
|
7
|
+
constructor(path: string, status: number, code: string, body: unknown);
|
|
8
|
+
}
|
|
9
|
+
export declare function isKeelApiError(err: unknown): err is KeelApiError;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// @keelcodes/sdk — 类型化错误(对齐契约 §3)
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.KeelApiError = void 0;
|
|
7
|
+
exports.isKeelApiError = isKeelApiError;
|
|
8
|
+
/** 引擎返回非 2xx 时抛出。`status` 为 HTTP 状态码,`code` 为契约错误码。 */
|
|
9
|
+
class KeelApiError extends Error {
|
|
10
|
+
constructor(path, status, code, body) {
|
|
11
|
+
super(`[keel-sdk] ${path} ${status} (${code}): ${body?.message ?? 'request failed'}`);
|
|
12
|
+
this.path = path;
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.code = code;
|
|
15
|
+
this.body = body;
|
|
16
|
+
this.name = 'KeelApiError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.KeelApiError = KeelApiError;
|
|
20
|
+
function isKeelApiError(err) {
|
|
21
|
+
return err instanceof KeelApiError;
|
|
22
|
+
}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { KeelConfig } from './types';
|
|
2
|
+
/** SDK 版本(契约 §5,基线 2.0.0,随包版本同步)。 */
|
|
3
|
+
export declare const SDK_VERSION = "2.0.0";
|
|
4
|
+
export declare class HttpClient {
|
|
5
|
+
private baseUrl;
|
|
6
|
+
private headers;
|
|
7
|
+
private timeout;
|
|
8
|
+
private wallet?;
|
|
9
|
+
private walletToken?;
|
|
10
|
+
constructor(config?: KeelConfig);
|
|
11
|
+
get<T>(path: string, headers?: Record<string, string>): Promise<T>;
|
|
12
|
+
post<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
13
|
+
put<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
14
|
+
private request;
|
|
15
|
+
/** 静态头 + (若配置)钱包签名头。签名按 WALLET_TOKEN_TTL_MS 复用。 */
|
|
16
|
+
private buildHeaders;
|
|
17
|
+
}
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// @keelcodes/sdk — HTTP 客户端(统一 Bearer key + 钱包签名 + 错误分级)
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HttpClient = exports.SDK_VERSION = void 0;
|
|
7
|
+
const errors_1 = require("./errors");
|
|
8
|
+
/** SDK 版本(契约 §5,基线 2.0.0,随包版本同步)。 */
|
|
9
|
+
exports.SDK_VERSION = '2.0.0';
|
|
10
|
+
/**
|
|
11
|
+
* 钱包签名的复用时长(ms):首次签名后在该窗口内复用,避免每个请求都触发钱包弹窗。
|
|
12
|
+
* 服务端会话 TTL 为 24h,此处取 1h 留足余量。
|
|
13
|
+
*/
|
|
14
|
+
const WALLET_TOKEN_TTL_MS = 60 * 60 * 1000;
|
|
15
|
+
class HttpClient {
|
|
16
|
+
constructor(config = {}) {
|
|
17
|
+
this.baseUrl = (config.baseUrl ?? 'https://keel.codes').replace(/\/+$/, '');
|
|
18
|
+
this.timeout = config.timeout ?? 30000;
|
|
19
|
+
this.headers = { 'Content-Type': 'application/json', 'X-Keel-Version': exports.SDK_VERSION };
|
|
20
|
+
if (config.apiKey)
|
|
21
|
+
this.headers['Authorization'] = `Bearer ${config.apiKey}`;
|
|
22
|
+
if (config.serviceKey)
|
|
23
|
+
this.headers['X-Service-Key'] = config.serviceKey;
|
|
24
|
+
if (config.wallet)
|
|
25
|
+
this.wallet = config.wallet;
|
|
26
|
+
}
|
|
27
|
+
async get(path, headers) {
|
|
28
|
+
return this.request('GET', path, undefined, headers);
|
|
29
|
+
}
|
|
30
|
+
async post(path, body, headers) {
|
|
31
|
+
return this.request('POST', path, body, headers);
|
|
32
|
+
}
|
|
33
|
+
async put(path, body, headers) {
|
|
34
|
+
return this.request('PUT', path, body, headers);
|
|
35
|
+
}
|
|
36
|
+
async request(method, path, body, extraHeaders) {
|
|
37
|
+
const controller = new AbortController();
|
|
38
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
39
|
+
let res;
|
|
40
|
+
try {
|
|
41
|
+
res = await fetch(this.baseUrl + path, {
|
|
42
|
+
method,
|
|
43
|
+
headers: { ...(await this.buildHeaders()), ...extraHeaders },
|
|
44
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
45
|
+
signal: controller.signal,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
clearTimeout(timer);
|
|
50
|
+
}
|
|
51
|
+
const json = await res.json().catch(() => ({}));
|
|
52
|
+
if (res.status < 200 || res.status >= 300) {
|
|
53
|
+
throw new errors_1.KeelApiError(path, res.status, json?.code ?? 'INTERNAL', json);
|
|
54
|
+
}
|
|
55
|
+
return json;
|
|
56
|
+
}
|
|
57
|
+
/** 静态头 + (若配置)钱包签名头。签名按 WALLET_TOKEN_TTL_MS 复用。 */
|
|
58
|
+
async buildHeaders() {
|
|
59
|
+
if (!this.wallet)
|
|
60
|
+
return this.headers;
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
if (this.walletToken && now - this.walletToken.ts < WALLET_TOKEN_TTL_MS) {
|
|
63
|
+
return { ...this.headers, ...this.walletToken.headers };
|
|
64
|
+
}
|
|
65
|
+
const timestamp = String(now);
|
|
66
|
+
const signature = await this.wallet.sign(`InfraX auth: ${timestamp}`);
|
|
67
|
+
const headers = {
|
|
68
|
+
'x-wallet-address': this.wallet.address.toLowerCase(),
|
|
69
|
+
'x-wallet-timestamp': timestamp,
|
|
70
|
+
'x-wallet-signature': signature,
|
|
71
|
+
};
|
|
72
|
+
this.walletToken = { ts: now, headers };
|
|
73
|
+
return { ...this.headers, ...headers };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.HttpClient = HttpClient;
|