@arkiv-network/sdk 0.1.1-dev.0 → 0.1.2-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.
Files changed (63) hide show
  1. package/README.md +22 -10
  2. package/dist/chains/index.cjs +1 -0
  3. package/dist/chains/index.d.ts +25 -25
  4. package/dist/chains/index.d.ts.map +1 -1
  5. package/dist/index.cjs +40 -10
  6. package/dist/index.js +13 -8
  7. package/dist/index.js.map +1 -1
  8. package/dist/query/index.cjs +1 -1
  9. package/dist/{queryBuilder-n9ocnT4P.cjs → queryBuilder-okYHE7jd.cjs} +1 -0
  10. package/dist/utils/index.cjs +1 -0
  11. package/dist/utils/index.d.cts.map +1 -1
  12. package/dist/utils/index.d.ts.map +1 -1
  13. package/package.json +22 -8
  14. package/src/accounts/index.ts +1 -0
  15. package/src/actions/public/buildQuery.ts +6 -0
  16. package/src/actions/public/getBlockTiming.ts +20 -0
  17. package/src/actions/public/getEntity.ts +18 -0
  18. package/src/actions/public/getEntityCount.ts +10 -0
  19. package/src/actions/public/query.ts +13 -0
  20. package/src/actions/public/subscribeEntityEvents.ts +105 -0
  21. package/src/actions/wallet/changeOwnership.ts +40 -0
  22. package/src/actions/wallet/createEntity.ts +45 -0
  23. package/src/actions/wallet/deleteEntity.ts +39 -0
  24. package/src/actions/wallet/extendEntity.ts +41 -0
  25. package/src/actions/wallet/mutateEntities.ts +100 -0
  26. package/src/actions/wallet/updateEntity.ts +47 -0
  27. package/src/chains/index.ts +3 -0
  28. package/src/chains/kaolin.ts +26 -0
  29. package/src/chains/localhost.ts +14 -0
  30. package/src/chains/marketplace.ts +26 -0
  31. package/src/clients/baseClient.ts +9 -0
  32. package/src/clients/createPublicClient.test.ts +22 -0
  33. package/src/clients/createPublicClient.ts +65 -0
  34. package/src/clients/createWalletClient.test.ts +23 -0
  35. package/src/clients/createWalletClient.ts +70 -0
  36. package/src/clients/decorators/arkivPublic.ts +203 -0
  37. package/src/clients/decorators/arkivWallet.ts +250 -0
  38. package/src/consts.ts +2 -0
  39. package/src/index.ts +21 -0
  40. package/src/query/engine.test.ts +288 -0
  41. package/src/query/engine.ts +112 -0
  42. package/src/query/errors.ts +23 -0
  43. package/src/query/index.ts +4 -0
  44. package/src/query/predicate.test.ts +418 -0
  45. package/src/query/predicate.ts +140 -0
  46. package/src/query/queryBuilder.test.ts +537 -0
  47. package/src/query/queryBuilder.ts +209 -0
  48. package/src/query/queryResult.test.ts +270 -0
  49. package/src/query/queryResult.ts +61 -0
  50. package/src/types/attributes.ts +4 -0
  51. package/src/types/entity.ts +36 -0
  52. package/src/types/events.ts +34 -0
  53. package/src/types/index.ts +4 -0
  54. package/src/types/mimeTypes.ts +27 -0
  55. package/src/types/rpcSchema.ts +61 -0
  56. package/src/types/txParams.ts +15 -0
  57. package/src/utils/arkivTransactions.ts +100 -0
  58. package/src/utils/compression.test.ts +32 -0
  59. package/src/utils/compression.ts +48 -0
  60. package/src/utils/entities.ts +23 -0
  61. package/src/utils/expirationTime.ts +13 -0
  62. package/src/utils/index.ts +3 -0
  63. package/src/utils/payload.ts +9 -0
