@arkiv-network/sdk 0.8.1 → 0.9.0-next.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/README.md +180 -61
- package/dist/chains/index.d.cts +17 -17
- package/dist/chains/index.d.ts +17 -17
- package/dist/changeOwnership-Cy9gfyjN.d.cts +1160 -0
- package/dist/changeOwnership-Cy9gfyjN.d.cts.map +1 -0
- package/dist/changeOwnership-gXf-lBqI.d.ts +1160 -0
- package/dist/changeOwnership-gXf-lBqI.d.ts.map +1 -0
- package/dist/entity/index.cjs +4 -10
- package/dist/entity/index.d.cts +3 -3
- package/dist/entity/index.d.ts +3 -3
- package/dist/entity/index.js +3 -4
- package/dist/entity-BM1unrQf.cjs +41 -0
- package/dist/{entity-DJ0Gml9c.cjs → entity-BgaFJSaV.cjs} +4 -4
- package/dist/entity-CFAI1KyG.js +36 -0
- package/dist/entity-CFAI1KyG.js.map +1 -0
- package/dist/{entity-CniBgBSd.js → entity-CGqx_AU0.js} +4 -4
- package/dist/entity-CGqx_AU0.js.map +1 -0
- package/dist/{payload-AfUfSctb.d.ts → expirationTime-C7PZK49K.d.ts} +8 -37
- package/dist/expirationTime-C7PZK49K.d.ts.map +1 -0
- package/dist/expirationTime-CkIGNAg8.cjs +140 -0
- package/dist/{payload-D167BlJR.d.cts → expirationTime-DOB8V4B8.d.cts} +8 -37
- package/dist/expirationTime-DOB8V4B8.d.cts.map +1 -0
- package/dist/{expiry-Cgdb_dbq.js → expirationTime-UKPuA-LM.js} +62 -27
- package/dist/expirationTime-UKPuA-LM.js.map +1 -0
- package/dist/expiry-B48I-yTA.d.cts +40 -0
- package/dist/expiry-B48I-yTA.d.cts.map +1 -0
- package/dist/expiry-S2PUL8Hg.d.ts +40 -0
- package/dist/expiry-S2PUL8Hg.d.ts.map +1 -0
- package/dist/index-C-mMF5WZ.d.cts +735 -0
- package/dist/index-C-mMF5WZ.d.cts.map +1 -0
- package/dist/{index-BkqSnGJH.d.ts → index-C4zZqJ9S.d.ts} +5 -27
- package/dist/index-C4zZqJ9S.d.ts.map +1 -0
- package/dist/{index-CLhsFyVH.d.cts → index-CcVWYB6v.d.cts} +5 -27
- package/dist/index-CcVWYB6v.d.cts.map +1 -0
- package/dist/index-DCx2XC6S.d.ts +489 -0
- package/dist/index-DCx2XC6S.d.ts.map +1 -0
- package/dist/index-DLb7BfIw.d.ts +735 -0
- package/dist/index-DLb7BfIw.d.ts.map +1 -0
- package/dist/index-DzriOUm8.d.cts +489 -0
- package/dist/index-DzriOUm8.d.cts.map +1 -0
- package/dist/index.cjs +162 -146
- package/dist/index.d.cts +180 -133
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +180 -133
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -83
- package/dist/index.js.map +1 -1
- package/dist/params-BuIrJA9a.cjs +45 -0
- package/dist/params-DDJOnsNi.js +22 -0
- package/dist/params-DDJOnsNi.js.map +1 -0
- package/dist/query/index.cjs +9 -4
- package/dist/query/index.d.cts +6 -6
- package/dist/query/index.d.ts +6 -6
- package/dist/query/index.js +4 -5
- package/dist/query-D0KtuFh2.cjs +1625 -0
- package/dist/query-DpRDozmj.js +1417 -0
- package/dist/query-DpRDozmj.js.map +1 -0
- package/dist/schema/index.cjs +46 -0
- package/dist/schema/index.d.cts +2 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +3 -0
- package/dist/{attr-BXTkpnoc.cjs → schema-B9AyXcgU.cjs} +513 -246
- package/dist/{attr-tmyREHtw.js → schema-DY4sqehl.js} +427 -244
- package/dist/schema-DY4sqehl.js.map +1 -0
- package/dist/types/index.cjs +1 -1
- package/dist/types/index.d.cts +5 -5
- package/dist/types/index.d.ts +5 -5
- package/dist/types/index.js +1 -1
- package/dist/utils/index.cjs +3 -5
- package/dist/utils/index.d.cts +3 -3
- package/dist/utils/index.d.ts +3 -3
- package/dist/utils/index.js +3 -3
- package/package.json +9 -12
- package/src/actions/public/getEntity.test.ts +69 -0
- package/src/actions/public/getEntity.ts +34 -20
- package/src/actions/public/predictEntityKeys.ts +8 -7
- package/src/actions/public/query.test.ts +58 -0
- package/src/actions/public/query.ts +41 -13
- package/src/actions/wallet/createEntity.ts +34 -63
- package/src/actions/wallet/executeBatch.test.ts +38 -0
- package/src/actions/wallet/executeBatch.ts +26 -9
- package/src/actions/wallet/extendEntity.ts +9 -8
- package/src/actions/wallet/patchEntity.ts +43 -52
- package/src/clients/createPublicClient.test.ts +10 -2
- package/src/clients/createWalletClient.ts +4 -1
- package/src/clients/decorators/arkivPublic.ts +123 -80
- package/src/clients/decorators/arkivWallet.ts +113 -65
- package/src/entity/create.test.ts +25 -21
- package/src/entity/expiry.ts +8 -6
- package/src/entity/flags.ts +1 -1
- package/src/entity/index.ts +2 -4
- package/src/entity/key.ts +3 -3
- package/src/entity/operations.ts +1 -1
- package/src/errors.ts +2 -11
- package/src/index.ts +18 -6
- package/src/query/builderBase.ts +166 -0
- package/src/query/countBuilder.test.ts +91 -0
- package/src/query/countBuilder.ts +67 -0
- package/src/query/engine.ts +9 -3
- package/src/query/errors.ts +24 -14
- package/src/query/expression.test.ts +129 -21
- package/src/query/expression.ts +323 -94
- package/src/query/index.ts +26 -4
- package/src/query/injection.test.ts +5 -11
- package/src/query/queryBuilder.test.ts +467 -58
- package/src/query/queryBuilder.ts +191 -98
- package/src/query/queryResult.ts +35 -9
- package/src/query/selection.test.ts +278 -24
- package/src/query/selection.ts +427 -86
- package/src/schema/attributes.test.ts +266 -0
- package/src/schema/attributes.ts +212 -0
- package/src/{attr → schema}/codec.test.ts +37 -5
- package/src/{attr → schema}/codec.ts +40 -11
- package/src/schema/column.ts +193 -0
- package/src/{attr → schema}/errors.ts +67 -10
- package/src/schema/index.ts +76 -0
- package/src/{attr → schema}/names.ts +4 -2
- package/src/schema/schema.test.ts +171 -0
- package/src/schema/schema.ts +250 -0
- package/src/{attr → schema}/types.ts +36 -30
- package/src/{attr → schema}/values.test.ts +62 -3
- package/src/{attr → schema}/values.ts +246 -65
- package/src/types/entity.test.ts +1 -44
- package/src/types/entity.ts +9 -55
- package/src/types/events.ts +1 -1
- package/src/types/index.ts +11 -4
- package/src/types/rpcSchema.ts +22 -16
- package/src/utils/arkivTransactions.test.ts +356 -116
- package/src/utils/arkivTransactions.ts +30 -38
- package/src/utils/entities.ts +10 -9
- package/src/utils/expirationTime.ts +5 -5
- package/src/utils/index.ts +0 -1
- package/src/utils/logger.test.ts +45 -0
- package/src/utils/logger.ts +5 -39
- package/src/utils/revert.test.ts +25 -0
- package/src/utils/revert.ts +28 -3
- package/dist/attr/index.cjs +0 -34
- package/dist/attr/index.d.cts +0 -2
- package/dist/attr/index.d.ts +0 -2
- package/dist/attr/index.js +0 -3
- package/dist/attr-tmyREHtw.js.map +0 -1
- package/dist/entity-B0t6sN7F.cjs +0 -71
- package/dist/entity-BIp_df9u.js +0 -67
- package/dist/entity-BIp_df9u.js.map +0 -1
- package/dist/entity-CniBgBSd.js.map +0 -1
- package/dist/expiry-BxOlvVWC.d.ts +0 -79
- package/dist/expiry-BxOlvVWC.d.ts.map +0 -1
- package/dist/expiry-CG9GhVXv.cjs +0 -135
- package/dist/expiry-Cgdb_dbq.js.map +0 -1
- package/dist/expiry-DRV29F1r.d.cts +0 -79
- package/dist/expiry-DRV29F1r.d.cts.map +0 -1
- package/dist/flags-DCD26uhe.cjs +0 -43
- package/dist/flags-DUT2gHEU.js +0 -33
- package/dist/flags-DUT2gHEU.js.map +0 -1
- package/dist/index-BkqSnGJH.d.ts.map +0 -1
- package/dist/index-C7fbakoI.d.cts +0 -278
- package/dist/index-C7fbakoI.d.cts.map +0 -1
- package/dist/index-CIcHPx2j.d.cts +0 -424
- package/dist/index-CIcHPx2j.d.cts.map +0 -1
- package/dist/index-CLhsFyVH.d.cts.map +0 -1
- package/dist/index-Cd2aaWme.d.ts +0 -424
- package/dist/index-Cd2aaWme.d.ts.map +0 -1
- package/dist/index-Cq6fa8AI.d.ts +0 -278
- package/dist/index-Cq6fa8AI.d.ts.map +0 -1
- package/dist/index-DaNeJUw8.d.ts +0 -955
- package/dist/index-DaNeJUw8.d.ts.map +0 -1
- package/dist/index-Dv16LO2s.d.cts +0 -955
- package/dist/index-Dv16LO2s.d.cts.map +0 -1
- package/dist/payload-AfUfSctb.d.ts.map +0 -1
- package/dist/payload-D167BlJR.d.cts.map +0 -1
- package/dist/payload-DE7wMztL.js +0 -92
- package/dist/payload-DE7wMztL.js.map +0 -1
- package/dist/payload-DqFweqiO.cjs +0 -108
- package/dist/query-9oojUdM7.cjs +0 -1128
- package/dist/query-Ber-lOJQ.js +0 -968
- package/dist/query-Ber-lOJQ.js.map +0 -1
- package/src/actions/public/getEntityCount.ts +0 -10
- package/src/attr/attributes.test.ts +0 -120
- package/src/attr/attributes.ts +0 -196
- package/src/attr/index.ts +0 -50
- package/src/types/mimeTypes.ts +0 -27
- package/src/utils/compression.test.ts +0 -32
- package/src/utils/compression.ts +0 -102
- package/src/utils/payload.ts +0 -36
- /package/src/{attr → schema}/decimal.ts +0 -0
package/README.md
CHANGED
|
@@ -85,12 +85,52 @@ npm install @arkiv-network/sdk viem
|
|
|
85
85
|
This command will update your `package.json` with a section like:
|
|
86
86
|
```json
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@arkiv-network/sdk": "^0.
|
|
88
|
+
"@arkiv-network/sdk": "^0.9.0",
|
|
89
89
|
"viem": "^2.38.2"
|
|
90
90
|
}
|
|
91
91
|
```
|
|
92
92
|
It will also create a `node_modules` directory with all dependencies installed.
|
|
93
93
|
|
|
94
|
+
### Define a Schema
|
|
95
|
+
|
|
96
|
+
Arkiv stores entities, and an entity is a set of named, typed attributes. You describe them once in a
|
|
97
|
+
schema, much as you would describe a table's columns in SQL, and choose per column whether the node
|
|
98
|
+
indexes it. Only indexed columns can be filtered on; the rest are stored and selectable, and do not
|
|
99
|
+
pay for an index.
|
|
100
|
+
|
|
101
|
+
The examples below use this schema for blog posts. Each example declares it at the top of its own
|
|
102
|
+
file, so that it runs as a single file under Node.js, Bun or `tsc` alike:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { addr, bytes, dec, defineSchema, str } from "@arkiv-network/sdk/schema"
|
|
106
|
+
|
|
107
|
+
// Called with no arguments, a type constructor describes a column.
|
|
108
|
+
const Posts = defineSchema("posts", {
|
|
109
|
+
author: addr().indexed(),
|
|
110
|
+
category: str().indexed(),
|
|
111
|
+
score: dec().indexed(),
|
|
112
|
+
title: str(), // stored, not indexed
|
|
113
|
+
body: bytes(), // a blob; bytes can never be indexed
|
|
114
|
+
thumbnail: bytes().optional(), // any number of bytes columns; this one may be absent
|
|
115
|
+
mimeType: str().default("text/markdown"), // written on create when left out
|
|
116
|
+
})
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The type constructors are `bool`, `i32`, `u64`, `u256`, `dec`, `str`, `addr`, `key`, `bytes32` and
|
|
120
|
+
`bytes`. Each column may be refined with `.indexed()` (every type but `bytes`), `.optional()` and
|
|
121
|
+
`.default(...)`.
|
|
122
|
+
|
|
123
|
+
The same constructors, called with a value, make a typed value: `dec("4.1")` is a decimal, the way SQL
|
|
124
|
+
has `DECIMAL` as a type and `DECIMAL '4.1'` as a literal.
|
|
125
|
+
|
|
126
|
+
A schema is an SDK-side convention: the node sees only attributes, each with a type and an indexed
|
|
127
|
+
flag. The schema is what types your writes and reads, and checks them at runtime.
|
|
128
|
+
|
|
129
|
+
The name, `"posts"`, is optional but recommended. A named schema tags every entity it creates with
|
|
130
|
+
an indexed `arkiv.schema` attribute holding its name, and a query through it only matches entities
|
|
131
|
+
with that tag — the way a collection keeps one model's documents apart from another's. For that
|
|
132
|
+
reason `arkiv.schema` cannot be used as a column name.
|
|
133
|
+
|
|
94
134
|
### Public Client Example (Query Data)
|
|
95
135
|
|
|
96
136
|
You can now use Arkiv's public client to query data. Paste the following in `read_example.ts`:
|
|
@@ -98,31 +138,41 @@ You can now use Arkiv's public client to query data. Paste the following in `rea
|
|
|
98
138
|
```typescript
|
|
99
139
|
import { createPublicClient } from "@arkiv-network/sdk"
|
|
100
140
|
import { tiramisu } from "@arkiv-network/sdk/chains"
|
|
101
|
-
import { eq } from "@arkiv-network/sdk/query"
|
|
141
|
+
import { and, eq, gt } from "@arkiv-network/sdk/query"
|
|
142
|
+
import { addr, bytes, dec, defineSchema, str } from "@arkiv-network/sdk/schema"
|
|
102
143
|
import { http } from "viem"
|
|
103
144
|
|
|
145
|
+
// The schema from "Define a Schema" above
|
|
146
|
+
const Posts = defineSchema("posts", {
|
|
147
|
+
author: addr().indexed(),
|
|
148
|
+
category: str().indexed(),
|
|
149
|
+
score: dec().indexed(),
|
|
150
|
+
title: str(),
|
|
151
|
+
body: bytes(),
|
|
152
|
+
thumbnail: bytes().optional(),
|
|
153
|
+
mimeType: str().default("text/markdown"),
|
|
154
|
+
})
|
|
155
|
+
|
|
104
156
|
const publicClient = createPublicClient({
|
|
105
157
|
chain: tiramisu, // "tiramisu" is Arkiv's testnet
|
|
106
158
|
transport: http(),
|
|
107
159
|
});
|
|
108
160
|
|
|
109
|
-
// Get
|
|
110
|
-
const
|
|
111
|
-
console.log('
|
|
161
|
+
// Get an entity by key, read through the schema
|
|
162
|
+
const post = await publicClient.getEntity('0xcadb830a3414251d65e5c92cd28ecb648d9e73d85f2203eff631839d5421f9d7', Posts);
|
|
163
|
+
console.log('Title:', post.title.value);
|
|
112
164
|
|
|
113
|
-
//
|
|
114
|
-
const entity = await publicClient.getEntity('0xcadb830a3414251d65e5c92cd28ecb648d9e73d85f2203eff631839d5421f9d7');
|
|
115
|
-
console.log('Entity:', entity);
|
|
116
|
-
|
|
117
|
-
// Build and execute a query using select()
|
|
165
|
+
// Build and execute a query: select what to return, name the schema, then filter
|
|
118
166
|
const result = await publicClient
|
|
119
|
-
.select({
|
|
120
|
-
.
|
|
121
|
-
.
|
|
167
|
+
.select({ $key: true, author: true, title: true, body: true })
|
|
168
|
+
.from(Posts)
|
|
169
|
+
.where(and(eq('category', 'docs'), gt('score', dec('4.0'))))
|
|
122
170
|
.limit(10)
|
|
123
171
|
.fetch();
|
|
124
172
|
|
|
125
|
-
|
|
173
|
+
for (const row of result.entities) {
|
|
174
|
+
console.log(row.$key, row.author.value, row.title.value);
|
|
175
|
+
}
|
|
126
176
|
|
|
127
177
|
// Pagination
|
|
128
178
|
if (result.hasNextPage()) {
|
|
@@ -131,46 +181,107 @@ if (result.hasNextPage()) {
|
|
|
131
181
|
}
|
|
132
182
|
|
|
133
183
|
// Or walk every page at once
|
|
134
|
-
for await (const
|
|
135
|
-
.select({ key: true })
|
|
136
|
-
.
|
|
137
|
-
|
|
184
|
+
for await (const row of publicClient
|
|
185
|
+
.select({ $key: true, title: true })
|
|
186
|
+
.from(Posts)
|
|
187
|
+
.where(eq('category', 'docs'))) {
|
|
188
|
+
console.log(row.$key, row.title.value);
|
|
138
189
|
}
|
|
139
190
|
```
|
|
140
191
|
|
|
141
192
|
#### Selecting fields with `select()`
|
|
142
193
|
|
|
143
|
-
Pass nothing (or `"*"`) to fetch everything
|
|
194
|
+
Pass nothing (or `"*"`) to fetch everything — through a schema, every entity field and every
|
|
195
|
+
column — or pass an object to fetch only specific fields. The selection names entity fields and
|
|
196
|
+
attributes side by side, and each result is a flat row. Entity fields start with `$`, as they do in
|
|
197
|
+
`where`: `$key`, `$owner`, `$creator`, `$createdAt`, `$updatedAt`, `$expiresAt` and
|
|
198
|
+
`$creationFlags`. Any other name is an attribute. An attribute name cannot start with `$`, so the
|
|
199
|
+
two never collide — an attribute called `owner` is just `owner`:
|
|
144
200
|
|
|
145
201
|
```typescript
|
|
146
|
-
//
|
|
147
|
-
await publicClient.select().where(eq("category", "docs")).fetch();
|
|
202
|
+
// Every entity field and every column
|
|
203
|
+
await publicClient.select().from(Posts).where(eq("category", "docs")).fetch();
|
|
148
204
|
|
|
149
205
|
// Only the fields you need
|
|
150
|
-
await publicClient.select({ key: true,
|
|
206
|
+
await publicClient.select({ $key: true, title: true }).from(Posts).where(eq("category", "docs")).fetch();
|
|
151
207
|
```
|
|
152
208
|
|
|
153
209
|
**Select only what you need.** Every selected field is fetched over the network, so requesting
|
|
154
210
|
data you won't use makes queries slower. Narrowing the selection keeps responses small and fast.
|
|
155
211
|
|
|
156
|
-
The result type is inferred from your selection
|
|
157
|
-
|
|
212
|
+
The result type is inferred from your selection and schema: each column is typed as the schema
|
|
213
|
+
declares it, and reading a field you didn't select is a compile error.
|
|
158
214
|
|
|
159
215
|
```typescript
|
|
160
|
-
const
|
|
161
|
-
await publicClient.select({ owner: true,
|
|
162
|
-
).entities
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
216
|
+
const row = (
|
|
217
|
+
await publicClient.select({ $owner: true, score: true }).from(Posts).where(eq("category", "docs")).fetch()
|
|
218
|
+
).entities[0]!;
|
|
219
|
+
row.$owner; // ✅ Hex
|
|
220
|
+
row.score; // ✅ DecValue — row.score.value is "4.1"
|
|
221
|
+
row.title; // ❌ compile error — not selected
|
|
166
222
|
```
|
|
167
223
|
|
|
224
|
+
`where` is checked against the schema too. It takes the schema's indexed columns and the system
|
|
225
|
+
attributes `$key`, `$owner`, `$creator` and `$expiresAt`. Filtering on a column the schema does not
|
|
226
|
+
index, or comparing a column against a value of another type, is a compile error:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
.where(eq("title", "x")) // ❌ title is not indexed
|
|
230
|
+
.where(eq("score", 5)) // ❌ score is a dec, 5 is an i32 — write dec(5)
|
|
231
|
+
.where(between("score", dec(1), 5)) // ❌ both bounds need one type
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
A named schema needs no `where` at all — `select().from(Posts)` matches every post: `fetch()`
|
|
235
|
+
returns the first page, and `for await` walks them all. An unnamed schema types a query without
|
|
236
|
+
filtering it, so `where` alone decides which entities match.
|
|
237
|
+
|
|
238
|
+
Only what you select is checked. An entity that matches but does not fit the schema — a selected
|
|
239
|
+
column that is required but missing or holds another type, or, for a named schema, another schema's
|
|
240
|
+
tag — is left out of the page. Anyone can write an entity a query matches, so one that does not
|
|
241
|
+
fit never fails the read of the others. A page can then hold fewer rows than its limit, and reports
|
|
242
|
+
how many it left out as `skipped`. Pass `{ onMismatch: "throw" }` to fail the fetch with a
|
|
243
|
+
`SchemaMismatchError` instead:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const page = await publicClient.select().from(Posts).where(eq("category", "docs")).fetch();
|
|
247
|
+
page.skipped; // matching entities on this page that did not fit Posts
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
A query reads the same without a schema — say, to explore what a node holds. Leave out
|
|
251
|
+
`.from(...)` and the selection means what it did (save `"*"`, below), and the rows keep their
|
|
252
|
+
shape. Only the checking is gone, along with a named schema's tag filter: each attribute comes back
|
|
253
|
+
as whatever value the entity holds, or `undefined`, and `where` takes any attribute:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
const row = (
|
|
257
|
+
await publicClient.select({ $key: true, title: true }).where(eq("category", "docs")).fetch()
|
|
258
|
+
).entities[0]!;
|
|
259
|
+
row.title; // ArkivValue | undefined — e.g. { type: "str", value: "Hello" }
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
To read every attribute without naming them, select `$attributes`, a map of all of them. `"*"` (or
|
|
263
|
+
nothing) fetches it alongside the entity fields when there is no schema, since there are no columns
|
|
264
|
+
to list.
|
|
265
|
+
|
|
266
|
+
`$attributeSchema` is for finding out what entities hold without fetching their values: each
|
|
267
|
+
attribute's name, its type, and whether it is indexed. Values can be large — a `bytes` attribute
|
|
268
|
+
holds up to 128 KiB — and an RPC endpoint may cap how big a response it sends, so a page of 100
|
|
269
|
+
entities with every attribute can be more than it will return. Fetch the schema first, then select
|
|
270
|
+
the attributes you need by name. It is never part of `"*"`; select it by name:
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
const page = await publicClient.select({ $key: true, $attributeSchema: true }).where(eq("category", "docs")).fetch();
|
|
274
|
+
page.entities[0]?.$attributeSchema; // { title: { type: "str", indexed: false }, body: { type: "bytes", indexed: false } }
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Both work through a schema too.
|
|
278
|
+
|
|
168
279
|
> **Footgun:** pass the selection inline. A selection stored in a variable widens its `true` values
|
|
169
|
-
> to `boolean`, so
|
|
170
|
-
>
|
|
280
|
+
> to `boolean`, so which fields come back is only known at runtime and every field of the result is
|
|
281
|
+
> optional. If you need to reuse one, annotate it `as const`:
|
|
171
282
|
> ```typescript
|
|
172
|
-
> const fields = { owner: true,
|
|
173
|
-
> await publicClient.select(fields).where(eq("category", "docs")).fetch();
|
|
283
|
+
> const fields = { $owner: true, title: true } as const;
|
|
284
|
+
> await publicClient.select(fields).from(Posts).where(eq("category", "docs")).fetch();
|
|
174
285
|
> ```
|
|
175
286
|
|
|
176
287
|
### Running the Example
|
|
@@ -208,19 +319,29 @@ You have several options to run your TypeScript sample:
|
|
|
208
319
|
node dist/read_example.js
|
|
209
320
|
```
|
|
210
321
|
|
|
211
|
-
### Wallet Client Example (Create Entity)
|
|
322
|
+
### Wallet Client Example (Create an Entity)
|
|
212
323
|
|
|
213
324
|
Now let's add storage (write) functionality.
|
|
214
325
|
Create a file named `write_example.ts` with the following content:
|
|
215
326
|
|
|
216
327
|
```typescript
|
|
217
|
-
import { createPublicClient, createWalletClient } from "@arkiv-network/sdk"
|
|
218
|
-
import { dec, i32 } from "@arkiv-network/sdk/attr"
|
|
328
|
+
import { createPublicClient, createWalletClient, ExpirationTime } from "@arkiv-network/sdk"
|
|
219
329
|
import { tiramisu } from "@arkiv-network/sdk/chains"
|
|
220
|
-
import {
|
|
221
|
-
import { http } from "viem"
|
|
330
|
+
import { addr, bytes, dec, defineSchema, str } from "@arkiv-network/sdk/schema"
|
|
331
|
+
import { http, stringToBytes } from "viem"
|
|
222
332
|
import { privateKeyToAccount } from "viem/accounts"
|
|
223
333
|
|
|
334
|
+
// The schema from "Define a Schema" above
|
|
335
|
+
const Posts = defineSchema("posts", {
|
|
336
|
+
author: addr().indexed(),
|
|
337
|
+
category: str().indexed(),
|
|
338
|
+
score: dec().indexed(),
|
|
339
|
+
title: str(),
|
|
340
|
+
body: bytes(),
|
|
341
|
+
thumbnail: bytes().optional(),
|
|
342
|
+
mimeType: str().default("text/markdown"),
|
|
343
|
+
})
|
|
344
|
+
|
|
224
345
|
// Create a public client
|
|
225
346
|
const publicClient = createPublicClient({
|
|
226
347
|
chain: tiramisu, // tiramisu is the Arkiv testnet
|
|
@@ -233,32 +354,30 @@ const client = createWalletClient({
|
|
|
233
354
|
account: privateKeyToAccount('0x...'), // Replace with your private key
|
|
234
355
|
});
|
|
235
356
|
|
|
236
|
-
// Create an entity
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
contentType: 'application/json',
|
|
246
|
-
// Attributes are keyed by name. Values carry their type: use the tagged constructors from
|
|
247
|
-
// "@arkiv-network/sdk/attr" (i32, u64, u256, dec, str, addr, key, bytes32, bool), or pass a bare
|
|
248
|
-
// boolean, number, bigint or string where the type is unambiguous.
|
|
249
|
-
attributes: {
|
|
250
|
-
category: 'documentation', // bare string -> str
|
|
251
|
-
version: i32(1),
|
|
357
|
+
// Create an entity. Every required column must be given; a defaulted one (mimeType) left out is
|
|
358
|
+
// written with its default. Values carry their type: use the constructors from
|
|
359
|
+
// "@arkiv-network/sdk/schema", or a bare string, boolean, number, bigint or Uint8Array where it is
|
|
360
|
+
// unambiguous (string -> str, Uint8Array -> bytes, ...).
|
|
361
|
+
const { entityKey, txHash } = await client.createEntity(
|
|
362
|
+
Posts,
|
|
363
|
+
{
|
|
364
|
+
author: addr(client.account.address),
|
|
365
|
+
category: 'docs',
|
|
252
366
|
score: dec('4.5'),
|
|
367
|
+
title: 'Hello from Arkiv',
|
|
368
|
+
body: stringToBytes('# Hello\n\nArkiv wishes you all the best!'),
|
|
253
369
|
},
|
|
254
|
-
|
|
255
|
-
|
|
370
|
+
{ expiration: ExpirationTime.fromDays(30) }, // Entity expires in 30 days
|
|
371
|
+
);
|
|
256
372
|
|
|
257
373
|
console.log('Created entity:', entityKey);
|
|
258
374
|
console.log('Transaction hash:', txHash);
|
|
259
375
|
|
|
260
|
-
|
|
261
|
-
|
|
376
|
+
// Change one column, leaving the rest alone
|
|
377
|
+
await client.patchEntity(Posts, entityKey, { set: { score: dec('4.7') } });
|
|
378
|
+
|
|
379
|
+
const post = await publicClient.getEntity(entityKey, Posts);
|
|
380
|
+
console.log('Post:', post);
|
|
262
381
|
```
|
|
263
382
|
|
|
264
383
|
Now you can run it in the same way as in the previous example:
|
|
@@ -356,12 +475,12 @@ For more information about refer to:
|
|
|
356
475
|
|
|
357
476
|
## Verbose Logging
|
|
358
477
|
|
|
359
|
-
|
|
478
|
+
Set the `DEBUG` environment variable (or, in a browser, the `DEBUG` key in `localStorage`) to view verbose logs:
|
|
360
479
|
|
|
361
480
|
```bash
|
|
362
481
|
DEBUG=arkiv:* bun run your-script
|
|
363
482
|
```
|
|
364
483
|
|
|
365
|
-
Adjust the namespace (for example, `arkiv:
|
|
484
|
+
Adjust the namespace (for example, `arkiv:query:*` or `arkiv:actions:wallet:*`) to target specific log sources, and prefix one with `-` to exclude it. Unset `DEBUG` to silence debug output.
|
|
366
485
|
|
|
367
486
|
|
package/dist/chains/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as viem8 from "viem";
|
|
2
2
|
|
|
3
3
|
//#region src/chains/localhost.d.ts
|
|
4
4
|
/**
|
|
@@ -19,13 +19,13 @@ declare const localhost: {
|
|
|
19
19
|
} | undefined | undefined;
|
|
20
20
|
blockTime?: number | undefined | undefined;
|
|
21
21
|
contracts?: {
|
|
22
|
-
[x: string]:
|
|
23
|
-
[sourceId: number]:
|
|
22
|
+
[x: string]: viem8.ChainContract | {
|
|
23
|
+
[sourceId: number]: viem8.ChainContract | undefined;
|
|
24
24
|
} | undefined;
|
|
25
|
-
ensRegistry?:
|
|
26
|
-
ensUniversalResolver?:
|
|
27
|
-
multicall3?:
|
|
28
|
-
erc6492Verifier?:
|
|
25
|
+
ensRegistry?: viem8.ChainContract | undefined;
|
|
26
|
+
ensUniversalResolver?: viem8.ChainContract | undefined;
|
|
27
|
+
multicall3?: viem8.ChainContract | undefined;
|
|
28
|
+
erc6492Verifier?: viem8.ChainContract | undefined;
|
|
29
29
|
} | undefined;
|
|
30
30
|
ensTlds?: readonly string[] | undefined;
|
|
31
31
|
id: 1337;
|
|
@@ -44,9 +44,9 @@ declare const localhost: {
|
|
|
44
44
|
sourceId?: number | undefined | undefined;
|
|
45
45
|
testnet?: boolean | undefined | undefined;
|
|
46
46
|
custom?: Record<string, unknown> | undefined;
|
|
47
|
-
fees?:
|
|
47
|
+
fees?: viem8.ChainFees<undefined> | undefined;
|
|
48
48
|
formatters?: undefined;
|
|
49
|
-
serializers?:
|
|
49
|
+
serializers?: viem8.ChainSerializers<undefined, viem8.TransactionSerializable> | undefined;
|
|
50
50
|
};
|
|
51
51
|
//#endregion
|
|
52
52
|
//#region src/chains/tiramisu.d.ts
|
|
@@ -68,13 +68,13 @@ declare const tiramisu: {
|
|
|
68
68
|
} | undefined | undefined;
|
|
69
69
|
blockTime?: number | undefined | undefined;
|
|
70
70
|
contracts?: {
|
|
71
|
-
[x: string]:
|
|
72
|
-
[sourceId: number]:
|
|
71
|
+
[x: string]: viem8.ChainContract | {
|
|
72
|
+
[sourceId: number]: viem8.ChainContract | undefined;
|
|
73
73
|
} | undefined;
|
|
74
|
-
ensRegistry?:
|
|
75
|
-
ensUniversalResolver?:
|
|
76
|
-
multicall3?:
|
|
77
|
-
erc6492Verifier?:
|
|
74
|
+
ensRegistry?: viem8.ChainContract | undefined;
|
|
75
|
+
ensUniversalResolver?: viem8.ChainContract | undefined;
|
|
76
|
+
multicall3?: viem8.ChainContract | undefined;
|
|
77
|
+
erc6492Verifier?: viem8.ChainContract | undefined;
|
|
78
78
|
} | undefined;
|
|
79
79
|
ensTlds?: readonly string[] | undefined;
|
|
80
80
|
id: 7738577;
|
|
@@ -94,9 +94,9 @@ declare const tiramisu: {
|
|
|
94
94
|
sourceId?: number | undefined | undefined;
|
|
95
95
|
testnet: true;
|
|
96
96
|
custom?: Record<string, unknown> | undefined;
|
|
97
|
-
fees?:
|
|
97
|
+
fees?: viem8.ChainFees<undefined> | undefined;
|
|
98
98
|
formatters?: undefined;
|
|
99
|
-
serializers?:
|
|
99
|
+
serializers?: viem8.ChainSerializers<undefined, viem8.TransactionSerializable> | undefined;
|
|
100
100
|
readonly network: "tiramisu";
|
|
101
101
|
};
|
|
102
102
|
//#endregion
|
package/dist/chains/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as viem0 from "viem";
|
|
2
2
|
|
|
3
3
|
//#region src/chains/localhost.d.ts
|
|
4
4
|
/**
|
|
@@ -19,13 +19,13 @@ declare const localhost: {
|
|
|
19
19
|
} | undefined | undefined;
|
|
20
20
|
blockTime?: number | undefined | undefined;
|
|
21
21
|
contracts?: {
|
|
22
|
-
[x: string]:
|
|
23
|
-
[sourceId: number]:
|
|
22
|
+
[x: string]: viem0.ChainContract | {
|
|
23
|
+
[sourceId: number]: viem0.ChainContract | undefined;
|
|
24
24
|
} | undefined;
|
|
25
|
-
ensRegistry?:
|
|
26
|
-
ensUniversalResolver?:
|
|
27
|
-
multicall3?:
|
|
28
|
-
erc6492Verifier?:
|
|
25
|
+
ensRegistry?: viem0.ChainContract | undefined;
|
|
26
|
+
ensUniversalResolver?: viem0.ChainContract | undefined;
|
|
27
|
+
multicall3?: viem0.ChainContract | undefined;
|
|
28
|
+
erc6492Verifier?: viem0.ChainContract | undefined;
|
|
29
29
|
} | undefined;
|
|
30
30
|
ensTlds?: readonly string[] | undefined;
|
|
31
31
|
id: 1337;
|
|
@@ -44,9 +44,9 @@ declare const localhost: {
|
|
|
44
44
|
sourceId?: number | undefined | undefined;
|
|
45
45
|
testnet?: boolean | undefined | undefined;
|
|
46
46
|
custom?: Record<string, unknown> | undefined;
|
|
47
|
-
fees?:
|
|
47
|
+
fees?: viem0.ChainFees<undefined> | undefined;
|
|
48
48
|
formatters?: undefined;
|
|
49
|
-
serializers?:
|
|
49
|
+
serializers?: viem0.ChainSerializers<undefined, viem0.TransactionSerializable> | undefined;
|
|
50
50
|
};
|
|
51
51
|
//#endregion
|
|
52
52
|
//#region src/chains/tiramisu.d.ts
|
|
@@ -68,13 +68,13 @@ declare const tiramisu: {
|
|
|
68
68
|
} | undefined | undefined;
|
|
69
69
|
blockTime?: number | undefined | undefined;
|
|
70
70
|
contracts?: {
|
|
71
|
-
[x: string]:
|
|
72
|
-
[sourceId: number]:
|
|
71
|
+
[x: string]: viem0.ChainContract | {
|
|
72
|
+
[sourceId: number]: viem0.ChainContract | undefined;
|
|
73
73
|
} | undefined;
|
|
74
|
-
ensRegistry?:
|
|
75
|
-
ensUniversalResolver?:
|
|
76
|
-
multicall3?:
|
|
77
|
-
erc6492Verifier?:
|
|
74
|
+
ensRegistry?: viem0.ChainContract | undefined;
|
|
75
|
+
ensUniversalResolver?: viem0.ChainContract | undefined;
|
|
76
|
+
multicall3?: viem0.ChainContract | undefined;
|
|
77
|
+
erc6492Verifier?: viem0.ChainContract | undefined;
|
|
78
78
|
} | undefined;
|
|
79
79
|
ensTlds?: readonly string[] | undefined;
|
|
80
80
|
id: 7738577;
|
|
@@ -94,9 +94,9 @@ declare const tiramisu: {
|
|
|
94
94
|
sourceId?: number | undefined | undefined;
|
|
95
95
|
testnet: true;
|
|
96
96
|
custom?: Record<string, unknown> | undefined;
|
|
97
|
-
fees?:
|
|
97
|
+
fees?: viem0.ChainFees<undefined> | undefined;
|
|
98
98
|
formatters?: undefined;
|
|
99
|
-
serializers?:
|
|
99
|
+
serializers?: viem0.ChainSerializers<undefined, viem0.TransactionSerializable> | undefined;
|
|
100
100
|
readonly network: "tiramisu";
|
|
101
101
|
};
|
|
102
102
|
//#endregion
|