clawmarket 0.4.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.
Files changed (94) hide show
  1. package/README.md +142 -0
  2. package/dist/api-proxy.d.ts +11 -0
  3. package/dist/api-proxy.d.ts.map +1 -0
  4. package/dist/api-proxy.js +98 -0
  5. package/dist/api-proxy.js.map +1 -0
  6. package/dist/buyer/discovery.d.ts +52 -0
  7. package/dist/buyer/discovery.d.ts.map +1 -0
  8. package/dist/buyer/discovery.js +121 -0
  9. package/dist/buyer/discovery.js.map +1 -0
  10. package/dist/buyer/index.d.ts +4 -0
  11. package/dist/buyer/index.d.ts.map +1 -0
  12. package/dist/buyer/index.js +4 -0
  13. package/dist/buyer/index.js.map +1 -0
  14. package/dist/buyer/mode.d.ts +60 -0
  15. package/dist/buyer/mode.d.ts.map +1 -0
  16. package/dist/buyer/mode.js +150 -0
  17. package/dist/buyer/mode.js.map +1 -0
  18. package/dist/buyer/relay.d.ts +27 -0
  19. package/dist/buyer/relay.d.ts.map +1 -0
  20. package/dist/buyer/relay.js +103 -0
  21. package/dist/buyer/relay.js.map +1 -0
  22. package/dist/cli.d.ts +11 -0
  23. package/dist/cli.d.ts.map +1 -0
  24. package/dist/cli.js +252 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/config.d.ts +29 -0
  27. package/dist/config.d.ts.map +1 -0
  28. package/dist/config.js +37 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/crypto/e2ee.d.ts +45 -0
  31. package/dist/crypto/e2ee.d.ts.map +1 -0
  32. package/dist/crypto/e2ee.js +87 -0
  33. package/dist/crypto/e2ee.js.map +1 -0
  34. package/dist/crypto/index.d.ts +3 -0
  35. package/dist/crypto/index.d.ts.map +1 -0
  36. package/dist/crypto/index.js +3 -0
  37. package/dist/crypto/index.js.map +1 -0
  38. package/dist/crypto/ticket.d.ts +62 -0
  39. package/dist/crypto/ticket.d.ts.map +1 -0
  40. package/dist/crypto/ticket.js +123 -0
  41. package/dist/crypto/ticket.js.map +1 -0
  42. package/dist/index.d.ts +11 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +13 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/local-proxy.d.ts +12 -0
  47. package/dist/local-proxy.d.ts.map +1 -0
  48. package/dist/local-proxy.js +593 -0
  49. package/dist/local-proxy.js.map +1 -0
  50. package/dist/openclaw-adapter.d.ts +105 -0
  51. package/dist/openclaw-adapter.d.ts.map +1 -0
  52. package/dist/openclaw-adapter.js +125 -0
  53. package/dist/openclaw-adapter.js.map +1 -0
  54. package/dist/provider.d.ts +116 -0
  55. package/dist/provider.d.ts.map +1 -0
  56. package/dist/provider.js +328 -0
  57. package/dist/provider.js.map +1 -0
  58. package/dist/seller/index.d.ts +4 -0
  59. package/dist/seller/index.d.ts.map +1 -0
  60. package/dist/seller/index.js +4 -0
  61. package/dist/seller/index.js.map +1 -0
  62. package/dist/seller/mode.d.ts +62 -0
  63. package/dist/seller/mode.d.ts.map +1 -0
  64. package/dist/seller/mode.js +179 -0
  65. package/dist/seller/mode.js.map +1 -0
  66. package/dist/seller/registry.d.ts +27 -0
  67. package/dist/seller/registry.d.ts.map +1 -0
  68. package/dist/seller/registry.js +95 -0
  69. package/dist/seller/registry.js.map +1 -0
  70. package/dist/seller/relay.d.ts +64 -0
  71. package/dist/seller/relay.d.ts.map +1 -0
  72. package/dist/seller/relay.js +171 -0
  73. package/dist/seller/relay.js.map +1 -0
  74. package/dist/seller-cli.d.ts +26 -0
  75. package/dist/seller-cli.d.ts.map +1 -0
  76. package/dist/seller-cli.js +354 -0
  77. package/dist/seller-cli.js.map +1 -0
  78. package/dist/seller-daemon.d.ts +7 -0
  79. package/dist/seller-daemon.d.ts.map +1 -0
  80. package/dist/seller-daemon.js +349 -0
  81. package/dist/seller-daemon.js.map +1 -0
  82. package/dist/types/config.d.ts +529 -0
  83. package/dist/types/config.d.ts.map +1 -0
  84. package/dist/types/config.js +81 -0
  85. package/dist/types/config.js.map +1 -0
  86. package/dist/types/index.d.ts +3 -0
  87. package/dist/types/index.d.ts.map +1 -0
  88. package/dist/types/index.js +3 -0
  89. package/dist/types/index.js.map +1 -0
  90. package/dist/types/protocol.d.ts +131 -0
  91. package/dist/types/protocol.d.ts.map +1 -0
  92. package/dist/types/protocol.js +2 -0
  93. package/dist/types/protocol.js.map +1 -0
  94. package/package.json +53 -0
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # ClawMarket Plugin
2
+
3
+ 去中心化 AI 算力市场 — 买 AI 便宜用,卖闲置额度赚钱。
4
+
5
+ ## 快速开始
6
+
7
+ ### 买家(用 AI)
8
+
9
+ ```bash
10
+ # 1. 安装
11
+ npm install -g github:luoluo3310/clawmarket-plugin
12
+
13
+ # 2. 启动
14
+ clawmarket
15
+
16
+ # 3. 充值(按提示操作)
17
+ ```
18
+
19
+ 首次运行会显示你的钱包地址,充值后即可使用。
20
+
21
+ ### 卖家(卖闲置额度)
22
+
23
+ ```bash
24
+ # 1. 安装(同上)
25
+ npm install -g github:luoluo3310/clawmarket-plugin
26
+
27
+ # 2. 启动卖家模式
28
+ clawmarket sell
29
+ ```
30
+
31
+ 启动后按提示操作:
32
+ 1. 选择模型来源(Claude Pro/Max、OpenAI Plus、API Key 等)
33
+ 2. 输入你的 API Key 或 API 地址
34
+ 3. 设置每日出售上限
35
+ 4. 自动注册、连接、开始接单
36
+
37
+ ## 命令
38
+
39
+ ```bash
40
+ # 买家
41
+ clawmarket # 配置 OpenClaw + 启动买家代理
42
+ clawmarket status # 查看状态(余额、代理、通道)
43
+ clawmarket stop # 停止代理
44
+
45
+ # 卖家
46
+ clawmarket sell # 启动卖家模式
47
+ clawmarket sell status # 查看卖家状态(今日收入、接单数等)
48
+ clawmarket sell stop # 停止卖家
49
+ clawmarket sell price # 查看/修改价格
50
+ ```
51
+
52
+ ## 定价
53
+
54
+ 当前市场价格(系统自动调整):
55
+
56
+ | 模型 | 输入 / 1M tokens | 输出 / 1M tokens |
57
+ |------|-----------------|-----------------|
58
+ | claude-opus-4-5 | $1.00 | $5.00 |
59
+
60
+ 对比官方 API 价格($15 / $75),ClawMarket 便宜 **93%**。
61
+
62
+ ### 卖家调价
63
+
64
+ 卖家可以通过重新注册来更新价格:
65
+
66
+ ```bash
67
+ # 方法 1:重新运行 sell 命令,选择新价格
68
+ clawmarket sell
69
+
70
+ # 方法 2:直接修改配置
71
+ clawmarket sell price --input 1.5 --output 7
72
+ ```
73
+
74
+ 系统会根据市场供需动态调整推荐价格,卖家也可以手动设置。
75
+
76
+ ## 充值说明
77
+
78
+ | 币种 | 数量 | 用途 |
79
+ |------|------|------|
80
+ | USDC | 10+ | 开通道押金 |
81
+ | ETH | 0.01 | Gas 费 |
82
+
83
+ **网络:Base Sepolia 测试网**
84
+
85
+ 获取测试币:
86
+ - USDC: https://faucet.circle.com/
87
+ - ETH: https://www.alchemy.com/faucets/base-sepolia
88
+
89
+ ## 工作原理
90
+
91
+ ```
92
+ 买家的 OpenClaw
93
+
94
+ 本地代理 (localhost:19082)
95
+ ↓ 签名 ticket(不上链,无 gas)
96
+ ClawMarket Gateway
97
+ ↓ 智能匹配最优卖家
98
+ 卖家节点 → AI API
99
+
100
+ 返回响应
101
+ ```
102
+
103
+ ### 买家
104
+ 1. 首次请求:自动开通道,锁定 10 USDC 到链上合约
105
+ 2. 每次请求:本地签名 ticket(不上链,无 gas)
106
+ 3. 通道到期:7 天后可取回未使用的余额
107
+
108
+ ### 卖家
109
+ 1. 注册后自动连接 Relay 等待买家请求
110
+ 2. 收到请求 → 调用自己的 AI API → 返回结果
111
+ 3. 系统记录 ticket,定期结算到卖家钱包
112
+ 4. 到达每日上限或 API 限速时自动下线保护
113
+
114
+ ## 卖家保护机制
115
+
116
+ - **每日上限**:到达设定的每日出售额度后自动停止接单
117
+ - **限速检测**:后端 API 返回 429 或超时时立即下线
118
+ - **自动恢复**:第二天零点自动重置,重新上线
119
+ - **零配置**:不需要手动管理,系统自动保护
120
+
121
+ ## 安全性
122
+
123
+ - 私钥只存在本地 (`~/.clawmarket/wallet.json`)
124
+ - 资金锁在链上合约,不在任何人钱包
125
+ - 端到端加密通信(E2EE)
126
+ - 卖家需要 stake 才能接单,作恶会被 slash
127
+
128
+ ## Dashboard
129
+
130
+ 市场实时数据:http://192.210.193.110:9082/
131
+
132
+ 查看在线卖家、可用模型、价格、交易量等。
133
+
134
+ ## 链接
135
+
136
+ - 合约 (Base Sepolia): `0x1577e78D8a446edF10244A80bEf990751e80E495`
137
+ - USDC (Base Sepolia): `0xcF0819eb156D6c6c1c5d9A515E351D2D1aefff7D`
138
+ - GitHub: https://github.com/luoluo3310/clawmarket-plugin
139
+
140
+ ## License
141
+
142
+ MIT
@@ -0,0 +1,11 @@
1
+ /**
2
+ * ClawMarket API 代理服务
3
+ *
4
+ * 提供 OpenAI 兼容的 API,让 OpenClaw 可以直接使用
5
+ *
6
+ * 用法:
7
+ * - baseUrl: http://shenjige.xyz:9082/v1
8
+ * - apiKey: 用户的 ClawMarket 钱包私钥
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=api-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-proxy.d.ts","sourceRoot":"","sources":["../src/api-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * ClawMarket API 代理服务
3
+ *
4
+ * 提供 OpenAI 兼容的 API,让 OpenClaw 可以直接使用
5
+ *
6
+ * 用法:
7
+ * - baseUrl: http://shenjige.xyz:9082/v1
8
+ * - apiKey: 用户的 ClawMarket 钱包私钥
9
+ */
10
+ import http from 'http';
11
+ import { ClawMarketProvider } from './provider.js';
12
+ const PORT = 9082;
13
+ const providers = new Map();
14
+ async function getProvider(apiKey) {
15
+ if (!providers.has(apiKey)) {
16
+ const provider = new ClawMarketProvider();
17
+ // TODO: 用 apiKey 作为私钥初始化钱包
18
+ await provider.initialize();
19
+ providers.set(apiKey, provider);
20
+ }
21
+ return providers.get(apiKey);
22
+ }
23
+ const server = http.createServer(async (req, res) => {
24
+ // CORS
25
+ res.setHeader('Access-Control-Allow-Origin', '*');
26
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
27
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
28
+ if (req.method === 'OPTIONS') {
29
+ res.writeHead(200);
30
+ res.end();
31
+ return;
32
+ }
33
+ const url = new URL(req.url || '/', `http://localhost:${PORT}`);
34
+ // GET /v1/models
35
+ if (req.method === 'GET' && url.pathname === '/v1/models') {
36
+ res.writeHead(200, { 'Content-Type': 'application/json' });
37
+ res.end(JSON.stringify({
38
+ object: 'list',
39
+ data: [
40
+ { id: 'claude-opus-4', object: 'model', created: Date.now(), owned_by: 'clawmarket' },
41
+ { id: 'claude-sonnet-4', object: 'model', created: Date.now(), owned_by: 'clawmarket' }
42
+ ]
43
+ }));
44
+ return;
45
+ }
46
+ // POST /v1/chat/completions
47
+ if (req.method === 'POST' && url.pathname === '/v1/chat/completions') {
48
+ let body = '';
49
+ req.on('data', chunk => body += chunk);
50
+ req.on('end', async () => {
51
+ try {
52
+ const apiKey = (req.headers.authorization || '').replace('Bearer ', '');
53
+ const request = JSON.parse(body);
54
+ console.log(`[API] ${request.model} - ${request.messages.length} messages`);
55
+ const provider = await getProvider(apiKey);
56
+ const response = await provider.chat({
57
+ model: request.model,
58
+ messages: request.messages
59
+ });
60
+ res.writeHead(200, { 'Content-Type': 'application/json' });
61
+ res.end(JSON.stringify({
62
+ id: `clawmarket-${Date.now()}`,
63
+ object: 'chat.completion',
64
+ created: Math.floor(Date.now() / 1000),
65
+ model: request.model,
66
+ choices: [{
67
+ index: 0,
68
+ message: { role: 'assistant', content: response },
69
+ finish_reason: 'stop'
70
+ }],
71
+ usage: {
72
+ prompt_tokens: 0,
73
+ completion_tokens: 0,
74
+ total_tokens: 0
75
+ }
76
+ }));
77
+ }
78
+ catch (err) {
79
+ console.error('[API] Error:', err.message);
80
+ res.writeHead(500, { 'Content-Type': 'application/json' });
81
+ res.end(JSON.stringify({ error: { message: err.message } }));
82
+ }
83
+ });
84
+ return;
85
+ }
86
+ // 404
87
+ res.writeHead(404, { 'Content-Type': 'application/json' });
88
+ res.end(JSON.stringify({ error: { message: 'Not found' } }));
89
+ });
90
+ server.listen(PORT, '0.0.0.0', () => {
91
+ console.log(`ClawMarket API 代理运行在 http://0.0.0.0:${PORT}`);
92
+ console.log('');
93
+ console.log('OpenClaw 配置:');
94
+ console.log(' baseUrl: http://shenjige.xyz:9082/v1');
95
+ console.log(' api: openai-completions');
96
+ console.log('');
97
+ });
98
+ //# sourceMappingURL=api-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-proxy.js","sourceRoot":"","sources":["../src/api-proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { BuyerConfig } from '../types/config.js';
2
+ import type { SellerInfo } from '../types/protocol.js';
3
+ /**
4
+ * Discovery client for buyers to find sellers
5
+ */
6
+ export declare class DiscoveryClient {
7
+ private config;
8
+ private sellersCache;
9
+ private lastFetch;
10
+ private cacheTtlMs;
11
+ constructor(config: BuyerConfig);
12
+ /**
13
+ * Fetch available sellers from Registry
14
+ */
15
+ fetchSellers(model?: string, forceRefresh?: boolean): Promise<SellerInfo[]>;
16
+ /**
17
+ * Filter sellers by model
18
+ */
19
+ private filterSellers;
20
+ /**
21
+ * Select best seller based on strategy
22
+ */
23
+ selectSeller(model: string): Promise<SellerInfo | null>;
24
+ /**
25
+ * Apply selection strategy
26
+ */
27
+ private applyStrategy;
28
+ /**
29
+ * Select seller with lowest price for the model
30
+ */
31
+ private selectLowestPrice;
32
+ /**
33
+ * Select seller with lowest latency
34
+ */
35
+ private selectLowestLatency;
36
+ /**
37
+ * Select seller with highest reputation
38
+ */
39
+ private selectHighestReputation;
40
+ /**
41
+ * Get pricing for a model from a seller
42
+ */
43
+ getModelPricing(seller: SellerInfo, model: string): {
44
+ inputPer1m: number;
45
+ outputPer1m: number;
46
+ } | null;
47
+ /**
48
+ * Clear cache
49
+ */
50
+ clearCache(): void;
51
+ }
52
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/buyer/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAuB,MAAM,sBAAsB,CAAC;AAE5E;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,WAAW;IAI/B;;OAEG;IACG,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAgC/E;;OAEG;IACH,OAAO,CAAC,aAAa;IAUrB;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAU7D;;OAEG;IACH,OAAO,CAAC,aAAa;IAmBrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAM/B;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAKtG;;OAEG;IACH,UAAU,IAAI,IAAI;CAInB"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Discovery client for buyers to find sellers
3
+ */
4
+ export class DiscoveryClient {
5
+ config;
6
+ sellersCache = [];
7
+ lastFetch = 0;
8
+ cacheTtlMs = 30000; // 30 seconds
9
+ constructor(config) {
10
+ this.config = config;
11
+ }
12
+ /**
13
+ * Fetch available sellers from Registry
14
+ */
15
+ async fetchSellers(model, forceRefresh = false) {
16
+ const now = Date.now();
17
+ if (!forceRefresh && this.sellersCache.length > 0 && now - this.lastFetch < this.cacheTtlMs) {
18
+ return this.filterSellers(this.sellersCache, model);
19
+ }
20
+ const params = new URLSearchParams({
21
+ status: 'active',
22
+ minReputation: this.config.minReputation.toString(),
23
+ });
24
+ if (model) {
25
+ params.set('model', model);
26
+ }
27
+ const response = await fetch(`${this.config.registryUrl}/v1/sellers?${params}`, { method: 'GET' });
28
+ if (!response.ok) {
29
+ throw new Error(`Failed to fetch sellers: ${response.status}`);
30
+ }
31
+ const data = await response.json();
32
+ this.sellersCache = data.sellers;
33
+ this.lastFetch = now;
34
+ return this.filterSellers(data.sellers, model);
35
+ }
36
+ /**
37
+ * Filter sellers by model
38
+ */
39
+ filterSellers(sellers, model) {
40
+ if (!model) {
41
+ return sellers;
42
+ }
43
+ return sellers.filter((s) => s.models.some((m) => m.model === model && (m.availableQuotaUsd ?? Infinity) > 0));
44
+ }
45
+ /**
46
+ * Select best seller based on strategy
47
+ */
48
+ async selectSeller(model) {
49
+ const sellers = await this.fetchSellers(model);
50
+ if (sellers.length === 0) {
51
+ return null;
52
+ }
53
+ return this.applyStrategy(sellers, model, this.config.strategy) ?? null;
54
+ }
55
+ /**
56
+ * Apply selection strategy
57
+ */
58
+ applyStrategy(sellers, model, strategy) {
59
+ if (sellers.length === 0)
60
+ return undefined;
61
+ switch (strategy) {
62
+ case 'lowest_price':
63
+ return this.selectLowestPrice(sellers, model);
64
+ case 'lowest_latency':
65
+ return this.selectLowestLatency(sellers);
66
+ case 'highest_reputation':
67
+ return this.selectHighestReputation(sellers);
68
+ default:
69
+ return sellers[0];
70
+ }
71
+ }
72
+ /**
73
+ * Select seller with lowest price for the model
74
+ */
75
+ selectLowestPrice(sellers, model) {
76
+ return sellers.reduce((best, current) => {
77
+ const bestModel = best.models.find((m) => m.model === model);
78
+ const currentModel = current.models.find((m) => m.model === model);
79
+ if (!bestModel)
80
+ return current;
81
+ if (!currentModel)
82
+ return best;
83
+ const bestPrice = bestModel.pricing.inputPer1m + bestModel.pricing.outputPer1m;
84
+ const currentPrice = currentModel.pricing.inputPer1m + currentModel.pricing.outputPer1m;
85
+ return currentPrice < bestPrice ? current : best;
86
+ });
87
+ }
88
+ /**
89
+ * Select seller with lowest latency
90
+ */
91
+ selectLowestLatency(sellers) {
92
+ return sellers.reduce((best, current) => {
93
+ const bestLatency = best.reputation.avgLatencyMs;
94
+ const currentLatency = current.reputation.avgLatencyMs;
95
+ return currentLatency < bestLatency ? current : best;
96
+ });
97
+ }
98
+ /**
99
+ * Select seller with highest reputation
100
+ */
101
+ selectHighestReputation(sellers) {
102
+ return sellers.reduce((best, current) => {
103
+ return current.reputation.score > best.reputation.score ? current : best;
104
+ });
105
+ }
106
+ /**
107
+ * Get pricing for a model from a seller
108
+ */
109
+ getModelPricing(seller, model) {
110
+ const modelInfo = seller.models.find((m) => m.model === model);
111
+ return modelInfo?.pricing ?? null;
112
+ }
113
+ /**
114
+ * Clear cache
115
+ */
116
+ clearCache() {
117
+ this.sellersCache = [];
118
+ this.lastFetch = 0;
119
+ }
120
+ }
121
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/buyer/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { DiscoveryClient } from './discovery.js';
2
+ export { RelayClient } from './relay.js';
3
+ export { BuyerMode } from './mode.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/buyer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { DiscoveryClient } from './discovery.js';
2
+ export { RelayClient } from './relay.js';
3
+ export { BuyerMode } from './mode.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/buyer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { EventEmitter } from 'events';
2
+ import type { BuyerConfig } from '../types/config.js';
3
+ import type { ChatCompletionRequest, ChatCompletionResponse } from '../types/protocol.js';
4
+ import { type KeyPair } from '../crypto/e2ee.js';
5
+ export interface BuyerModeEvents {
6
+ request: (model: string, sellerId: string) => void;
7
+ response: (model: string, sellerId: string, success: boolean) => void;
8
+ fallback: (model: string, reason: string) => void;
9
+ error: (error: Error) => void;
10
+ }
11
+ /**
12
+ * Buyer mode handler
13
+ * - Discovers sellers
14
+ * - Selects best seller
15
+ * - Sends encrypted requests
16
+ * - Handles payments
17
+ */
18
+ export declare class BuyerMode extends EventEmitter {
19
+ private config;
20
+ private discovery;
21
+ private relay;
22
+ private keyPair;
23
+ private ticketSigner;
24
+ private channels;
25
+ private nonceCounters;
26
+ constructor(config: BuyerConfig, privateKey: `0x${string}`, contractAddress: `0x${string}`, rpcUrl: string, chainId?: number, keyPair?: KeyPair);
27
+ /**
28
+ * Send a chat completion request through ClawMarket
29
+ */
30
+ chatCompletion(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
31
+ /**
32
+ * Handle fallback to direct provider
33
+ */
34
+ private handleFallback;
35
+ /**
36
+ * Get or create payment channel with seller
37
+ */
38
+ private getOrCreateChannel;
39
+ /**
40
+ * Get next nonce for a channel
41
+ */
42
+ private getNextNonce;
43
+ /**
44
+ * Estimate token usage for a request
45
+ */
46
+ private estimateTokens;
47
+ /**
48
+ * Get buyer's public key
49
+ */
50
+ get publicKey(): Uint8Array;
51
+ /**
52
+ * Get buyer's wallet address
53
+ */
54
+ get address(): `0x${string}`;
55
+ /**
56
+ * Refresh seller cache
57
+ */
58
+ refreshSellers(): Promise<void>;
59
+ }
60
+ //# sourceMappingURL=mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../src/buyer/mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAEV,qBAAqB,EACrB,sBAAsB,EAEvB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAML,KAAK,OAAO,EACb,MAAM,mBAAmB,CAAC;AAG3B,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACtE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,qBAAa,SAAU,SAAQ,YAAY;IACzC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAwC;IACxD,OAAO,CAAC,aAAa,CAAkC;gBAGrD,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,KAAK,MAAM,EAAE,EACzB,eAAe,EAAE,KAAK,MAAM,EAAE,EAC9B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,OAAO;IAUnB;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA+ErF;;OAEG;YACW,cAAc;IAc5B;;OAEG;YACW,kBAAkB;IA4BhC;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,cAAc;IAWtB;;OAEG;IACH,IAAI,SAAS,IAAI,UAAU,CAE1B;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,KAAK,MAAM,EAAE,CAE3B;IAED;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC"}