wao 0.9.0 → 0.9.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.
@@ -1,484 +1,8 @@
1
- import * as WarpArBundles from "warp-arbundles"
2
- const pkg = WarpArBundles.default ?? WarpArBundles
3
- const { DataItem } = pkg
4
-
5
- import crypto from "crypto"
6
- import base64url from "base64url"
7
-
8
- import {
9
- tags,
10
- action,
11
- tag,
12
- buildTags,
13
- isJSON,
14
- jsonToStr,
15
- dirname,
16
- } from "./utils.js"
17
- import ArMem from "./armem-web.js"
18
- import weavedrive from "./weavedrive.js"
19
- import AoLoader from "./ao-loader.js"
20
- import { scheduler, mu, su, cu, acc } from "./web.js"
21
- import { is, clone, fromPairs, map, mergeLeft, isNil } from "ramda"
1
+ import base from "./aoconnect-base.js"
22
2
  import AR from "./war.js"
3
+ import { mu, su, cu, acc } from "./web.js"
4
+ import AoLoader from "./ao-loader.js"
5
+ import ArMem from "./armem-web.js"
6
+ const scheduler = "_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA"
23
7
 
24
- export const connect = (mem, { cache, log = false, extensions = {} } = {}) => {
25
- const isMem = mem?.__type__ === "mem"
26
- if (!isMem) {
27
- let args = { cache }
28
- if (mem?.SU_URL) {
29
- args = mergeLeft(mem, args)
30
- args.scheduler = scheduler
31
- }
32
- mem = new ArMem(args)
33
- }
34
- const ar = new AR({ mem, log })
35
- for (const k in extensions) extensions[k] = new extensions[k](ar).ext
36
- extensions.WeaveDrive = new weavedrive(ar).ext
37
-
38
- const transform = input => {
39
- const output = { Tags: [] }
40
- if (input.Data) output.Data = input.Data
41
- Object.entries(input).forEach(([key, value]) => {
42
- if (key !== "Data" && key !== "Tags" && typeof value === "string") {
43
- output.Tags.push({ name: key, value })
44
- }
45
- })
46
- input.Tags?.forEach(tag => {
47
- const tagKey = Object.keys(tag)[0]
48
- const tagValue = tag[tagKey]
49
- if (typeof tagValue === "string") {
50
- output.Tags.push({ name: tagKey, value: tagValue })
51
- }
52
- })
53
-
54
- return output
55
- }
56
-
57
- const genMsg = async (Id, p, data, Tags, from, Owner, dry = false) => {
58
- if (!dry) p.height += 1
59
- return {
60
- Id,
61
- Target: p.id,
62
- Owner,
63
- Data: data?.length ? data : "",
64
- "Block-Height": (await mem.get("height")).toString(),
65
- Timestamp: Date.now().toString(),
66
- Module: p.module,
67
- From: from,
68
- Cron: false,
69
- Tags: Tags?.length ? Tags : [],
70
- }
71
- }
72
-
73
- const genEnv = async ({ pid, owner = "", module = "" }) => {
74
- return {
75
- Process: {
76
- Id: pid,
77
- Tags: (await mem.get("txs", pid))?.tags ?? [],
78
- Owner: owner,
79
- },
80
- Module: {
81
- Id: module,
82
- Tags: (await mem.get("txs", module))?.tags ?? [],
83
- },
84
- }
85
- }
86
- const spawn = async (opt = {}) => {
87
- if (!opt.module) throw Error("module missing")
88
- if (!opt.scheduler) throw Error("scheduler missing")
89
- const { mod, wasm, format } = await mem.getWasm(opt.module, mem)
90
- opt.tags = buildTags(
91
- null,
92
- mergeLeft(tags(opt.tags ?? []), {
93
- "Data-Protocol": "ao",
94
- Variant: "ao.TN.1",
95
- Type: "Process",
96
- SDK: "aoconnect",
97
- Module: mod,
98
- Scheduler: opt.scheduler,
99
- "Content-Type": "text/plain",
100
- Authority: mu.addr,
101
- }),
102
- )
103
- let ex = false
104
- for (let v of opt.tags) if (v.name === "Type") ex = true
105
- if (!ex) opt.tags.push({ name: "Type", value: "Process" })
106
- if (opt.for) opt.tags.push({ name: "Pushed-For", value: opt.for })
107
- const {
108
- id,
109
- owner,
110
- item,
111
- tags: __tags,
112
- } = await ar.dataitem({
113
- item: opt.item,
114
- data: opt.data,
115
- signer: opt.signer,
116
- tags: tags(opt.tags),
117
- })
118
- opt.tags = buildTags(null, __tags)
119
- if (opt.item) opt.data = base64url.decode(item.data)
120
- await ar.postItems(item, su.jwk)
121
- const now = Date.now
122
- const t = tags(opt.tags)
123
- const ext = t.Extension || "WeaveDrive"
124
- const wdrive = extensions[ext]
125
- let handle = null
126
- try {
127
- handle = await AoLoader(wasm, {
128
- format,
129
- WeaveDrive: wdrive,
130
- spawn: item,
131
- module: await mem.get("txs", mod),
132
- })
133
- } catch (e) {}
134
- if (!handle) return null
135
- let _module = null
136
- _module = { handle, id: mod }
137
- Date.now = now
138
- const _tags = tags(opt.tags)
139
- let res = null
140
- let memory = opt.memory ?? null
141
- let p = {
142
- extension: ext,
143
- item: item?.binary,
144
- format,
145
- id: id,
146
- epochs: [],
147
- handle: _module.handle,
148
- module: _module.id,
149
- hash: id,
150
- memory,
151
- owner,
152
- height: 0,
153
- res: { [id]: res },
154
- results: [id],
155
- txs: [],
156
- opt,
157
- }
158
- if (memory) {
159
- // forking...
160
- } else if (_tags["On-Boot"] || true) {
161
- let data = ""
162
- if (_tags["On-Boot"] === "Data") data = opt.data ?? ""
163
- else data = (await mem.get("msgs", _tags["On-Boot"]))?.data ?? ""
164
- let msg = await genMsg(id, p, data, opt.tags, owner, mu.addr, true)
165
- const _env = await genEnv({
166
- pid: p.id,
167
- owner: p.owner,
168
- module: p.module,
169
- })
170
- res = await _module.handle(null, msg, _env)
171
- p.memory = res.Memory
172
- delete res.Memory
173
- p.res[id] = res
174
- } else {
175
- p.height += 1
176
- }
177
- await mem.set(opt, "msgs", id)
178
- if (_tags["Cron-Interval"]) {
179
- let [num, unit] = _tags["Cron-Interval"].split("-")
180
- let int = 0
181
- switch (unit.replace(/s$/, "")) {
182
- case "millisecond":
183
- int = num
184
- break
185
- case "second":
186
- int = num * 1000
187
- break
188
- case "minute":
189
- int = num * 1000 * 60
190
- break
191
- case "hour":
192
- int = num * 1000 * 60 * 60
193
- break
194
- case "day":
195
- int = num * 1000 * 60 * 60 * 24
196
- break
197
- case "month":
198
- int = num * 1000 * 60 * 60 * 24 * 30
199
- break
200
- case "year":
201
- int = num * 1000 * 60 * 60 * 24 * 365
202
- break
203
- }
204
- let cronTags = []
205
- for (const k in _tags) {
206
- if (/^Cron-Tag-/.test(k)) {
207
- cronTags.push({ name: k.replace(/Cron-Tag-/, ""), value: _tags[k] })
208
- }
209
- }
210
- p.cronTags = cronTags
211
- p.span = int
212
- }
213
- await mem.set(p, "env", id)
214
- return id
215
- }
216
-
217
- function genHashChain(previousHash, previousMessageId = null) {
218
- const hasher = crypto.createHash("sha256")
219
- hasher.update(Buffer.from(previousHash, "base64"))
220
- if (previousMessageId) {
221
- hasher.update(Buffer.from(previousMessageId, "base64"))
222
- }
223
- return base64url(hasher.digest())
224
- }
225
-
226
- const assign = async opt => {
227
- const p = await mem.get("env", opt.process)
228
- if (!p) return null
229
- let _opt = await mem.get("msgs", opt.message)
230
- let hash = genHashChain(p.hash, opt.message)
231
- p.hash = hash
232
- opt.tags = buildTags(
233
- null,
234
- mergeLeft(tags(opt.tags ?? []), {
235
- Timestamp: Date.now(),
236
- Epoch: p.epochs.length,
237
- Nonce: "0",
238
- "Data-Protocol": "ao",
239
- Variant: "ao.TN.1",
240
- SDK: "aoconnect",
241
- Type: "Assignment",
242
- "Block-Height": await mem.get("height"),
243
- Process: opt.process,
244
- Message: opt.message,
245
- "Hash-Chain": hash,
246
- }),
247
- )
248
- p.epochs.push([opt.message])
249
- const { id, owner, item } = await ar.dataitem({
250
- data: opt.data,
251
- signer: opt.signer,
252
- tags: tags(opt.tags),
253
- target: opt.process,
254
- })
255
- if (opt.message_item) {
256
- await ar.postItems([opt.message_item, item], su.jwk)
257
- } else {
258
- await ar.postItems(item, su.jwk)
259
- }
260
- try {
261
- let data = _opt.data ?? ""
262
- let _tags = _opt.tags
263
- let from = _opt.from ?? opt.from ?? owner
264
- if (_opt.item) {
265
- try {
266
- data = base64url.decode(_opt.item.data)
267
- _tags = _opt.item.tags
268
- if (!from) {
269
- const raw_owner = _opt.item.rawOwner
270
- const hashBuffer = Buffer.from(
271
- await crypto.subtle.digest("SHA-256", raw_owner),
272
- )
273
- from = base64url.encode(hashBuffer)
274
- }
275
- } catch (e) {
276
- console.log(e)
277
- }
278
- }
279
- // check: is owner=mu.addr right?
280
- const msg = await genMsg(opt.message, p, data, _tags, from, mu.addr)
281
- const _env = await genEnv({
282
- pid: p.id,
283
- owner: p.owner,
284
- module: p.module,
285
- })
286
- if (!p.handle) {
287
- const { format, mod, wasm } = await mem.getWasm(p.modulea)
288
- const wdrive = extensions[p.extention]
289
- p.handle = await AoLoader(wasm, {
290
- format,
291
- WeaveDrive: wdrive,
292
- spawn: new DataItem(p.item),
293
- module: await mem.get("txs", mod),
294
- })
295
- mem.env[opt.process].handle = p.handle
296
- }
297
- const res = await p.handle(p.memory, msg, _env)
298
- p.memory = res.Memory
299
- delete res.Memory
300
- p.res[opt.message] = res
301
- p.results.push(opt.message)
302
- p.txs.unshift({ id, ...opt })
303
- await mem.set(p, "env", opt.process)
304
- await mem.set(_opt, "msgs", opt.message)
305
- for (const v of res.Messages ?? []) {
306
- if (await mem.get("env", v.Target)) {
307
- await message({
308
- for: opt.message,
309
- process: v.Target,
310
- tags: v.Tags,
311
- data: v.Data,
312
- signer: mu.signer,
313
- from: opt.process,
314
- })
315
- }
316
- }
317
- for (const v of res.Spawns ?? []) {
318
- const __tags = tags(v.Tags)
319
- await spawn({
320
- for: opt.message,
321
- module: __tags.Module,
322
- scheduler,
323
- tags: v.Tags,
324
- data: v.Data,
325
- from: __tags["From-Process"],
326
- signer: mu.signer,
327
- })
328
- }
329
- for (const v of res.Assignments ?? []) {
330
- for (const v2 of v.Processes) {
331
- await assign({
332
- message: v.Message,
333
- process: v2,
334
- from: opt.process,
335
- signer: mu.signer,
336
- })
337
- }
338
- }
339
-
340
- return id
341
- } catch (e) {
342
- console.log(e)
343
- }
344
- return null
345
- }
346
-
347
- const message = async opt => {
348
- const p = await mem.get("env", opt.process)
349
- if (!p) return null
350
- let ex = false
351
- let id = opt?.item?.id ?? ""
352
- let owner = opt.owner ?? ""
353
- let item = opt.item
354
- if (!opt.item && opt.signer) {
355
- for (let v of opt.tags) if (v.name === "Type") ex = true
356
- opt.tags = buildTags(
357
- null,
358
- mergeLeft(tags(opt.tags ?? []), {
359
- "Data-Protocol": "ao",
360
- Variant: "ao.TN.1",
361
- Type: "Message",
362
- SDK: "aoconnect",
363
- }),
364
- )
365
- if (opt.for) {
366
- opt.tags.push({ name: "Pushed-For", value: opt.for })
367
- opt.tags.push({ name: "From-Process", value: opt.from })
368
- const pr = (await mem.get("txs", opt.from))?.tags ?? []
369
- const module = tags(pr).Module
370
- if (module) opt.tags.push({ name: "From-Module", value: module })
371
- }
372
- ;({ item, id, owner } = await ar.dataitem({
373
- data: opt.data,
374
- signer: opt.signer,
375
- tags: tags(opt.tags),
376
- target: opt.process,
377
- }))
378
- }
379
- await mem.set(opt, "msgs", id)
380
- await assign({
381
- message_item: item,
382
- message: id,
383
- process: opt.process,
384
- from: owner,
385
- signer: mu.signer,
386
- })
387
- return id
388
- }
389
-
390
- return {
391
- message,
392
- unmonitor: async opt => {
393
- const p = await mem.get("env", opt.process)
394
- try {
395
- clearInterval(p.cron)
396
- p.cron = null
397
- } catch (e) {}
398
- },
399
- monitor: async opt => {
400
- const p = await mem.get("env", opt.process)
401
- if (isNil(p.cron)) {
402
- p.cron = setInterval(async () => {
403
- await message({
404
- tags: p.cronTags,
405
- process: opt.process,
406
- signer: mu.signer,
407
- from: mu.addr,
408
- })
409
- }, p.span)
410
- }
411
- },
412
- spawn,
413
- assign,
414
- ar,
415
- result: async opt => (await mem.get("env", opt.process))?.res[opt.message],
416
- results: async opt => {
417
- const p = await mem.get("env", opt.process)
418
- let results = []
419
- const limit = opt.limit ?? 25
420
- if (opt.sort === "DESC") {
421
- for (let i = p.results.length - 1; 0 < i; i--) {
422
- results.push({ cursor: p.results[i], node: p.res[p.results[i]] })
423
- if (results.length >= limit) break
424
- }
425
- } else {
426
- for (let i = 0; i < p.results.length; i++) {
427
- results.push({ node: p.res[p.results[i]] })
428
- if (results.length >= limit) break
429
- }
430
- }
431
- return { edges: results }
432
- },
433
- dryrun: async opt => {
434
- const p = await mem.get("env", opt.process)
435
- if (!p) return null
436
- let id = opt.id ?? ""
437
- let owner = opt.owner ?? ""
438
- if (!opt.id && opt.signer) {
439
- ;({ id, owner } = await ar.dataitem({ ...opt, target: opt.process }))
440
- }
441
- try {
442
- const msg = await genMsg(
443
- id,
444
- p,
445
- opt.data ?? "",
446
- opt.tags,
447
- owner,
448
- mu.addr,
449
- true,
450
- )
451
- const _env = await genEnv({
452
- pid: p.id,
453
- owner: p.owner,
454
- module: p.module,
455
- })
456
- function cloneMemory(memory) {
457
- const buffer = memory.buffer.slice(0)
458
- return new WebAssembly.Memory({
459
- initial: memory.buffer.byteLength / 65536,
460
- maximum: memory.maximum || undefined,
461
- shared: memory.shared || false,
462
- })
463
- }
464
- if (!p.handle) {
465
- const { format, mod, wasm } = await mem.getWasm(p.modulea)
466
- const wdrive = extensions[p.extention]
467
- p.handle = await AoLoader(wasm, {
468
- format,
469
- WeaveDrive: wdrive,
470
- spawn: new DataItem(p.item),
471
- module: await mem.get("txs", mod),
472
- })
473
- mem.env[opt.process].handle = p.handle
474
- }
475
- const res = await p.handle(p.memory, msg, _env)
476
- return res
477
- } catch (e) {
478
- console.log(e)
479
- }
480
- return null
481
- },
482
- mem,
483
- }
484
- }
8
+ export const connect = base({ AR, scheduler, mu, su, cu, acc, AoLoader, ArMem })