@arkiv-network/sdk 0.6.8 → 0.7.0-dev.1

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 (101) hide show
  1. package/README.md +52 -16
  2. package/dist/consts-Bz0LZQZY.js +7 -0
  3. package/dist/consts-Bz0LZQZY.js.map +1 -0
  4. package/dist/consts-CxT1-RXU.cjs +18 -0
  5. package/dist/entity-BhSXaB23.cjs +81 -0
  6. package/dist/{query-CO6f35AE.d.cts → entity-CN41IOrq.d.cts} +125 -59
  7. package/dist/entity-CN41IOrq.d.cts.map +1 -0
  8. package/dist/entity-DGfVyB-a.js +71 -0
  9. package/dist/entity-DGfVyB-a.js.map +1 -0
  10. package/dist/{query-BhdmAzYg.d.ts → entity-NnEVlePN.d.ts} +125 -59
  11. package/dist/entity-NnEVlePN.d.ts.map +1 -0
  12. package/dist/index-ClkpS6s_.d.ts +481 -0
  13. package/dist/index-ClkpS6s_.d.ts.map +1 -0
  14. package/dist/index-w4qop0Pe.d.cts +481 -0
  15. package/dist/index-w4qop0Pe.d.cts.map +1 -0
  16. package/dist/index.cjs +285 -233
  17. package/dist/index.d.cts +100 -6
  18. package/dist/index.d.cts.map +1 -1
  19. package/dist/index.d.ts +101 -7
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +280 -230
  22. package/dist/index.js.map +1 -1
  23. package/dist/payload-BpNUPOnY.js +13 -0
  24. package/dist/payload-BpNUPOnY.js.map +1 -0
  25. package/dist/{payload-Da9gJMG5.d.ts → payload-C2KHOUoj.d.ts} +1 -1
  26. package/dist/{payload-Da9gJMG5.d.ts.map → payload-C2KHOUoj.d.ts.map} +1 -1
  27. package/dist/{payload-vwU3Rc6P.cjs → payload-D8YLKcJj.cjs} +1 -18
  28. package/dist/query/index.cjs +11 -28
  29. package/dist/query/index.d.cts +3 -3
  30. package/dist/query/index.d.ts +3 -3
  31. package/dist/query/index.js +8 -28
  32. package/dist/query/index.js.map +1 -1
  33. package/dist/{queryBuilder-DonAg1aq.js → queryBuilder-BE_XhLLa.js} +303 -152
  34. package/dist/queryBuilder-BE_XhLLa.js.map +1 -0
  35. package/dist/{queryBuilder-DM-YO1Y7.cjs → queryBuilder-J37buGCi.cjs} +372 -149
  36. package/dist/types/index.cjs +4 -1
  37. package/dist/types/index.d.cts +2 -2
  38. package/dist/types/index.d.ts +2 -2
  39. package/dist/types/index.js +4 -1
  40. package/dist/utils/index.cjs +4 -10
  41. package/dist/utils/index.d.cts +0 -1
  42. package/dist/utils/index.d.cts.map +1 -1
  43. package/dist/utils/index.d.ts +1 -2
  44. package/dist/utils/index.d.ts.map +1 -1
  45. package/dist/utils/index.js +2 -3
  46. package/dist/utils/index.js.map +1 -1
  47. package/package.json +11 -15
  48. package/src/actions/public/buildQuery.ts +4 -0
  49. package/src/actions/public/query.ts +10 -0
  50. package/src/actions/public/subscribeEntityEvents.ts +25 -51
  51. package/src/actions/wallet/changeOwnership.ts +6 -6
  52. package/src/actions/wallet/createEntity.ts +19 -6
  53. package/src/actions/wallet/deleteEntity.ts +2 -3
  54. package/src/actions/wallet/extendEntity.ts +9 -5
  55. package/src/actions/wallet/mutateEntities.ts +11 -54
  56. package/src/actions/wallet/updateEntity.ts +15 -6
  57. package/src/clients/createPublicClient.test.ts +2 -0
  58. package/src/clients/decorators/arkivPublic.ts +67 -2
  59. package/src/clients/decorators/arkivWallet.ts +23 -1
  60. package/src/consts.ts +2 -1
  61. package/src/errors.ts +46 -0
  62. package/src/index.ts +0 -3
  63. package/src/query/engine.test.ts +45 -0
  64. package/src/query/engine.ts +28 -14
  65. package/src/query/index.ts +1 -0
  66. package/src/query/predicate.test.ts +43 -0
  67. package/src/query/predicate.ts +14 -10
  68. package/src/query/queryBuilder.test.ts +22 -0
  69. package/src/query/queryBuilder.ts +221 -106
  70. package/src/query/queryResult.ts +13 -7
  71. package/src/query/selectQueryBuilder.test.ts +213 -0
  72. package/src/query/selection.test.ts +120 -0
  73. package/src/query/selection.ts +116 -0
  74. package/src/types/attributes.ts +25 -1
  75. package/src/types/entity.ts +12 -2
  76. package/src/types/events.ts +14 -16
  77. package/src/types/index.ts +1 -0
  78. package/src/types/rpcSchema.ts +7 -2
  79. package/src/utils/arkivTransactions.test.ts +260 -0
  80. package/src/utils/arkivTransactions.ts +255 -92
  81. package/src/utils/entities.ts +17 -7
  82. package/src/utils/index.ts +0 -1
  83. package/src/utils/payload.ts +4 -2
  84. package/src/utils/validation.test.ts +106 -0
  85. package/src/utils/validation.ts +80 -0
  86. package/dist/accounts/index.cjs +0 -9
  87. package/dist/accounts/index.d.cts +0 -1
  88. package/dist/accounts/index.d.ts +0 -1
  89. package/dist/accounts/index.js +0 -1
  90. package/dist/payload-DKBYYjeA.js +0 -18
  91. package/dist/payload-DKBYYjeA.js.map +0 -1
  92. package/dist/query-BhdmAzYg.d.ts.map +0 -1
  93. package/dist/query-CO6f35AE.d.cts.map +0 -1
  94. package/dist/queryBuilder-BvoQXa_u.d.ts +0 -328
  95. package/dist/queryBuilder-BvoQXa_u.d.ts.map +0 -1
  96. package/dist/queryBuilder-DonAg1aq.js.map +0 -1
  97. package/dist/queryBuilder-zTsKXctT.d.cts +0 -328
  98. package/dist/queryBuilder-zTsKXctT.d.cts.map +0 -1
  99. package/src/accounts/index.ts +0 -1
  100. /package/dist/{types-H-TSmRpm.js → types-Ci4BRClw.js} +0 -0
  101. /package/dist/{types-o3zWarRp.cjs → types-a8gm_IaQ.cjs} +0 -0
