wao 0.16.1 → 0.16.2

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/cjs/web.js CHANGED
@@ -15,6 +15,12 @@ Object.defineProperty(exports, "AR", {
15
15
  return _war["default"];
16
16
  }
17
17
  });
18
+ Object.defineProperty(exports, "Adaptor", {
19
+ enumerable: true,
20
+ get: function get() {
21
+ return _adaptorWeb["default"];
22
+ }
23
+ });
18
24
  Object.defineProperty(exports, "ArMem", {
19
25
  enumerable: true,
20
26
  get: function get() {
@@ -60,6 +66,7 @@ Object.defineProperty(exports, "su", {
60
66
  });
61
67
  var _accountsWeb = require("./accounts-web.js");
62
68
  var _aoconnectWeb = require("./aoconnect-web.js");
69
+ var _adaptorWeb = _interopRequireDefault(require("./adaptor-web.js"));
63
70
  var _wao = _interopRequireDefault(require("./wao.js"));
64
71
  var _war = _interopRequireDefault(require("./war.js"));
65
72
  var _tgql = _interopRequireDefault(require("./tgql.js"));
@@ -0,0 +1,514 @@
1
+ import HB from "./hb.js"
2
+ import { DataItem } from "arbundles"
3
+ import {
4
+ toANS104Request,
5
+ parseSignatureInput,
6
+ tags,
7
+ toGraphObj,
8
+ } from "./utils.js"
9
+ import { connect } from "./aoconnect.js"
10
+ import { GQL, cu, su, mu } from "./test.js"
11
+ import { keys, map, isNil, reverse, omit } from "ramda"
12
+ //import { httpbis, createVerifier } from "http-message-signatures"
13
+ //import { createPublicKey } from "node:crypto"
14
+ //const { verifyMessage } = httpbis
15
+
16
+ class Adaptor {
17
+ constructor({
18
+ hb_url,
19
+ aoconnect,
20
+ log = false,
21
+ db,
22
+ connect,
23
+ GQL,
24
+ cu,
25
+ su,
26
+ mu,
27
+ }) {
28
+ this.data = {}
29
+ let hb = null
30
+ if (hb_url) hb = new HB({ url: hb_url })
31
+ const {
32
+ ar: _ar,
33
+ message,
34
+ spawn,
35
+ dryrun,
36
+ result,
37
+ results,
38
+ mem,
39
+ monitor,
40
+ unmonitor,
41
+ recover,
42
+ } = connect(aoconnect, { log, cache: db, hb })
43
+ this.recover = recover
44
+ this.monitor = monitor
45
+ this.unmonitor = unmonitor
46
+ this.spawn = spawn
47
+ this._ar = _ar
48
+ this.message = message
49
+ this.dryrun = dryrun
50
+ this.result = result
51
+ this.results = results
52
+ this.mem = mem
53
+ this.gql = new GQL({ mem })
54
+ }
55
+ async get(req, res) {
56
+ res(await this[req.device](req))
57
+ }
58
+ async bd(req) {
59
+ return await this[`bd_${req.method.toLowerCase()}`](req)
60
+ }
61
+ async ar(req) {
62
+ return await this[`ar_${req.method.toLowerCase()}`](req)
63
+ }
64
+ async su(req) {
65
+ return await this[`su_${req.method.toLowerCase()}`](req)
66
+ }
67
+ async mu(req) {
68
+ return await this[`mu_${req.method.toLowerCase()}`](req)
69
+ }
70
+ async cu(req) {
71
+ return await this[`cu_${req.method.toLowerCase()}`](req)
72
+ }
73
+ async bd_get(req) {
74
+ switch (req.path) {
75
+ default:
76
+ }
77
+ }
78
+
79
+ async bd_post(req) {
80
+ switch (req.path) {
81
+ case "/tx":
82
+ return await this.bd_post_tx(req)
83
+ default:
84
+ return await this.bad()
85
+ }
86
+ }
87
+
88
+ async ar_get(req) {
89
+ switch (req.path) {
90
+ case "/":
91
+ return await this.ar_get_root(req)
92
+ case "/wallet/:id/balance":
93
+ return await this.ar_get_wallet_balance(req)
94
+ case "/mint/:id/:amount":
95
+ return await this.ar_get_mint(req)
96
+ case "/tx/:id/offset":
97
+ return await this.ar_get_tx_offset(req)
98
+ case "/tx_anchor":
99
+ return await this.ar_get_tx_anchor(req)
100
+ case "/mine":
101
+ return await this.ar_get_mine(req)
102
+ case "/:id":
103
+ return await this.ar_get_id(req)
104
+ case "/price/:id":
105
+ return await this.ar_get_price(req)
106
+ default:
107
+ return await this.bad()
108
+ }
109
+ }
110
+
111
+ async ar_post(req) {
112
+ switch (req.path) {
113
+ case "/graphql":
114
+ return await this.ar_post_graphql(req)
115
+ case "/:id":
116
+ return await this.ar_post_id(req)
117
+ default:
118
+ return await this.bad()
119
+ }
120
+ }
121
+
122
+ async su_get(req) {
123
+ switch (req.path) {
124
+ case "/":
125
+ return await this.su_get_root(req)
126
+ case "/timestamp":
127
+ return await this.su_get_timestamp(req)
128
+ case "/:pid":
129
+ return await this.su_get_pid(req)
130
+ default:
131
+ return await this.bad()
132
+ }
133
+ }
134
+
135
+ async su_post(req) {
136
+ switch (req.path) {
137
+ default:
138
+ return await this.bad()
139
+ }
140
+ }
141
+
142
+ async mu_get(req) {
143
+ switch (req.path) {
144
+ case "/":
145
+ return await this.mu_get_root(req)
146
+ case "/monitor:pid":
147
+ return await this.mu_get_monitor(req)
148
+ default:
149
+ return await this.bad()
150
+ }
151
+ }
152
+
153
+ async mu_delete(req) {
154
+ switch (req.path) {
155
+ case "/monitor:pid":
156
+ return await this.mu_delete_monitor(req)
157
+ default:
158
+ return await this.bad()
159
+ }
160
+ }
161
+
162
+ async mu_post(req) {
163
+ switch (req.path) {
164
+ case "/":
165
+ return await this.mu_post_root(req)
166
+ case "/monitor:pid":
167
+ return await this.mu_post_monitor(req)
168
+ default:
169
+ return await this.bad()
170
+ }
171
+ }
172
+
173
+ async cu_get(req) {
174
+ switch (req.path) {
175
+ case "/":
176
+ return await this.cu_get_root(req)
177
+ case "/result/:mid":
178
+ return await this.cu_get_result(req)
179
+ case "/results/:pid":
180
+ return await this.cu_get_results(req)
181
+ case "/state/:pid":
182
+ return await this.cu_get_state(req)
183
+ default:
184
+ return await this.bad()
185
+ }
186
+ }
187
+
188
+ async cu_post(req) {
189
+ switch (req.path) {
190
+ case "/result/:mid": // not in the AO spec, but HyperBEAM queries it
191
+ return await this.cu_post_result(req)
192
+ case "/dry-run": // not in the AO spec
193
+ return await this.cu_post_dryrun(req)
194
+ default:
195
+ return await this.bad()
196
+ }
197
+ }
198
+ async bad({}) {
199
+ return { status: 400, error: "bad request" }
200
+ }
201
+
202
+ async bd_post_tx({ query, params, body, headers, method }) {
203
+ // todo: items from HB has wrong sigs and ids
204
+ return { send: "Success" }
205
+ if (!Buffer.isBuffer(body)) {
206
+ console.log("BD: Invalid body | expected raw Buffer")
207
+ return { status: 400, send: "Invalid body: expected raw Buffer" }
208
+ }
209
+ const lines = body.toString("utf8").split(/\r?\n/)
210
+ const sigs = {}
211
+ let currentKey = null
212
+
213
+ for (let line of lines) {
214
+ const trimmed = line.trim()
215
+ if (/^--[a-zA-Z0-9_\-=]+/.test(trimmed)) {
216
+ currentKey = null
217
+ continue
218
+ }
219
+ const headerMatch = trimmed.match(/^([a-zA-Z0-9_-]+):\s*(.*)$/)
220
+ if (headerMatch && !headerMatch[2].includes(": ")) {
221
+ const key = headerMatch[1]
222
+ const value = headerMatch[2]
223
+ sigs[key] = value
224
+ currentKey = key
225
+ } else if (currentKey) sigs[currentKey] += "\n" + line
226
+ }
227
+ sigs.target = headers.process
228
+ sigs.slot = headers.slot
229
+ /*
230
+ const input = parseSignatureInput(headers["signature-input"])
231
+ const key = { kty: "RSA", n: input.keyid, e: "AQAB" }
232
+ const verifier = createVerifier(
233
+ createPublicKey({ key, format: "jwk" }),
234
+ "rsa-pss-sha512"
235
+ )*/
236
+ let id = null
237
+ try {
238
+ /*
239
+ const isValid = await verifyMessage(
240
+ { keyLookup: params => ({ verify: verifier }) },
241
+ {
242
+ method: method,
243
+ headers: headers,
244
+ url: `http://ao.com${headers.path}`,
245
+ }
246
+ )*/
247
+ const item = toANS104Request(sigs).item
248
+
249
+ if (sigs.slot === "0" || sigs.type === "Process") {
250
+ for (let v of item.tags) if (v.name === "Type") v.value = "Process"
251
+ const res = await this.spawn({
252
+ http_msg: item,
253
+ module: sigs.module,
254
+ scheduler: sigs.scheduler,
255
+ })
256
+ } else if (sigs.type === "Message") {
257
+ for (let v of item.tags) if (v.name === "id") item.target = v.value
258
+ const res = await this.message({
259
+ slot: sigs.slot,
260
+ http_msg: item,
261
+ process: sigs.target,
262
+ })
263
+ }
264
+ } catch (e) {
265
+ console.log(e)
266
+ }
267
+ return { send: "Success" }
268
+ }
269
+
270
+ async cu_get_root({ query, params, body, headers, method }) {
271
+ return { json: { timestamp: Date.now(), address: cu.addr } }
272
+ }
273
+
274
+ async cu_get_state({ query, params, body, headers, method }) {
275
+ const pid = params.pid
276
+ const memory = this.mem.env[pid]?.memory ?? null
277
+ if (!memory) {
278
+ return {
279
+ status: 404,
280
+ error: `TransactionNotFound: Process ${pid} was not found on gateway`,
281
+ }
282
+ } else return { send: Buffer.from(memory) }
283
+ }
284
+
285
+ async cu_post_dryrun({ query, params, body, headers, method }) {
286
+ const process = query["process-id"]
287
+ const { Id: id, Owner: owner, Tags: tags, Data: data } = body
288
+ const res2 = await this.dryrun({ id, owner, tags, data, process })
289
+ if (!res2) return { status: 400, error: true }
290
+ else {
291
+ delete res2.Memory
292
+ return { json: res2 }
293
+ }
294
+ }
295
+ async cu_post_results({ query, params, body, headers, method }) {
296
+ const pid = params.pid
297
+ const { from = null, to = null, sort = "ASC", limit = 25 } = query
298
+ let results = this.mem.env[pid]?.results ?? []
299
+ if (sort === "DESC") results = reverse(results)
300
+ let _res = []
301
+ let i = 1
302
+ let count = 0
303
+ let started = isNil(from)
304
+ for (let v of results) {
305
+ if (started) {
306
+ _res.push({ cursor: v, node: this.mem.msgs[v]?.res })
307
+ count++
308
+ if (!isNil(to) && v === to) break
309
+ if (limit <= count) break
310
+ } else if (from === v) started = true
311
+
312
+ i++
313
+ }
314
+ return { json: { edges: _res } }
315
+ }
316
+
317
+ async cu_get_result({ query, params, body, headers, method }) {
318
+ let message = params.mid
319
+ const process = query["process-id"]
320
+ // check if recovery is ongoing and
321
+ if (isNil(this.mem.env[process])) {
322
+ const { success } = await this.recover(process)
323
+ if (!success) {
324
+ console.log("process not found:", query["process-id"])
325
+ return { status: 404, error: "not Found" }
326
+ }
327
+ }
328
+ const slot = message
329
+ if (!/^--[0-9a-zA-Z_-]{43,44}$/.test(message)) {
330
+ message = this.mem.env[process]?.results?.[slot]
331
+ }
332
+ if (isNil(message)) {
333
+ await this.recover(process)
334
+ message = this.mem.env[process]?.results?.[slot]
335
+ if (isNil(message)) return { status: 404, error: "not Found" }
336
+ }
337
+ const res2 = await this.result({ message, process })
338
+ if (isNil(message)) return { json: res2 }
339
+ }
340
+
341
+ async su_get_root({ query, params, body, headers, method }) {
342
+ return {
343
+ json: {
344
+ Unit: "Scheduler",
345
+ Timestamp: Date.now(),
346
+ Address: su.addr,
347
+ Processes: keys(this.mem.env),
348
+ },
349
+ }
350
+ }
351
+
352
+ async su_get_timestamp({ query, params, body, headers, method }) {
353
+ return { json: { timestamp: Date.now(), block_height: this.mem.height } }
354
+ }
355
+ async su_get_pid({ query, params, body, headers, method }) {
356
+ const pid = params.pid
357
+ const edges = map(async v => {
358
+ const tx = await this.mem.getTx(v)
359
+ const _tags = tags(v.tags)
360
+ const mid = _tags.Message
361
+ const mtx = await this.mem.getTx(mid)
362
+ return {
363
+ cursor: v,
364
+ node: {
365
+ message: {
366
+ id: mtx.id,
367
+ tags: mtx.tags,
368
+ owner: this.mem.addrmap[mtx.owner],
369
+ anchor: mtx.anchor ?? null,
370
+ target: pid,
371
+ signature: mtx.signature,
372
+ data: tx.data,
373
+ },
374
+ assignment: {
375
+ id: tx.id,
376
+ tags: tx.tags,
377
+ owner: this.mem.addrmap[tx.owner],
378
+ anchor: tx.anchor ?? null,
379
+ target: null,
380
+ signature: tx.signature,
381
+ },
382
+ },
383
+ }
384
+ })(reverse(this.mem.env[pid]?.results ?? [])) // need mod
385
+ return { json: { page_info: { has_next_page: false }, edges } }
386
+ }
387
+
388
+ async mu_get_root({ query, params, body, headers, method }) {
389
+ return { send: "ao messenger unit" }
390
+ }
391
+
392
+ async mu_post_root({ query, params, body, headers, method }) {
393
+ let valid = await DataItem.verify(body)
394
+ let type = null
395
+ let item = null
396
+ if (valid) item = new DataItem(body)
397
+ const _tags = tags(item.tags)
398
+ let err = null
399
+ if (_tags.Type === "Process") {
400
+ const res = await this.spawn({
401
+ item,
402
+ module: _tags.Module,
403
+ scheduler: _tags.Scheduler,
404
+ })
405
+ if (!res) err = "bad requrest"
406
+ } else if (_tags.Type === "Message") {
407
+ await this.message({ item, process: item.target })
408
+ } else err = true
409
+
410
+ if (err) return { status: 400, error: err }
411
+ else return { json: { id: item.id } }
412
+ }
413
+
414
+ async mu_post_monitor({ query, params, body, headers, method }) {
415
+ await this.monitor({ process: params.pid })
416
+ return { json: { id: params.pid, messag: "cron monitored!" } }
417
+ }
418
+ async mu_delete_monitor({ query, params, body, headers, method }) {
419
+ await this.unmonitor({ process: params.pid })
420
+ return { json: { id: params.pid, message: "cron deleted!" } }
421
+ }
422
+
423
+ async ar_get_root({ query, params, body, headers, method }) {
424
+ return {
425
+ json: {
426
+ version: 1,
427
+ timestamp: Date.now(),
428
+ height: this.mem.height,
429
+ network: "wao.LN.1",
430
+ current: this.mem.getAnchor(),
431
+ },
432
+ }
433
+ }
434
+ async ar_get_wallet_balance({ query, params, body, headers, method }) {
435
+ return { send: "0" }
436
+ }
437
+ async ar_get_mint({ query, params, body, headers, method }) {
438
+ return { json: { id: "0" } }
439
+ }
440
+ async ar_get_tx_offset({ query, params, body, headers, method }) {
441
+ return { status: 400, send: null }
442
+ }
443
+ async ar_get_tx_anchor({ query, params, body, headers, method }) {
444
+ return { send: this.mem.getAnchor() }
445
+ }
446
+ async ar_get_mine({ query, params, body, headers, method }) {
447
+ return { json: params }
448
+ }
449
+ async ar_get_id({ query, params, body, headers, method }) {
450
+ const _data = await this._ar.data(params.id)
451
+ if (!_data) return { status: 404, send: null }
452
+ else return { send: Buffer.from(_data, "base64") }
453
+ }
454
+ async ar_get_price({ query, params, body, headers, method }) {
455
+ return { send: "0" }
456
+ }
457
+ async ar_post_graphql({ query, params, body, headers, method }) {
458
+ try {
459
+ const { query, variables } = body
460
+ const { tar, args } = toGraphObj({ query, variables })
461
+ let res2 = null
462
+ if (tar === "transactions") {
463
+ res2 = await this.gql.txs({ ...args })
464
+ } else if (tar === "blocks") {
465
+ res2 = await this.gql.blocks({ ...args })
466
+ }
467
+ const edges = map(v => ({ node: v, cursor: v.cursor }), res2)
468
+ return {
469
+ json: {
470
+ data: { transactions: { pageInfo: { hasNextPage: true }, edges } },
471
+ },
472
+ }
473
+ } catch (e) {
474
+ console.log(e)
475
+ return { status: 400, error: "bad request" }
476
+ }
477
+ }
478
+ async ar_post_id({ query, params, body, headers, method }) {
479
+ // id = "tx" | "chunk"
480
+ if (body.chunk) {
481
+ if (this.data[body.data_root]) {
482
+ this.data[body.data_root].data += body.chunk
483
+ const buf = Buffer.from(body.chunk, "base64")
484
+ if (!this.data[body.data_root].chunks) {
485
+ this.data[body.data_root].chunks = buf
486
+ } else {
487
+ this.data[body.data_root].chunks = Buffer.concat([
488
+ this.data[body.data_root].chunks,
489
+ buf,
490
+ ])
491
+ }
492
+ delete body.chunk
493
+ if (
494
+ this.data[body.data_root].data_size <=
495
+ this.data[body.data_root].chunks.length
496
+ ) {
497
+ this.data[body.data_root].data =
498
+ this.data[body.data_root].chunks.toString("base64")
499
+ await this._ar.postTx(this.data[body.data_root])
500
+ delete this.data[body.data_root]
501
+ }
502
+ }
503
+ return { json: { id: body.id } }
504
+ } else {
505
+ if (body.data_root && body.data === "") {
506
+ this.data[body.data_root] = body
507
+ } else {
508
+ await this._ar.postTx(body)
509
+ }
510
+ return { json: { id: body.id } }
511
+ }
512
+ }
513
+ }
514
+ export default Adaptor
@@ -0,0 +1,11 @@
1
+ import { connect } from "./aoconnect-web.js"
2
+ import { cu, su, mu } from "./accounts-web.js"
3
+ import GQL from "./tgql.js"
4
+ import Base from "./adaptor-base.js"
5
+
6
+ class Adaptor extends Base {
7
+ constructor(obj) {
8
+ super({ ...obj, GQL, cu, su, mu, connect })
9
+ }
10
+ }
11
+ export default Adaptor