wao 0.5.6 → 0.6.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.
- package/cjs/ao.js +145 -50
- package/cjs/aoconnect.js +127 -114
- package/cjs/ar.js +14 -6
- package/cjs/armem.js +2 -1
- package/cjs/gql.js +27 -15
- package/cjs/helpers.js +217 -82
- package/cjs/lua/process.wasm +0 -0
- package/cjs/run.js +3 -1
- package/cjs/server.js +80 -153
- package/cjs/tao.js +13 -11
- package/cjs/tar.js +347 -206
- package/cjs/test.js +6 -0
- package/cjs/tgql.js +23 -8
- package/cjs/utils.js +141 -1
- package/cjs/weavedrive.js +86 -60
- package/esm/ao.js +30 -1
- package/esm/aoconnect.js +24 -15
- package/esm/ar.js +9 -3
- package/esm/armem.js +1 -0
- package/esm/gql.js +15 -6
- package/esm/helpers.js +50 -2
- package/esm/lua/process.wasm +0 -0
- package/esm/run.js +1 -1
- package/esm/server.js +30 -187
- package/esm/tao.js +7 -5
- package/esm/tar.js +125 -85
- package/esm/test.js +2 -1
- package/esm/tgql.js +12 -4
- package/esm/utils.js +227 -0
- package/esm/weavedrive.js +31 -25
- package/package.json +1 -1
package/esm/tar.js
CHANGED
|
@@ -3,20 +3,27 @@ import { buildTags, tags as t } from "./utils.js"
|
|
|
3
3
|
import * as WarpArBundles from "warp-arbundles"
|
|
4
4
|
const pkg = WarpArBundles.default ?? WarpArBundles
|
|
5
5
|
const { DataItem } = pkg
|
|
6
|
-
|
|
6
|
+
import { bundleAndSignData, ArweaveSigner } from "arbundles"
|
|
7
7
|
import base64url from "base64url"
|
|
8
8
|
import ArMem from "./armem.js"
|
|
9
9
|
import GQL from "./tgql.js"
|
|
10
|
-
import { last } from "ramda"
|
|
10
|
+
import { last, is, includes, isNil } from "ramda"
|
|
11
11
|
class AR extends MAR {
|
|
12
12
|
constructor(opt = {}) {
|
|
13
13
|
super({ ...opt, in_memory: true })
|
|
14
|
+
this.log = opt.log === true
|
|
14
15
|
this.in_memory = true
|
|
15
16
|
this.mem = opt.mem ?? new ArMem()
|
|
16
17
|
this.gql = new GQL({ mem: this.mem })
|
|
17
18
|
this.arweave = this.mem.arweave
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
+
async owner(di) {
|
|
21
|
+
const raw_owner = di.rawOwner
|
|
22
|
+
const hashBuffer = Buffer.from(
|
|
23
|
+
await crypto.subtle.digest("SHA-256", raw_owner),
|
|
24
|
+
)
|
|
25
|
+
return base64url.encode(hashBuffer)
|
|
26
|
+
}
|
|
20
27
|
async dataitem({ target = "", data = "1984", tags = {}, signer, item }) {
|
|
21
28
|
let di = item
|
|
22
29
|
if (!di) {
|
|
@@ -26,65 +33,68 @@ class AR extends MAR {
|
|
|
26
33
|
} else {
|
|
27
34
|
tags = t(di.tags)
|
|
28
35
|
}
|
|
29
|
-
const
|
|
30
|
-
const hashBuffer = Buffer.from(
|
|
31
|
-
await crypto.subtle.digest("SHA-256", raw_owner),
|
|
32
|
-
)
|
|
33
|
-
const owner = base64url.encode(hashBuffer)
|
|
36
|
+
const owner = await this.owner(di)
|
|
34
37
|
return { id: await di.id, owner, item: di, tags }
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
async post({ data = "1984", tags = {}, jwk }) {
|
|
41
|
+
let err = null
|
|
42
|
+
;({ err, jwk } = await this.checkWallet({ jwk }))
|
|
43
|
+
if (err) return { err }
|
|
38
44
|
let tx = await this.arweave.createTransaction({ data: data })
|
|
39
45
|
let _tags = buildTags(null, tags)
|
|
40
46
|
for (const v of _tags) tx.addTag(v.name, v.value)
|
|
41
|
-
|
|
42
|
-
this.mem.addrmap[owner] = { address: owner, key: jwk.n }
|
|
43
|
-
return await this.postTx(tx, jwk, {
|
|
44
|
-
recipient: "",
|
|
45
|
-
tags: _tags,
|
|
46
|
-
data,
|
|
47
|
-
owner,
|
|
48
|
-
})
|
|
47
|
+
return await this.postTx(tx, jwk)
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
async
|
|
50
|
+
async postItems(items, jwk) {
|
|
51
|
+
let err = null
|
|
52
|
+
;({ err, jwk } = await this.checkWallet({ jwk }))
|
|
53
|
+
if (err) return { err }
|
|
54
|
+
if (!is(Array, items)) items = [items]
|
|
55
|
+
let _items = []
|
|
56
|
+
for (const di of items) {
|
|
57
|
+
di._id = await di.id
|
|
58
|
+
const data_size = Buffer.byteLength(di.rawData).toString()
|
|
59
|
+
let data_type = ""
|
|
60
|
+
for (const t of di.tags)
|
|
61
|
+
if (t.name === "Content-Type") data_type = t.value
|
|
62
|
+
const owner = await this.owner(di)
|
|
63
|
+
this.mem.addrmap[owner] = { key: di.owner, address: owner }
|
|
64
|
+
let data = di.data
|
|
65
|
+
try {
|
|
66
|
+
data = base64url.decode(di.data)
|
|
67
|
+
} catch (e) {}
|
|
68
|
+
let _item = {
|
|
69
|
+
_data: { size: data_size, type: data_type },
|
|
70
|
+
anchor: di.anchor,
|
|
71
|
+
signature: di.signature,
|
|
72
|
+
recipient: di.target,
|
|
73
|
+
id: await di.id,
|
|
74
|
+
item: di,
|
|
75
|
+
owner,
|
|
76
|
+
tags: di.tags,
|
|
77
|
+
data,
|
|
78
|
+
}
|
|
79
|
+
this.mem.txs[await di.id] = _item
|
|
80
|
+
_items.push(_item)
|
|
81
|
+
}
|
|
82
|
+
const bundle = await bundleAndSignData(items, new ArweaveSigner(jwk))
|
|
52
83
|
const tx = await this.mem.arweave.createTransaction(
|
|
53
|
-
{ data:
|
|
84
|
+
{ data: bundle.binary },
|
|
54
85
|
jwk,
|
|
55
86
|
)
|
|
56
87
|
tx.addTag("Bundle-Format", "binary")
|
|
57
88
|
tx.addTag("Bundle-Version", "2.0.0")
|
|
58
|
-
|
|
59
|
-
let data_type = ""
|
|
60
|
-
for (const t of di.tags) if (t.name === "Content-Type") data_type = t.value
|
|
61
|
-
const rowner = di.rawOwner
|
|
62
|
-
const hashBuffer = Buffer.from(
|
|
63
|
-
await crypto.subtle.digest("SHA-256", rowner),
|
|
64
|
-
)
|
|
65
|
-
const owner = base64url.encode(hashBuffer)
|
|
66
|
-
this.mem.addrmap[owner] = { key: di.owner, address: owner }
|
|
67
|
-
let data = di.data
|
|
68
|
-
try {
|
|
69
|
-
data = base64url.decode(di.data)
|
|
70
|
-
} catch (e) {}
|
|
71
|
-
let _item = {
|
|
72
|
-
_data: { size: data_size, type: data_type },
|
|
73
|
-
anchor: di.anchor,
|
|
74
|
-
signature: di.signature,
|
|
75
|
-
recipient: di.target,
|
|
76
|
-
id: await di.id,
|
|
77
|
-
item: di,
|
|
78
|
-
owner,
|
|
79
|
-
tags: di.tags,
|
|
80
|
-
data,
|
|
81
|
-
}
|
|
82
|
-
this.mem.txs[await di.id] = _item
|
|
83
|
-
return await this.postTx(tx, jwk, _item)
|
|
89
|
+
return await this.postTx(tx, jwk, _items)
|
|
84
90
|
}
|
|
85
91
|
|
|
86
|
-
async postTx(tx, jwk,
|
|
87
|
-
let
|
|
92
|
+
async postTx(tx, jwk, items = []) {
|
|
93
|
+
let err = null
|
|
94
|
+
;({ err, jwk } = await this.checkWallet({ jwk }))
|
|
95
|
+
if (err) return { err }
|
|
96
|
+
|
|
97
|
+
let res = null
|
|
88
98
|
if (!tx.id) await this.mem.arweave.transactions.sign(tx, jwk)
|
|
89
99
|
this.mem.height += 1
|
|
90
100
|
let block = {
|
|
@@ -92,42 +102,51 @@ class AR extends MAR {
|
|
|
92
102
|
timestamp: Date.now(),
|
|
93
103
|
height: this.mem.height,
|
|
94
104
|
previous: last(this.mem.blocks) ?? "",
|
|
105
|
+
txs: [],
|
|
95
106
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.mem.txs[
|
|
100
|
-
this.mem.txs[
|
|
101
|
-
this.mem.txs[
|
|
102
|
-
this.mem.txs[
|
|
107
|
+
let msg = null
|
|
108
|
+
if (items) {
|
|
109
|
+
for (const item of items) {
|
|
110
|
+
this.mem.txs[item.id] = item
|
|
111
|
+
this.mem.txs[item.id].parent = { id: tx.id }
|
|
112
|
+
this.mem.txs[item.id].bundledIn = { id: tx.id }
|
|
113
|
+
this.mem.txs[item.id].anchor = ""
|
|
114
|
+
const _tags = t(item.tags)
|
|
115
|
+
if (
|
|
116
|
+
includes(_tags.Type, [
|
|
117
|
+
"Message",
|
|
118
|
+
"Process",
|
|
119
|
+
"Module",
|
|
120
|
+
"Scheduler-Location",
|
|
121
|
+
"Attestation",
|
|
122
|
+
"Available",
|
|
123
|
+
])
|
|
124
|
+
) {
|
|
125
|
+
msg = { id: item.id, type: _tags.Type }
|
|
126
|
+
if (msg.type === "Process") msg.pid = item.recipient
|
|
127
|
+
}
|
|
103
128
|
let data_type = ""
|
|
104
|
-
for (const v of
|
|
105
|
-
if (
|
|
106
|
-
v.get("name", { decode: true, string: true }) === "Content-Type"
|
|
107
|
-
) {
|
|
108
|
-
data_type = v.get("value", { decode: true, string: true })
|
|
109
|
-
}
|
|
129
|
+
for (const v of item.item.tags) {
|
|
130
|
+
if (v.name === "Content-Type") data_type = v.value
|
|
110
131
|
}
|
|
111
|
-
this.mem.txs[tx.id]._data = { size: tx.data_size, type: data_type }
|
|
112
|
-
|
|
113
|
-
this.mem.txs[item.id].
|
|
132
|
+
//this.mem.txs[tx.id]._data = { size: tx.data_size, type: data_type }
|
|
133
|
+
block.txs.push(item.id)
|
|
134
|
+
this.mem.txs[item.id].block = block.id
|
|
114
135
|
}
|
|
115
|
-
block.txs = [item.id]
|
|
116
|
-
this.mem.txs[item.id].block = block.id
|
|
117
|
-
} else {
|
|
118
|
-
let _tags = []
|
|
119
|
-
for (const v of tx.tags) {
|
|
120
|
-
_tags.push({
|
|
121
|
-
name: base64url.decode(v.name),
|
|
122
|
-
value: base64url.decode(v.value),
|
|
123
|
-
})
|
|
124
|
-
}
|
|
125
|
-
tx.tags = _tags
|
|
126
|
-
tx.owner = await this.arweave.wallets.jwkToAddress({ n: tx.owner })
|
|
127
|
-
this.mem.txs[tx.id] = tx
|
|
128
|
-
block.txs = [tx.id]
|
|
129
|
-
this.mem.txs[tx.id].block = block.id
|
|
130
136
|
}
|
|
137
|
+
|
|
138
|
+
let _tags = []
|
|
139
|
+
for (const v of tx.tags) {
|
|
140
|
+
_tags.push({
|
|
141
|
+
name: base64url.decode(v.name),
|
|
142
|
+
value: base64url.decode(v.value),
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
tx.tags = _tags
|
|
146
|
+
tx.owner = await this.arweave.wallets.jwkToAddress({ n: tx.owner })
|
|
147
|
+
this.mem.txs[tx.id] = tx
|
|
148
|
+
block.txs.push(tx.id)
|
|
149
|
+
this.mem.txs[tx.id].block = block.id
|
|
131
150
|
this.mem.blocks.push(block.id)
|
|
132
151
|
this.mem.blockmap[block.id] = block
|
|
133
152
|
|
|
@@ -136,6 +155,15 @@ class AR extends MAR {
|
|
|
136
155
|
this.mem.addrmap[owner] = { address: owner, key: jwk.n }
|
|
137
156
|
}
|
|
138
157
|
res = { id: tx.id, status: 200, statusText: "200" }
|
|
158
|
+
if (this.log) {
|
|
159
|
+
if (msg) {
|
|
160
|
+
console.log(
|
|
161
|
+
`New ${msg.type}:\t${msg.id}${msg.pid ? ` > ${msg.pid}` : ""}`,
|
|
162
|
+
)
|
|
163
|
+
} else {
|
|
164
|
+
console.log(`New Post:\t${tx.id}`)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
139
167
|
return { res, err, id: tx.id }
|
|
140
168
|
}
|
|
141
169
|
|
|
@@ -143,15 +171,27 @@ class AR extends MAR {
|
|
|
143
171
|
return this.mem.txs[id]
|
|
144
172
|
}
|
|
145
173
|
|
|
146
|
-
async data(id,
|
|
174
|
+
async data(id, _string) {
|
|
175
|
+
let decode = true
|
|
176
|
+
let string = _string
|
|
177
|
+
if (is(Object, _string)) {
|
|
178
|
+
if (!isNil(_string.decode)) decode = _string.decode
|
|
179
|
+
if (!isNil(_string.string)) string = _string.string
|
|
180
|
+
}
|
|
181
|
+
|
|
147
182
|
let tx = this.mem.txs[id]
|
|
148
|
-
let _data =
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
183
|
+
let _data = tx?.data ?? null
|
|
184
|
+
let isBuf = is(Uint8Array, _data) || is(ArrayBuffer, _data)
|
|
185
|
+
let isStr = is(String, _data)
|
|
186
|
+
if (decode === false) {
|
|
187
|
+
if (isStr) _data = new TextEncoder().encode(_data)
|
|
188
|
+
return base64url.encode(_data)
|
|
189
|
+
} else {
|
|
190
|
+
if (isBuf && string) {
|
|
191
|
+
return Buffer.from(_data).toString()
|
|
192
|
+
} else if (isStr && string !== true) {
|
|
193
|
+
return new TextEncoder().encode(_data)
|
|
194
|
+
}
|
|
155
195
|
}
|
|
156
196
|
return _data
|
|
157
197
|
}
|
package/esm/test.js
CHANGED
|
@@ -7,7 +7,7 @@ import AR from "./tar.js"
|
|
|
7
7
|
import GQL from "./tgql.js"
|
|
8
8
|
import ArMem from "./armem.js"
|
|
9
9
|
import { dirname } from "./utils.js"
|
|
10
|
-
import { Src, setup, ok, fail } from "./helpers.js"
|
|
10
|
+
import { Testnet, Src, setup, ok, fail } from "./helpers.js"
|
|
11
11
|
import Server from "./server.js"
|
|
12
12
|
|
|
13
13
|
const blueprint = async pkg => {
|
|
@@ -16,6 +16,7 @@ const blueprint = async pkg => {
|
|
|
16
16
|
const scheduler = "_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA"
|
|
17
17
|
|
|
18
18
|
export {
|
|
19
|
+
Testnet,
|
|
19
20
|
Server,
|
|
20
21
|
GQL,
|
|
21
22
|
ArMem,
|
package/esm/tgql.js
CHANGED
|
@@ -8,6 +8,7 @@ const subs = {
|
|
|
8
8
|
tags: ["name", "value"],
|
|
9
9
|
block: ["id", "timestamp", "height", "previous"],
|
|
10
10
|
parent: ["id"],
|
|
11
|
+
bundledIn: ["id"],
|
|
11
12
|
}
|
|
12
13
|
const field = (key, val = true) => {
|
|
13
14
|
if (includes(key, ["id", "anchor", "signature", "recipient"])) {
|
|
@@ -59,8 +60,11 @@ export default class GQL {
|
|
|
59
60
|
_block = {}
|
|
60
61
|
if (!isNil(opt.block[0])) _block.min = opt.block[0]
|
|
61
62
|
if (!isNil(opt.block[1])) _block.max = opt.block[1]
|
|
63
|
+
} else if (is(Object, opt.block)) {
|
|
64
|
+
if (!isNil(opt.block.min)) _block.min = opt.block.min
|
|
65
|
+
if (!isNil(opt.block.max)) _block.max = opt.block.max
|
|
62
66
|
}
|
|
63
|
-
let first = opt.first ??
|
|
67
|
+
let first = opt.first ?? 10
|
|
64
68
|
let tags = []
|
|
65
69
|
for (const k in opt.tags ?? {}) {
|
|
66
70
|
if (is(String, opt.tags[k])) {
|
|
@@ -126,14 +130,18 @@ export default class GQL {
|
|
|
126
130
|
if (tag_unmatch) continue
|
|
127
131
|
let _tx = {
|
|
128
132
|
cursor: tx.id,
|
|
129
|
-
|
|
133
|
+
id: tx.id,
|
|
134
|
+
recipient: tx.recipient ?? "",
|
|
130
135
|
data: tx._data,
|
|
136
|
+
tags: tx.tags,
|
|
137
|
+
parent: tx.parent ?? { id: "" },
|
|
138
|
+
bundledIn: tx.bundledIn ?? { id: "" },
|
|
131
139
|
block: pick(["id", "timestamp", "height", "previous"], block),
|
|
132
140
|
anchor: tx.anchor ?? "",
|
|
133
141
|
signature: tx.signature ?? "",
|
|
134
142
|
owner: { address: tx.owner, key: this.mem.addrmap[tx.owner] },
|
|
135
|
-
fee: { ar: "0", winston: "0" },
|
|
136
|
-
quantity: { ar: "0", winston: "0" },
|
|
143
|
+
fee: { ar: "0.000000000000", winston: "0" },
|
|
144
|
+
quantity: { ar: "0.000000000000", winston: "0" },
|
|
137
145
|
data: { size: "0", type: "" },
|
|
138
146
|
}
|
|
139
147
|
if (!isNil(opt.fields)) {
|
package/esm/utils.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { graphql, parse, validate, buildSchema } from "graphql"
|
|
2
|
+
|
|
1
3
|
import { clone, is, includes, fromPairs, map, isNil } from "ramda"
|
|
2
4
|
|
|
3
5
|
const allows = [
|
|
@@ -293,7 +295,232 @@ function isJSON(obj) {
|
|
|
293
295
|
const jsonToStr = obj =>
|
|
294
296
|
isJSON(obj) || (is(Number, obj) ? Number(obj).toString() : obj)
|
|
295
297
|
|
|
298
|
+
const schema = buildSchema(`
|
|
299
|
+
type Query {
|
|
300
|
+
transaction(id: ID!): Transaction
|
|
301
|
+
transactions(
|
|
302
|
+
ids: [ID!]
|
|
303
|
+
owners: [String!]
|
|
304
|
+
recipients: [String!]
|
|
305
|
+
tags: [TagFilter!]
|
|
306
|
+
bundledIn: [ID!]
|
|
307
|
+
block: BlockFilter
|
|
308
|
+
first: Int = 10
|
|
309
|
+
after: String
|
|
310
|
+
sort: SortOrder = HEIGHT_DESC
|
|
311
|
+
): TransactionConnection!
|
|
312
|
+
block(id: String): Block
|
|
313
|
+
blocks(
|
|
314
|
+
ids: [ID!]
|
|
315
|
+
height: BlockFilter
|
|
316
|
+
first: Int = 10
|
|
317
|
+
after: String
|
|
318
|
+
sort: SortOrder = HEIGHT_DESC
|
|
319
|
+
): BlockConnection!
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
enum SortOrder {
|
|
323
|
+
HEIGHT_ASC
|
|
324
|
+
HEIGHT_DESC
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
input TagFilter {
|
|
328
|
+
name: String!
|
|
329
|
+
values: [String!]!
|
|
330
|
+
op: TagOperator = EQ
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
input BlockFilter {
|
|
334
|
+
min: Int
|
|
335
|
+
max: Int
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
type BlockConnection {
|
|
339
|
+
pageInfo: PageInfo!
|
|
340
|
+
edges: [BlockEdge!]!
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
type BlockEdge {
|
|
344
|
+
cursor: String!
|
|
345
|
+
node: Block!
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
type TransactionConnection {
|
|
349
|
+
pageInfo: PageInfo!
|
|
350
|
+
edges: [TransactionEdge!]!
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
type TransactionEdge {
|
|
354
|
+
cursor: String!
|
|
355
|
+
node: Transaction!
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
type PageInfo {
|
|
359
|
+
hasNextPage: Boolean!
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
type Transaction {
|
|
363
|
+
id: ID!
|
|
364
|
+
anchor: String!
|
|
365
|
+
signature: String!
|
|
366
|
+
recipient: String!
|
|
367
|
+
owner: Owner!
|
|
368
|
+
fee: Amount!
|
|
369
|
+
quantity: Amount!
|
|
370
|
+
data: MetaData!
|
|
371
|
+
tags: [Tag!]!
|
|
372
|
+
block: Block
|
|
373
|
+
parent: Parent @deprecated(reason: "Use \`bundledIn\`")
|
|
374
|
+
bundledIn: Bundle
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
type Parent {
|
|
378
|
+
id: ID!
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
type Bundle {
|
|
382
|
+
id: ID!
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
type Block {
|
|
386
|
+
id: ID!
|
|
387
|
+
timestamp: Int!
|
|
388
|
+
height: Int!
|
|
389
|
+
previous: ID!
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
type MetaData {
|
|
393
|
+
size: String!
|
|
394
|
+
type: String
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
type Amount {
|
|
398
|
+
winston: String!
|
|
399
|
+
ar: String!
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
type Owner {
|
|
403
|
+
address: String!
|
|
404
|
+
key: String!
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
type Tag {
|
|
408
|
+
name: String!
|
|
409
|
+
value: String!
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
enum TagOperator {
|
|
413
|
+
EQ
|
|
414
|
+
NEQ
|
|
415
|
+
}
|
|
416
|
+
`)
|
|
417
|
+
|
|
418
|
+
const root = {
|
|
419
|
+
transactions: ({ first }) => ({
|
|
420
|
+
edges: [],
|
|
421
|
+
pageInfo: {
|
|
422
|
+
hasNextPage: false,
|
|
423
|
+
},
|
|
424
|
+
}),
|
|
425
|
+
block: ({ id }) => ({
|
|
426
|
+
id,
|
|
427
|
+
timestamp: Date.now(),
|
|
428
|
+
height: 123456,
|
|
429
|
+
previous: "previous-block-id",
|
|
430
|
+
transactions: [],
|
|
431
|
+
miner: "example-miner",
|
|
432
|
+
reward: "1000",
|
|
433
|
+
tags: [],
|
|
434
|
+
indepHash: "example-indep-hash",
|
|
435
|
+
nonce: "000000",
|
|
436
|
+
}),
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const mapParsed = (parsedQuery, variables) => {
|
|
440
|
+
const operation = parsedQuery.definitions[0]
|
|
441
|
+
|
|
442
|
+
if (operation.operation !== "query") {
|
|
443
|
+
throw new Error("Only 'query' operations are supported.")
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const rootField = operation.selectionSet.selections[0]
|
|
447
|
+
const rootFieldName = rootField.name.value
|
|
448
|
+
|
|
449
|
+
const parseArgumentValue = argValue => {
|
|
450
|
+
if (argValue.kind === "Variable") {
|
|
451
|
+
return variables[argValue.name.value]
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (argValue.kind === "ListValue") {
|
|
455
|
+
return argValue.values.map(value => parseArgumentValue(value))
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (argValue.kind === "ObjectValue") {
|
|
459
|
+
return argValue.fields.reduce((obj, field) => {
|
|
460
|
+
obj[field.name.value] = parseArgumentValue(field.value)
|
|
461
|
+
return obj
|
|
462
|
+
}, {})
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return argValue.value
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const args = rootField.arguments.reduce((acc, arg) => {
|
|
469
|
+
acc[arg.name.value] = parseArgumentValue(arg.value)
|
|
470
|
+
return acc
|
|
471
|
+
}, {})
|
|
472
|
+
|
|
473
|
+
const extractFields = selectionSet => {
|
|
474
|
+
return selectionSet.selections.map(selection => {
|
|
475
|
+
const fieldName = selection.name.value
|
|
476
|
+
|
|
477
|
+
if (selection.selectionSet) {
|
|
478
|
+
return {
|
|
479
|
+
[fieldName]: extractFields(selection.selectionSet),
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return fieldName
|
|
483
|
+
})
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const fields = extractFields(rootField.selectionSet)
|
|
487
|
+
|
|
488
|
+
return { rootFieldName, args, fields }
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const toGraphObj = ({ query, variables }) => {
|
|
492
|
+
const parsedQuery = parse(query)
|
|
493
|
+
const errors = validate(schema, parsedQuery)
|
|
494
|
+
const parsed = mapParsed(parsedQuery, variables)
|
|
495
|
+
const tar = parsed.rootFieldName
|
|
496
|
+
let fields = null
|
|
497
|
+
for (const v of parsed.fields) {
|
|
498
|
+
if (v.edges) {
|
|
499
|
+
for (const v2 of v.edges) {
|
|
500
|
+
if (v2.node) {
|
|
501
|
+
fields = v2.node
|
|
502
|
+
break
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const args = parsed.args
|
|
508
|
+
if (args.block) {
|
|
509
|
+
for (const k in args.block) args.block[k] *= 1
|
|
510
|
+
}
|
|
511
|
+
if (args.first) args.first *= 1
|
|
512
|
+
if (fields) args.fields = fields
|
|
513
|
+
if (args.sort && args.sort === "HEIGHT_ASC") args.asc = true
|
|
514
|
+
delete args.sort
|
|
515
|
+
if (args.tags) {
|
|
516
|
+
let _tags = {}
|
|
517
|
+
for (const v of args.tags) _tags[v.name] = v.values
|
|
518
|
+
args.tags = _tags
|
|
519
|
+
}
|
|
520
|
+
return { tar, args }
|
|
521
|
+
}
|
|
296
522
|
export {
|
|
523
|
+
toGraphObj,
|
|
297
524
|
jsonToStr,
|
|
298
525
|
mergeChecks,
|
|
299
526
|
isCheckComplete,
|
package/esm/weavedrive.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import Arweave from "arweave"
|
|
2
|
+
import { toGraphObj } from "./utils.js"
|
|
3
|
+
import { map } from "ramda"
|
|
4
|
+
|
|
2
5
|
const KB = 1024
|
|
3
6
|
const MB = KB * 1024
|
|
4
7
|
const CACHE_SZ = 32 * KB
|
|
5
8
|
const CHUNK_SZ = 128 * MB
|
|
6
9
|
const NOTIFY_SZ = 512 * MB
|
|
7
|
-
|
|
10
|
+
const log = console.log
|
|
8
11
|
export default class WeaveDrive {
|
|
9
12
|
constructor(ar) {
|
|
10
13
|
this.drive = function WeaveDrive(mod, FS) {
|
|
@@ -76,9 +79,9 @@ export default class WeaveDrive {
|
|
|
76
79
|
var bytesLength = await this.customFetch(`/${id}`, {
|
|
77
80
|
method: "HEAD",
|
|
78
81
|
}).then(res => res.headers.get("Content-Length"))
|
|
79
|
-
|
|
82
|
+
*/
|
|
80
83
|
let data = await ar.data(id)
|
|
81
|
-
const bytesLength = data
|
|
84
|
+
const bytesLength = data?.length ?? 0
|
|
82
85
|
node.total_size = Number(bytesLength)
|
|
83
86
|
node.cache = new Uint8Array(0)
|
|
84
87
|
node.position = 0
|
|
@@ -370,11 +373,8 @@ export default class WeaveDrive {
|
|
|
370
373
|
})
|
|
371
374
|
|
|
372
375
|
const reader = response.body.getReader()
|
|
373
|
-
|
|
374
|
-
const data =
|
|
375
|
-
(await ar.data(stream.node.name)) ?? "",
|
|
376
|
-
)
|
|
377
|
-
|
|
376
|
+
*/
|
|
377
|
+
const data = await ar.data(stream.node.name)
|
|
378
378
|
// Extract the Range header to determine the start and end of the requested chunk
|
|
379
379
|
const start = 0
|
|
380
380
|
const end = data.length
|
|
@@ -520,7 +520,6 @@ export default class WeaveDrive {
|
|
|
520
520
|
// CAUTION: If the module is initiated with `mode = test` we don't check availability.
|
|
521
521
|
return true
|
|
522
522
|
}
|
|
523
|
-
|
|
524
523
|
// Check if we are attempting to load the On-Boot id, if so allow it
|
|
525
524
|
// this was added for AOP 6 Boot loader See: https://github.com/permaweb/aos/issues/342
|
|
526
525
|
const bootTag = this.getTagValue("On-Boot", mod.spawn.tags)
|
|
@@ -533,6 +532,7 @@ export default class WeaveDrive {
|
|
|
533
532
|
mod.module.tags,
|
|
534
533
|
)
|
|
535
534
|
const moduleHasWeaveDrive = moduleExtensions.includes("WeaveDrive")
|
|
535
|
+
|
|
536
536
|
const processExtensions = this.getTagValues(
|
|
537
537
|
"Extension",
|
|
538
538
|
mod.spawn.tags,
|
|
@@ -577,9 +577,9 @@ export default class WeaveDrive {
|
|
|
577
577
|
...this.getTagValues("Attestor", mod.spawn.tags),
|
|
578
578
|
].filter(t => !!t),
|
|
579
579
|
)
|
|
580
|
-
|
|
581
580
|
// Init a set of GraphQL queries to run in order to find a valid attestation
|
|
582
581
|
// Every WeaveDrive process has at least the "Assignments" availability check form.
|
|
582
|
+
|
|
583
583
|
const assignmentsHaveID = await this.queryHasResult(
|
|
584
584
|
`query {
|
|
585
585
|
transactions(
|
|
@@ -603,10 +603,7 @@ export default class WeaveDrive {
|
|
|
603
603
|
}
|
|
604
604
|
}`,
|
|
605
605
|
)
|
|
606
|
-
|
|
607
|
-
if (assignmentsHaveID) {
|
|
608
|
-
return true
|
|
609
|
-
}
|
|
606
|
+
if (assignmentsHaveID) return true
|
|
610
607
|
|
|
611
608
|
if (processMode == "Individual") {
|
|
612
609
|
const individualsHaveID = await this.queryHasResult(
|
|
@@ -633,9 +630,7 @@ export default class WeaveDrive {
|
|
|
633
630
|
}`,
|
|
634
631
|
)
|
|
635
632
|
|
|
636
|
-
if (individualsHaveID)
|
|
637
|
-
return true
|
|
638
|
-
}
|
|
633
|
+
if (individualsHaveID) return true
|
|
639
634
|
}
|
|
640
635
|
|
|
641
636
|
// Halt message processing if the process requires Library mode.
|
|
@@ -657,7 +652,7 @@ export default class WeaveDrive {
|
|
|
657
652
|
|
|
658
653
|
getTagValues(key, tags) {
|
|
659
654
|
var values = []
|
|
660
|
-
for (i = 0; i < tags.length; i++) {
|
|
655
|
+
for (let i = 0; i < tags.length; i++) {
|
|
661
656
|
if (tags[i].name == key) {
|
|
662
657
|
values.push(tags[i].value)
|
|
663
658
|
}
|
|
@@ -674,7 +669,6 @@ export default class WeaveDrive {
|
|
|
674
669
|
const json = await this.gqlQuery(query, variables).then(res =>
|
|
675
670
|
res.json(),
|
|
676
671
|
)
|
|
677
|
-
|
|
678
672
|
return !!json?.data?.transactions?.edges?.length
|
|
679
673
|
},
|
|
680
674
|
|
|
@@ -695,13 +689,25 @@ export default class WeaveDrive {
|
|
|
695
689
|
},
|
|
696
690
|
|
|
697
691
|
async gqlQuery(query, variables) {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
692
|
+
let json = null
|
|
693
|
+
try {
|
|
694
|
+
const { tar, args } = toGraphObj({ query, variables })
|
|
695
|
+
let res2 = null
|
|
696
|
+
if (tar === "transactions") {
|
|
697
|
+
res2 = await ar.gql.txs({ ...args })
|
|
698
|
+
} else if (tar === "blocks") {
|
|
699
|
+
res2 = await ar.gql.blocks({ ...args })
|
|
700
|
+
}
|
|
701
|
+
const edges = map(v => ({ node: v, cursor: v.cursor }), res2)
|
|
702
|
+
json = {
|
|
703
|
+
data: {
|
|
704
|
+
transactions: { pageInfo: { hasNextPage: true }, edges },
|
|
705
|
+
},
|
|
706
|
+
}
|
|
707
|
+
} catch (e) {
|
|
708
|
+
log(e)
|
|
702
709
|
}
|
|
703
|
-
|
|
704
|
-
return this.customFetch("graphql", options)
|
|
710
|
+
return { json: () => json }
|
|
705
711
|
},
|
|
706
712
|
}
|
|
707
713
|
}
|