package/dist/index.js CHANGED
@@ -1,19 +1,19 @@
1
1
  import { t as chains_exports } from "./chains-CrtkVbBh.js";
2
- import { a as entityFromRpcResult, c as NoEntityFoundError, l as NoMoreResultsError, o as EntityMutationError, s as NoCursorOrLimitError, t as QueryBuilder, u as getLogger } from "./queryBuilder-DonAg1aq.js";
3
- import { i as BLOCK_TIME, n as stringToPayload, r as ARKIV_ADDRESS, t as jsonToPayload } from "./payload-DKBYYjeA.js";
4
- import "./types-H-TSmRpm.js";
5
- import { TransactionExecutionError, bytesToHex, createClient, decodeEventLog, hexToBytes, hexToString, numberToHex, parseAbi, publicActions, toBytes, toHex, toRlp, walletActions } from "viem";
6
-
7
- export * from "viem"
2
+ import { S as getLogger, _ as InvalidContentTypeError, b as NoEntityFoundError, c as isEntityKey, d as entityFromRpcResult, f as RpcAttributeValueType, g as InvalidAttributeKeyError, h as InvalidAttributeError, l as validateAttribute, m as EntityMutationError, n as QueryBuilder, p as DuplicateAttributeError, r as SelectQueryBuilder, u as validateExpiresIn, v as InvalidExpirationError, x as NoMoreResultsError, y as NoCursorOrLimitError } from "./queryBuilder-BE_XhLLa.js";
3
+ import { n as BLOCK_TIME, t as ARKIV_ADDRESS } from "./consts-Bz0LZQZY.js";
4
+ import { n as EntityOperationType } from "./entity-DGfVyB-a.js";
5
+ import "./types-Ci4BRClw.js";
6
+ import { n as stringToPayload, t as jsonToPayload } from "./payload-BpNUPOnY.js";
7
+ import { ContractFunctionExecutionError, ContractFunctionRevertedError, TransactionExecutionError, bytesToHex, createClient, decodeEventLog, encodePacked, hexToBytes, keccak256, numberToHex, parseAbi, publicActions, stringToBytes, toBytes, toHex, walletActions } from "viem";
8
8
 
9
9
  //#region src/actions/public/getBlockTiming.ts
