openclaw-overlay-plugin 0.8.14 → 0.8.16

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 (190) hide show
  1. package/dist/index.js +6705 -326
  2. package/dist/index.js.map +7 -0
  3. package/dist/src/cli.js +7498 -11
  4. package/dist/src/cli.js.map +7 -0
  5. package/index.ts +1 -1
  6. package/openclaw.plugin.json +1 -1
  7. package/package.json +8 -8
  8. package/src/scripts/messaging/handlers.ts +1 -1
  9. package/src/scripts/overlay/advertisement.ts +1 -1
  10. package/src/scripts/overlay/registration.ts +1 -1
  11. package/src/scripts/overlay/services.ts +1 -1
  12. package/src/scripts/overlay/transaction.ts +1 -1
  13. package/src/scripts/payment/build.ts +1 -1
  14. package/src/scripts/payment/commands.ts +1 -1
  15. package/src/scripts/wallet/balance.ts +1 -1
  16. package/src/scripts/wallet/setup.ts +1 -1
  17. package/src/test/identity-consistency.test.ts +1 -1
  18. package/src/test/wallet.test.ts +1 -2
  19. package/dist/index.d.ts +0 -9
  20. package/dist/src/cli-main.d.ts +0 -7
  21. package/dist/src/cli-main.js +0 -202
  22. package/dist/src/cli.d.ts +0 -8
  23. package/dist/src/compatibility.test.d.ts +0 -4
  24. package/dist/src/compatibility.test.js +0 -41
  25. package/dist/src/core/config.d.ts +0 -11
  26. package/dist/src/core/config.js +0 -15
  27. package/dist/src/core/index.d.ts +0 -25
  28. package/dist/src/core/index.js +0 -26
  29. package/dist/src/core/payment.d.ts +0 -16
  30. package/dist/src/core/payment.js +0 -94
  31. package/dist/src/core/types.d.ts +0 -94
  32. package/dist/src/core/types.js +0 -4
  33. package/dist/src/core/verify.d.ts +0 -28
  34. package/dist/src/core/verify.js +0 -104
  35. package/dist/src/core/wallet.d.ts +0 -105
  36. package/dist/src/core/wallet.js +0 -256
  37. package/dist/src/scripts/baemail/commands.d.ts +0 -35
  38. package/dist/src/scripts/baemail/commands.js +0 -282
  39. package/dist/src/scripts/baemail/handler.d.ts +0 -36
  40. package/dist/src/scripts/baemail/handler.js +0 -284
  41. package/dist/src/scripts/baemail/index.d.ts +0 -5
  42. package/dist/src/scripts/baemail/index.js +0 -5
  43. package/dist/src/scripts/config.d.ts +0 -52
  44. package/dist/src/scripts/config.js +0 -75
  45. package/dist/src/scripts/index.d.ts +0 -7
  46. package/dist/src/scripts/index.js +0 -7
  47. package/dist/src/scripts/messaging/connect.d.ts +0 -8
  48. package/dist/src/scripts/messaging/connect.js +0 -168
  49. package/dist/src/scripts/messaging/handlers.d.ts +0 -21
  50. package/dist/src/scripts/messaging/handlers.js +0 -334
  51. package/dist/src/scripts/messaging/inbox.d.ts +0 -11
  52. package/dist/src/scripts/messaging/inbox.js +0 -51
  53. package/dist/src/scripts/messaging/index.d.ts +0 -8
  54. package/dist/src/scripts/messaging/index.js +0 -8
  55. package/dist/src/scripts/messaging/poll.d.ts +0 -7
  56. package/dist/src/scripts/messaging/poll.js +0 -52
  57. package/dist/src/scripts/messaging/send.d.ts +0 -7
  58. package/dist/src/scripts/messaging/send.js +0 -43
  59. package/dist/src/scripts/output.d.ts +0 -13
  60. package/dist/src/scripts/output.js +0 -28
  61. package/dist/src/scripts/overlay/advertisement.d.ts +0 -16
  62. package/dist/src/scripts/overlay/advertisement.js +0 -122
  63. package/dist/src/scripts/overlay/discover.d.ts +0 -7
  64. package/dist/src/scripts/overlay/discover.js +0 -74
  65. package/dist/src/scripts/overlay/index.d.ts +0 -7
  66. package/dist/src/scripts/overlay/index.js +0 -7
  67. package/dist/src/scripts/overlay/registration.d.ts +0 -19
  68. package/dist/src/scripts/overlay/registration.js +0 -176
  69. package/dist/src/scripts/overlay/services.d.ts +0 -29
  70. package/dist/src/scripts/overlay/services.js +0 -167
  71. package/dist/src/scripts/overlay/transaction.d.ts +0 -42
  72. package/dist/src/scripts/overlay/transaction.js +0 -103
  73. package/dist/src/scripts/payment/build.d.ts +0 -24
  74. package/dist/src/scripts/payment/build.js +0 -54
  75. package/dist/src/scripts/payment/commands.d.ts +0 -15
  76. package/dist/src/scripts/payment/commands.js +0 -73
  77. package/dist/src/scripts/payment/index.d.ts +0 -6
  78. package/dist/src/scripts/payment/index.js +0 -6
  79. package/dist/src/scripts/payment/types.d.ts +0 -56
  80. package/dist/src/scripts/payment/types.js +0 -4
  81. package/dist/src/scripts/services/index.d.ts +0 -6
  82. package/dist/src/scripts/services/index.js +0 -6
  83. package/dist/src/scripts/services/queue.d.ts +0 -11
  84. package/dist/src/scripts/services/queue.js +0 -28
  85. package/dist/src/scripts/services/request.d.ts +0 -7
  86. package/dist/src/scripts/services/request.js +0 -82
  87. package/dist/src/scripts/services/respond.d.ts +0 -11
  88. package/dist/src/scripts/services/respond.js +0 -132
  89. package/dist/src/scripts/types.d.ts +0 -107
  90. package/dist/src/scripts/types.js +0 -4
  91. package/dist/src/scripts/utils/index.d.ts +0 -6
  92. package/dist/src/scripts/utils/index.js +0 -6
  93. package/dist/src/scripts/utils/merkle.d.ts +0 -12
  94. package/dist/src/scripts/utils/merkle.js +0 -47
  95. package/dist/src/scripts/utils/storage.d.ts +0 -66
  96. package/dist/src/scripts/utils/storage.js +0 -211
  97. package/dist/src/scripts/utils/woc.d.ts +0 -26
  98. package/dist/src/scripts/utils/woc.js +0 -91
  99. package/dist/src/scripts/wallet/balance.d.ts +0 -22
  100. package/dist/src/scripts/wallet/balance.js +0 -240
  101. package/dist/src/scripts/wallet/identity.d.ts +0 -71
  102. package/dist/src/scripts/wallet/identity.js +0 -152
  103. package/dist/src/scripts/wallet/index.d.ts +0 -6
  104. package/dist/src/scripts/wallet/index.js +0 -6
  105. package/dist/src/scripts/wallet/setup.d.ts +0 -19
  106. package/dist/src/scripts/wallet/setup.js +0 -119
  107. package/dist/src/scripts/x-verification/commands.d.ts +0 -27
  108. package/dist/src/scripts/x-verification/commands.js +0 -222
  109. package/dist/src/scripts/x-verification/index.d.ts +0 -4
  110. package/dist/src/scripts/x-verification/index.js +0 -4
  111. package/dist/src/services/built-in/api-proxy/index.d.ts +0 -6
  112. package/dist/src/services/built-in/api-proxy/index.js +0 -23
  113. package/dist/src/services/built-in/code-develop/index.d.ts +0 -6
  114. package/dist/src/services/built-in/code-develop/index.js +0 -23
  115. package/dist/src/services/built-in/code-review/index.d.ts +0 -10
  116. package/dist/src/services/built-in/code-review/index.js +0 -51
  117. package/dist/src/services/built-in/image-analysis/index.d.ts +0 -6
  118. package/dist/src/services/built-in/image-analysis/index.js +0 -33
  119. package/dist/src/services/built-in/memory-store/index.d.ts +0 -6
  120. package/dist/src/services/built-in/memory-store/index.js +0 -22
  121. package/dist/src/services/built-in/roulette/index.d.ts +0 -6
  122. package/dist/src/services/built-in/roulette/index.js +0 -27
  123. package/dist/src/services/built-in/summarize/index.d.ts +0 -6
  124. package/dist/src/services/built-in/summarize/index.js +0 -21
  125. package/dist/src/services/built-in/tell-joke/handler.d.ts +0 -7
  126. package/dist/src/services/built-in/tell-joke/handler.js +0 -122
  127. package/dist/src/services/built-in/tell-joke/index.d.ts +0 -9
  128. package/dist/src/services/built-in/tell-joke/index.js +0 -31
  129. package/dist/src/services/built-in/translate/index.d.ts +0 -6
  130. package/dist/src/services/built-in/translate/index.js +0 -21
  131. package/dist/src/services/built-in/web-research/index.d.ts +0 -9
  132. package/dist/src/services/built-in/web-research/index.js +0 -51
  133. package/dist/src/services/index.d.ts +0 -13
  134. package/dist/src/services/index.js +0 -14
  135. package/dist/src/services/loader.d.ts +0 -77
  136. package/dist/src/services/loader.js +0 -292
  137. package/dist/src/services/manager.d.ts +0 -86
  138. package/dist/src/services/manager.js +0 -255
  139. package/dist/src/services/registry.d.ts +0 -98
  140. package/dist/src/services/registry.js +0 -204
  141. package/dist/src/services/types.d.ts +0 -230
  142. package/dist/src/services/types.js +0 -30
  143. package/dist/src/test/cli.test.d.ts +0 -7
  144. package/dist/src/test/cli.test.js +0 -330
  145. package/dist/src/test/comprehensive-overlay.test.d.ts +0 -13
  146. package/dist/src/test/comprehensive-overlay.test.js +0 -593
  147. package/dist/src/test/identity-consistency.test.d.ts +0 -6
  148. package/dist/src/test/identity-consistency.test.js +0 -60
  149. package/dist/src/test/key-derivation.test.d.ts +0 -12
  150. package/dist/src/test/key-derivation.test.js +0 -86
  151. package/dist/src/test/network-address.test.d.ts +0 -9
  152. package/dist/src/test/network-address.test.js +0 -37
  153. package/dist/src/test/overlay-submit.test.d.ts +0 -10
  154. package/dist/src/test/overlay-submit.test.js +0 -460
  155. package/dist/src/test/request-response-flow.test.d.ts +0 -5
  156. package/dist/src/test/request-response-flow.test.js +0 -210
  157. package/dist/src/test/service-system.test.d.ts +0 -5
  158. package/dist/src/test/service-system.test.js +0 -190
  159. package/dist/src/test/taskflow.test.d.ts +0 -7
  160. package/dist/src/test/taskflow.test.js +0 -82
  161. package/dist/src/test/utils/server-logic.d.ts +0 -98
  162. package/dist/src/test/utils/server-logic.js +0 -286
  163. package/dist/src/test/wallet.test.d.ts +0 -7
  164. package/dist/src/test/wallet.test.js +0 -146
  165. package/src/core/README.md +0 -246
  166. package/src/core/config.d.ts +0 -12
  167. package/src/core/config.d.ts.map +0 -1
  168. package/src/core/config.js +0 -14
  169. package/src/core/config.js.map +0 -1
  170. package/src/core/config.ts +0 -22
  171. package/src/core/index.ts +0 -42
  172. package/src/core/payment.d.ts +0 -17
  173. package/src/core/payment.d.ts.map +0 -1
  174. package/src/core/payment.js +0 -95
  175. package/src/core/payment.js.map +0 -1
  176. package/src/core/payment.ts +0 -111
  177. package/src/core/types.d.ts +0 -95
  178. package/src/core/types.d.ts.map +0 -1
  179. package/src/core/types.js +0 -5
  180. package/src/core/types.js.map +0 -1
  181. package/src/core/types.ts +0 -102
  182. package/src/core/verify.d.ts +0 -29
  183. package/src/core/verify.d.ts.map +0 -1
  184. package/src/core/verify.js +0 -105
  185. package/src/core/verify.js.map +0 -1
  186. package/src/core/verify.ts +0 -119
  187. package/src/core/wallet.d.ts +0 -100
  188. package/src/core/wallet.d.ts.map +0 -1
  189. package/src/core/wallet.js.map +0 -1
  190. package/src/core/wallet.ts +0 -323
