Querying Data
Read entities from Arkiv using the TypeScript SDK’s public client and its chainable query builder — with support for filtering, pagination, ordering, and payload retrieval.
PublicClient Setup
Section titled “PublicClient Setup”All queries use the read-only public client:
import { createPublicClient, http } from "@arkiv-network/sdk"import { kaolin } from "@arkiv-network/sdk/chains"
const publicClient = createPublicClient({ chain: kaolin, transport: http(),})Building Queries
Section titled “Building Queries”Use buildQuery() to construct queries with chainable methods:
import { eq, gt } from "@arkiv-network/sdk/query"
const result = await publicClient .buildQuery() .where(eq('type', 'note')) .where(gt('created', Date.now() - 86400000)) .withPayload(true) .withAttributes(true) .limit(10) .fetch()
console.log('Found:', result.entities.length)Query Builder Methods
Section titled “Query Builder Methods”| Method | Description |
|---|---|
.where(condition) | Add a filter condition (chainable) |
.withPayload(true) | Include entity payload in results |
.withAttributes(true) | Include attributes in results |
.withMetadata(true) | Include metadata (owner, creator, TTL) |
.ownedBy(address) | Filter by current owner |
.createdBy(address) | Filter by original creator (immutable) |
.orderBy(desc('field', 'type')) | Order results |
.limit(n) | Limit number of results |
.fetch() | Execute the query |
Passing Multiple Conditions
Section titled “Passing Multiple Conditions”You can chain .where() calls or pass an array:
// Chained — each .where() adds an AND conditionconst result = await publicClient .buildQuery() .where(eq('type', 'note')) .where(gt('priority', 3)) .fetch()
// Array syntax — equivalent to aboveconst result = await publicClient .buildQuery() .where([eq('type', 'note'), gt('priority', 3)]) .fetch()Query Operators
Section titled “Query Operators”import { eq, gt, lt, gte, lte } from "@arkiv-network/sdk/query"
eq('type', 'note') // type = "note"gt('priority', 3) // priority > 3lt('price', 1000) // price < 1000gte('created', timestamp) // created >= timestamplte('expiration', limit) // expiration <= limitFiltering by Owner and Creator
Section titled “Filtering by Owner and Creator”Every entity has two metadata fields:
$owner— The wallet that currently owns the entity. Can change via ownership transfer.$creator— The wallet that originally created the entity. Immutable — can never change.
// Filter by current ownerconst owned = await publicClient .buildQuery() .where(eq('type', 'note')) .ownedBy('0xOwnerAddress') .withPayload(true) .withMetadata(true) .fetch()
// Filter by original creator (tamper-proof)const created = await publicClient .buildQuery() .where(eq('type', 'note')) .createdBy('0xCreatorAddress') .withPayload(true) .withMetadata(true) .fetch()Getting a Single Entity
Section titled “Getting a Single Entity”Retrieve a specific entity by key:
const entity = await publicClient.getEntity(entityKey)
// Parse the payloadconst data = entity.toJson() // JSON payloadconst text = entity.toText() // Text payloadReading Results
Section titled “Reading Results”const result = await publicClient .buildQuery() .where(eq('type', 'note')) .withPayload(true) .withAttributes(true) .fetch()
for (const entity of result.entities) { // Access payload const data = entity.toJson() console.log(data.title, data.content)
// Access entity key console.log('Key:', entity.key)
// Access attributes (when withAttributes is true) for (const attr of entity.attributes) { console.log(`${attr.key}: ${attr.value}`) }}Pagination
Section titled “Pagination”Arkiv uses cursor-based pagination. Results per page are capped at 200.
const result = await publicClient .buildQuery() .where(eq('type', 'note')) .withPayload(true) .limit(10) .fetch()
console.log('Page 1:', result.entities.length)
// Check for more pagesif (result.hasNextPage()) { await result.next() console.log('Page 2:', result.entities.length)}Ordering Results
Section titled “Ordering Results”import { desc } from "@arkiv-network/sdk/query"
const result = await publicClient .buildQuery() .where(eq('type', 'sketch')) .ownedBy(userAddress) .orderBy(desc('timestamp', 'number')) .withPayload(true) .limit(9) .fetch()