10
- const logger$9 = getLogger("actions:public:get-block-timing");
10
+ const logger$8 = getLogger("actions:public:get-block-timing");
11
11
  async function getBlockTiming(client) {
12
12
  const blockTiming = await client.request({
13
13
  method: "arkiv_getBlockTiming",
14
14
  params: []
15
15
  });
16
- logger$9("Block timing %o", blockTiming);
16
+ logger$8("Block timing %o", blockTiming);
17
17
  return {
18
18
  currentBlock: BigInt(blockTiming.current_block),
19
19
  currentBlockTime: blockTiming.current_block_time,
@@ -99,78 +99,289 @@ async function query(client, query$1, queryOptions) {
99
99
  }
100
100
 
101
101
  //#endregion
102
- //#region src/actions/public/subscribeEntityEvents.ts
103
- const logger$8 = getLogger("actions:public:subscribe-entity-events");
104
- const arkivABI = parseAbi([
105
- "event ArkivEntityCreated(uint256 indexed entityKey, address indexed ownerAddress, uint256 expirationBlock, uint256 cost)",
106
- "event ArkivEntityUpdated(uint256 indexed entityKey, address indexed ownerAddress, uint256 oldExpirationBlock, uint256 newExpirationBlock, uint256 cost)",
107
- "event ArkivEntityExpired(uint256 indexed entityKey, address indexed ownerAddress)",
108
- "event ArkivEntityDeleted(uint256 indexed entityKey, address indexed ownerAddress)",
109
- "event ArkivEntityBTLExtended(uint256 indexed entityKey, address indexed ownerAddress, uint256 oldExpirationBlock, uint256 newExpirationBlock, uint256 cost)",
110
- "event ArkivEntityOwnerChanged(uint256 indexed entityKey, address indexed oldOwnerAddress, address indexed newOwnerAddress)"
102
+ //#region src/utils/arkivTransactions.ts
103
+ const logger$7 = getLogger("utils:arkiv-transactions");
104
+ const MIME_REGEX = /^[a-z][a-z0-9!#$&\-^_]*\/[a-z0-9][a-z0-9!#$&\-^_.+]*$/;
105
+ function validateContentType(contentType) {
106
+ if (!MIME_REGEX.test(contentType)) throw new InvalidContentTypeError(contentType);
107
+ }
108
+ const ENTITY_EXECUTE_ABI = parseAbi(["function execute((uint8 operationType, bytes32 entityKey, bytes payload, (bytes32[4] data) contentType, (bytes32 name, uint8 valueType, bytes32[4] value)[] attributes, uint32 expiresIn, address newOwner)[] ops) external"]);
109
+ const ENTITY_OPERATION_EVENT_ABI = parseAbi(["event EntityOperation(bytes32 indexed entityKey, uint8 indexed operationType, address indexed owner, uint32 expiresAt, bytes32 entityHash)"]);
110
+ const ENTITY_ERRORS_ABI = parseAbi([
111
+ "error EmptyBatch()",
112
+ "error AttributesNotSorted()",
113
+ "error InvalidValueType(bytes32 name, uint8 valueType)",
114
+ "error InvalidOpType(uint8 operationType)",
115
+ "error ExpiryInPast(uint32 expiresAt, uint32 currentBlock)",
116
+ "error TooManyAttributes(uint256 count, uint256 maxCount)",
117
+ "error EntityNotFound(bytes32 entityKey)",
118
+ "error NotOwner(bytes32 entityKey, address caller, address owner)",
119
+ "error EntityExpired(bytes32 entityKey, uint32 expiresAt)",
120
+ "error ExpiryNotExtended(bytes32 entityKey, uint32 newExpiresAt, uint32 currentExpiresAt)",
121
+ "error TransferToZeroAddress(bytes32 entityKey)",
122
+ "error TransferToSelf(bytes32 entityKey)",
123
+ "error EntityNotExpired(bytes32 entityKey, uint32 expiresAt)",
124
+ "error Ident32Empty()",
125
+ "error Ident32TooLong(uint256 length)",
126
+ "error Ident32InvalidByte(uint256 position, bytes1 value)",
127
+ "error MimeEmpty()",
128
+ "error MimeTooLong(uint256 length, uint256 maxLength)",
129
+ "error MimeInvalidByte(uint256 position, bytes1 value)",
130
+ "error MimeIncomplete()"
111
131
  ]);
132
+ const EXECUTE_ABI = [...ENTITY_EXECUTE_ABI, ...ENTITY_ERRORS_ABI];
133
+ const ENTITY_NONCE_ABI = parseAbi(["function nonces(address owner) view returns (uint32)"]);
134
+ const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
135
+ const ZERO_32 = `0x${"00".repeat(32)}`;
136
+ const EMPTY_BYTES128 = [
137
+ ZERO_32,
138
+ ZERO_32,
139
+ ZERO_32,
140
+ ZERO_32
141
+ ];
142
+ function encodeBytes128(data) {
143
+ const padded = new Uint8Array(128);
144
+ padded.set(data.slice(0, 128));
145
+ return [
146
+ toHex(padded.slice(0, 32)),
147
+ toHex(padded.slice(32, 64)),
148
+ toHex(padded.slice(64, 96)),
149
+ toHex(padded.slice(96, 128))
150
+ ];
151
+ }
152
+ function encodeMime128(contentType) {
153
+ return { data: contentType ? encodeBytes128(stringToBytes(contentType)) : EMPTY_BYTES128 };
154
+ }
155
+ function encodeAttribute(attr) {
156
+ validateAttribute(attr);
157
+ const name = toHex(attr.key, { size: 32 });
158
+ if (typeof attr.value === "string") {
159
+ if (isEntityKey(attr.value)) return {
160
+ name,
161
+ valueType: RpcAttributeValueType.EntityKey,
162
+ value: [
163
+ toHex(toBytes(attr.value), { size: 32 }),
164
+ ZERO_32,
165
+ ZERO_32,
166
+ ZERO_32
167
+ ]
168
+ };
169
+ return {
170
+ name,
171
+ valueType: RpcAttributeValueType.String,
172
+ value: encodeBytes128(stringToBytes(attr.value))
173
+ };
174
+ }
175
+ return {
176
+ name,
177
+ valueType: RpcAttributeValueType.Uint,
178
+ value: [
179
+ toHex(BigInt(attr.value), { size: 32 }),
180
+ ZERO_32,
181
+ ZERO_32,
182
+ ZERO_32
183
+ ]
184
+ };
185
+ }
186
+ function encodeAttributes(attrs) {
187
+ const encoded = attrs.map((attr) => ({
188
+ key: attr.key,
189
+ ...encodeAttribute(attr)
190
+ })).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
191
+ for (let i = 1; i < encoded.length; i++) if (encoded[i].name === encoded[i - 1].name) throw new DuplicateAttributeError(encoded[i].key);
192
+ return encoded.map(({ key: _,...attr }) => attr);
193
+ }
194
+ function toBTL(expiresIn) {
195
+ validateExpiresIn(expiresIn);
196
+ return Math.ceil(expiresIn / BLOCK_TIME);
197
+ }
198
+ function deriveEntityKey(chainId, owner, nonce) {
199
+ return keccak256(encodePacked([
200
+ "uint256",
201
+ "address",
202
+ "address",
203
+ "uint32"
204
+ ], [
205
+ BigInt(chainId),
206
+ ARKIV_ADDRESS,
207
+ owner,
208
+ Number(nonce)
209
+ ]));
210
+ }
211
+ async function sendArkivTransaction(client, ops, txParams) {
212
+ if (!client.account) throw new Error("Account required");
213
+ if (!client.chain) throw new Error("Chain required");
214
+ const walletClient = client;
215
+ const { creates, updates, deletes, extensions, ownershipChanges } = ops;
216
+ const owner = client.account.address;
217
+ const ownerNonce = creates?.length ? BigInt(await walletClient.readContract({
218
+ address: ARKIV_ADDRESS,
219
+ abi: ENTITY_NONCE_ABI,
220
+ functionName: "nonces",
221
+ args: [owner]
222
+ })) : 0n;
223
+ const createdEntityKeys = (creates ?? []).map((_, i) => deriveEntityKey(client.chain.id, owner, ownerNonce + BigInt(i)));
224
+ for (const item of creates ?? []) validateContentType(item.contentType);
225
+ for (const item of updates ?? []) validateContentType(item.contentType);
226
+ const operations = [
227
+ ...(creates ?? []).map((item, i) => ({
228
+ operationType: EntityOperationType.Create,
229
+ entityKey: createdEntityKeys[i],
230
+ payload: toHex(item.payload),
231
+ contentType: encodeMime128(item.contentType),
232
+ attributes: encodeAttributes(item.attributes),
233
+ expiresIn: toBTL(item.expiresIn),
234
+ newOwner: ZERO_ADDRESS
235
+ })),
236
+ ...(updates ?? []).map((item) => ({
237
+ operationType: EntityOperationType.Update,
238
+ entityKey: item.entityKey,
239
+ payload: toHex(item.payload),
240
+ contentType: encodeMime128(item.contentType),
241
+ attributes: encodeAttributes(item.attributes),
242
+ expiresIn: 0,
243
+ newOwner: ZERO_ADDRESS
244
+ })),
245
+ ...(deletes ?? []).map((item) => ({
246
+ operationType: EntityOperationType.Delete,
247
+ entityKey: item.entityKey,
248
+ payload: "0x",
249
+ contentType: encodeMime128(""),
250
+ attributes: [],
251
+ expiresIn: 0,
252
+ newOwner: ZERO_ADDRESS
253
+ })),
254
+ ...(extensions ?? []).map((item) => ({
255
+ operationType: EntityOperationType.Extend,
256
+ entityKey: item.entityKey,
257
+ payload: "0x",
258
+ contentType: encodeMime128(""),
259
+ attributes: [],
260
+ expiresIn: toBTL(item.expiresIn),
261
+ newOwner: ZERO_ADDRESS
262
+ })),
263
+ ...(ownershipChanges ?? []).map((item) => ({
264
+ operationType: EntityOperationType.Transfer,
265
+ entityKey: item.entityKey,
266
+ payload: "0x",
267
+ contentType: encodeMime128(""),
268
+ attributes: [],
269
+ expiresIn: 0,
270
+ newOwner: item.newOwner
271
+ }))
272
+ ];
273
+ logger$7("Sending execute with %d operations %s", operations.length, JSON.stringify(operations));
274
+ try {
275
+ const txHash = await walletClient.writeContract({
276
+ address: ARKIV_ADDRESS,
277
+ abi: EXECUTE_ABI,
278
+ functionName: "execute",
279
+ args: [operations],
280
+ account: client.account,
281
+ chain: client.chain,
282
+ ...txParams
283
+ });
284
+ const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash });
285
+ logger$7("Tx receipt %o", receipt);
286
+ if (receipt.status === "reverted") {
287
+ try {
288
+ await walletClient.simulateContract({
289
+ address: ARKIV_ADDRESS,
290
+ abi: EXECUTE_ABI,
291
+ functionName: "execute",
292
+ args: [operations],
293
+ account: client.account,
294
+ chain: client.chain
295
+ });
296
+ } catch (err) {
297
+ const error = err;
298
+ const reason = error.shortMessage ?? error.cause?.details ?? "No reason provided by backend.";
299
+ throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Reason: ${reason}`);
300
+ }
301
+ throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. No reason provided by backend.`);
302
+ }
303
+ return {
304
+ receipt,
305
+ createdEntityKeys
306
+ };
307
+ } catch (error) {
308
+ let message = "Transaction failed";
309
+ if (error instanceof TransactionExecutionError) message += `: ${error.details}`;
310
+ else if (error instanceof ContractFunctionExecutionError) {
311
+ logger$7("Contract function execution error data:", error.shortMessage);
312
+ if (error.cause instanceof ContractFunctionRevertedError) message += `: ${error.cause.message}`;
313
+ else message += ": Execution error without revert data";
314
+ } else if (error instanceof EntityMutationError) throw error;
315
+ throw new EntityMutationError(message);
316
+ }
317
+ }
318
+
319
+ //#endregion
320
+ //#region src/actions/public/subscribeEntityEvents.ts
321
+ const logger$6 = getLogger("actions:public:subscribe-entity-events");
322
+ const arkivABI = ENTITY_OPERATION_EVENT_ABI;
112
323
  async function subscribeEntityEvents(client, { onError, onEntityCreated, onEntityUpdated, onEntityDeleted, onEntityExpired, onEntityExpiresInExtended, onEntityOwnerChanged }, pollingInterval, fromBlock) {
113
324
  return client.watchEvent({
114
325
  pollingInterval: pollingInterval ?? 1e3,
115
326
  fromBlock,
116
327
  events: arkivABI,
117
328
  onLogs: (logs) => {
118
- logger$8("logs from subscribeEntityEvents %o", logs);
329
+ logger$6("logs from subscribeEntityEvents %o", logs);
119
330
  for (const log of logs) {
120
331
  const event = decodeEventLog({
121
332
  abi: arkivABI,
122
333
  topics: log.topics,
123
334
  data: log.data
124
335
  });
125
- logger$8("event from subscribeEntityEvents %o", event);
126
- switch (event.eventName) {
127
- case "ArkivEntityCreated":
336
+ logger$6("event from subscribeEntityEvents %o", event);
337
+ if (event.eventName !== "EntityOperation") continue;
338
+ const entityKey = event.args.entityKey;
339
+ const owner = event.args.owner;
340
+ const expiresAt = event.args.expiresAt;
341
+ const entityHash = event.args.entityHash;
342
+ switch (Number(event.args.operationType)) {
343
+ case EntityOperationType.Create:
128
344
  onEntityCreated?.({
129
- entityKey: toHex(event.args.entityKey, { size: 32 }),
130
- owner: event.args.ownerAddress,
131
- expirationBlock: Number(event.args.expirationBlock),
132
- cost: event.args.cost
345
+ entityKey,
346
+ owner,
347
+ expiresAt,
348
+ entityHash
133
349
  });
134
350
  break;
135
- case "ArkivEntityUpdated":
351
+ case EntityOperationType.Update:
136
352
  onEntityUpdated?.({
137
- entityKey: toHex(event.args.entityKey, { size: 32 }),
138
- owner: event.args.ownerAddress,
139
- oldExpirationBlock: Number(event.args.oldExpirationBlock),
140
- newExpirationBlock: Number(event.args.newExpirationBlock),
141
- cost: event.args.cost
142
- });
143
- break;
144
- case "ArkivEntityDeleted":
145
- onEntityDeleted?.({
146
- entityKey: toHex(event.args.entityKey, { size: 32 }),
147
- owner: event.args.ownerAddress
353
+ entityKey,
354
+ owner,
355
+ expiresAt,
356
+ entityHash
148
357
  });
149
358
  break;
150
- case "ArkivEntityBTLExtended":
359
+ case EntityOperationType.Extend:
151
360
  onEntityExpiresInExtended?.({
152
- entityKey: toHex(event.args.entityKey, { size: 32 }),
153
- owner: event.args.ownerAddress,
154
- oldExpirationBlock: Number(event.args.oldExpirationBlock),
155
- newExpirationBlock: Number(event.args.newExpirationBlock),
156
- cost: event.args.cost
361
+ entityKey,
362
+ owner,
363
+ expiresAt,
364
+ entityHash
157
365
  });
158
366
  break;
159
- case "ArkivEntityExpired":
160
- onEntityExpired?.({
161
- entityKey: toHex(event.args.entityKey, { size: 32 }),
162
- owner: event.args.ownerAddress
367
+ case EntityOperationType.Transfer:
368
+ onEntityOwnerChanged?.({
369
+ entityKey,
370
+ owner,
371
+ entityHash
163
372
  });
164
373
  break;
165
- case "ArkivEntityOwnerChanged":
166
- onEntityOwnerChanged?.({
167
- entityKey: toHex(event.args.entityKey, { size: 32 }),
168
- oldOwner: event.args.oldOwnerAddress,
169
- newOwner: event.args.newOwnerAddress
374
+ case EntityOperationType.Delete:
375
+ onEntityDeleted?.({
376
+ entityKey,
377
+ owner
170
378
  });
171
379
  break;
172
380
  default:
173
- console.warn("unknown event from subscribeEntityEvents", event);
381
+ onEntityExpired?.({
382
+ entityKey,
383
+ owner
384
+ });
174
385
  break;
175
386
  }
176
387
  }
@@ -189,6 +400,7 @@ function publicArkivActions(client) {
189
400
  getEntity: (key) => getEntity(client, key),
190
401
  query: (rawQuery, queryOptions) => query(client, rawQuery, queryOptions),
191
402
  buildQuery: () => new QueryBuilder(client),
403
+ select: (selection) => new SelectQueryBuilder(client, selection),
192
404
  getBlockTiming: () => getBlockTiming(client),
193
405
  getEntityCount: () => getEntityCount(client),
194
406
  subscribeEntityEvents: ({ onError, onEntityCreated, onEntityUpdated, onEntityDeleted, onEntityExpired, onEntityExpiresInExtended }, pollingInterval, fromBlock) => subscribeEntityEvents(client, {
@@ -232,141 +444,12 @@ function createPublicClient(parameters) {
232
444
  }).extend(publicActions).extend(publicArkivActions);
233
445
  }
234
446
 
235
- //#endregion
236
- //#region src/utils/compression.ts
237
- const logger$7 = getLogger("utils:compression");
238
- const isNode = typeof process !== "undefined" && process.versions?.node != null;
239
- let zlib = null;
240
- let brotli = null;
241
- async function getZlib() {
242
- if (!isNode) return null;
243
- if (!zlib) try {
244
- zlib = await import("zlib");
245
- } catch (error) {
246
- console.error("Error importing zlib", error);
247
- return null;
248
- }
249
- return zlib;
250
- }
251
- async function getBrotli() {
252
- if (brotli) return brotli;
253
- try {
254
- const brotliModule = await import("brotli-wasm");
255
- brotli = brotliModule.default ? await brotliModule.default : brotliModule;
256
- } catch (error) {
257
- console.error("Error importing brotli-wasm", error);
258
- return null;
259
- }
260
- return brotli;
261
- }
262
- async function compress(data) {
263
- logger$7("Compressing data size %d", data.length);
264
- if (isNode) {
265
- const zlibModule = await getZlib();
266
- if (zlibModule) try {
267
- const buffer = Buffer.from(data);
268
- const compressed = zlibModule.brotliCompressSync(buffer);
269
- const result = new Uint8Array(compressed);
270
- logger$7("Brotli compressed with zlib size %d", result.length);
271
- return result;
272
- } catch (error) {
273
- console.warn("zlib compression failed, falling back to brotli-wasm", error);
274
- }
275
- }
276
- const brotliInstance = await getBrotli();
277
- if (!brotliInstance) {
278
- console.warn("Brotli instance not found, not compressing data");
279
- return data;
280
- }
281
- const brotliCompressed = brotliInstance.compress(data);
282
- logger$7("Brotli compressed with wasm size %d", brotliCompressed.length);
283
- return brotliCompressed;
284
- }
285
-
286
- //#endregion
287
- //#region src/utils/arkivTransactions.ts
288
- const logger$6 = getLogger("utils:arkiv-transactions");
289
- function opsToTxData({ creates, updates, deletes, extensions, ownershipChanges }) {
290
- function formatAttributes(attribute) {
291
- return [toHex(attribute.key), toHex(typeof attribute.value === "number" && attribute.value === 0 ? "" : attribute.value)];
292
- }
293
- const payload = [
294
- (creates ?? []).map((item) => [
295
- toHex(Math.ceil(item.expiresIn / BLOCK_TIME)),
296
- toHex(item.contentType),
297
- toHex(item.payload),
298
- item.attributes.filter((attribute) => typeof attribute.value === "string").map(formatAttributes),
299
- item.attributes.filter((attribute) => typeof attribute.value === "number").map(formatAttributes)
300
- ]),
301
- (updates ?? []).map((item) => [
302
- item.entityKey,
303
- toHex(item.contentType),
304
- toHex(Math.ceil(item.expiresIn / BLOCK_TIME)),
305
- toHex(item.payload),
306
- item.attributes.filter((attribute) => typeof attribute.value === "string").map(formatAttributes),
307
- item.attributes.filter((attribute) => typeof attribute.value === "number").map(formatAttributes)
308
- ]),
309
- (deletes ?? []).map((item) => item.entityKey),
310
- (extensions ?? []).map((item) => [item.entityKey, toHex(Math.ceil(item.expiresIn / BLOCK_TIME))]),
311
- (ownershipChanges ?? []).map((item) => [item.entityKey, item.newOwner])
312
- ];
313
- logger$6("txData to send as RLP %o length %d", payload, payload.length);
314
- return toRlp(payload);
315
- }
316
- async function sendArkivTransaction(client, data, txParams) {
317
- if (!client.account) throw new Error("Account required");
318
- const walletClient = client;
319
- logger$6("Sending transaction %o", {
320
- account: client.account,
321
- chain: client.chain,
322
- to: ARKIV_ADDRESS,
323
- value: 0n,
324
- data,
325
- ...txParams
326
- });
327
- try {
328
- const compressed = await compress(toBytes(data));
329
- const txHash = await walletClient.sendTransaction({
330
- account: client.account,
331
- chain: client.chain,
332
- to: ARKIV_ADDRESS,
333
- value: 0n,
334
- data: toHex(compressed),
335
- ...txParams
336
- });
337
- const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash });
338
- logger$6("Tx receipt %o", receipt);
339
- if (receipt.status === "reverted") try {
340
- const callResult = await walletClient.call({
341
- account: client.account,
342
- to: ARKIV_ADDRESS,
343
- value: 0n,
344
- data: toHex(compressed),
345
- ...txParams
346
- });
347
- throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Please make sure the data for entities doesn't contain invalid characters or invalid data types.
348
- Reason: ${callResult.data ? hexToString(callResult.data) : "No reason provided by backend."}`);
349
- } catch (err) {
350
- const reason = err.cause?.details ?? "No reason provided by backend.";
351
- logger$6("Error while calling to get more details about reverted transaction. Reason: %s", reason);
352
- throw new EntityMutationError(`Transaction ${receipt.transactionHash} reverted. Reason: ${reason}`);
353
- }
354
- return receipt;
355
- } catch (error) {
356
- let message = "Transaction failed";
357
- if (error instanceof TransactionExecutionError) message += `: ${error.details}`;
358
- else if (error instanceof EntityMutationError) throw error;
359
- logger$6("%s Detailed error stack: %o", message, error);
360
- throw new EntityMutationError(message);
361
- }
362
- }
363
-
364
447
  //#endregion
365
448
  //#region src/actions/wallet/changeOwnership.ts
366
449
  const logger$5 = getLogger("actions:wallet:change-ownership");
367
450
  async function changeOwnership(client, data, txParams) {
368
451
  logger$5("changeOwnership %o", data);
369
- const receipt = await sendArkivTransaction(client, opsToTxData({ ownershipChanges: [data] }), txParams);
452
+ const { receipt } = await sendArkivTransaction(client, { ownershipChanges: [data] }, txParams);
370
453
  logger$5("Receipt from changeOwnership %o", receipt);
371
454
  return {
372
455
  txHash: receipt.transactionHash,
@@ -379,11 +462,11 @@ async function changeOwnership(client, data, txParams) {
379
462
  const logger$4 = getLogger("actions:wallet:create-entity");
380
463
  async function createEntity(client, data, txParams) {
381
464
  logger$4("createEntity %o", data);
382
- const receipt = await sendArkivTransaction(client, opsToTxData({ creates: [data] }), txParams);
465
+ const { receipt, createdEntityKeys } = await sendArkivTransaction(client, { creates: [data] }, txParams);
383
466
  logger$4("Receipt from createEntity %o", receipt);
384
467
  return {
385
468
  txHash: receipt.transactionHash,
386
- entityKey: receipt.logs[0].topics[1]
469
+ entityKey: createdEntityKeys[0]
387
470
  };
388
471
  }
389
472
 
@@ -392,7 +475,7 @@ async function createEntity(client, data, txParams) {
392
475
  const logger$3 = getLogger("actions:wallet:delete-entity");
393
476
  async function deleteEntity(client, data, txParams) {
394
477
  logger$3("deleteEntity %o", data);
395
- const receipt = await sendArkivTransaction(client, opsToTxData({ deletes: [data] }), txParams);
478
+ const { receipt } = await sendArkivTransaction(client, { deletes: [data] }, txParams);
396
479
  logger$3("Receipt from deleteEntity %o", receipt);
397
480
  return {
398
481
  txHash: receipt.transactionHash,
@@ -405,61 +488,28 @@ async function deleteEntity(client, data, txParams) {
405
488
  const logger$2 = getLogger("actions:wallet:extend-entity");
406
489
  async function extendEntity(client, data, txParams) {
407
490
  logger$2("extendEntity %o", data);
408
- const receipt = await sendArkivTransaction(client, opsToTxData({ extensions: [data] }), txParams);
491
+ const { receipt } = await sendArkivTransaction(client, { extensions: [data] }, txParams);
409
492
  logger$2("Receipt from extendEntity %o", receipt);
410
493
  return {
411
494
  txHash: receipt.transactionHash,
412
- entityKey: receipt.logs[0].topics[1]
495
+ entityKey: data.entityKey
413
496
  };
414
497
  }
415
498
 
416
499
  //#endregion
417
500
  //#region src/actions/wallet/mutateEntities.ts
418
501
  const logger$1 = getLogger("actions:wallet:mutate-entities");
419
- function parseReceipt(receipt, params) {
420
- const createdEntities = [];
421
- const updatedEntities = [];
422
- const deletedEntities = [];
423
- const extendedEntities = [];
424
- const ownershipChanges = [];
425
- const totalCreates = params.creates?.length ?? 0;
426
- const totalUpdates = params.updates?.length ?? 0;
427
- const totalDeletes = params.deletes?.length ?? 0;
428
- const totalExtensions = params.extensions?.length ?? 0;
429
- for (let index = 0; index < receipt.logs.length; index++) {
430
- const log = receipt.logs[index];
431
- if (index < totalCreates) createdEntities.push(log.topics[1]);
432
- else if (index < totalCreates + totalDeletes) deletedEntities.push(log.topics[1]);
433
- else if (index < totalCreates + totalUpdates + totalDeletes) updatedEntities.push(log.topics[1]);
434
- else if (index < totalCreates + totalUpdates + totalDeletes + totalExtensions) extendedEntities.push(log.topics[1]);
435
- else ownershipChanges.push(log.topics[1]);
436
- }
437
- return {
438
- createdEntities,
439
- updatedEntities,
440
- deletedEntities,
441
- extendedEntities,
442
- ownershipChanges
443
- };
444
- }
445
502
  async function mutateEntities(client, data, txParams) {
446
503
  if (!data.creates && !data.updates && !data.deletes && !data.extensions) throw new Error("No operations to perform");
447
- const receipt = await sendArkivTransaction(client, opsToTxData({
448
- creates: data.creates ?? [],
449
- updates: data.updates ?? [],
450
- deletes: data.deletes ?? [],
451
- extensions: data.extensions ?? [],
452
- ownershipChanges: data.ownershipChanges ?? []
453
- }), txParams);
504
+ const { receipt, createdEntityKeys } = await sendArkivTransaction(client, data, txParams);
454
505
  logger$1("Receipt from mutateEntities %o", receipt);
455
- const { createdEntities, updatedEntities, deletedEntities, extendedEntities, ownershipChanges } = parseReceipt(receipt, data);
456
506
  return {
457
507
  txHash: receipt.transactionHash,
458
- createdEntities,
459
- updatedEntities,
460
- deletedEntities,
461
- extendedEntities,
462
- ownershipChanges
508
+ createdEntities: createdEntityKeys,
509
+ updatedEntities: (data.updates ?? []).map((u) => u.entityKey),
510
+ deletedEntities: (data.deletes ?? []).map((d) => d.entityKey),
511
+ extendedEntities: (data.extensions ?? []).map((e) => e.entityKey),
512
+ ownershipChanges: (data.ownershipChanges ?? []).map((o) => o.entityKey)
463
513
  };
464
514
  }
465
515
 
@@ -468,11 +518,11 @@ async function mutateEntities(client, data, txParams) {
468
518
  const logger = getLogger("actions:wallet:update-entity");
469
519
  async function updateEntity(client, data, txParams) {
470
520
  logger("updateEntity %o", data);
471
- const receipt = await sendArkivTransaction(client, opsToTxData({ updates: [data] }), txParams);
521
+ const { receipt } = await sendArkivTransaction(client, { updates: [data] }, txParams);
472
522
  logger("Receipt from updateEntity %o", receipt);
473
523
  return {
474
524
  txHash: receipt.transactionHash,
475
- entityKey: receipt.logs[0].topics[1]
525
+ entityKey: data.entityKey
476
526
  };
477
527
  }
478
528
 
@@ -535,5 +585,5 @@ function chainFromName(name) {
535
585
  }
536
586
 
537
587
  //#endregion
538
- export { EntityMutationError, NoCursorOrLimitError, NoEntityFoundError, NoMoreResultsError, chainFromName, createPublicClient, createWalletClient, jsonToPayload, stringToPayload };
588
+ export { DuplicateAttributeError, EntityMutationError, EntityOperationType, InvalidAttributeError, InvalidAttributeKeyError, InvalidContentTypeError, InvalidExpirationError, NoCursorOrLimitError, NoEntityFoundError, NoMoreResultsError, chainFromName, createPublicClient, createWalletClient, jsonToPayload, stringToPayload };
539
589
  //# sourceMappingURL=index.js.map