wao 0.26.2 → 0.27.1

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/esm/signer.js CHANGED
@@ -1,95 +1,5 @@
1
- import base64url from "base64url"
2
- import { hash } from "fast-sha256"
3
- import { httpbis } from "http-message-signatures"
4
- import { parseItem, serializeList } from "structured-headers"
5
- const { verifyMessage } = httpbis
6
- const {
7
- augmentHeaders,
8
- createSignatureBase,
9
- createSigningParameters,
10
- formatSignatureBase,
11
- } = httpbis
12
-
13
- export function hbEncodeValue(value) {
14
- if (isBytes(value)) {
15
- if (value.byteLength === 0) return hbEncodeValue("")
16
- return [undefined, value]
17
- }
18
-
19
- if (typeof value === "string") {
20
- if (value.length === 0) return ["empty-binary", undefined]
21
- return [undefined, value]
22
- }
23
-
24
- if (Array.isArray(value)) {
25
- if (value.length === 0) return ["empty-list", undefined]
26
- if (value.some(isPojo)) {
27
- throw new Error(
28
- `Array with objects should have been lifted: ${JSON.stringify(value)}`
29
- )
30
- }
31
-
32
- const encoded = value
33
- .map(v => {
34
- if (typeof v === "string") {
35
- if (v === "") return `"(ao-type-empty-binary) "`
36
- const escaped = v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')
37
- return `"${escaped}"`
38
- } else if (typeof v === "number") return String(v)
39
- else if (typeof v === "boolean") return v ? "?1" : "?0"
40
- else if (typeof v === "symbol") {
41
- const desc = v.description || "symbol"
42
- const escaped = desc.replace(/\\/g, "\\\\").replace(/"/g, '\\"')
43
- return `"(ao-type-atom) ${escaped}"`
44
- } else if (v === null) return `"(ao-type-atom) null"`
45
- else if (v === undefined) return `"(ao-type-atom) undefined"`
46
- else if (Array.isArray(v) && v.length === 0) {
47
- return `"(ao-type-empty-list) "`
48
- }
49
- return `"${String(v)}"`
50
- })
51
- .join(", ")
52
- return ["list", encoded]
53
- }
54
-
55
- if (typeof value === "number") {
56
- if (!Number.isInteger(value)) return ["float", `${value}`]
57
- return ["integer", String(value)]
58
- }
59
-
60
- if (typeof value === "boolean") {
61
- return ["atom", `"${value ? "true" : "false"}"`]
62
- }
63
-
64
- if (typeof value === "symbol") {
65
- const desc = value.description || "symbol"
66
- return ["atom", `"${desc}"`]
67
- }
68
-
69
- if (value === null) return ["atom", `"null"`]
70
-
71
- if (value === undefined) return ["atom", `"undefined"`]
72
-
73
- throw new Error(`Cannot encode value: ${String(value)}`)
74
- }
75
-
76
- const toView = value => {
77
- if (ArrayBuffer.isView(value)) {
78
- return Buffer.from(value.buffer, value.byteOffset, value.byteLength)
79
- } else if (typeof value === "string") return base64url.toBuffer(value)
80
-
81
- throw new Error(
82
- "Value must be Uint8Array, ArrayBuffer, or base64url-encoded string"
83
- )
84
- }
85
-
86
- const httpSigName = address => {
87
- const decoded = base64url.toBuffer(address)
88
- const hexString = [...decoded.subarray(1, 9)]
89
- .map(byte => byte.toString(16).padStart(2, "0"))
90
- .join("")
91
- return `http-sig-${hexString}`
92
- }
1
+ import { toHttpSigner } from "./send.js"
2
+ import { enc } from "./encode.js"
93
3
 
94
4
  const joinUrl = ({ url, path }) => {
95
5
  if (path.startsWith("http://") || path.startsWith("https://")) {
@@ -98,542 +8,17 @@ const joinUrl = ({ url, path }) => {
98
8
  return url.endsWith("/") ? url.slice(0, -1) + path : url + path
99
9
  }
100
10
 
101
- const MAX_HEADER_LENGTH = 4096
102
-
103
- function encode_body_keys(bodyKeys) {
104
- if (!bodyKeys || bodyKeys.length === 0) return ""
105
- const items = bodyKeys.map(key => `"${key}"`)
106
- const result = items.join(", ")
107
- return result
108
- }
109
-
110
- async function hasNewline(value) {
111
- if (typeof value === "string") return value.includes("\n")
112
- if (value instanceof Blob) {
113
- value = await value.text()
114
- return value.includes("\n")
115
- }
116
- if (isBytes(value)) return Buffer.from(value).includes("\n")
117
- return false
118
- }
119
-
120
- async function sha256(data) {
121
- // Convert data to Uint8Array if needed
122
- let uint8Array
123
- if (data instanceof ArrayBuffer) {
124
- uint8Array = new Uint8Array(data)
125
- } else if (data instanceof Uint8Array) {
126
- uint8Array = data
127
- } else if (ArrayBuffer.isView(data)) {
128
- uint8Array = new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
129
- } else {
130
- throw new Error("sha256 expects ArrayBuffer or ArrayBufferView")
131
- }
132
-
133
- // fast-sha256 returns Uint8Array, convert to ArrayBuffer
134
- const hashResult = hash(uint8Array)
135
- return hashResult.buffer.slice(
136
- hashResult.byteOffset,
137
- hashResult.byteOffset + hashResult.byteLength
138
- )
139
- }
140
-
141
- function isBytes(value) {
142
- return value instanceof ArrayBuffer || ArrayBuffer.isView(value)
143
- }
144
-
145
- function isPojo(value) {
146
- return (
147
- !isBytes(value) &&
148
- !Array.isArray(value) &&
149
- !(value instanceof Blob) &&
150
- typeof value === "object" &&
151
- value !== null
152
- )
153
- }
154
-
155
- function hbEncodeLift(obj, parent = "", top = {}) {
156
- const [flattened, types] = Object.entries({ ...obj }).reduce(
157
- (acc, [key, value]) => {
158
- const storageKey = parent ? `${parent}/${key}` : key
159
- if (value == null) {
160
- const [type, encoded] = hbEncodeValue(value)
161
- if (encoded !== undefined) acc[0][key] = encoded
162
- if (type) acc[1][key.toLowerCase()] = type
163
- return acc
164
- }
165
- if (Array.isArray(value)) {
166
- const hasObjects = value.some(isPojo)
167
- const hasBinary = value.some(isBytes)
168
- if (hasObjects || hasBinary) {
169
- const indexedObj = value.reduce(
170
- (obj, v, idx) => Object.assign(obj, { [idx]: v }),
171
- {}
172
- )
173
- acc[1][key.toLowerCase()] = "list"
174
- hbEncodeLift(indexedObj, storageKey, top)
175
- return acc
176
- } else {
177
- const [type, encoded] = hbEncodeValue(value)
178
- if (type) acc[1][key.toLowerCase()] = type
179
- if (encoded !== undefined) acc[0][key] = encoded
180
- return acc
181
- }
182
- }
183
-
184
- const originalValue = value
185
-
186
- if (isPojo(value)) {
187
- if (Object.keys(value).length === 0) {
188
- acc[1][key.toLowerCase()] = "empty-message"
189
- return acc
190
- }
191
-
192
- const hasComplexValues = Object.values(value).some(
193
- v => isPojo(v) || (Array.isArray(v) && v.some(item => isPojo(item)))
194
- )
195
-
196
- if (!hasComplexValues) {
197
- const items = []
198
- const hasAnyNonEmptyValues = Object.values(value).some(v => {
199
- return !(
200
- v === null ||
201
- v === undefined ||
202
- v === "" ||
203
- (Array.isArray(v) && v.length === 0) ||
204
- (isPojo(v) && Object.keys(v).length === 0)
205
- )
206
- })
207
-
208
- Object.entries(value).forEach(([k, v]) => {
209
- const subKey = k.toLowerCase()
210
-
211
- if (v === null) {
212
- items.push(`${subKey}="null"`)
213
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "atom"
214
- } else if (v === undefined) {
215
- items.push(`${subKey}="undefined"`)
216
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "atom"
217
- } else if (typeof v === "string") {
218
- if (v === "") {
219
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "empty-binary"
220
- } else {
221
- const escaped = v.replace(/\\/g, "\\\\").replace(/"/g, '\\"')
222
- items.push(`${subKey}="${escaped}"`)
223
- }
224
- } else if (typeof v === "number") {
225
- items.push(`${subKey}=${v}`)
226
- if (Number.isInteger(v)) {
227
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "integer"
228
- } else {
229
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "float"
230
- }
231
- } else if (typeof v === "boolean") {
232
- items.push(`${subKey}=${v ? "?1" : "?0"}`)
233
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "boolean"
234
- } else if (typeof v === "symbol") {
235
- const desc = v.description || "symbol"
236
- const escaped = desc.replace(/\\/g, "\\\\").replace(/"/g, '\\"')
237
- items.push(`${subKey}="${escaped}"`)
238
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "atom"
239
- } else if (Array.isArray(v) && !v.some(item => isPojo(item))) {
240
- if (v.length === 0) {
241
- items.push(`${subKey}=()`)
242
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "empty-list"
243
- } else {
244
- const listItems = v.map(item => {
245
- if (typeof item === "string") {
246
- return `"${item.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`
247
- } else if (typeof item === "number") {
248
- return String(item)
249
- } else if (typeof item === "boolean") {
250
- return item ? "?1" : "?0"
251
- } else if (typeof item === "symbol") {
252
- const desc = item.description || "symbol"
253
- return `"${desc.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`
254
- } else if (item === null) {
255
- return `"null"`
256
- } else if (item === undefined) {
257
- return `"undefined"`
258
- } else {
259
- return `"${String(item)}"`
260
- }
261
- })
262
- items.push(`${subKey}=(${listItems.join(" ")})`)
263
- }
264
- } else if (isPojo(v) && Object.keys(v).length === 0) {
265
- items.push(`${subKey}`)
266
- acc[1][`${key.toLowerCase()}%2f${subKey}`] = "empty-message"
267
- }
268
- })
269
-
270
- const encodedValue = items.join(", ")
271
-
272
- const hasOnlyEmptyValues = Object.entries(value).every(([k, v]) => {
273
- return (
274
- v === null ||
275
- v === undefined ||
276
- v === "" ||
277
- (Array.isArray(v) && v.length === 0) ||
278
- (isPojo(v) && Object.keys(v).length === 0)
279
- )
280
- })
281
-
282
- if (!hasAnyNonEmptyValues) {
283
- acc[1][key.toLowerCase()] = "map"
284
- } else if (encodedValue === "") {
285
- acc[1][key.toLowerCase()] = "empty-message"
286
- } else {
287
- acc[0][key] = encodedValue
288
- acc[1][key.toLowerCase()] = "map"
289
- }
290
- } else hbEncodeLift(value, storageKey, top)
291
- return acc
292
- }
293
-
294
- const [type, encoded] = hbEncodeValue(value)
295
-
296
- if (encoded !== undefined) {
297
- if (isBytes(encoded)) top[storageKey] = encoded
298
- else {
299
- acc[0][key] = encoded
300
- if (type) acc[1][key.toLowerCase()] = type
301
- }
302
- } else if (type) acc[1][key.toLowerCase()] = type
303
- return acc
304
- },
305
- [{}, {}]
306
- )
307
-
308
- if (Object.keys(flattened).length === 0 && Object.keys(types).length === 0)
309
- return top
310
-
311
- if (Object.keys(types).length > 0) {
312
- const aoTypeItems = Object.entries(types).map(([key, value]) => {
313
- const safeKey = key
314
- .toLowerCase()
315
- .replace(
316
- /[^a-z0-9_\-.*\/]/g,
317
- c => "%" + c.charCodeAt(0).toString(16).padStart(2, "0")
318
- )
319
- .replace(/\//g, "%2f")
320
- return `${safeKey}="${value}"`
321
- })
322
- aoTypeItems.sort()
323
- const aoTypes = aoTypeItems.join(", ")
324
-
325
- if (Buffer.from(aoTypes).byteLength > MAX_HEADER_LENGTH) {
326
- const flatK = parent ? `${parent}/ao-types` : "ao-types"
327
- top[flatK] = aoTypes
328
- } else flattened["ao-types"] = aoTypes
329
- }
330
-
331
- if (parent) top[parent] = flattened
332
- else Object.assign(top, flattened)
333
- return top
334
- }
335
-
336
- function encodePart(name, { headers = {}, body }) {
337
- const headerEntries =
338
- headers instanceof Headers
339
- ? Array.from(headers.entries())
340
- : Object.entries(headers || {})
341
-
342
- const parts = headerEntries.reduce(
343
- (acc, [name, value]) => {
344
- acc.push(`${name}: `, value, "\r\n")
345
- return acc
346
- },
347
- [`content-disposition: form-data;name="${name}"\r\n`]
348
- )
349
-
350
- if (body) parts.push("\r\n", body)
351
-
352
- return new Blob(parts)
353
- }
354
-
355
- async function encode(obj = {}) {
356
- if (Object.keys(obj).length === 0) return { headers: {}, body: undefined }
357
- const originalObj = obj
358
- const flattened = hbEncodeLift(obj)
359
-
360
- const bodyKeys = []
361
- const headerKeys = []
362
-
363
- await Promise.all(
364
- Object.keys(flattened).map(async key => {
365
- const value = flattened[key]
366
-
367
- if (isPojo(value)) {
368
- const subPart = await encode(value)
369
- if (!subPart) return
370
-
371
- bodyKeys.push(key)
372
- flattened[key] = encodePart(key, subPart)
373
- return
374
- }
375
-
376
- if (isBytes(value)) {
377
- bodyKeys.push(key)
378
- const uint8Array =
379
- value instanceof Uint8Array
380
- ? value
381
- : value instanceof ArrayBuffer
382
- ? new Uint8Array(value)
383
- : Buffer.isBuffer(value)
384
- ? new Uint8Array(value.buffer, value.byteOffset, value.length)
385
- : new Uint8Array(
386
- value.buffer,
387
- value.byteOffset,
388
- value.byteLength
389
- )
390
- flattened[key] = new Blob([
391
- `content-disposition: form-data;name="${key}"\r\n\r\n`,
392
- uint8Array,
393
- ])
394
- return
395
- }
396
-
397
- const valueStr = String(value)
398
- if (
399
- (await hasNewline(valueStr)) ||
400
- key.includes("/") ||
401
- Buffer.from(valueStr).byteLength > MAX_HEADER_LENGTH ||
402
- (isPojo(value) && valueStr === "[object Object]")
403
- ) {
404
- bodyKeys.push(key)
405
- flattened[key] = new Blob([
406
- `content-disposition: form-data;name="${key}"\r\n\r\n`,
407
- value,
408
- ])
409
- return
410
- }
411
-
412
- headerKeys.push(key)
413
- })
414
- )
415
-
416
- const headers = {}
417
- headerKeys.forEach(key => {
418
- headers[key] = flattened[key]
419
- })
420
-
421
- if ("data" in originalObj && !bodyKeys.includes("data")) {
422
- bodyKeys.push("data")
423
- delete headers["data"]
424
- }
425
-
426
- if ("body" in originalObj && !bodyKeys.includes("body")) {
427
- bodyKeys.push("body")
428
- delete headers["body"]
429
- }
430
-
431
- if (bodyKeys.length > 0) {
432
- headers["body-keys"] = encode_body_keys(bodyKeys)
433
- }
434
-
435
- let body = undefined
436
- let promoteToBody = true
437
- if (bodyKeys.length > 0) {
438
- if (bodyKeys.length === 1) {
439
- const bodyKey = bodyKeys[0]
440
- const originalValue = originalObj[bodyKey]
441
- const flattenedValue = flattened[bodyKey]
442
-
443
- if (
444
- !isPojo(originalValue) ||
445
- (isPojo(originalValue) && typeof flattenedValue === "string")
446
- ) {
447
- if (
448
- (bodyKey === "body" || bodyKey === "data") &&
449
- isPojo(originalValue) &&
450
- typeof flattenedValue === "string"
451
- ) {
452
- body = new Blob([flattenedValue])
453
- } else if (Array.isArray(originalValue)) {
454
- const hasSymbols = originalValue.some(
455
- item => typeof item === "symbol"
456
- )
457
- if (hasSymbols) {
458
- const [type, encoded] = hbEncodeValue(originalValue)
459
- body = new Blob([encoded || originalValue.toString()])
460
- } else body = new Blob([originalValue.toString()])
461
- } else body = new Blob([originalValue || flattenedValue])
462
- headers["inline-body-key"] = bodyKey
463
- } else promoteToBody = false
464
- }
465
-
466
- if (!promoteToBody || bodyKeys.length > 1) {
467
- const bodyParts = await Promise.all(
468
- bodyKeys.map(async name => {
469
- if (flattened[name] instanceof Blob) return flattened[name]
470
- const value = originalObj[name] || flattened[name] || ""
471
- if (
472
- name === "body" &&
473
- isPojo(originalObj[name]) &&
474
- typeof flattened[name] === "string"
475
- ) {
476
- const partBlob = new Blob([
477
- `content-disposition: form-data;name="${name}"\r\n\r\n`,
478
- flattened[name],
479
- ])
480
- return partBlob
481
- }
482
-
483
- let valueToEncode = value
484
- if (Array.isArray(value)) {
485
- const hasSymbols = value.some(item => typeof item === "symbol")
486
- if (hasSymbols) {
487
- const [type, encoded] = hbEncodeValue(value)
488
- valueToEncode = encoded || value.toString()
489
- }
490
- } else if (isBytes(value)) valueToEncode = value
491
- let partBlob
492
- if (isBytes(valueToEncode)) {
493
- const uint8Array =
494
- valueToEncode instanceof Uint8Array
495
- ? valueToEncode
496
- : valueToEncode instanceof ArrayBuffer
497
- ? new Uint8Array(valueToEncode)
498
- : Buffer.isBuffer(valueToEncode)
499
- ? new Uint8Array(
500
- valueToEncode.buffer,
501
- valueToEncode.byteOffset,
502
- valueToEncode.length
503
- )
504
- : new Uint8Array(
505
- valueToEncode.buffer,
506
- valueToEncode.byteOffset,
507
- valueToEncode.byteLength
508
- )
509
- partBlob = new Blob([
510
- `content-disposition: form-data;name="${name}"\r\n\r\n`,
511
- uint8Array,
512
- ])
513
- } else {
514
- partBlob = new Blob([
515
- `content-disposition: form-data;name="${name}"\r\n\r\n`,
516
- valueToEncode,
517
- ])
518
- }
519
- return partBlob
520
- })
521
- )
522
-
523
- const allPartsBuffer = await new Blob(bodyParts).arrayBuffer()
524
- const hashResult = await sha256(allPartsBuffer)
525
- const boundary = base64url.encode(Buffer.from(hashResult))
526
-
527
- const finalParts = []
528
- for (const part of bodyParts) {
529
- finalParts.push(`--${boundary}\r\n`)
530
- finalParts.push(part)
531
- finalParts.push("\r\n")
532
- }
533
- finalParts.push(`--${boundary}--`)
534
-
535
- headers["content-type"] = `multipart/form-data; boundary="${boundary}"`
536
- body = new Blob(finalParts)
537
- }
538
-
539
- if (body) {
540
- const finalContent = await body.arrayBuffer()
541
- const contentDigest = await sha256(finalContent)
542
- const base64 = base64url.toBase64(base64url.encode(contentDigest))
543
- headers["content-digest"] = `sha-256=:${base64}:`
544
- headers["content-length"] = String(finalContent.byteLength)
545
- }
546
- }
547
-
548
- return { headers, body }
549
- }
550
-
551
- const toHttpSigner = signer => {
552
- const params = ["alg", "keyid"].sort()
553
-
554
- return async ({ request, fields }) => {
555
- let signatureBase
556
- let signatureInput
557
- let createCalled = false
558
-
559
- const create = injected => {
560
- createCalled = true
561
-
562
- const { publicKey, alg = "rsa-pss-sha512" } = injected
563
-
564
- const publicKeyBuffer = toView(publicKey)
565
-
566
- const signingParameters = createSigningParameters({
567
- params,
568
- paramValues: {
569
- keyid: base64url.encode(publicKeyBuffer),
570
- alg,
571
- },
572
- })
573
-
574
- const signatureBaseArray = createSignatureBase({ fields }, request)
575
- signatureInput = serializeList([
576
- [
577
- signatureBaseArray.map(([item]) => parseItem(item)),
578
- signingParameters,
579
- ],
580
- ])
581
-
582
- signatureBaseArray.push(['"@signature-params"', [signatureInput]])
583
- signatureBase = formatSignatureBase(signatureBaseArray)
584
-
585
- return new TextEncoder().encode(signatureBase)
586
- }
587
-
588
- const result = await signer(create, "httpsig")
589
-
590
- if (!createCalled) {
591
- throw new Error(
592
- "create() must be invoked in order to construct the data to sign"
593
- )
594
- }
595
-
596
- if (!result.signature || !result.address) {
597
- throw new Error("Signer must return signature and address")
598
- }
599
-
600
- const signatureBuffer = toView(result.signature)
601
- const signedHeaders = augmentHeaders(
602
- request.headers,
603
- signatureBuffer,
604
- signatureInput,
605
- httpSigName(result.address)
606
- )
607
-
608
- const finalHeaders = {}
609
- for (const [key, value] of Object.entries(signedHeaders)) {
610
- if (key === "Signature" || key === "Signature-Input") {
611
- finalHeaders[key.toLowerCase()] = value
612
- } else finalHeaders[key] = value
613
- }
614
-
615
- return { ...request, headers: finalHeaders }
616
- }
617
- }
618
-
619
- export function createRequest(config) {
11
+ export function signer(config) {
620
12
  const { signer, url = "http://localhost:10001" } = config
621
13
 
622
14
  if (!signer) {
623
15
  throw new Error("Signer is required for mainnet mode")
624
16
  }
625
17
 
626
- return async function request(fields) {
18
+ return async function sign(fields) {
627
19
  const { path = "/relay/process", method = "POST", ...restFields } = fields
628
20
  const aoFields = { ...restFields }
629
- const rootKeys = Object.keys(aoFields)
630
- const binaryKeys = rootKeys.filter(key => isBytes(aoFields[key]))
631
-
632
- if (binaryKeys.length > 1 && !aoFields.body && !aoFields.data) {
633
- aoFields.body = "1984"
634
- }
635
-
636
- const encoded = await encode(aoFields)
21
+ const encoded = await enc(aoFields)
637
22
  const headersObj = encoded ? encoded.headers : {}
638
23
  const body = encoded ? encoded.body : undefined
639
24
 
@@ -685,34 +70,3 @@ export function createRequest(config) {
685
70
  return result
686
71
  }
687
72
  }
688
- export async function send(signedMsg, fetchImpl = fetch) {
689
- const fetchOptions = {
690
- method: signedMsg.method,
691
- headers: signedMsg.headers,
692
- redirect: "follow",
693
- }
694
- if (
695
- signedMsg.body !== undefined &&
696
- signedMsg.method !== "GET" &&
697
- signedMsg.method !== "HEAD"
698
- ) {
699
- fetchOptions.body = signedMsg.body
700
- }
701
- const response = await fetchImpl(signedMsg.url, fetchOptions)
702
-
703
- if (response.status >= 400) {
704
- throw new Error(`${response.status}: ${await response.text()}`)
705
- }
706
-
707
- let headers = {}
708
- if (response.headers && typeof response.headers.forEach === "function") {
709
- response.headers.forEach((v, k) => (headers[k] = v))
710
- } else headers = response.headers
711
-
712
- return {
713
- response,
714
- headers,
715
- body: await response.text(),
716
- status: response.status,
717
- }
718
- }
@@ -1,22 +1,19 @@
1
1
  import assert from "assert"
2
2
  import { describe, it, before, after, beforeEach } from "node:test"
3
- import { wait, toAddr } from "wao/test"
4
- import { HyperBEAM, HB } from "wao"
3
+ import { HyperBEAM, wait, toAddr } from "wao/test"
4
+ import { HB } from "wao"
5
5
  import { resolve } from "path"
6
6
  import { readFileSync } from "fs"
7
7
 
8
- const cwd = "../../HyperBEAM"
8
+ const cwd = "../dev/wao/HyperBEAM"
9
9
  const wallet = ".wallet.json"
10
10
 
11
11
  describe("HyperBEAM", function () {
12
12
  let hbeam, hb, jwk
13
13
 
14
14
  before(async () => {
15
- hbeam = new HyperBEAM({ cwd, wallet })
16
- jwk = JSON.parse(
17
- readFileSync(resolve(import.meta.dirname, cwd, wallet), "utf8")
18
- )
19
- await wait(5000)
15
+ hbeam = await new HyperBEAM({ c: "12", cmake: "3.5", cwd, wallet }).ready()
16
+ jwk = JSON.parse(readFileSync(resolve(process.cwd(), cwd, wallet), "utf8"))
20
17
  })
21
18
 
22
19
  beforeEach(async () => (hb = await new HB({}).init(jwk)))
@@ -24,7 +21,7 @@ describe("HyperBEAM", function () {
24
21
  after(async () => hbeam.kill())
25
22
 
26
23
  it("should run a HyperBEAM node", async () => {
27
- const info = await hb.meta.info()
24
+ const info = await hb.getJSON({ path: "/~meta@1.0/info" })
28
25
  assert.equal(info.address, toAddr(jwk.n))
29
26
  })
30
27
  })