@arkiv-network/sdk 0.1.1-dev.0 → 0.1.3-dev.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/README.md +22 -10
- package/dist/chains/index.d.ts +25 -25
- package/dist/chains/index.d.ts.map +1 -1
- package/dist/index.cjs +30 -9
- package/dist/index.js +30 -16
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +22 -8
- package/src/accounts/index.ts +1 -0
- package/src/actions/public/buildQuery.ts +6 -0
- package/src/actions/public/getBlockTiming.ts +20 -0
- package/src/actions/public/getEntity.ts +18 -0
- package/src/actions/public/getEntityCount.ts +10 -0
- package/src/actions/public/query.ts +13 -0
- package/src/actions/public/subscribeEntityEvents.ts +105 -0
- package/src/actions/wallet/changeOwnership.ts +40 -0
- package/src/actions/wallet/createEntity.ts +45 -0
- package/src/actions/wallet/deleteEntity.ts +39 -0
- package/src/actions/wallet/extendEntity.ts +41 -0
- package/src/actions/wallet/mutateEntities.ts +100 -0
- package/src/actions/wallet/updateEntity.ts +47 -0
- package/src/chains/index.ts +3 -0
- package/src/chains/kaolin.ts +26 -0
- package/src/chains/localhost.ts +14 -0
- package/src/chains/marketplace.ts +26 -0
- package/src/clients/baseClient.ts +9 -0
- package/src/clients/createPublicClient.test.ts +22 -0
- package/src/clients/createPublicClient.ts +65 -0
- package/src/clients/createWalletClient.test.ts +23 -0
- package/src/clients/createWalletClient.ts +70 -0
- package/src/clients/decorators/arkivPublic.ts +203 -0
- package/src/clients/decorators/arkivWallet.ts +250 -0
- package/src/consts.ts +2 -0
- package/src/index.ts +21 -0
- package/src/query/engine.test.ts +288 -0
- package/src/query/engine.ts +112 -0
- package/src/query/errors.ts +23 -0
- package/src/query/index.ts +4 -0
- package/src/query/predicate.test.ts +418 -0
- package/src/query/predicate.ts +140 -0
- package/src/query/queryBuilder.test.ts +537 -0
- package/src/query/queryBuilder.ts +209 -0
- package/src/query/queryResult.test.ts +270 -0
- package/src/query/queryResult.ts +61 -0
- package/src/types/attributes.ts +4 -0
- package/src/types/entity.ts +36 -0
- package/src/types/events.ts +34 -0
- package/src/types/index.ts +4 -0
- package/src/types/mimeTypes.ts +27 -0
- package/src/types/rpcSchema.ts +61 -0
- package/src/types/txParams.ts +15 -0
- package/src/utils/arkivTransactions.ts +100 -0
- package/src/utils/compression.test.ts +32 -0
- package/src/utils/compression.ts +99 -0
- package/src/utils/entities.ts +23 -0
- package/src/utils/expirationTime.ts +13 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/payload.ts +9 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { describe, expect, it, jest } from "bun:test"
|
|
2
|
+
import type { ArkivClient } from "../clients/baseClient"
|
|
3
|
+
import { processQuery } from "./engine"
|
|
4
|
+
import type { Predicate } from "./predicate"
|
|
5
|
+
|
|
6
|
+
describe("processQuery tests", () => {
|
|
7
|
+
const client = {
|
|
8
|
+
request: jest.fn(),
|
|
9
|
+
} as unknown as ArkivClient
|
|
10
|
+
|
|
11
|
+
it("should process single predicate", async () => {
|
|
12
|
+
const predicates = [{ type: "eq" as const, key: "key", value: "value" }]
|
|
13
|
+
await processQuery(client, {
|
|
14
|
+
predicates,
|
|
15
|
+
limit: undefined,
|
|
16
|
+
cursor: undefined,
|
|
17
|
+
ownedBy: undefined,
|
|
18
|
+
validAtBlock: undefined,
|
|
19
|
+
withAttributes: undefined,
|
|
20
|
+
withMetadata: undefined,
|
|
21
|
+
withPayload: undefined,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
expect(client.request).lastCalledWith({
|
|
25
|
+
method: "arkiv_query",
|
|
26
|
+
params: [
|
|
27
|
+
`key = "value"`,
|
|
28
|
+
{
|
|
29
|
+
includeData: {
|
|
30
|
+
key: true,
|
|
31
|
+
attributes: false,
|
|
32
|
+
contentType: false,
|
|
33
|
+
payload: false,
|
|
34
|
+
expiration: false,
|
|
35
|
+
owner: false,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it("should process all simple predicates - flat", async () => {
|
|
43
|
+
const predicates = [
|
|
44
|
+
{ type: "eq" as const, key: "key", value: "value" },
|
|
45
|
+
{ type: "gt" as const, key: "key2", value: 1 },
|
|
46
|
+
{ type: "gte" as const, key: "key3", value: 2 },
|
|
47
|
+
{ type: "lt" as const, key: "key4", value: 3 },
|
|
48
|
+
{ type: "lte" as const, key: "key5", value: 4 },
|
|
49
|
+
{ type: "neq" as const, key: "key6", value: "value6" },
|
|
50
|
+
]
|
|
51
|
+
await processQuery(client, {
|
|
52
|
+
predicates,
|
|
53
|
+
limit: undefined,
|
|
54
|
+
cursor: undefined,
|
|
55
|
+
ownedBy: undefined,
|
|
56
|
+
validAtBlock: undefined,
|
|
57
|
+
withAttributes: undefined,
|
|
58
|
+
withMetadata: undefined,
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
expect(client.request).lastCalledWith({
|
|
62
|
+
method: "arkiv_query",
|
|
63
|
+
params: [
|
|
64
|
+
`key = "value" && key2 > 1 && key3 >= 2 && key4 < 3 && key5 <= 4 && key6 != "value6"`,
|
|
65
|
+
{
|
|
66
|
+
includeData: {
|
|
67
|
+
key: true,
|
|
68
|
+
attributes: false,
|
|
69
|
+
contentType: false,
|
|
70
|
+
payload: false,
|
|
71
|
+
expiration: false,
|
|
72
|
+
owner: false,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
})
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it("should process multiple predicates - nested with or", async () => {
|
|
80
|
+
const predicates = [
|
|
81
|
+
{ type: "eq" as const, key: "key", value: "value" },
|
|
82
|
+
{
|
|
83
|
+
type: "or" as const,
|
|
84
|
+
predicates: [
|
|
85
|
+
{ type: "eq" as const, key: "key2", value: "value2" },
|
|
86
|
+
{ type: "eq" as const, key: "key3", value: "value3" },
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
]
|
|
90
|
+
await processQuery(client, {
|
|
91
|
+
predicates,
|
|
92
|
+
limit: undefined,
|
|
93
|
+
cursor: undefined,
|
|
94
|
+
ownedBy: undefined,
|
|
95
|
+
validAtBlock: undefined,
|
|
96
|
+
withAttributes: undefined,
|
|
97
|
+
withMetadata: undefined,
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
expect(client.request).lastCalledWith({
|
|
101
|
+
method: "arkiv_query",
|
|
102
|
+
params: [
|
|
103
|
+
`key = "value" && (key2 = "value2" || key3 = "value3")`,
|
|
104
|
+
{
|
|
105
|
+
includeData: {
|
|
106
|
+
key: true,
|
|
107
|
+
attributes: false,
|
|
108
|
+
contentType: false,
|
|
109
|
+
payload: false,
|
|
110
|
+
expiration: false,
|
|
111
|
+
owner: false,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it("should process multiple predicates - nested with and", async () => {
|
|
119
|
+
const predicates = [
|
|
120
|
+
{ type: "eq" as const, key: "key", value: "value" },
|
|
121
|
+
{
|
|
122
|
+
type: "and" as const,
|
|
123
|
+
predicates: [
|
|
124
|
+
{ type: "eq" as const, key: "key2", value: "value2" },
|
|
125
|
+
{ type: "eq" as const, key: "key3", value: "value3" },
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
]
|
|
129
|
+
await processQuery(client, {
|
|
130
|
+
predicates,
|
|
131
|
+
limit: undefined,
|
|
132
|
+
cursor: undefined,
|
|
133
|
+
ownedBy: undefined,
|
|
134
|
+
validAtBlock: undefined,
|
|
135
|
+
withAttributes: undefined,
|
|
136
|
+
withMetadata: undefined,
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
expect(client.request).lastCalledWith({
|
|
140
|
+
method: "arkiv_query",
|
|
141
|
+
params: [
|
|
142
|
+
`key = "value" && (key2 = "value2" && key3 = "value3")`,
|
|
143
|
+
{
|
|
144
|
+
includeData: {
|
|
145
|
+
key: true,
|
|
146
|
+
attributes: false,
|
|
147
|
+
contentType: false,
|
|
148
|
+
payload: false,
|
|
149
|
+
expiration: false,
|
|
150
|
+
owner: false,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it("should process multiple predicates - nested with and and or", async () => {
|
|
158
|
+
const predicates = [
|
|
159
|
+
{ type: "eq" as const, key: "key", value: "value" },
|
|
160
|
+
{
|
|
161
|
+
type: "and" as const,
|
|
162
|
+
predicates: [
|
|
163
|
+
{ type: "eq" as const, key: "key2", value: "value2" },
|
|
164
|
+
{
|
|
165
|
+
type: "or" as const,
|
|
166
|
+
predicates: [
|
|
167
|
+
{ type: "eq" as const, key: "key3", value: "value3" },
|
|
168
|
+
{ type: "eq" as const, key: "key4", value: "value4" },
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
]
|
|
174
|
+
await processQuery(client, {
|
|
175
|
+
predicates,
|
|
176
|
+
limit: undefined,
|
|
177
|
+
cursor: undefined,
|
|
178
|
+
ownedBy: undefined,
|
|
179
|
+
validAtBlock: undefined,
|
|
180
|
+
withAttributes: undefined,
|
|
181
|
+
withMetadata: undefined,
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
expect(client.request).lastCalledWith({
|
|
185
|
+
method: "arkiv_query",
|
|
186
|
+
params: [
|
|
187
|
+
`key = "value" && (key2 = "value2" && (key3 = "value3" || key4 = "value4"))`,
|
|
188
|
+
{
|
|
189
|
+
includeData: {
|
|
190
|
+
key: true,
|
|
191
|
+
attributes: false,
|
|
192
|
+
contentType: false,
|
|
193
|
+
payload: false,
|
|
194
|
+
expiration: false,
|
|
195
|
+
owner: false,
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
})
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
it("should process simple predicates with ownedBy", async () => {
|
|
203
|
+
const predicates = [{ type: "eq" as const, key: "key", value: "value" }]
|
|
204
|
+
await processQuery(client, {
|
|
205
|
+
predicates,
|
|
206
|
+
limit: undefined,
|
|
207
|
+
cursor: undefined,
|
|
208
|
+
ownedBy: "0x123",
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
expect(client.request).lastCalledWith({
|
|
212
|
+
method: "arkiv_query",
|
|
213
|
+
params: [
|
|
214
|
+
`key = "value" && $owner=0x123`,
|
|
215
|
+
{
|
|
216
|
+
includeData: {
|
|
217
|
+
key: true,
|
|
218
|
+
attributes: false,
|
|
219
|
+
contentType: false,
|
|
220
|
+
payload: false,
|
|
221
|
+
expiration: false,
|
|
222
|
+
owner: false,
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
it("should process only ownedBy", async () => {
|
|
230
|
+
const predicates = [] as Predicate[]
|
|
231
|
+
await processQuery(client, {
|
|
232
|
+
predicates,
|
|
233
|
+
limit: undefined,
|
|
234
|
+
cursor: undefined,
|
|
235
|
+
validAtBlock: undefined,
|
|
236
|
+
withAttributes: undefined,
|
|
237
|
+
withMetadata: undefined,
|
|
238
|
+
ownedBy: "0x123",
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
expect(client.request).lastCalledWith({
|
|
242
|
+
method: "arkiv_query",
|
|
243
|
+
params: [
|
|
244
|
+
`$owner=0x123`,
|
|
245
|
+
{
|
|
246
|
+
includeData: {
|
|
247
|
+
key: true,
|
|
248
|
+
attributes: false,
|
|
249
|
+
contentType: false,
|
|
250
|
+
payload: false,
|
|
251
|
+
expiration: false,
|
|
252
|
+
owner: false,
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
it("should process simple predicate with validAtBlock and paging", async () => {
|
|
260
|
+
const predicates = [{ type: "eq" as const, key: "key", value: "value" }]
|
|
261
|
+
await processQuery(client, {
|
|
262
|
+
predicates,
|
|
263
|
+
limit: 10,
|
|
264
|
+
cursor: undefined,
|
|
265
|
+
validAtBlock: 123n,
|
|
266
|
+
ownedBy: "0x123",
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
expect(client.request).lastCalledWith({
|
|
270
|
+
method: "arkiv_query",
|
|
271
|
+
params: [
|
|
272
|
+
`key = "value" && $owner=0x123`,
|
|
273
|
+
{
|
|
274
|
+
atBlock: 123,
|
|
275
|
+
resultsPerPage: 10,
|
|
276
|
+
includeData: {
|
|
277
|
+
key: true,
|
|
278
|
+
attributes: false,
|
|
279
|
+
contentType: false,
|
|
280
|
+
payload: false,
|
|
281
|
+
expiration: false,
|
|
282
|
+
owner: false,
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
})
|
|
287
|
+
})
|
|
288
|
+
})
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { Hex } from "viem"
|
|
2
|
+
import type { ArkivClient } from "../clients/baseClient"
|
|
3
|
+
import type { RpcQueryOptions } from "../types/rpcSchema"
|
|
4
|
+
import type { Predicate } from "./predicate"
|
|
5
|
+
|
|
6
|
+
function processPredicates(predicates: Predicate[]): string {
|
|
7
|
+
const processValue = (value: string | number) => {
|
|
8
|
+
if (typeof value === "string") {
|
|
9
|
+
return `"${value}"`
|
|
10
|
+
}
|
|
11
|
+
return value
|
|
12
|
+
}
|
|
13
|
+
return predicates
|
|
14
|
+
.map((predicate) => {
|
|
15
|
+
switch (predicate.type) {
|
|
16
|
+
case "eq":
|
|
17
|
+
return `${predicate.key} = ${processValue(predicate.value)}`
|
|
18
|
+
case "neq":
|
|
19
|
+
return `${predicate.key} != ${processValue(predicate.value)}`
|
|
20
|
+
case "gt":
|
|
21
|
+
return `${predicate.key} > ${processValue(predicate.value)}`
|
|
22
|
+
case "gte":
|
|
23
|
+
return `${predicate.key} >= ${processValue(predicate.value)}`
|
|
24
|
+
case "lt":
|
|
25
|
+
return `${predicate.key} < ${processValue(predicate.value)}`
|
|
26
|
+
case "lte":
|
|
27
|
+
return `${predicate.key} <= ${processValue(predicate.value)}`
|
|
28
|
+
case "not":
|
|
29
|
+
return `!${predicate.key}`
|
|
30
|
+
case "or":
|
|
31
|
+
return `(${predicate.predicates.map((predicate) => processPredicates([predicate])).join(" || ")})`
|
|
32
|
+
case "and":
|
|
33
|
+
return `(${predicate.predicates.map((predicate) => processPredicates([predicate])).join(" && ")})`
|
|
34
|
+
default:
|
|
35
|
+
return ""
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
.join(" && ")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function processQuery(
|
|
42
|
+
client: ArkivClient,
|
|
43
|
+
queryParams: {
|
|
44
|
+
predicates: Predicate[]
|
|
45
|
+
limit: number | undefined
|
|
46
|
+
cursor: string | undefined
|
|
47
|
+
ownedBy: Hex | undefined
|
|
48
|
+
validAtBlock?: bigint | undefined
|
|
49
|
+
withAttributes?: boolean | undefined
|
|
50
|
+
withMetadata?: boolean | undefined
|
|
51
|
+
withPayload?: boolean | undefined
|
|
52
|
+
},
|
|
53
|
+
) {
|
|
54
|
+
const {
|
|
55
|
+
predicates,
|
|
56
|
+
limit,
|
|
57
|
+
cursor,
|
|
58
|
+
ownedBy,
|
|
59
|
+
validAtBlock,
|
|
60
|
+
withAttributes,
|
|
61
|
+
withMetadata,
|
|
62
|
+
withPayload,
|
|
63
|
+
} = queryParams
|
|
64
|
+
|
|
65
|
+
console.debug(
|
|
66
|
+
`Processing query with params: predicates: ${predicates}, cursor: ${cursor}, limit: ${limit}, ownedBy: ${ownedBy}, validAtBlock: ${validAtBlock}, withAttributes: ${withAttributes}, withMetadata: ${withMetadata}, withPayload: ${withPayload}`,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
let query = processPredicates(predicates)
|
|
70
|
+
if (ownedBy) {
|
|
71
|
+
query += ` && $owner=${ownedBy}`
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// remove leading and trailing spaces and leading &&
|
|
75
|
+
query = query.trim()
|
|
76
|
+
if (query.startsWith("&& ")) {
|
|
77
|
+
query = query.slice(3)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const queryOptions: RpcQueryOptions = {
|
|
81
|
+
includeData: {
|
|
82
|
+
key: true,
|
|
83
|
+
attributes: withAttributes ?? false,
|
|
84
|
+
payload: withPayload ?? false,
|
|
85
|
+
contentType: withMetadata ?? false,
|
|
86
|
+
expiration: withMetadata ?? false,
|
|
87
|
+
owner: withMetadata ?? false,
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (validAtBlock !== undefined) {
|
|
92
|
+
queryOptions.atBlock = Number(validAtBlock)
|
|
93
|
+
}
|
|
94
|
+
if (limit !== undefined) {
|
|
95
|
+
queryOptions.resultsPerPage = limit
|
|
96
|
+
}
|
|
97
|
+
if (cursor !== undefined) {
|
|
98
|
+
queryOptions.cursor = cursor
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.debug(
|
|
102
|
+
`Built query to send: ${query}, queryOptions: ${JSON.stringify({ includeData: queryOptions.includeData, atBlock: queryOptions.atBlock?.toString(), resultsPerPage: queryOptions.resultsPerPage, cursor: queryOptions.cursor })}`,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
const result = await client.request({
|
|
106
|
+
method: "arkiv_query",
|
|
107
|
+
params: [query, queryOptions],
|
|
108
|
+
})
|
|
109
|
+
console.debug("Raw result from query: ", result)
|
|
110
|
+
|
|
111
|
+
return result
|
|
112
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class NoMoreResultsError extends Error {
|
|
2
|
+
constructor() {
|
|
3
|
+
super("No more results")
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class NoCursorOrLimitError extends Error {
|
|
8
|
+
constructor() {
|
|
9
|
+
super("Cursor and limit must be defined to fetch next")
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class OffsetCannotBeLessThanZeroError extends Error {
|
|
14
|
+
constructor() {
|
|
15
|
+
super("Offset cannot be less than 0")
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class NoEntityFoundError extends Error {
|
|
20
|
+
constructor() {
|
|
21
|
+
super("No entity found")
|
|
22
|
+
}
|
|
23
|
+
}
|