@@ -0,0 +1,61 @@
1
+ import type { Hex, PublicRpcSchema } from "viem"
2
+ import type { MimeType } from "./mimeTypes"
3
+
4
+ export type RpcEntity = {
5
+ key: Hex
6
+ contentType: MimeType
7
+ value: string
8
+ expiresAt: bigint
9
+ owner: Hex
10
+ stringAttributes?: [{ key: string; value: string }]
11
+ numericAttributes?: [{ key: string; value: number }]
12
+ }
13
+
14
+ export type RpcQueryOptions = {
15
+ atBlock?: number
16
+ includeData?: RpcIncludeData
17
+ resultsPerPage?: number
18
+ cursor?: string
19
+ }
20
+
21
+ export type RpcIncludeData = {
22
+ key: boolean
23
+ attributes: boolean
24
+ payload: boolean
25
+ contentType: boolean
26
+ expiration: boolean
27
+ owner: boolean
28
+ }
29
+
30
+ export type ArkivRpcSchema = [
31
+ {
32
+ Method: "golembase_getStorageValue"
33
+ Parameters?: [entityId: Hex]
34
+ ReturnType: string
35
+ },
36
+ {
37
+ Method: "arkiv_query"
38
+ Parameters?: [query: string, queryOptions?: RpcQueryOptions]
39
+ ReturnType: {
40
+ data: [RpcEntity]
41
+ blockNumber: bigint
42
+ cursor: string
43
+ }
44
+ },
45
+ {
46
+ Method: "arkiv_getBlockTiming"
47
+ Parameters?: []
48
+ ReturnType: {
49
+ current_block: bigint
50
+ current_block_time: number
51
+ duration: number
52
+ }
53
+ },
54
+ {
55
+ Method: "arkiv_getEntityCount"
56
+ Parameters?: []
57
+ ReturnType: number
58
+ },
59
+ ]
60
+
61
+ export type PublicArkivRpcSchema = [...PublicRpcSchema, ...ArkivRpcSchema]
@@ -0,0 +1,15 @@
1
+ export type TxParams =
2
+ | {
3
+ gas?: bigint
4
+ nonce?: number
5
+ gasPrice?: bigint
6
+ maxFeePerGas?: never
7
+ maxPriorityFeePerGas?: never
8
+ }
9
+ | {
10
+ gas?: bigint
11
+ nonce?: number
12
+ maxFeePerGas?: bigint
13
+ maxPriorityFeePerGas?: bigint
14
+ gasPrice?: never
15
+ }
@@ -0,0 +1,100 @@
1
+ import { type Hex, toBytes, toHex, toRlp } from "viem"
2
+ import type { ChangeOwnershipParameters } from "../actions/wallet/changeOwnership"
3
+ import type { CreateEntityParameters } from "../actions/wallet/createEntity"
4
+ import type { DeleteEntityParameters } from "../actions/wallet/deleteEntity"
5
+ import type { ExtendEntityParameters } from "../actions/wallet/extendEntity"
6
+ import type { UpdateEntityParameters } from "../actions/wallet/updateEntity"
7
+ import type { ArkivClient } from "../clients/baseClient"
8
+ import type { WalletArkivClient } from "../clients/createWalletClient"
9
+ import { ARKIV_ADDRESS, BLOCK_TIME } from "../consts"
10
+ import type { TxParams } from "../types"
11
+ import { compress } from "./compression"
12
+
13
+ export function opsToTxData({
14
+ creates,
15
+ updates,
16
+ deletes,
17
+ extensions,
18
+ ownershipChanges,
19
+ }: {
20
+ creates?: CreateEntityParameters[]
21
+ updates?: UpdateEntityParameters[]
22
+ deletes?: DeleteEntityParameters[]
23
+ extensions?: ExtendEntityParameters[]
24
+ ownershipChanges?: ChangeOwnershipParameters[]
25
+ }) {
26
+ function formatAttributes<T extends string | number | bigint | boolean>(attribute: {
27
+ key: string
28
+ value: T
29
+ }): [Hex, Hex] {
30
+ return [toHex(attribute.key), toHex(attribute.value)]
31
+ }
32
+
33
+ const payload = [
34
+ //creates
35
+ (creates ?? []).map((item) => [
36
+ toHex(item.expiresIn / BLOCK_TIME),
37
+ toHex(item.contentType),
38
+ toHex(item.payload),
39
+ item.attributes
40
+ .filter((attribute) => typeof attribute.value === "string")
41
+ .map(formatAttributes),
42
+ item.attributes
43
+ .filter((attribute) => typeof attribute.value === "number")
44
+ .map(formatAttributes),
45
+ ]),
46
+ //updates
47
+ (updates ?? []).map((item) => [
48
+ item.entityKey,
49
+ toHex(item.contentType),
50
+ toHex(item.expiresIn / BLOCK_TIME),
51
+ toHex(item.payload),
52
+ item.attributes
53
+ .filter((attribute) => typeof attribute.value === "string")
54
+ .map(formatAttributes),
55
+ item.attributes
56
+ .filter((attribute) => typeof attribute.value === "number")
57
+ .map(formatAttributes),
58
+ ]),
59
+ //deletes
60
+ (deletes ?? []).map((item) => item.entityKey),
61
+ //extends
62
+ (extensions ?? []).map((item) => [item.entityKey, toHex(item.expiresIn / BLOCK_TIME)]),
63
+ //ownershipChanges TODO
64
+ (ownershipChanges ?? []).map((item) => [item.entityKey, item.newOwner]),
65
+ ]
66
+
67
+ console.debug("txData to send as RLP", payload, payload.length)
68
+
69
+ return toRlp(payload)
70
+ }
71
+
72
+ export async function sendArkivTransaction(client: ArkivClient, data: Hex, txParams?: TxParams) {
73
+ if (!client.account) throw new Error("Account required")
74
+ const walletClient = client as WalletArkivClient
75
+
76
+ console.debug("Sending transaction", {
77
+ account: client.account,
78
+ chain: client.chain,
79
+ to: ARKIV_ADDRESS,
80
+ value: 0n,
81
+ data,
82
+ ...txParams,
83
+ })
84
+
85
+ const compressed = await compress(toBytes(data))
86
+ const txHash = await walletClient.sendTransaction({
87
+ account: client.account,
88
+ chain: client.chain,
89
+ to: ARKIV_ADDRESS,
90
+ value: 0n,
91
+ data: toHex(compressed),
92
+ ...txParams,
93
+ })
94
+
95
+ const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash })
96
+
97
+ console.debug("Tx receipt", receipt)
98
+
99
+ return receipt
100
+ }
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from "bun:test"
2
+ import { compress, decompress } from "./compression"
3
+
4
+ describe("compression", () => {
5
+ it("should compress data", async () => {
6
+ const originalData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
7
+ const compressed = await compress(originalData)
8
+
9
+ expect(compressed).toBeInstanceOf(Uint8Array)
10
+ expect(compressed.length).toBeGreaterThan(0)
11
+ // Compressed data should be different from original
12
+ expect(compressed).not.toEqual(originalData)
13
+ })
14
+
15
+ it("should compress data with large payload into smaller size", async () => {
16
+ const originalData = new Uint8Array(1000).fill(1)
17
+ const compressed = await compress(originalData)
18
+
19
+ expect(compressed).toBeInstanceOf(Uint8Array)
20
+ expect(compressed.length).toBeGreaterThan(0)
21
+ expect(compressed.length).toBeLessThan(originalData.length)
22
+ })
23
+
24
+ it("should decompress data", async () => {
25
+ const originalData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
26
+ const compressed = await compress(originalData)
27
+ const decompressed = await decompress(compressed)
28
+
29
+ expect(decompressed).toBeInstanceOf(Uint8Array)
30
+ expect(decompressed).toEqual(originalData)
31
+ })
32
+ })
@@ -0,0 +1,48 @@
1
+ // src/utils/compression.ts
2
+
3
+ import type { BrotliWasmType } from "brotli-wasm"
4
+ import brotliPromise from "brotli-wasm"
5
+
6
+ let brotli: BrotliWasmType | null = null
7
+
8
+ async function getBrotli(): Promise<BrotliWasmType | null> {
9
+ if (brotli) return brotli
10
+
11
+ if (!brotliPromise) {
12
+ console.debug("Importing brotli-wasm")
13
+ try {
14
+ console.debug("Importing brotli-wasm as module")
15
+ brotli = await brotliPromise
16
+ console.debug("Imported brotli-wasm as module", brotli)
17
+ } catch (error) {
18
+ console.error("Error importing brotli-wasm", error)
19
+ console.debug("Importing brotli-wasm as require")
20
+ brotli = require("brotli-wasm")
21
+ console.debug("Imported brotli-wasm as require", brotli)
22
+ }
23
+ }
24
+
25
+ brotli = await brotliPromise
26
+ return brotli
27
+ }
28
+
29
+ export async function compress(data: Uint8Array): Promise<Uint8Array> {
30
+ const brotliInstance = await getBrotli()
31
+ console.debug(`Compressing data (size: ${data.length})`)
32
+ if (!brotliInstance) {
33
+ console.warn("Brotli instance not found, not compressing data")
34
+ return data
35
+ }
36
+ const brotliCompressed = brotliInstance.compress(data)
37
+ console.debug(`Brotli compressed data (size: ${brotliCompressed.length})`)
38
+ return brotliCompressed
39
+ }
40
+
41
+ export async function decompress(data: Uint8Array): Promise<Uint8Array> {
42
+ const brotliInstance = await getBrotli()
43
+ if (!brotliInstance) {
44
+ console.warn("Brotli instance not found, not decompressing data")
45
+ return data
46
+ }
47
+ return brotliInstance.decompress(data)
48
+ }
@@ -0,0 +1,23 @@
1
+ import { toBytes } from "viem"
2
+ import { Entity } from "../types/entity"
3
+ import type { RpcEntity } from "../types/rpcSchema"
4
+
5
+ export async function entityFromRpcResult(rpcEntity: RpcEntity) {
6
+ return new Entity(
7
+ rpcEntity.key,
8
+ rpcEntity.contentType,
9
+ rpcEntity.owner,
10
+ rpcEntity.expiresAt,
11
+ toBytes(rpcEntity.value),
12
+ [
13
+ ...(rpcEntity.stringAttributes ?? []).map(({ key, value }) => ({
14
+ key,
15
+ value,
16
+ })),
17
+ ...(rpcEntity.numericAttributes ?? []).map(({ key, value }) => ({
18
+ key,
19
+ value: Number(value),
20
+ })),
21
+ ],
22
+ )
23
+ }
@@ -0,0 +1,13 @@
1
+ import { BLOCK_TIME } from "../consts"
2
+
3
+ export const ExpirationTime = {
4
+ fromSeconds: (seconds: number) => seconds,
5
+ fromMinutes: (minutes: number) => minutes * 60,
6
+ fromHours: (hours: number) => hours * 60 * 60,
7
+ fromDays: (days: number) => days * 24 * 60 * 60,
8
+ fromWeeks: (weeks: number) => weeks * 7 * 24 * 60 * 60,
9
+ fromMonths: (months: number) => months * 30 * 24 * 60 * 60,
10
+ fromYears: (years: number) => years * 365 * 24 * 60 * 60,
11
+ fromBlocks: (blocks: number) => blocks * BLOCK_TIME,
12
+ fromDate: (date: Date) => Math.floor(date.getTime() / 1000) - Math.floor(Date.now() / 1000),
13
+ }
@@ -0,0 +1,3 @@
1
+ export * from "viem/utils"
2
+ export * from "./expirationTime"
3
+ export * from "./payload"
@@ -0,0 +1,9 @@
1
+ import { toBytes } from "viem"
2
+
3
+ export function jsonToPayload(json: object): Uint8Array {
4
+ return toBytes(JSON.stringify(json))
5
+ }
6
+
7
+ export function stringToPayload(data: string): Uint8Array {
8
+ return toBytes(data)
9
+ }