@@ -1,286 +0,0 @@
1
- /**
2
- * Server validation logic mirrored from openclaw-overlay.
3
- *
4
- * This module contains the exact same parsing and validation logic
5
- * used by the server's topic managers, allowing us to validate
6
- * client output before submission.
7
- *
8
- * Updated to use PushDrop tokens instead of plain OP_RETURN.
9
- */
10
- import { OP, Beef, PushDrop } from '@bsv/sdk';
11
- export const PROTOCOL_ID = 'openclaw-overlay-v1';
12
- // ============================================================================
13
- // Script Parsing using PushDrop.decode()
14
- // ============================================================================
15
- /**
16
- * Extract data fields from a PushDrop script using the SDK's decode method.
17
- * Returns the fields array or null if not a valid PushDrop script.
18
- */
19
- export function extractPushDropFields(script) {
20
- try {
21
- const decoded = PushDrop.decode(script);
22
- return decoded.fields;
23
- }
24
- catch {
25
- return null;
26
- }
27
- }
28
- /**
29
- * Legacy function for backwards compatibility - extracts from OP_RETURN scripts.
30
- * @deprecated Use extractPushDropFields instead
31
- */
32
- export function extractOpReturnPushes(script) {
33
- const chunks = script.chunks;
34
- // Legacy 4+ chunk format: OP_FALSE OP_RETURN <data> <data> ...
35
- if (chunks.length >= 4 &&
36
- chunks[0].op === OP.OP_FALSE &&
37
- chunks[1].op === OP.OP_RETURN) {
38
- const pushes = [];
39
- for (let i = 2; i < chunks.length; i++) {
40
- if (chunks[i].data) {
41
- pushes.push(new Uint8Array(chunks[i].data));
42
- }
43
- }
44
- return pushes;
45
- }
46
- // Collapsed 2-chunk format: OP_FALSE OP_RETURN with data blob
47
- if (chunks.length === 2 &&
48
- chunks[0].op === OP.OP_FALSE &&
49
- chunks[1].op === OP.OP_RETURN &&
50
- chunks[1].data) {
51
- const blob = chunks[1].data;
52
- const pushes = [];
53
- let pos = 0;
54
- while (pos < blob.length) {
55
- const op = blob[pos++];
56
- if (op > 0 && op <= 75) {
57
- const end = Math.min(pos + op, blob.length);
58
- pushes.push(new Uint8Array(blob.slice(pos, end)));
59
- pos = end;
60
- }
61
- else if (op === 0x4c) {
62
- const len = blob[pos++] ?? 0;
63
- const end = Math.min(pos + len, blob.length);
64
- pushes.push(new Uint8Array(blob.slice(pos, end)));
65
- pos = end;
66
- }
67
- else if (op === 0x4d) {
68
- const len = (blob[pos] ?? 0) | ((blob[pos + 1] ?? 0) << 8);
69
- pos += 2;
70
- const end = Math.min(pos + len, blob.length);
71
- pushes.push(new Uint8Array(blob.slice(pos, end)));
72
- pos = end;
73
- }
74
- else if (op === 0x4e) {
75
- const len = ((blob[pos] ?? 0) |
76
- ((blob[pos + 1] ?? 0) << 8) |
77
- ((blob[pos + 2] ?? 0) << 16) |
78
- ((blob[pos + 3] ?? 0) << 24)) >>> 0;
79
- pos += 4;
80
- const end = Math.min(pos + len, blob.length);
81
- pushes.push(new Uint8Array(blob.slice(pos, end)));
82
- pos = end;
83
- }
84
- else {
85
- break;
86
- }
87
- }
88
- return pushes.length >= 2 ? pushes : null;
89
- }
90
- return null;
91
- }
92
- // ============================================================================
93
- // Payload Parsing - Updated for PushDrop
94
- // ============================================================================
95
- /**
96
- * Parse identity payload from a PushDrop script.
97
- * The first field contains the JSON payload.
98
- */
99
- export function parseIdentityOutput(script) {
100
- const fields = extractPushDropFields(script);
101
- if (!fields || fields.length < 1)
102
- return null;
103
- try {
104
- const payload = JSON.parse(new TextDecoder().decode(new Uint8Array(fields[0])));
105
- // Server validation rules
106
- if (payload.protocol !== PROTOCOL_ID)
107
- return null;
108
- if (payload.type !== 'identity')
109
- return null;
110
- if (typeof payload.identityKey !== 'string' || !/^[0-9a-fA-F]{66}$/.test(payload.identityKey))
111
- return null;
112
- if (typeof payload.name !== 'string' || payload.name.length === 0)
113
- return null;
114
- if (!Array.isArray(payload.capabilities))
115
- return null;
116
- if (typeof payload.timestamp !== 'string')
117
- return null;
118
- return payload;
119
- }
120
- catch {
121
- return null;
122
- }
123
- }
124
- /**
125
- * Parse identity revocation payload from a PushDrop script.
126
- */
127
- export function parseRevocationOutput(script) {
128
- const fields = extractPushDropFields(script);
129
- if (!fields || fields.length < 1)
130
- return null;
131
- try {
132
- const payload = JSON.parse(new TextDecoder().decode(new Uint8Array(fields[0])));
133
- if (payload.protocol !== PROTOCOL_ID)
134
- return null;
135
- if (payload.type !== 'identity-revocation')
136
- return null;
137
- if (typeof payload.identityKey !== 'string' || !/^[0-9a-fA-F]{66}$/.test(payload.identityKey))
138
- return null;
139
- if (typeof payload.timestamp !== 'string')
140
- return null;
141
- return payload;
142
- }
143
- catch {
144
- return null;
145
- }
146
- }
147
- /**
148
- * Parse service payload from a PushDrop script.
149
- */
150
- export function parseServiceOutput(script) {
151
- const fields = extractPushDropFields(script);
152
- if (!fields || fields.length < 1)
153
- return null;
154
- try {
155
- const payload = JSON.parse(new TextDecoder().decode(new Uint8Array(fields[0])));
156
- if (payload.protocol !== PROTOCOL_ID)
157
- return null;
158
- if (payload.type !== 'service')
159
- return null;
160
- if (typeof payload.identityKey !== 'string' || !/^[0-9a-fA-F]{66}$/.test(payload.identityKey))
161
- return null;
162
- if (typeof payload.serviceId !== 'string' || payload.serviceId.length === 0)
163
- return null;
164
- if (typeof payload.name !== 'string' || payload.name.length === 0)
165
- return null;
166
- if (!payload.pricing || typeof payload.pricing.amountSats !== 'number')
167
- return null;
168
- if (typeof payload.timestamp !== 'string')
169
- return null;
170
- return payload;
171
- }
172
- catch {
173
- return null;
174
- }
175
- }
176
- // ============================================================================
177
- // Topic Manager Simulation
178
- // ============================================================================
179
- /**
180
- * Simulate the identity topic manager's identifyAdmissibleOutputs.
181
- */
182
- export function identifyIdentityOutputs(beef) {
183
- const parsedBeef = Beef.fromBinary(beef);
184
- const subjectTx = parsedBeef.txs[0]?._tx;
185
- if (!subjectTx) {
186
- return { outputsToAdmit: [], coinsToRetain: [] };
187
- }
188
- const outputsToAdmit = [];
189
- for (let i = 0; i < subjectTx.outputs.length; i++) {
190
- const output = subjectTx.outputs[i];
191
- if (output.lockingScript) {
192
- // Check identity
193
- const identity = parseIdentityOutput(output.lockingScript);
194
- if (identity !== null) {
195
- outputsToAdmit.push(i);
196
- continue;
197
- }
198
- // Check revocation
199
- const revocation = parseRevocationOutput(output.lockingScript);
200
- if (revocation !== null) {
201
- outputsToAdmit.push(i);
202
- }
203
- }
204
- }
205
- return { outputsToAdmit, coinsToRetain: [] };
206
- }
207
- /**
208
- * Simulate the services topic manager's identifyAdmissibleOutputs.
209
- */
210
- export function identifyServiceOutputs(beef) {
211
- const parsedBeef = Beef.fromBinary(beef);
212
- const subjectTx = parsedBeef.txs[0]?._tx;
213
- if (!subjectTx) {
214
- return { outputsToAdmit: [], coinsToRetain: [] };
215
- }
216
- const outputsToAdmit = [];
217
- for (let i = 0; i < subjectTx.outputs.length; i++) {
218
- const output = subjectTx.outputs[i];
219
- if (output.lockingScript) {
220
- const service = parseServiceOutput(output.lockingScript);
221
- if (service !== null) {
222
- outputsToAdmit.push(i);
223
- }
224
- }
225
- }
226
- return { outputsToAdmit, coinsToRetain: [] };
227
- }
228
- // ============================================================================
229
- // BEEF Validation
230
- // ============================================================================
231
- /**
232
- * Validate BEEF format and structure.
233
- */
234
- export function validateBeef(beef) {
235
- try {
236
- // Check magic bytes
237
- if (beef.length < 4) {
238
- return { valid: false, error: 'BEEF too short' };
239
- }
240
- const magic = beef.slice(0, 4);
241
- const magicHex = magic.map(b => b.toString(16).padStart(2, '0')).join('');
242
- if (magicHex !== '0100beef' && magicHex !== '0200beef') {
243
- return { valid: false, error: `Invalid magic bytes: ${magicHex}` };
244
- }
245
- const version = magicHex === '0100beef' ? 1 : 2;
246
- // Parse BEEF
247
- const parsed = Beef.fromBinary(beef);
248
- if (!parsed.txs || parsed.txs.length === 0) {
249
- return { valid: false, error: 'BEEF contains no transactions' };
250
- }
251
- // Check for merkle proofs
252
- const hasProofs = parsed.bumps && parsed.bumps.length > 0;
253
- return {
254
- valid: true,
255
- version,
256
- txCount: parsed.txs.length,
257
- hasProofs,
258
- };
259
- }
260
- catch (e) {
261
- return { valid: false, error: e instanceof Error ? e.message : 'Unknown error' };
262
- }
263
- }
264
- /**
265
- * Validate BEEF has proper ancestry chain.
266
- */
267
- export function validateBeefAncestry(beef) {
268
- try {
269
- const parsed = Beef.fromBinary(beef);
270
- const chain = [];
271
- for (const btx of parsed.txs) {
272
- const txid = btx.txid || btx._tx?.id('hex');
273
- if (txid)
274
- chain.push(txid);
275
- }
276
- // Use Beef's built-in validation
277
- const isValid = parsed.isValid(false);
278
- if (!isValid) {
279
- return { valid: false, error: 'BEEF ancestry chain is invalid', chain };
280
- }
281
- return { valid: true, chain };
282
- }
283
- catch (e) {
284
- return { valid: false, error: e instanceof Error ? e.message : 'Unknown error' };
285
- }
286
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * @a2a-bsv/core — Wallet tests
3
- *
4
- * These tests verify that BSVAgentWallet can be instantiated and its basic
5
- * methods are callable. Full integration tests require a funded testnet wallet.
6
- */
7
- export {};
@@ -1,146 +0,0 @@
1
- /**
2
- * @a2a-bsv/core — Wallet tests
3
- *
4
- * These tests verify that BSVAgentWallet can be instantiated and its basic
5
- * methods are callable. Full integration tests require a funded testnet wallet.
6
- */
7
- import { BSVAgentWallet } from '../core/index.js';
8
- import { verifyPayment } from '../core/verify.js';
9
- import * as fs from 'node:fs';
10
- import * as path from 'node:path';
11
- import * as os from 'node:os';
12
- // Simple test runner (no jest dependency needed)
13
- let passed = 0;
14
- let failed = 0;
15
- function test(name, fn) {
16
- return (async () => {
17
- try {
18
- await fn();
19
- console.log(` ✓ ${name}`);
20
- passed++;
21
- }
22
- catch (err) {
23
- const msg = err instanceof Error ? err.message : String(err);
24
- console.log(` ✗ ${name}`);
25
- console.log(` ${msg}`);
26
- failed++;
27
- }
28
- })();
29
- }
30
- function assert(condition, message) {
31
- if (!condition)
32
- throw new Error(`Assertion failed: ${message}`);
33
- }
34
- async function run() {
35
- console.log('@a2a-bsv/core tests\n');
36
- // ── Verify payment (pure, no wallet needed) ──────────────────────────
37
- await test('verifyPayment rejects empty beef', async () => {
38
- const result = await verifyPayment({ beef: '' });
39
- assert(!result.valid, 'should be invalid');
40
- assert(result.errors.length > 0, 'should have errors');
41
- });
42
- await test('verifyPayment rejects garbage base64', async () => {
43
- const result = await verifyPayment({ beef: 'dGhpcyBpcyBub3QgYmVlZg==' });
44
- assert(!result.valid, 'should be invalid');
45
- assert(result.errors.length > 0, 'should have errors');
46
- });
47
- await test('verifyPayment validates expectedSender format', async () => {
48
- const result = await verifyPayment({
49
- beef: 'dGhpcyBpcyBub3QgYmVlZg==',
50
- expectedSender: 'not-a-pubkey',
51
- });
52
- assert(!result.valid, 'should be invalid');
53
- assert(result.errors.length >= 2, 'should have both BEEF and sender errors');
54
- const hasSenderError = result.errors.some(e => e.includes('public key'));
55
- assert(hasSenderError, 'should flag invalid sender key');
56
- });
57
- // ── Wallet creation ──────────────────────────────────────────────────
58
- await test('BSVAgentWallet.load creates a wallet and identity file', async () => {
59
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'a2a-test-'));
60
- try {
61
- const wallet = await BSVAgentWallet.load({
62
- network: 'testnet',
63
- storageDir: tmpDir,
64
- });
65
- // Identity file should exist
66
- const identityPath = path.join(tmpDir, 'wallet-identity.json');
67
- assert(fs.existsSync(identityPath), 'identity file should exist');
68
- // Should have a valid identity key
69
- const identityKey = await wallet.getIdentityKey();
70
- assert(/^0[23][0-9a-f]{64}$/.test(identityKey), `identityKey should be compressed pubkey, got: ${identityKey}`);
71
- // Balance should be 0 for a fresh wallet
72
- const balance = await wallet.getBalance();
73
- assert(balance === 0, `fresh wallet balance should be 0, got: ${balance}`);
74
- await wallet.destroy();
75
- }
76
- finally {
77
- fs.rmSync(tmpDir, { recursive: true, force: true });
78
- }
79
- });
80
- await test('BSVAgentWallet.load loads an existing wallet', async () => {
81
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'a2a-test-'));
82
- try {
83
- // Create first
84
- const wallet1 = await BSVAgentWallet.load({
85
- network: 'testnet',
86
- storageDir: tmpDir,
87
- });
88
- const key1 = await wallet1.getIdentityKey();
89
- await wallet1.destroy();
90
- // Load
91
- const wallet2 = await BSVAgentWallet.load({
92
- network: 'testnet',
93
- storageDir: tmpDir,
94
- });
95
- const key2 = await wallet2.getIdentityKey();
96
- await wallet2.destroy();
97
- assert(key1 === key2, `loaded wallet should have same identity key`);
98
- }
99
- finally {
100
- fs.rmSync(tmpDir, { recursive: true, force: true });
101
- }
102
- });
103
- await test('BSVAgentWallet.load throws for missing wallet', async () => {
104
- const tmpDir = path.join(os.tmpdir(), 'a2a-nonexistent-' + Date.now());
105
- try {
106
- await BSVAgentWallet.load({ network: 'testnet', storageDir: tmpDir, createIfMissing: false });
107
- throw new Error('Should have thrown');
108
- }
109
- catch (err) {
110
- const msg = err instanceof Error ? err.message : String(err);
111
- assert(msg.includes('No wallet found'), `should say no wallet found, got: ${msg}`);
112
- }
113
- });
114
- await test('createPayment rejects address (requires pubkey)', async () => {
115
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'a2a-test-'));
116
- try {
117
- const wallet = await BSVAgentWallet.load({
118
- network: 'testnet',
119
- storageDir: tmpDir,
120
- });
121
- try {
122
- await wallet.createPayment({
123
- to: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', // address, not pubkey
124
- satoshis: 100,
125
- });
126
- throw new Error('Should have thrown');
127
- }
128
- catch (err) {
129
- const msg = err instanceof Error ? err.message : String(err);
130
- assert(msg.includes('compressed public key'), `should require pubkey, got: ${msg}`);
131
- }
132
- await wallet.destroy();
133
- }
134
- finally {
135
- fs.rmSync(tmpDir, { recursive: true, force: true });
136
- }
137
- });
138
- // ── Summary ──────────────────────────────────────────────────────────
139
- console.log(`\n${passed} passed, ${failed} failed`);
140
- if (failed > 0)
141
- process.exit(1);
142
- }
143
- run().catch(err => {
144
- console.error(err);
145
- process.exit(1);
146
- });
@@ -1,246 +0,0 @@
1
- # @a2a-bsv/core
2
-
3
- BSV agent-to-agent payment library. Wraps [`@bsv/sdk`](https://github.com/bsv-blockchain/ts-sdk) and [`@bsv/wallet-toolbox`](https://github.com/bsv-blockchain/wallet-toolbox) to provide exactly the operations AI agents need to pay each other on the BSV blockchain.
4
-
5
- ## Features
6
-
7
- - **BRC-100 compliant wallet** backed by SQLite for local persistence
8
- - **BRC-29 payments** — privacy-preserving key derivation, no address reuse
9
- - **SPV verification** via Atomic BEEF transaction format
10
- - **noSend workflow** — sender builds the transaction, recipient verifies and broadcasts
11
- - **Clean API** — minimal surface area designed for automated agent use
12
-
13
- ## Installation
14
-
15
- ```bash
16
- npm install @a2a-bsv/core
17
- ```
18
-
19
- > Requires Node.js 18+ and SQLite3 (native dependency via `@bsv/wallet-toolbox`).
20
-
21
- ## Quick Start
22
-
23
- ```typescript
24
- import { BSVAgentWallet } from '@a2a-bsv/core';
25
-
26
- // 1. Create wallets for two agents
27
- const agentA = await BSVAgentWallet.load({
28
- network: 'testnet',
29
- storageDir: './wallet-agent-a',
30
- });
31
-
32
- const agentB = await BSVAgentWallet.load({
33
- network: 'testnet',
34
- storageDir: './wallet-agent-b',
35
- });
36
-
37
- const agentBKey = await agentB.getIdentityKey();
38
- console.log('Agent B identity:', agentBKey);
39
-
40
- // 2. Agent A builds a payment to Agent B (requires funded wallet)
41
- const payment = await agentA.createPayment({
42
- to: agentBKey,
43
- satoshis: 500,
44
- description: 'Payment for code review',
45
- });
46
-
47
- // 3. Agent B verifies the payment
48
- const verification = await agentB.verifyPayment({
49
- beef: payment.beef,
50
- });
51
-
52
- // 4. Agent B accepts (internalizes) the payment
53
- if (verification.valid) {
54
- const receipt = await agentB.acceptPayment({
55
- beef: payment.beef,
56
- derivationPrefix: payment.derivationPrefix,
57
- derivationSuffix: payment.derivationSuffix,
58
- senderIdentityKey: payment.senderIdentityKey,
59
- description: 'Code review payment received',
60
- });
61
- console.log('Payment accepted:', receipt.accepted);
62
- }
63
-
64
- // 5. Clean up
65
- await agentA.destroy();
66
- await agentB.destroy();
67
- ```
68
-
69
- ## API
70
-
71
- ### `BSVAgentWallet`
72
-
73
- #### Factory Methods
74
-
75
- | Method | Description |
76
- |--------|-------------|
77
- | `BSVAgentWallet.load(config)` | Create a new wallet (generates keys, creates SQLite DB) |
78
- | `BSVAgentWallet.load(config)` | Load an existing wallet from storage |
79
-
80
- #### `WalletConfig`
81
-
82
- ```typescript
83
- interface WalletConfig {
84
- network: 'mainnet' | 'testnet';
85
- storageDir: string; // Directory for SQLite DB and identity file
86
- rootKeyHex?: string; // Optional: provide your own root key
87
- taalApiKey?: string; // Optional: TAAL API key for ARC broadcasting
88
- }
89
- ```
90
-
91
- #### Wallet Lifecycle
92
-
93
- | Method | Returns | Description |
94
- |--------|---------|-------------|
95
- | `getIdentityKey()` | `Promise<string>` | Compressed public key (hex) — share this with other agents |
96
- | `getBalance()` | `Promise<number>` | Balance in satoshis |
97
- | `destroy()` | `Promise<void>` | Close DB connections, stop monitor |
98
-
99
- #### Payments (Sender Side)
100
-
101
- ```typescript
102
- const payment = await wallet.createPayment({
103
- to: recipientPublicKey, // Compressed hex pubkey (required)
104
- satoshis: 500, // Amount in satoshis
105
- description: 'Agent task payment',
106
- });
107
- ```
108
-
109
- Returns a `PaymentResult`:
110
-
111
- ```typescript
112
- interface PaymentResult {
113
- beef: string; // Base64-encoded Atomic BEEF
114
- txid: string; // Transaction ID
115
- satoshis: number; // Amount paid
116
- derivationPrefix: string; // BRC-29 derivation info (send to recipient)
117
- derivationSuffix: string; // BRC-29 derivation info (send to recipient)
118
- senderIdentityKey: string; // Sender's identity key (send to recipient)
119
- }
120
- ```
121
-
122
- > **Important:** The `derivationPrefix`, `derivationSuffix`, and `senderIdentityKey` MUST be transmitted to the recipient alongside the `beef`. These are needed for the recipient to claim the payment.
123
-
124
- #### Payments (Receiver Side)
125
-
126
- **Verify** (includes SPV verification):
127
-
128
- ```typescript
129
- const result = await wallet.verifyPayment({
130
- beef: payment.beef,
131
- expectedSender: senderKey, // Optional
132
- });
133
- // result.valid, result.txid, result.errors
134
- ```
135
-
136
- **Accept** (internalize into wallet):
137
-
138
- ```typescript
139
- const receipt = await wallet.acceptPayment({
140
- beef: payment.beef,
141
- vout: 0, // Output index (default: 0)
142
- derivationPrefix: payment.derivationPrefix,
143
- derivationSuffix: payment.derivationSuffix,
144
- senderIdentityKey: payment.senderIdentityKey,
145
- description: 'Payment received',
146
- });
147
- // receipt.accepted
148
- ```
149
-
150
- #### Advanced Access
151
-
152
- ```typescript
153
- // Access underlying wallet-toolbox SetupWallet for advanced operations
154
- const setup = wallet.getSetup();
155
- // setup.wallet — the BRC-100 Wallet instance
156
- // setup.rootKey — the root PrivateKey
157
- // setup.services — network Services
158
- // setup.storage — WalletStorageManager
159
- ```
160
-
161
- ## Architecture
162
-
163
- ```
164
- BSVAgentWallet
165
- ├── Wallet (BRC-100) — from @bsv/wallet-toolbox
166
- │ ├── CachedKeyDeriver — BRC-42 key derivation
167
- │ ├── WalletStorageManager — manages storage providers
168
- │ │ └── StorageKnex — SQLite via knex
169
- │ ├── Services — ARC broadcasting, chain tracking
170
- │ └── Monitor — background task processing
171
- └── ScriptTemplateBRC29 — BRC-29 payment scripts
172
- ```
173
-
174
- ### Payment Flow
175
-
176
- ```
177
- Agent A (Payer) Agent B (Merchant)
178
- ───────────────── ──────────────────
179
- 1. createPayment(to=B, sat=500)
180
- → builds BRC-29 tx (noSend)
181
- → returns BEEF + derivation info
182
- ──→
183
- 2. verifyPayment(beef)
184
- → structural checks
185
- → returns valid/errors
186
-
187
- 3. acceptPayment(beef, derivation)
188
- → wallet.internalizeAction()
189
- → SPV verification
190
- → broadcasts to network
191
- → output added to wallet
192
- ```
193
-
194
- ## Key Concepts
195
-
196
- ### BRC-29 Key Derivation
197
- Each payment uses unique derivation prefixes and suffixes to generate a one-time key. This means:
198
- - No address reuse (privacy preserving)
199
- - Recipient needs the derivation info to claim the payment
200
- - The sender's identity key is also needed for key derivation
201
-
202
- ### Atomic BEEF
203
- Transactions are packaged as Atomic BEEF (Background Evaluation Extended Format), which includes:
204
- - The payment transaction itself
205
- - All ancestor transactions needed for SPV verification
206
- - Merkle proofs linking to block headers
207
-
208
- This allows the recipient to verify the payment without trusting any third party.
209
-
210
- ### noSend Workflow
211
- The sender builds and signs the transaction but does NOT broadcast it. Instead:
212
- 1. The signed transaction (as Atomic BEEF) is sent directly to the recipient
213
- 2. The recipient verifies it via SPV
214
- 3. The recipient internalizes it (claiming the output and broadcasting)
215
-
216
- This is the BRC-100 Direct Instant Payments (DIP) pattern.
217
-
218
- ## Storage
219
-
220
- Each wallet creates:
221
- - `wallet-identity.json` — Contains the root key hex, identity key, and network
222
- - `a2a_agent_wallet.sqlite` — SQLite database with all wallet state
223
-
224
- > ⚠️ **Security:** The `wallet-identity.json` file contains the root private key. Guard it carefully in production.
225
-
226
- ## Known Issues
227
-
228
- - **Wallet-toolbox bug:** `Setup.createWalletSQLite` has an internal `randomBytesHex` stub that throws. This library works around it by constructing wallet components manually.
229
- - **Funding required:** `createPayment()` requires the wallet to have spendable UTXOs. On testnet, use the [WitnessOnChain faucet](https://witnessonchain.com/faucet/tbsv) to fund your wallet. Track transactions on [WhatsonChain testnet](https://test.whatsonchain.com/) or [WhatsonChain mainnet](https://whatsonchain.com/).
230
-
231
- ## Development
232
-
233
- ```bash
234
- # Type check
235
- npm run check
236
-
237
- # Build
238
- npm run build
239
-
240
- # Test
241
- npm test
242
- ```
243
-
244
- ## License
245
-
246
- MIT
@@ -1,12 +0,0 @@
1
- /**
2
- * @a2a-bsv/core — Configuration defaults and helpers.
3
- */
4
- import type { WalletConfig } from './types.js';
5
- /** Map our 'mainnet'/'testnet' to the wallet-toolbox's 'main'/'test' chain type. */
6
- export type Chain = 'main' | 'test';
7
- export declare function toChain(network: WalletConfig['network']): Chain;
8
- /** Default TAAL API keys from the wallet-toolbox examples. */
9
- export declare const DEFAULT_TAAL_API_KEYS: Record<Chain, string>;
10
- /** Default SQLite database name. */
11
- export declare const DEFAULT_DB_NAME = "a2a_agent_wallet";
12
- //# sourceMappingURL=config.d.ts.map