@arkiv-network/sdk 0.7.0-dev.1 → 0.8.0-advanced.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.
Files changed (237) hide show
  1. package/README.md +71 -16
  2. package/dist/actions/advanced/index.cjs +13 -0
  3. package/dist/actions/advanced/index.d.cts +8 -0
  4. package/dist/actions/advanced/index.d.ts +9 -0
  5. package/dist/actions/advanced/index.js +9 -0
  6. package/dist/advanced-8ZPTmmaN.js +598 -0
  7. package/dist/advanced-8ZPTmmaN.js.map +1 -0
  8. package/dist/advanced-fPImL6lW.cjs +656 -0
  9. package/dist/arkivTransactions-D74gERHG.d.cts +571 -0
  10. package/dist/arkivTransactions-D74gERHG.d.cts.map +1 -0
  11. package/dist/arkivTransactions-NtGD6uk5.d.ts +571 -0
  12. package/dist/arkivTransactions-NtGD6uk5.d.ts.map +1 -0
  13. package/dist/attr/index.cjs +35 -0
  14. package/dist/attr/index.d.cts +2 -0
  15. package/dist/attr/index.d.ts +3 -0
  16. package/dist/attr/index.js +4 -0
  17. package/dist/attributes-BhY5DwJp.js +809 -0
  18. package/dist/attributes-BhY5DwJp.js.map +1 -0
  19. package/dist/attributes-Df9IsCVs.cjs +1029 -0
  20. package/dist/chains/index.cjs +2 -3
  21. package/dist/chains/index.d.cts +22 -60
  22. package/dist/chains/index.d.cts.map +1 -1
  23. package/dist/chains/index.d.ts +22 -60
  24. package/dist/chains/index.d.ts.map +1 -1
  25. package/dist/chains/index.js +2 -2
  26. package/dist/chains-BJrZs6sG.js +57 -0
  27. package/dist/chains-BJrZs6sG.js.map +1 -0
  28. package/dist/chains-BYRTTipa.cjs +73 -0
  29. package/dist/codec-Car3KkFF.d.ts +102 -0
  30. package/dist/codec-Car3KkFF.d.ts.map +1 -0
  31. package/dist/entity/index.cjs +20 -0
  32. package/dist/entity/index.d.cts +4 -0
  33. package/dist/entity/index.d.ts +5 -0
  34. package/dist/entity/index.js +7 -0
  35. package/dist/entity-B00Li04j.cjs +71 -0
  36. package/dist/entity-B7G8q_Eo.cjs +0 -0
  37. package/dist/entity-BYQR1uoe.js +67 -0
  38. package/dist/entity-BYQR1uoe.js.map +1 -0
  39. package/dist/entity-CD_qFF2M.js +0 -0
  40. package/dist/errors-BVbjKVMN.cjs +56 -0
  41. package/dist/errors-LTe7bOYS.js +33 -0
  42. package/dist/errors-LTe7bOYS.js.map +1 -0
  43. package/dist/expiry-BELY2Kpw.cjs +135 -0
  44. package/dist/expiry-BjpxZZQU.js +95 -0
  45. package/dist/expiry-BjpxZZQU.js.map +1 -0
  46. package/dist/expiry-DRV29F1r.d.cts +79 -0
  47. package/dist/expiry-DRV29F1r.d.cts.map +1 -0
  48. package/dist/expiry-nDbCgZX4.d.ts +79 -0
  49. package/dist/expiry-nDbCgZX4.d.ts.map +1 -0
  50. package/dist/flags-5dTNRnow.d.ts +41 -0
  51. package/dist/flags-5dTNRnow.d.ts.map +1 -0
  52. package/dist/flags-CRjPpoh3.d.cts +41 -0
  53. package/dist/flags-CRjPpoh3.d.cts.map +1 -0
  54. package/dist/flags-DFBs2J94.js +33 -0
  55. package/dist/flags-DFBs2J94.js.map +1 -0
  56. package/dist/flags-kr276q6i.cjs +43 -0
  57. package/dist/index-B5j76711.d.ts +184 -0
  58. package/dist/index-B5j76711.d.ts.map +1 -0
  59. package/dist/index-BF7Mq9Is.d.cts +280 -0
  60. package/dist/index-BF7Mq9Is.d.cts.map +1 -0
  61. package/dist/index-CA4V7Pdh.d.cts +167 -0
  62. package/dist/index-CA4V7Pdh.d.cts.map +1 -0
  63. package/dist/index-CV5zCdpa.d.cts +417 -0
  64. package/dist/index-CV5zCdpa.d.cts.map +1 -0
  65. package/dist/index-DHDud2hC.d.ts +280 -0
  66. package/dist/index-DHDud2hC.d.ts.map +1 -0
  67. package/dist/index-DvYvrkdk.d.ts +320 -0
  68. package/dist/index-DvYvrkdk.d.ts.map +1 -0
  69. package/dist/index-EeUO0nnJ.d.cts +184 -0
  70. package/dist/index-EeUO0nnJ.d.cts.map +1 -0
  71. package/dist/index-fX_XyqLp.d.ts +167 -0
  72. package/dist/index-fX_XyqLp.d.ts.map +1 -0
  73. package/dist/index.cjs +411 -405
  74. package/dist/index.d.cts +360 -209
  75. package/dist/index.d.cts.map +1 -1
  76. package/dist/index.d.ts +361 -209
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +342 -387
  79. package/dist/index.js.map +1 -1
  80. package/dist/key-D1Bh7MF0.js +70 -0
  81. package/dist/key-D1Bh7MF0.js.map +1 -0
  82. package/dist/key-WKhXnXuU.cjs +98 -0
  83. package/dist/logger-CVpvU8ik.js +153 -0
  84. package/dist/logger-CVpvU8ik.js.map +1 -0
  85. package/dist/logger-Cr15lPAQ.cjs +188 -0
  86. package/dist/payload-BNoud2KZ.d.cts +94 -0
  87. package/dist/payload-BNoud2KZ.d.cts.map +1 -0
  88. package/dist/payload-Bz6651ax.js +67 -0
  89. package/dist/payload-Bz6651ax.js.map +1 -0
  90. package/dist/payload-CcUj85ys.d.ts +94 -0
  91. package/dist/payload-CcUj85ys.d.ts.map +1 -0
  92. package/dist/payload-KC14SDlN.cjs +83 -0
  93. package/dist/query/index.cjs +26 -150
  94. package/dist/query/index.d.cts +5 -3
  95. package/dist/query/index.d.ts +6 -3
  96. package/dist/query/index.js +8 -138
  97. package/dist/queryBuilder-DM6AWCBa.js +820 -0
  98. package/dist/queryBuilder-DM6AWCBa.js.map +1 -0
  99. package/dist/queryBuilder-DbUMEZln.cjs +944 -0
  100. package/dist/selection-C4UhsMOO.d.ts +434 -0
  101. package/dist/selection-C4UhsMOO.d.ts.map +1 -0
  102. package/dist/selection-DPg0uyJf.d.cts +433 -0
  103. package/dist/selection-DPg0uyJf.d.cts.map +1 -0
  104. package/dist/types/index.cjs +3 -3
  105. package/dist/types/index.d.cts +7 -2
  106. package/dist/types/index.d.ts +8 -2
  107. package/dist/types/index.js +3 -3
  108. package/dist/types-Bu_ZwMbZ.js +0 -0
  109. package/dist/types-NRqymi6S.cjs +0 -0
  110. package/dist/utils/index.cjs +4 -17
  111. package/dist/utils/index.d.cts +3 -17
  112. package/dist/utils/index.d.ts +3 -17
  113. package/dist/utils/index.js +4 -18
  114. package/package.json +26 -5
  115. package/src/actions/advanced/advanced.test.ts +258 -0
  116. package/src/actions/advanced/buildMutation.ts +104 -0
  117. package/src/actions/advanced/getMutationResult.ts +112 -0
  118. package/src/actions/advanced/index.ts +21 -0
  119. package/src/actions/advanced/pingTransaction.ts +43 -0
  120. package/src/actions/advanced/sendMutation.ts +59 -0
  121. package/src/actions/public/getEntity.ts +27 -43
  122. package/src/actions/public/getEntityNonce.ts +30 -0
  123. package/src/actions/public/predictEntityKeys.test.ts +143 -0
  124. package/src/actions/public/predictEntityKeys.ts +138 -0
  125. package/src/actions/public/query.ts +35 -67
  126. package/src/actions/public/watchEntityEvents.test.ts +414 -0
  127. package/src/actions/public/watchEntityEvents.ts +225 -0
  128. package/src/actions/wallet/changeOwnership.ts +2 -2
  129. package/src/actions/wallet/createEntity.ts +99 -24
  130. package/src/actions/wallet/extendEntity.ts +37 -13
  131. package/src/actions/wallet/mutateEntities.test.ts +76 -0
  132. package/src/actions/wallet/mutateEntities.ts +16 -33
  133. package/src/actions/wallet/patchEntity.ts +90 -0
  134. package/src/attr/attributes.test.ts +120 -0
  135. package/src/attr/attributes.ts +190 -0
  136. package/src/attr/codec.test.ts +162 -0
  137. package/src/attr/codec.ts +220 -0
  138. package/src/attr/decimal.ts +86 -0
  139. package/src/attr/errors.ts +145 -0
  140. package/src/attr/index.ts +50 -0
  141. package/src/attr/names.ts +106 -0
  142. package/src/attr/types.ts +150 -0
  143. package/src/attr/values.test.ts +271 -0
  144. package/src/attr/values.ts +502 -0
  145. package/src/chains/cheesecake.ts +22 -0
  146. package/src/chains/index.ts +1 -2
  147. package/src/clients/createPublicClient.test.ts +3 -5
  148. package/src/clients/createPublicClient.ts +5 -4
  149. package/src/clients/createWalletClient.test.ts +2 -2
  150. package/src/clients/createWalletClient.ts +13 -7
  151. package/src/clients/decorators/arkivAdvanced.ts +144 -0
  152. package/src/clients/decorators/arkivPublic.ts +172 -139
  153. package/src/clients/decorators/arkivWallet.ts +101 -94
  154. package/src/entity/create.test.ts +184 -0
  155. package/src/entity/errors.ts +38 -0
  156. package/src/entity/events.ts +16 -0
  157. package/src/entity/expiry.test.ts +195 -0
  158. package/src/entity/expiry.ts +181 -0
  159. package/src/entity/flags.ts +65 -0
  160. package/src/entity/index.ts +15 -0
  161. package/src/entity/key.ts +68 -0
  162. package/src/entity/operations.ts +134 -0
  163. package/src/entity/params.ts +15 -0
  164. package/src/errors.ts +26 -49
  165. package/src/index.ts +19 -0
  166. package/src/query/engine.ts +68 -137
  167. package/src/query/errors.ts +151 -0
  168. package/src/query/expression.test.ts +286 -0
  169. package/src/query/expression.ts +493 -0
  170. package/src/query/index.ts +40 -4
  171. package/src/query/injection.test.ts +151 -0
  172. package/src/query/queryBuilder.test.ts +342 -637
  173. package/src/query/queryBuilder.ts +133 -359
  174. package/src/query/queryResult.ts +54 -51
  175. package/src/query/selection.test.ts +48 -98
  176. package/src/query/selection.ts +77 -65
  177. package/src/types/entity.test.ts +44 -155
  178. package/src/types/entity.ts +60 -52
  179. package/src/types/events.ts +59 -16
  180. package/src/types/index.ts +20 -17
  181. package/src/types/rpcSchema.ts +69 -37
  182. package/src/utils/arkivTransactions.test.ts +600 -155
  183. package/src/utils/arkivTransactions.ts +350 -219
  184. package/src/utils/chains.test.ts +21 -24
  185. package/src/utils/compression.ts +1 -1
  186. package/src/utils/entities.test.ts +62 -0
  187. package/src/utils/entities.ts +109 -37
  188. package/src/utils/expirationTime.ts +114 -10
  189. package/src/utils/logger.ts +2 -2
  190. package/src/utils/revert.test.ts +99 -0
  191. package/src/utils/revert.ts +145 -0
  192. package/dist/chains-BifaY04V.cjs +0 -108
  193. package/dist/chains-CrtkVbBh.js +0 -86
  194. package/dist/chains-CrtkVbBh.js.map +0 -1
  195. package/dist/consts-Bz0LZQZY.js +0 -7
  196. package/dist/consts-Bz0LZQZY.js.map +0 -1
  197. package/dist/consts-CxT1-RXU.cjs +0 -18
  198. package/dist/entity-BhSXaB23.cjs +0 -81
  199. package/dist/entity-CN41IOrq.d.cts +0 -401
  200. package/dist/entity-CN41IOrq.d.cts.map +0 -1
  201. package/dist/entity-DGfVyB-a.js +0 -71
  202. package/dist/entity-DGfVyB-a.js.map +0 -1
  203. package/dist/entity-NnEVlePN.d.ts +0 -401
  204. package/dist/entity-NnEVlePN.d.ts.map +0 -1
  205. package/dist/index-ClkpS6s_.d.ts +0 -481
  206. package/dist/index-ClkpS6s_.d.ts.map +0 -1
  207. package/dist/index-w4qop0Pe.d.cts +0 -481
  208. package/dist/index-w4qop0Pe.d.cts.map +0 -1
  209. package/dist/payload-BpNUPOnY.js +0 -13
  210. package/dist/payload-BpNUPOnY.js.map +0 -1
  211. package/dist/payload-C2KHOUoj.d.ts +0 -6
  212. package/dist/payload-C2KHOUoj.d.ts.map +0 -1
  213. package/dist/payload-CJN8fTvX.d.cts +0 -6
  214. package/dist/payload-CJN8fTvX.d.cts.map +0 -1
  215. package/dist/payload-D8YLKcJj.cjs +0 -23
  216. package/dist/query/index.js.map +0 -1
  217. package/dist/queryBuilder-BE_XhLLa.js +0 -735
  218. package/dist/queryBuilder-BE_XhLLa.js.map +0 -1
  219. package/dist/queryBuilder-J37buGCi.cjs +0 -865
  220. package/dist/utils/index.d.cts.map +0 -1
  221. package/dist/utils/index.d.ts.map +0 -1
  222. package/dist/utils/index.js.map +0 -1
  223. package/src/actions/public/buildQuery.ts +0 -10
  224. package/src/actions/public/subscribeEntityEvents.ts +0 -93
  225. package/src/actions/wallet/updateEntity.ts +0 -59
  226. package/src/chains/braga.ts +0 -26
  227. package/src/chains/kaolin.ts +0 -29
  228. package/src/query/engine.test.ts +0 -571
  229. package/src/query/predicate.test.ts +0 -461
  230. package/src/query/predicate.ts +0 -144
  231. package/src/query/queryResult.test.ts +0 -270
  232. package/src/query/selectQueryBuilder.test.ts +0 -213
  233. package/src/types/attributes.ts +0 -28
  234. package/src/utils/validation.test.ts +0 -106
  235. package/src/utils/validation.ts +0 -80
  236. /package/dist/{types-Ci4BRClw.js → attr-DlmErkvR.cjs} +0 -0
  237. /package/dist/{types-a8gm_IaQ.cjs → attr-GcQKatub.js} +0 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["logger","bytes: Uint8Array","rpcQueryOptions: RpcQueryOptions","query","logger","ZERO_ADDRESS: Address","AttributeValueType","ownerNonce: bigint","createdEntityKeys: Hex[]","logger","logger","logger","logger","logger","logger","chains"],"sources":["../src/actions/public/getBlockTiming.ts","../src/actions/public/getEntity.ts","../src/actions/public/getEntityCount.ts","../src/actions/public/query.ts","../src/utils/arkivTransactions.ts","../src/actions/public/subscribeEntityEvents.ts","../src/clients/decorators/arkivPublic.ts","../src/clients/createPublicClient.ts","../src/actions/wallet/changeOwnership.ts","../src/actions/wallet/createEntity.ts","../src/actions/wallet/deleteEntity.ts","../src/actions/wallet/extendEntity.ts","../src/actions/wallet/mutateEntities.ts","../src/actions/wallet/updateEntity.ts","../src/clients/decorators/arkivWallet.ts","../src/clients/createWalletClient.ts","../src/utils/chains.ts"],"sourcesContent":["import type { ArkivClient } from \"../../clients/baseClient\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:public:get-block-timing\")\n\nexport type GetBlockTimingReturnType = {\n currentBlock: bigint\n currentBlockTime: number\n blockDuration: number\n}\n\nexport async function getBlockTiming(client: ArkivClient) {\n const blockTiming = await client.request({\n method: \"arkiv_getBlockTiming\",\n params: [],\n })\n logger(\"Block timing %o\", blockTiming)\n return {\n currentBlock: BigInt(blockTiming.current_block),\n currentBlockTime: blockTiming.current_block_time,\n blockDuration: blockTiming.duration,\n }\n}\n","import { bytesToHex, type Hex, hexToBytes } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport { NoEntityFoundError } from \"../../errors\"\nimport { entityFromRpcResult } from \"../../utils/entities\"\n\nexport async function getEntity(client: ArkivClient, key: Hex) {\n // Normalize the key into bytes\n let bytes: Uint8Array\n try {\n bytes = hexToBytes(key)\n } catch {\n throw new Error(`Invalid key format: ${key}. Key must be a valid hex string.`)\n }\n\n if (bytes.length !== 32) {\n throw new Error(\n `Invalid key length: ${bytes.length} bytes. Key must be 32 bytes (64 hex characters) long.`,\n )\n }\n\n const hexKey = bytesToHex(bytes)\n\n const result = await client.request({\n method: \"arkiv_query\",\n params: [\n `$key = ${hexKey}`,\n {\n includeData: {\n key: true,\n attributes: true,\n payload: true,\n contentType: true,\n expiration: true,\n owner: true,\n creator: true,\n createdAtBlock: true,\n lastModifiedAtBlock: true,\n transactionIndexInBlock: true,\n operationIndexInTransaction: true,\n },\n },\n ],\n })\n\n if (!result.data.length) {\n throw new NoEntityFoundError()\n }\n\n return await entityFromRpcResult(result.data[0])\n}\n","import type { ArkivClient } from \"../../clients/baseClient\"\n\nexport async function getEntityCount(client: ArkivClient) {\n const count = await client.request({\n method: \"arkiv_getEntityCount\",\n params: [],\n })\n\n return count\n}\n","import { numberToHex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { Entity } from \"../../types/entity\"\nimport type { RpcQueryOptions } from \"../../types/rpcSchema\"\nimport { entityFromRpcResult } from \"../../utils/entities\"\n\nexport type QueryOptionsIncludeData = {\n attributes?: boolean\n payload?: boolean\n metadata?: boolean\n}\n/**\n * @deprecated Server-side ordering is not supported by the network. Sort the fetched\n * entities in JavaScript instead (e.g. `entities.sort(...)`). This type will be removed\n * in a future release.\n */\nexport type QueryOptionsOrderBy = {\n name: string\n type: \"string\" | \"numeric\"\n desc: \"asc\" | \"desc\"\n}\n\nexport type QueryOptions = {\n includeData?: QueryOptionsIncludeData\n atBlock?: bigint\n /**\n * @deprecated Server-side ordering is not supported by the network, so this option has no\n * effect on the returned order. Sort the fetched entities in JavaScript instead\n * (e.g. `entities.sort(...)`). This option will be removed in a future release.\n */\n orderBy?: QueryOptionsOrderBy[]\n resultsPerPage?: number | undefined\n cursor?: string | undefined\n}\n\nexport type QueryReturnType = {\n entities: Entity[]\n cursor: string | undefined\n blockNumber: bigint | undefined\n}\n\nexport async function query(client: ArkivClient, query: string, queryOptions?: QueryOptions) {\n const rpcQueryOptions: RpcQueryOptions = {\n includeData: {\n key: true,\n payload: queryOptions?.includeData?.payload ?? true,\n attributes: queryOptions?.includeData?.attributes ?? false,\n contentType: queryOptions?.includeData?.metadata ?? false,\n expiration: queryOptions?.includeData?.metadata ?? false,\n owner: queryOptions?.includeData?.metadata ?? false,\n creator: queryOptions?.includeData?.metadata ?? false,\n createdAtBlock: queryOptions?.includeData?.metadata ?? false,\n lastModifiedAtBlock: queryOptions?.includeData?.metadata ?? false,\n transactionIndexInBlock: queryOptions?.includeData?.metadata ?? false,\n operationIndexInTransaction: queryOptions?.includeData?.metadata ?? false,\n },\n ...(queryOptions?.atBlock !== undefined && { atBlock: numberToHex(queryOptions.atBlock) }),\n ...(queryOptions?.orderBy && {\n orderBy: queryOptions?.orderBy.map((order) => ({\n name: order.name,\n type: order.type,\n desc: order.desc === \"desc\",\n })),\n }),\n ...(queryOptions?.resultsPerPage !== undefined && {\n resultsPerPage: numberToHex(queryOptions.resultsPerPage),\n }),\n ...(queryOptions?.cursor !== undefined && { cursor: queryOptions?.cursor }),\n }\n\n const result = await client.request({\n method: \"arkiv_query\",\n params: [query, rpcQueryOptions],\n })\n\n const entities = await Promise.all(result.data.map((entity) => entityFromRpcResult(entity)))\n\n return {\n entities,\n cursor: result.cursor,\n blockNumber: BigInt(result.blockNumber),\n }\n}\n","import {\n type Address,\n ContractFunctionExecutionError,\n ContractFunctionRevertedError,\n encodePacked,\n type Hex,\n keccak256,\n parseAbi,\n stringToBytes,\n TransactionExecutionError,\n type TransactionReceipt,\n toBytes,\n toHex,\n} from \"viem\"\nimport type { ChangeOwnershipParameters } from \"../actions/wallet/changeOwnership\"\nimport type { CreateEntityParameters } from \"../actions/wallet/createEntity\"\nimport type { DeleteEntityParameters } from \"../actions/wallet/deleteEntity\"\nimport type { ExtendEntityParameters } from \"../actions/wallet/extendEntity\"\nimport type { UpdateEntityParameters } from \"../actions/wallet/updateEntity\"\nimport type { ArkivClient } from \"../clients/baseClient\"\nimport type { WalletArkivClient } from \"../clients/createWalletClient\"\nimport { ARKIV_ADDRESS, BLOCK_TIME } from \"../consts\"\nimport { DuplicateAttributeError, EntityMutationError, InvalidContentTypeError } from \"../errors\"\nimport type { TxParams } from \"../types\"\nimport { EntityOperationType } from \"../types/entity\"\nimport { RpcAttributeValueType as AttributeValueType } from \"../types/rpcSchema\"\n\nimport { getLogger } from \"./logger\"\nimport { isEntityKey, validateAttribute, validateExpiresIn } from \"./validation\"\n\nconst logger = getLogger(\"utils:arkiv-transactions\")\n\n// RFC 2045 token chars, lowercase only. Rejects uppercase to prevent text/plain vs Text/Plain ambiguity.\nconst MIME_REGEX = /^[a-z][a-z0-9!#$&\\-^_]*\\/[a-z0-9][a-z0-9!#$&\\-^_.+]*$/\n\nfunction validateContentType(contentType: string): void {\n if (!MIME_REGEX.test(contentType)) {\n throw new InvalidContentTypeError(contentType)\n }\n}\n\n// Mime128 = struct { bytes32[4] data } (128-byte fixed MIME type container)\n// Attribute = struct { bytes32 name, uint8 valueType, bytes32[4] value }\n// BlockNumber = type BlockNumber is uint32\nexport const ENTITY_EXECUTE_ABI = parseAbi([\n \"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\",\n])\n\nexport const ENTITY_OPERATION_EVENT_ABI = parseAbi([\n \"event EntityOperation(bytes32 indexed entityKey, uint8 indexed operationType, address indexed owner, uint32 expiresAt, bytes32 entityHash)\",\n])\n\nexport const ENTITY_ERRORS_ABI = parseAbi([\n \"error EmptyBatch()\",\n \"error AttributesNotSorted()\",\n \"error InvalidValueType(bytes32 name, uint8 valueType)\",\n \"error InvalidOpType(uint8 operationType)\",\n \"error ExpiryInPast(uint32 expiresAt, uint32 currentBlock)\",\n \"error TooManyAttributes(uint256 count, uint256 maxCount)\",\n \"error EntityNotFound(bytes32 entityKey)\",\n \"error NotOwner(bytes32 entityKey, address caller, address owner)\",\n \"error EntityExpired(bytes32 entityKey, uint32 expiresAt)\",\n \"error ExpiryNotExtended(bytes32 entityKey, uint32 newExpiresAt, uint32 currentExpiresAt)\",\n \"error TransferToZeroAddress(bytes32 entityKey)\",\n \"error TransferToSelf(bytes32 entityKey)\",\n \"error EntityNotExpired(bytes32 entityKey, uint32 expiresAt)\",\n \"error Ident32Empty()\",\n \"error Ident32TooLong(uint256 length)\",\n \"error Ident32InvalidByte(uint256 position, bytes1 value)\",\n \"error MimeEmpty()\",\n \"error MimeTooLong(uint256 length, uint256 maxLength)\",\n \"error MimeInvalidByte(uint256 position, bytes1 value)\",\n \"error MimeIncomplete()\",\n])\n\nconst EXECUTE_ABI = [...ENTITY_EXECUTE_ABI, ...ENTITY_ERRORS_ABI]\n\nconst ENTITY_NONCE_ABI = parseAbi([\"function nonces(address owner) view returns (uint32)\"])\n\nconst ZERO_ADDRESS: Address = \"0x0000000000000000000000000000000000000000\"\nconst ZERO_32 = `0x${\"00\".repeat(32)}` as Hex\nconst EMPTY_BYTES128 = [ZERO_32, ZERO_32, ZERO_32, ZERO_32] as const\n\n// Encode a string or bytes into a bytes32[4] (128-byte) container, left-aligned.\nfunction encodeBytes128(data: Uint8Array): readonly [Hex, Hex, Hex, Hex] {\n const padded = new Uint8Array(128)\n padded.set(data.slice(0, 128))\n return [\n toHex(padded.slice(0, 32)),\n toHex(padded.slice(32, 64)),\n toHex(padded.slice(64, 96)),\n toHex(padded.slice(96, 128)),\n ]\n}\n\n// Mime128 struct: bytes32[4] data, string packed left-aligned into 128 bytes.\nfunction encodeMime128(contentType: string): { data: readonly [Hex, Hex, Hex, Hex] } {\n return { data: contentType ? encodeBytes128(stringToBytes(contentType)) : EMPTY_BYTES128 }\n}\n\nfunction encodeAttribute(attr: { key: string; value: Hex | string | number }) {\n validateAttribute(attr)\n const name = toHex(attr.key, { size: 32 })\n\n if (typeof attr.value === \"string\") {\n // Only exact 32-byte hex (an entity key) gets the EntityKey type; shorter or\n // longer hex-looking strings are stored as plain strings so they round-trip\n // unchanged and stay matchable by quoted string queries.\n if (isEntityKey(attr.value)) {\n return {\n name,\n valueType: AttributeValueType.EntityKey,\n value: [toHex(toBytes(attr.value), { size: 32 }), ZERO_32, ZERO_32, ZERO_32] as const,\n }\n }\n return {\n name,\n valueType: AttributeValueType.String,\n // stringToBytes, not toBytes: toBytes hex-decodes hex-looking strings, which\n // would corrupt string values like \"0xab\" instead of UTF-8 encoding them\n value: encodeBytes128(stringToBytes(attr.value)),\n }\n }\n\n return {\n name,\n valueType: AttributeValueType.Uint,\n value: [toHex(BigInt(attr.value), { size: 32 }), ZERO_32, ZERO_32, ZERO_32] as const,\n }\n}\n\n// The registry requires attributes strictly ascending by their bytes32 name — the\n// canonical serialization hashes into the state root, and strict ordering doubles as\n// the uniqueness check (AttributesNotSorted). Sort here so callers can pass any order;\n// duplicates would revert on-chain, so reject them client-side with a clear error.\nfunction encodeAttributes(attrs: { key: string; value: Hex | string | number }[]) {\n const encoded = attrs\n .map((attr) => ({ key: attr.key, ...encodeAttribute(attr) }))\n .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))\n for (let i = 1; i < encoded.length; i++) {\n if (encoded[i].name === encoded[i - 1].name) {\n throw new DuplicateAttributeError(encoded[i].key)\n }\n }\n return encoded.map(({ key: _, ...attr }) => attr)\n}\n\nfunction toBTL(expiresIn: number): number {\n validateExpiresIn(expiresIn)\n return Math.ceil(expiresIn / BLOCK_TIME)\n}\n\n// entityKey = keccak256(chainId || registryAddress || ownerAddress || nonce)\nfunction deriveEntityKey(chainId: number, owner: Address, nonce: bigint): Hex {\n return keccak256(\n encodePacked(\n [\"uint256\", \"address\", \"address\", \"uint32\"],\n [BigInt(chainId), ARKIV_ADDRESS, owner, Number(nonce)],\n ),\n )\n}\n\nexport type SendArkivTransactionResult = {\n receipt: TransactionReceipt\n createdEntityKeys: Hex[]\n}\n\nexport async function sendArkivTransaction(\n client: ArkivClient,\n ops: {\n creates?: CreateEntityParameters[]\n updates?: UpdateEntityParameters[]\n deletes?: DeleteEntityParameters[]\n extensions?: ExtendEntityParameters[]\n ownershipChanges?: ChangeOwnershipParameters[]\n },\n txParams?: TxParams,\n): Promise<SendArkivTransactionResult> {\n if (!client.account) throw new Error(\"Account required\")\n if (!client.chain) throw new Error(\"Chain required\")\n const walletClient = client as WalletArkivClient\n\n const { creates, updates, deletes, extensions, ownershipChanges } = ops\n const owner = client.account.address as Address\n\n const ownerNonce: bigint = creates?.length\n ? BigInt(\n await walletClient.readContract({\n address: ARKIV_ADDRESS,\n abi: ENTITY_NONCE_ABI,\n functionName: \"nonces\",\n args: [owner],\n }),\n )\n : 0n\n\n const createdEntityKeys: Hex[] = (creates ?? []).map((_, i) =>\n deriveEntityKey(client.chain!.id, owner, ownerNonce + BigInt(i)),\n )\n\n for (const item of creates ?? []) validateContentType(item.contentType)\n for (const item of updates ?? []) validateContentType(item.contentType)\n\n const operations = [\n ...(creates ?? []).map((item, i) => ({\n operationType: EntityOperationType.Create,\n entityKey: createdEntityKeys[i],\n payload: toHex(item.payload),\n contentType: encodeMime128(item.contentType),\n attributes: encodeAttributes(item.attributes),\n expiresIn: toBTL(item.expiresIn),\n newOwner: ZERO_ADDRESS,\n })),\n ...(updates ?? []).map((item) => ({\n operationType: EntityOperationType.Update,\n entityKey: item.entityKey,\n payload: toHex(item.payload),\n contentType: encodeMime128(item.contentType),\n attributes: encodeAttributes(item.attributes),\n expiresIn: 0, // contract ignores expiresAt on UPDATE\n newOwner: ZERO_ADDRESS,\n })),\n ...(deletes ?? []).map((item) => ({\n operationType: EntityOperationType.Delete,\n entityKey: item.entityKey,\n payload: \"0x\" as Hex,\n contentType: encodeMime128(\"\"),\n attributes: [] as never[],\n expiresIn: 0,\n newOwner: ZERO_ADDRESS,\n })),\n ...(extensions ?? []).map((item) => ({\n operationType: EntityOperationType.Extend,\n entityKey: item.entityKey,\n payload: \"0x\" as Hex,\n contentType: encodeMime128(\"\"),\n attributes: [] as never[],\n expiresIn: toBTL(item.expiresIn),\n newOwner: ZERO_ADDRESS,\n })),\n ...(ownershipChanges ?? []).map((item) => ({\n operationType: EntityOperationType.Transfer,\n entityKey: item.entityKey,\n payload: \"0x\" as Hex,\n contentType: encodeMime128(\"\"),\n attributes: [] as never[],\n expiresIn: 0,\n newOwner: item.newOwner as Address,\n })),\n ]\n\n logger(\"Sending execute with %d operations %s\", operations.length, JSON.stringify(operations))\n\n try {\n const txHash = await walletClient.writeContract({\n address: ARKIV_ADDRESS,\n abi: EXECUTE_ABI,\n functionName: \"execute\",\n args: [operations],\n account: client.account,\n chain: client.chain,\n ...txParams,\n })\n\n const receipt = await walletClient.waitForTransactionReceipt({ hash: txHash })\n logger(\"Tx receipt %o\", receipt)\n\n if (receipt.status === \"reverted\") {\n try {\n await walletClient.simulateContract({\n address: ARKIV_ADDRESS,\n abi: EXECUTE_ABI,\n functionName: \"execute\",\n args: [operations],\n account: client.account,\n chain: client.chain,\n })\n } catch (err) {\n const error = err as { shortMessage?: string; cause?: { details?: string } }\n const reason =\n error.shortMessage ?? error.cause?.details ?? \"No reason provided by backend.\"\n throw new EntityMutationError(\n `Transaction ${receipt.transactionHash} reverted. Reason: ${reason}`,\n )\n }\n throw new EntityMutationError(\n `Transaction ${receipt.transactionHash} reverted. No reason provided by backend.`,\n )\n }\n\n return { receipt, createdEntityKeys }\n } catch (error) {\n let message = \"Transaction failed\"\n if (error instanceof TransactionExecutionError) {\n message += `: ${error.details}`\n } else if (error instanceof ContractFunctionExecutionError) {\n logger(\"Contract function execution error data:\", error.shortMessage)\n if (error.cause instanceof ContractFunctionRevertedError) {\n message += `: ${error.cause.message}`\n } else {\n message += \": Execution error without revert data\"\n }\n } else if (error instanceof EntityMutationError) {\n throw error\n }\n\n throw new EntityMutationError(message)\n }\n}\n","import { decodeEventLog, type Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { PublicArkivClient } from \"../../clients/createPublicClient\"\nimport { EntityOperationType } from \"../../types/entity\"\nimport type {\n OnEntityCreatedEvent,\n OnEntityDeletedEvent,\n OnEntityExpiredEvent,\n OnEntityExpiresInExtendedEvent,\n OnEntityOwnerChangedEvent,\n OnEntityUpdatedEvent,\n} from \"../../types/events\"\nimport { ENTITY_OPERATION_EVENT_ABI } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:public:subscribe-entity-events\")\n\nexport const arkivABI = ENTITY_OPERATION_EVENT_ABI\n\nexport async function subscribeEntityEvents(\n client: ArkivClient,\n {\n onError,\n onEntityCreated,\n onEntityUpdated,\n onEntityDeleted,\n onEntityExpired,\n onEntityExpiresInExtended,\n onEntityOwnerChanged,\n }: {\n onError: ((error: Error) => void) | undefined\n onEntityCreated?: ((event: OnEntityCreatedEvent) => void) | undefined\n onEntityUpdated?: ((event: OnEntityUpdatedEvent) => void) | undefined\n onEntityDeleted?: ((event: OnEntityDeletedEvent) => void) | undefined\n onEntityExpired?: ((event: OnEntityExpiredEvent) => void) | undefined\n onEntityExpiresInExtended?: ((event: OnEntityExpiresInExtendedEvent) => void) | undefined\n onEntityOwnerChanged?: ((event: OnEntityOwnerChangedEvent) => void) | undefined\n },\n pollingInterval?: number,\n fromBlock?: bigint,\n): Promise<() => void> {\n const unsubscribe = (client as PublicArkivClient).watchEvent({\n pollingInterval: pollingInterval ?? 1000,\n fromBlock,\n events: arkivABI,\n onLogs: (logs) => {\n logger(\"logs from subscribeEntityEvents %o\", logs)\n for (const log of logs) {\n const event = decodeEventLog({\n abi: arkivABI,\n topics: log.topics as [Hex, ...Hex[]] | [],\n data: log.data,\n })\n logger(\"event from subscribeEntityEvents %o\", event)\n\n if (event.eventName !== \"EntityOperation\") continue\n\n const entityKey = event.args.entityKey as Hex\n const owner = event.args.owner\n const expiresAt = event.args.expiresAt\n const entityHash = event.args.entityHash as Hex\n const opType = Number(event.args.operationType)\n\n switch (opType) {\n case EntityOperationType.Create:\n onEntityCreated?.({ entityKey, owner, expiresAt, entityHash })\n break\n case EntityOperationType.Update:\n onEntityUpdated?.({ entityKey, owner, expiresAt, entityHash })\n break\n case EntityOperationType.Extend:\n onEntityExpiresInExtended?.({ entityKey, owner, expiresAt, entityHash })\n break\n case EntityOperationType.Transfer:\n onEntityOwnerChanged?.({ entityKey, owner, entityHash })\n break\n case EntityOperationType.Delete:\n onEntityDeleted?.({ entityKey, owner })\n break\n default:\n onEntityExpired?.({ entityKey, owner })\n break\n }\n }\n },\n onError: (error) => {\n console.error(\"error from subscribeEntityEvents\", error)\n onError?.(error)\n },\n })\n\n return unsubscribe\n}\n","import type { Account, Chain, Client, Hex, PublicActions, Transport } from \"viem\"\nimport { getBlockTiming } from \"../../actions/public/getBlockTiming\"\nimport { getEntity } from \"../../actions/public/getEntity\"\nimport { getEntityCount } from \"../../actions/public/getEntityCount\"\nimport { type QueryOptions, type QueryReturnType, query } from \"../../actions/public/query\"\nimport { subscribeEntityEvents } from \"../../actions/public/subscribeEntityEvents\"\nimport { QueryBuilder, SelectQueryBuilder } from \"../../query/queryBuilder\"\nimport type { EntitySelection, FullEntity, ProjectedEntity, SelectArg } from \"../../query/selection\"\nimport type { Entity } from \"../../types/entity\"\nimport type {\n OnEntityCreatedEvent,\n OnEntityDeletedEvent,\n OnEntityExpiredEvent,\n OnEntityExpiresInExtendedEvent,\n OnEntityUpdatedEvent,\n} from \"../../types/events\"\n\nexport type PublicArkivActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n> = Pick<\n PublicActions<transport, chain, account>,\n | \"getBalance\"\n | \"getBlock\"\n | \"getBlockNumber\"\n | \"getChainId\"\n | \"getLogs\"\n | \"getTransaction\"\n | \"getTransactionCount\"\n | \"getTransactionReceipt\"\n | \"waitForTransactionReceipt\"\n | \"watchEvent\"\n> & {\n /**\n * Returns the entity with the given key.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/public/getEntity\n *\n * @param key - The entity key (hex string)\n * @returns The entity with the given key. {@link Entity}\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n * const entity = await client.getEntity(\"0x123\")\n * // {\n * // key: \"0x123\",\n * // value: \"0x123\",\n * // }\n */\n getEntity: (key: Hex) => Promise<Entity>\n\n /**\n * Returns a SelectQueryBuilder for building and executing queries — the recommended way to\n * read entities. You declare up front which parts of an entity you want returned, so results\n * always contain exactly the data you asked for.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/public/query\n *\n * @param selection - What to include in the results. Omit it (or pass `\"*\"`) to select everything,\n * or pass an object to select specific parts (at least one field is required). Every part is\n * opt-in, including the `key`. The selection is flat — each field maps to an entity field.\n * {@link SelectArg}\n * @returns A SelectQueryBuilder instance for building and executing queries. {@link SelectQueryBuilder}\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n * import { eq } from 'arkiv/query'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n * // select everything\n * await client.select().where(eq(\"category\", \"docs\")).fetch()\n * await client.select(\"*\").where(eq(\"category\", \"docs\")).fetch()\n * // only the key\n * await client.select({ key: true }).where(eq(\"category\", \"docs\")).fetch()\n * // select specific fields — result typed { owner: Hex; attributes: Attribute[] }\n * await client.select({ owner: true, attributes: true }).fetch()\n * // a single field — result typed { owner: Hex }\n * await client.select({ owner: true }).fetch()\n */\n select: {\n /** Select every field. Pass nothing or `\"*\"`; the returned entities contain all fields. */\n (selection?: \"*\"): SelectQueryBuilder<FullEntity>\n /**\n * Pick the entity fields to return. Set the ones you want to `true` (at least one is required);\n * the result is typed to exactly those fields, so reading anything else is a compile error.\n *\n * Available fields: `key`, `owner`, `creator`, `contentType`, `payload`, `attributes`,\n * `expiresAtBlock`, `createdAtBlock`, `lastModifiedAtBlock`, `transactionIndexInBlock`,\n * `operationIndexInTransaction`.\n *\n * Pass the selection inline so its fields stay literal `true`. A selection stored in a `let`/\n * `const` variable widens to `boolean` and the result type can no longer be narrowed — annotate\n * it `as const` (e.g. `const sel = { owner: true } as const`) in that case.\n *\n * @example\n * client.select({ owner: true, attributes: true }) // entities typed { owner, attributes }\n * client.select({ key: true, payload: true }) // includes payload → toText()/toJson() too\n */\n <const S extends EntitySelection>(selection: S): SelectQueryBuilder<ProjectedEntity<S>>\n /**\n * Dynamic selection: accepts a value typed {@link SelectArg} (e.g. built at runtime). The\n * result cannot be narrowed in this case, so the entities are typed as the full entity.\n */\n (selection: SelectArg): SelectQueryBuilder<FullEntity>\n }\n\n /**\n * Returns a QueryBuilder instance for building and executing queries.\n * The QueryBuilder object follows the Builder pattern, allowing you to chain methods to build a query and then execute it.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/public/query\n *\n * @deprecated Use {@link select} instead. `buildQuery()` returns only the entity `key` unless\n * you remember to opt in to data with `withAttributes()`/`withMetadata()`/`withPayload()`, which\n * is an easy mistake. `select()` makes the selection explicit. This method remains for backwards\n * compatibility and will be removed in a future release.\n *\n * @returns A QueryBuilder instance for building and executing queries. {@link QueryBuilder}\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n * const query = client.buildQuery()\n * const entities = await query.where(\"key\", \"=\", \"value\").ownedBy(\"0x123\").fetch()\n *\n */\n buildQuery: () => QueryBuilder\n\n /**\n * Returns a QueryResult instance for fetching the results of a raw query.\n * If no query options are provided, all payload is included, but no metadata (like owner, expiredAt, etc.) and attributes.\n * @param query - The raw query string\n * @param queryOptions - The optional query options - {@link QueryOptions}\n * @returns A QueryReturnType instance - {@link QueryReturnType}\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n * const queryResult = client.query('key = value && $owner = 0x123')\n * // queryResult = { entities: [{ key: \"0x123\", value: \"0x123\" }], cursor: undefined, blockNumber: undefined }\n * const queryResultWithOptions = client.query('key = value && $owner = 0x123', {\n * includeData: {\n * attributes: false,\n * payload: true,\n * metadata: true,\n * },\n * resultsPerPage: 10,\n * cursor: undefined,\n * atBlock: undefined,\n * })\n * // queryResultWithOptions = { entities: [{ key: \"0x123\", value: \"0x123\" }], cursor: \"...\", blockNumber: 32223n }\n */\n query: (query: string, queryOptions?: QueryOptions) => Promise<QueryReturnType>\n\n /**\n * Returns the number of entities in the DBChain.\n * @returns The number of entities in the DBChain\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n * const entityCount = await client.getEntityCount()\n * // entityCount = 0\n */\n getEntityCount: () => Promise<number>\n\n /**\n * Returns the current block timing.\n * @returns The current block timing. {@link GetBlockTimingReturnType}\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n * const blockTiming = await client.getBlockTiming()\n * // {\n * // currentBlock: 10n, // block number\n * // currentBlockTime: 1234567890, // block timestamp\n * // blockDuration: 2, // in seconds\n * // }\n */\n getBlockTiming: () => Promise<{\n currentBlock: bigint\n currentBlockTime: number\n blockDuration: number\n }>\n\n /**\n * Subscribes to entity events.\n * Takes an object with event handlers: {onError, onEntityCreated, onEntityUpdated, onEntityDeleted, onEntityExpiresInExtended}\n * @param pollingInterval - The polling interval in milliseconds\n * @param fromBlock - The block number to start from\n * @returns A function to unsubscribe from the events\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n * const unsubscribe = await client.subscribeEntityEvents({\n * onError: (error) => console.error(\"subscribeEntityEvents error\", error),\n * })\n * unsubscribe() // unsubscribe from the events\n */\n subscribeEntityEvents: (\n {\n onError,\n onEntityCreated,\n onEntityUpdated,\n onEntityDeleted,\n onEntityExpiresInExtended,\n }: {\n onError?: (error: Error) => void\n onEntityCreated?: (event: OnEntityCreatedEvent) => void\n onEntityUpdated?: (event: OnEntityUpdatedEvent) => void\n onEntityDeleted?: (event: OnEntityDeletedEvent) => void\n onEntityExpired?: (event: OnEntityExpiredEvent) => void\n onEntityExpiresInExtended?: (event: OnEntityExpiresInExtendedEvent) => void\n },\n pollingInterval?: number,\n fromBlock?: bigint,\n ) => Promise<() => void>\n}\n\nexport function publicArkivActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n>(client: Client<transport, chain, account>) {\n return {\n getEntity: (key: Hex) => getEntity(client, key),\n query: (rawQuery: string, queryOptions?: QueryOptions) => query(client, rawQuery, queryOptions),\n buildQuery: () => new QueryBuilder(client),\n select: (selection?: SelectArg) => new SelectQueryBuilder(client, selection),\n getBlockTiming: () => getBlockTiming(client),\n getEntityCount: () => getEntityCount(client),\n subscribeEntityEvents: (\n {\n onError,\n onEntityCreated,\n onEntityUpdated,\n onEntityDeleted,\n onEntityExpired,\n onEntityExpiresInExtended,\n }: {\n onError?: (error: Error) => void\n onEntityCreated?: (event: OnEntityCreatedEvent) => void\n onEntityUpdated?: (event: OnEntityUpdatedEvent) => void\n onEntityDeleted?: (event: OnEntityDeletedEvent) => void\n onEntityExpired?: (event: OnEntityExpiredEvent) => void\n onEntityExpiresInExtended?: (event: OnEntityExpiresInExtendedEvent) => void\n },\n pollingInterval?: number,\n fromBlock?: bigint,\n ) =>\n subscribeEntityEvents(\n client,\n {\n onError,\n onEntityCreated,\n onEntityUpdated,\n onEntityDeleted,\n onEntityExpired,\n onEntityExpiresInExtended,\n },\n pollingInterval,\n fromBlock,\n ),\n }\n}\n","import type {\n Account,\n Address,\n Chain,\n Client,\n ParseAccount,\n Prettify,\n PublicClientConfig,\n RpcSchema,\n Transport,\n} from \"viem\"\nimport { createClient, publicActions } from \"viem\"\nimport type { ArkivRpcSchema } from \"../types/rpcSchema\"\nimport { type PublicArkivActions, publicArkivActions } from \"./decorators/arkivPublic\"\n\nexport type PublicArkivClient<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n accountOrAddress extends Account | undefined = undefined,\n rpcSchema extends RpcSchema | undefined = ArkivRpcSchema,\n> = Prettify<\n Client<transport, chain, accountOrAddress, rpcSchema, PublicArkivActions<transport, chain>>\n>\n\n/**\n * Creates a Public Client with a given [Transport](https://viem.sh/docs/clients/intro) configured for a [Chain](https://viem.sh/docs/clients/chains).\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/clients/public\n *\n * A Public Client is an interface to \"public\" [Ethereum JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/), [Arkiv JSON-RPC API](https://docs.arkiv.network/json-rpc/), and [Braga JSON-RPC API](https://braga.holesky.arkiv.network/rpc) methods such as retrieving block numbers, transactions, reading from smart contracts, etc through [Public Actions](/docs/actions/public/introduction).\n *\n * @param parameters - Configuration object for the public client (chain, transport, etc.)\n * @returns A Arkiv Public Client. {@link PublicArkivClient}\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n */\nexport function createPublicClient<\n transport extends Transport,\n chain extends Chain | undefined = undefined,\n accountOrAddress extends Account | Address | undefined = undefined,\n rpcSchema extends RpcSchema | undefined = ArkivRpcSchema,\n>(\n parameters: PublicClientConfig<transport, chain, accountOrAddress, rpcSchema>,\n): PublicArkivClient<transport, chain, ParseAccount<accountOrAddress>, rpcSchema> {\n const { key = \"public\", name = \"Public Client\" } = parameters\n const client = createClient({\n ...parameters,\n key,\n name,\n })\n\n return client.extend(publicActions).extend(publicArkivActions) as unknown as PublicArkivClient<\n transport,\n chain,\n ParseAccount<accountOrAddress>,\n rpcSchema\n >\n}\n","import type { Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:change-ownership\")\n\n/**\n * Parameters for the changeOwnership function.\n * - entityKey: The key of the entity.\n * - newOwner: The address of the new owner.\n */\nexport type ChangeOwnershipParameters = {\n entityKey: Hex\n newOwner: Hex\n}\n\n/**\n * Return type for the changeOwnership function.\n * - entityKey: The key of the entity.\n * - txHash: The transaction hash.\n */\nexport type ChangeOwnershipReturnType = {\n entityKey: Hex\n txHash: string\n}\n\nexport async function changeOwnership(\n client: ArkivClient,\n data: ChangeOwnershipParameters,\n txParams?: TxParams,\n): Promise<ChangeOwnershipReturnType> {\n logger(\"changeOwnership %o\", data)\n const { receipt } = await sendArkivTransaction(client, { ownershipChanges: [data] }, txParams)\n\n logger(\"Receipt from changeOwnership %o\", receipt)\n\n return {\n txHash: receipt.transactionHash,\n entityKey: data.entityKey,\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { Attribute, MimeType, TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:create-entity\")\n\n/**\n * Parameters for the createEntity function.\n * - payload: The payload of the entity.\n * - attributes: The attributes of the entity. Attribute values may be strings\n * or numbers, but numeric values **must be integers**. To store a non-integer,\n * scale it to an integer (e.g. `1.5` -> `1500`) to preserve numeric ordering,\n * or pass it as a string (e.g. `\"1.5\"`). A non-integer numeric value throws an\n * {@link InvalidAttributeError}.\n * - contentType: The content type of the entity.\n * - expiresIn: How long until the entity expires, in seconds. Because Arkiv\n * measures expiration in blocks (1 block = 2 seconds), this **must be a\n * positive integer and a multiple of the block time (2 seconds)**\n * Invalid values throw an {@link InvalidExpirationError}.\n */\nexport type CreateEntityParameters = {\n payload: Uint8Array\n /** Entity attributes. Numeric values must be integers (scale non-integers, e.g. `1.5` -> `1500`, or use a string). Throws {@link InvalidAttributeError} otherwise. */\n attributes: Attribute[]\n contentType: MimeType | string\n /** Seconds until expiry. Must be a positive integer and a multiple of the 2s block time.\n * Throws {@link InvalidExpirationError} otherwise. */\n expiresIn: number\n}\n\n/**\n * Return type for the createEntity function.\n * - entityKey: The key of the entity.\n * - txHash: The transaction hash.\n */\nexport type CreateEntityReturnType = {\n entityKey: Hex\n txHash: Hash\n}\n\nexport async function createEntity(\n client: ArkivClient,\n data: CreateEntityParameters,\n txParams?: TxParams,\n): Promise<CreateEntityReturnType> {\n logger(\"createEntity %o\", data)\n const { receipt, createdEntityKeys } = await sendArkivTransaction(\n client,\n { creates: [data] },\n txParams,\n )\n\n logger(\"Receipt from createEntity %o\", receipt)\n\n return {\n txHash: receipt.transactionHash as Hash,\n entityKey: createdEntityKeys[0],\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:delete-entity\")\n\n/**\n * Parameters for the deleteEntity function.\n * - entityKey: The key of the entity to delete.\n */\nexport type DeleteEntityParameters = {\n entityKey: Hex\n}\n\n/**\n * Return type for the deleteEntity function.\n * - entityKey: The key of the entity.\n * - txHash: The transaction hash.\n */\nexport type DeleteEntityReturnType = {\n entityKey: Hex\n txHash: Hash\n}\n\nexport async function deleteEntity(\n client: ArkivClient,\n data: DeleteEntityParameters,\n txParams?: TxParams,\n): Promise<DeleteEntityReturnType> {\n logger(\"deleteEntity %o\", data)\n const { receipt } = await sendArkivTransaction(client, { deletes: [data] }, txParams)\n\n logger(\"Receipt from deleteEntity %o\", receipt)\n\n return {\n txHash: receipt.transactionHash as Hash,\n entityKey: data.entityKey,\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:extend-entity\")\n\n/**\n * Parameters for the extendEntity function.\n * - entityKey: The key of the entity to extend.\n * - expiresIn: How long to extend the entity by, in seconds. Because Arkiv\n * measures expiration in blocks (1 block = 2 seconds), this **must be a\n * positive integer and a multiple of the block time (2 seconds)**.\n * Invalid values throw an {@link InvalidExpirationError}.\n */\nexport type ExtendEntityParameters = {\n entityKey: Hex\n /** Seconds to extend by. Must be a positive integer and a multiple of the 2s block time.\n * Throws {@link InvalidExpirationError} otherwise. */\n expiresIn: number\n}\n\n/**\n * Return type for the extendEntity function.\n * - entityKey: The key of the entity.\n * - txHash: The transaction hash.\n */\nexport type ExtendEntityReturnType = {\n entityKey: Hex\n txHash: Hash\n}\n\nexport async function extendEntity(\n client: ArkivClient,\n data: ExtendEntityParameters,\n txParams?: TxParams,\n): Promise<ExtendEntityReturnType> {\n logger(\"extendEntity %o\", data)\n const { receipt } = await sendArkivTransaction(client, { extensions: [data] }, txParams)\n\n logger(\"Receipt from extendEntity %o\", receipt)\n\n return {\n txHash: receipt.transactionHash as Hash,\n entityKey: data.entityKey,\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\nimport type { ChangeOwnershipParameters } from \"./changeOwnership\"\nimport type { CreateEntityParameters } from \"./createEntity\"\nimport type { DeleteEntityParameters } from \"./deleteEntity\"\nimport type { ExtendEntityParameters } from \"./extendEntity\"\nimport type { UpdateEntityParameters } from \"./updateEntity\"\n\nconst logger = getLogger(\"actions:wallet:mutate-entities\")\n\n/**\n * Parameters for the mutateEntities function.\n * - creates: The creates to perform.\n * - updates: The updates to perform.\n * - deletes: The deletes to perform.\n * - extensions: The extensions to perform.\n */\nexport type MutateEntitiesParameters = {\n creates?: CreateEntityParameters[]\n updates?: UpdateEntityParameters[]\n deletes?: DeleteEntityParameters[]\n extensions?: ExtendEntityParameters[]\n ownershipChanges?: ChangeOwnershipParameters[]\n}\n\n/**\n * Return type for the mutateEntities function.\n * - txHash: The transaction hash.\n * - createdEntities: The keys of the created entities.\n * - updatedEntities: The keys of the updated entities.\n * - deletedEntities: The keys of the deleted entities.\n * - extendedEntities: The keys of the extended entities.\n * - ownershipChanges: The keys of the ownership changes.\n */\nexport type MutateEntitiesReturnType = {\n txHash: Hash\n createdEntities: Hex[]\n updatedEntities: Hex[]\n deletedEntities: Hex[]\n extendedEntities: Hex[]\n ownershipChanges: Hex[]\n}\n\nexport async function mutateEntities(\n client: ArkivClient,\n data: MutateEntitiesParameters,\n txParams?: TxParams,\n): Promise<MutateEntitiesReturnType> {\n if (!data.creates && !data.updates && !data.deletes && !data.extensions) {\n throw new Error(\"No operations to perform\")\n }\n\n const { receipt, createdEntityKeys } = await sendArkivTransaction(client, data, txParams)\n\n logger(\"Receipt from mutateEntities %o\", receipt)\n\n return {\n txHash: receipt.transactionHash as Hash,\n createdEntities: createdEntityKeys,\n updatedEntities: (data.updates ?? []).map((u) => u.entityKey),\n deletedEntities: (data.deletes ?? []).map((d) => d.entityKey),\n extendedEntities: (data.extensions ?? []).map((e) => e.entityKey),\n ownershipChanges: (data.ownershipChanges ?? []).map((o) => o.entityKey),\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { Attribute, MimeType, TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:update-entity\")\n\n/**\n * Parameters for the updateEntity function.\n * - entityKey: The key of the entity to update.\n * - payload: The payload of the entity.\n * - attributes: The attributes of the entity. Attribute values may be strings\n * or numbers, but numeric values **must be integers**. To store a non-integer,\n * scale it to an integer (e.g. `1.5` -> `1500`) to preserve numeric ordering,\n * or pass it as a string (e.g. `\"1.5\"`). A non-integer numeric value throws an\n * {@link InvalidAttributeError}.\n * - contentType: The content type of the entity.\n * - expiresIn: How long until the entity expires, in seconds. Because Arkiv\n * measures expiration in blocks (1 block = 2 seconds), this **must be a\n * positive integer and a multiple of the block time (2 seconds)**.\n * Invalid values throw an {@link InvalidExpirationError}.\n */\nexport type UpdateEntityParameters = {\n entityKey: Hex\n payload: Uint8Array\n /** Entity attributes. Numeric values must be integers (scale non-integers, e.g. `1.5` -> `1500`, or use a string). Throws {@link InvalidAttributeError} otherwise. */\n attributes: Attribute[]\n contentType: MimeType | string\n /** Seconds until expiry. Must be a positive integer and a multiple of the 2s block time.\n * Throws {@link InvalidExpirationError} otherwise. */\n expiresIn: number\n}\n\n/**\n * Return type for the updateEntity function.\n * - entityKey: The key of the entity.\n * - txHash: The transaction hash.\n */\nexport type UpdateEntityReturnType = {\n entityKey: Hex\n txHash: Hash\n}\n\nexport async function updateEntity(\n client: ArkivClient,\n data: UpdateEntityParameters,\n txParams?: TxParams,\n): Promise<UpdateEntityReturnType> {\n logger(\"updateEntity %o\", data)\n const { receipt } = await sendArkivTransaction(client, { updates: [data] }, txParams)\n\n logger(\"Receipt from updateEntity %o\", receipt)\n\n return {\n txHash: receipt.transactionHash as Hash,\n entityKey: data.entityKey,\n }\n}\n","import type { Account, Chain, Client, PublicActions, Transport, WalletActions } from \"viem\"\nimport type {\n ChangeOwnershipParameters,\n ChangeOwnershipReturnType,\n} from \"../../actions/wallet/changeOwnership\"\nimport { changeOwnership } from \"../../actions/wallet/changeOwnership\"\nimport {\n type CreateEntityParameters,\n type CreateEntityReturnType,\n createEntity,\n} from \"../../actions/wallet/createEntity\"\nimport type {\n DeleteEntityParameters,\n DeleteEntityReturnType,\n} from \"../../actions/wallet/deleteEntity\"\nimport { deleteEntity } from \"../../actions/wallet/deleteEntity\"\nimport type {\n ExtendEntityParameters,\n ExtendEntityReturnType,\n} from \"../../actions/wallet/extendEntity\"\nimport { extendEntity } from \"../../actions/wallet/extendEntity\"\nimport type {\n MutateEntitiesParameters,\n MutateEntitiesReturnType,\n} from \"../../actions/wallet/mutateEntities\"\nimport { mutateEntities } from \"../../actions/wallet/mutateEntities\"\nimport type {\n UpdateEntityParameters,\n UpdateEntityReturnType,\n} from \"../../actions/wallet/updateEntity\"\nimport { updateEntity } from \"../../actions/wallet/updateEntity\"\nimport type { TxParams } from \"../../types\"\n\nexport type WalletArkivActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n> = Pick<\n PublicActions<transport, chain, account>,\n \"waitForTransactionReceipt\" | \"call\" | \"simulateContract\" | \"readContract\" | \"getBlockNumber\"\n> &\n Pick<\n WalletActions<chain, account>,\n | \"addChain\"\n | \"sendCalls\"\n | \"waitForCallsStatus\"\n | \"sendTransaction\"\n | \"sendRawTransaction\"\n | \"signMessage\"\n | \"signTransaction\"\n | \"writeContract\"\n > & {\n /**\n * Creates a new entity.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/createEntity\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The entity creation parameters\n * @param txParams - Optional transaction parameters\n * @returns The created entity with transaction hash\n *\n * @throws {InvalidExpirationError} If `expiresIn` is not a positive integer\n * that is a multiple of the block time (2 seconds).\n * @throws {InvalidAttributeError} If a numeric attribute value is not an\n * integer.\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n * const { entityKey, txHash } = await client.createEntity({\n * payload: toBytes(JSON.stringify({ entity: { entityType: \"testType\", entityId: \"testId\" } })),\n * attributes: [{ key: \"testKey\", value: \"testValue\" }],\n * expiresIn: 1000,\n * })\n * console.log(\"entityKey\", entityKey)\n * console.log(\"txHash\", txHash)\n * // {\n * // entityKey: \"0x123\",\n * // txHash: \"0x123\",\n * // }\n */\n createEntity: (\n data: CreateEntityParameters,\n txParams?: TxParams,\n ) => Promise<CreateEntityReturnType>\n\n /**\n * Updates the entity with the given key.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/updateEntity\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The entity update parameters\n * @param txParams - Optional transaction parameters\n * @returns The updated entity with transaction hash\n *\n * @throws {InvalidExpirationError} If `expiresIn` is not a positive integer\n * that is a multiple of the block time (2 seconds).\n * @throws {InvalidAttributeError} If a numeric attribute value is not an\n * integer.\n *\n * @example\n * import { createWalletClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createWalletClient({\n * chain: braga,\n * transport: http(),\n * })\n */\n updateEntity: (\n data: UpdateEntityParameters,\n txParams?: TxParams,\n ) => Promise<UpdateEntityReturnType>\n\n /**\n * Deletes the entity with the given key.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/deleteEntity\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The entity deletion parameters\n * @param txParams - Optional transaction parameters\n * @returns The deleted entity with transaction hash\n *\n * @example\n * import { createWalletClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createWalletClient({\n * chain: braga,\n * transport: http(),\n * })\n * const { entityKey, txHash } = await client.deleteEntity({ entityKey: \"0x123\" })\n * console.log(\"entityKey\", entityKey)\n * console.log(\"txHash\", txHash)\n * // {\n * // entityKey: \"0x123\",\n * // txHash: \"0x123\",\n * // }\n */\n deleteEntity: (\n data: DeleteEntityParameters,\n txParams?: TxParams,\n ) => Promise<DeleteEntityReturnType>\n\n /**\n * Extends the entity with the given key.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/extendEntity\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The entity update parameters\n * @param txParams - Optional transaction parameters\n * @returns The updated entity with transaction hash\n *\n * @throws {InvalidExpirationError} If `expiresIn` is not a positive integer\n * that is a multiple of the block time (2 seconds).\n *\n * @example\n * import { createWalletClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createWalletClient({\n * chain: braga,\n * transport: http(),\n * })\n * const { entityKey, txHash } = await client.extendEntity(\"0x123\", {\n * expiresIn: 1000,\n * })\n * console.log(\"entityKey\", entityKey)\n * console.log(\"txHash\", txHash)\n * // {\n * // entityKey: \"0x123\",\n * // txHash: \"0x123\",\n * // }\n */\n extendEntity: (\n data: ExtendEntityParameters,\n txParams?: TxParams,\n ) => Promise<ExtendEntityReturnType>\n\n /**\n * Changes the ownership of the entity with the given address.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/changeOwnership\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The ownership change parameters\n * @param txParams - Optional transaction parameters\n * @returns The entity with updated ownership and transaction hash\n */\n changeOwnership: (\n data: ChangeOwnershipParameters,\n txParams?: TxParams,\n ) => Promise<ChangeOwnershipReturnType>\n\n /**\n * Mutates the entities with the given keys.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/mutateEntities\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The mutation parameters (creates, updates, deletes, extensions)\n * @param txParams - Optional transaction parameters\n * @returns The mutation result with transaction hash\n *\n * @throws {InvalidExpirationError} If any create/update/extension `expiresIn`\n * is not a positive integer that is a multiple of the block time (2 seconds).\n * @throws {InvalidAttributeError} If a numeric attribute value is not an\n * integer.\n *\n * @example\n * import { createWalletClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createWalletClient({\n * chain: braga,\n * transport: http(),\n * })\n * const { entityKey, txHash } = await client.mutateEntities({\n * creates: [{\n * payload: toBytes(JSON.stringify({ entity: { entityType: \"testType\", entityId: \"testId\" } })),\n * attriubutes: [{ key: \"testKey\", value: \"testValue\" }],\n * expiresIn: 1000,\n * }],\n * updates: [{\n * entityKey: \"0x123\",\n * payload: toBytes(JSON.stringify({ entity: { entityType: \"testType\", entityId: \"testId\" } })),\n * attributes: [{ key: \"testKey\", value: \"testValue\" }],\n * expiresIn: 1000,\n * }],\n * deletes: [{\n * entityKey: \"0x321\",\n * }],\n * extensions: [{\n * entityKey: \"0x1234\",\n * expiresIn: 1000,\n * }],\n * })\n * console.log(\"entityKey\", entityKey)\n * console.log(\"txHash\", txHash)\n * // {\n * // entityKey: \"0x123\",\n * // txHash: \"0x123\",\n * // }\n */\n mutateEntities: (\n data: MutateEntitiesParameters,\n txParams?: TxParams,\n ) => Promise<MutateEntitiesReturnType>\n }\n\nexport function walletArkivActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n>(client: Client<transport, chain, account>) {\n return {\n createEntity: (data: CreateEntityParameters, txParams?: TxParams) =>\n createEntity(client, data, txParams),\n updateEntity: (data: UpdateEntityParameters, txParams?: TxParams) =>\n updateEntity(client, data, txParams),\n deleteEntity: (data: DeleteEntityParameters, txParams?: TxParams) =>\n deleteEntity(client, data, txParams),\n extendEntity: (data: ExtendEntityParameters, txParams?: TxParams) =>\n extendEntity(client, data, txParams),\n changeOwnership: (data: ChangeOwnershipParameters, txParams?: TxParams) =>\n changeOwnership(client, data, txParams),\n mutateEntities: (data: MutateEntitiesParameters, txParams?: TxParams) =>\n mutateEntities(client, data, txParams),\n }\n}\n","import type {\n Account,\n Address,\n Chain,\n Client,\n ParseAccount,\n Prettify,\n RpcSchema,\n Transport,\n WalletClientConfig,\n} from \"viem\"\nimport { createClient, publicActions, walletActions } from \"viem\"\nimport type { ArkivRpcSchema } from \"../types/rpcSchema\"\nimport { type WalletArkivActions, walletArkivActions } from \"./decorators/arkivWallet\"\n\nexport type WalletArkivClient<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n rpcSchema extends RpcSchema | undefined = ArkivRpcSchema,\n> = Prettify<\n Client<transport, chain, account, rpcSchema, WalletArkivActions<transport, chain, account>>\n>\n\n/**\n * Creates a Public Client with a given [Transport](https://viem.sh/docs/clients/intro) configured for a [Chain](https://viem.sh/docs/clients/chains).\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/clients/public\n *\n * A Public Client is an interface to \"public\" [Ethereum JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/), [Arkiv JSON-RPC API](https://docs.arkiv.network/json-rpc/), and [Braga JSON-RPC API](https://braga.holesky.arkiv.network/rpc) methods such as retrieving block numbers, transactions, reading from smart contracts, etc through [Public Actions](/docs/actions/public/introduction).\n *\n * @param parameters - Configuration object for the wallet client (chain, transport, account, etc.)\n * @returns A Arkiv Wallet Client. {@link WalletArkivClient}\n *\n * @example\n * import { createPublicClient, http } from 'arkiv'\n * import { braga } from 'arkiv/chains'\n *\n * const client = createPublicClient({\n * chain: braga,\n * transport: http(),\n * })\n */\nexport function createWalletClient<\n transport extends Transport,\n chain extends Chain | undefined = undefined,\n accountOrAddress extends Account | Address | undefined = undefined,\n rpcSchema extends RpcSchema | undefined = ArkivRpcSchema,\n>(\n parameters: WalletClientConfig<transport, chain, accountOrAddress, rpcSchema>,\n): WalletArkivClient<transport, chain, ParseAccount<accountOrAddress>, rpcSchema> {\n const { key = \"wallet\", name = \"Wallet Client\" } = parameters\n const client = createClient({\n ...parameters,\n key,\n name,\n })\n\n return client\n .extend(publicActions)\n .extend(walletActions)\n .extend(walletArkivActions) as unknown as WalletArkivClient<\n transport,\n chain,\n ParseAccount<accountOrAddress>,\n rpcSchema\n >\n}\n","import type { Chain } from \"viem\"\nimport * as chains from \"../chains\"\n\n// Create a lookup map from all exported chains\nconst chainMap = new Map(Object.entries(chains).map(([key, value]) => [key.toLowerCase(), value]))\n\n/**\n * Get a chain from its name\n * @param name - The name of the chain, case insensitive\n * @returns The chain\n * @throws An error if the chain is not found\n */\nexport function chainFromName(name: string): Chain {\n const chain = chainMap.get(name.toLowerCase())\n if (!chain) {\n throw new Error(`Unknown chain: ${name}`)\n }\n return chain as Chain\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["logger","logger","query","logger","context: EntityEventContext","event: EntityEvent","key","logger","logger","logger","logger","logger","chains","key"],"sources":["../src/actions/public/getBlockTiming.ts","../src/actions/public/getEntity.ts","../src/actions/public/getEntityCount.ts","../src/actions/public/getEntityNonce.ts","../src/actions/public/predictEntityKeys.ts","../src/actions/public/query.ts","../src/actions/public/watchEntityEvents.ts","../src/clients/decorators/arkivAdvanced.ts","../src/clients/decorators/arkivPublic.ts","../src/clients/createPublicClient.ts","../src/actions/wallet/changeOwnership.ts","../src/actions/wallet/createEntity.ts","../src/actions/wallet/deleteEntity.ts","../src/actions/wallet/extendEntity.ts","../src/actions/wallet/mutateEntities.ts","../src/actions/wallet/patchEntity.ts","../src/clients/decorators/arkivWallet.ts","../src/clients/createWalletClient.ts","../src/utils/chains.ts"],"sourcesContent":["import type { ArkivClient } from \"../../clients/baseClient\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:public:get-block-timing\")\n\nexport type GetBlockTimingReturnType = {\n currentBlock: bigint\n currentBlockTime: number\n blockDuration: number\n}\n\nexport async function getBlockTiming(client: ArkivClient) {\n const blockTiming = await client.request({\n method: \"arkiv_getBlockTiming\",\n params: [],\n })\n logger(\"Block timing %o\", blockTiming)\n return {\n currentBlock: BigInt(blockTiming.current_block),\n currentBlockTime: blockTiming.current_block_time,\n blockDuration: blockTiming.duration,\n }\n}\n","import type { Hex } from \"viem\"\nimport { key } from \"../../attr\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport { NoEntityFoundError } from \"../../errors\"\nimport { runQuery } from \"../../query/engine\"\nimport { eq } from \"../../query/expression\"\nimport { type FullEntity, toRpcSelect } from \"../../query/selection\"\n\n/**\n * Reads one entity by key, with every field selected.\n *\n * Returns a {@link FullEntity} rather than an {@link Entity}: the selection is fixed at `\"*\"`, so\n * every field is populated and none of them needs a `?` at the call site. The bare `Entity` type\n * has every field optional because a `select()` result carries only what it asked for.\n *\n * @throws {InvalidValueError} If the key is not 32 bytes.\n * @throws {NoEntityFoundError} If no live entity has that key — it never existed, or it was\n * deleted or has expired.\n */\nexport async function getEntity(client: ArkivClient, entityKey: Hex): Promise<FullEntity> {\n const { entities } = await runQuery(client, {\n query: eq(\"$key\", key(entityKey)).toString(),\n select: toRpcSelect(\"*\"),\n limit: 1,\n })\n\n const entity = entities[0]\n if (entity === undefined) {\n throw new NoEntityFoundError(entityKey)\n }\n // Every field was selected, so the runtime Entity carries them all; the cast is the same\n // narrowing `client.select(\"*\")` gets from its own inference.\n return entity as unknown as FullEntity\n}\n","import type { ArkivClient } from \"../../clients/baseClient\"\n\nexport async function getEntityCount(client: ArkivClient) {\n const count = await client.request({\n method: \"arkiv_getEntityCount\",\n params: [],\n })\n\n return count\n}\n","import type { Address } from \"viem\"\nimport { readContract } from \"viem/actions\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport { ARKIV_ADDRESS } from \"../../consts\"\nimport { ENTITY_NONCE_ABI } from \"../../entity/operations\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:public:get-entity-nonce\")\n\n/**\n * Reads an owner's entity-minting nonce — how many entities that account has created.\n *\n * This is not the account's transaction nonce. The engine keeps a separate counter per creator and\n * mixes it into every key it mints, which is what makes two identical creates from one account land\n * on different keys.\n *\n * @param owner - The account whose nonce to read.\n * @returns The number of entities `owner` has created so far, which is the nonce its next create\n * will use.\n */\nexport async function getEntityNonce(client: ArkivClient, owner: Address): Promise<bigint> {\n const nonce = await readContract(client, {\n address: ARKIV_ADDRESS,\n abi: ENTITY_NONCE_ABI,\n functionName: \"entityNonce\",\n args: [owner],\n })\n logger(\"entity nonce of %s is %s\", owner, nonce)\n return nonce\n}\n","import type { Address, Hex } from \"viem\"\nimport { getChainId } from \"viem/actions\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport { predictEntityKey, randomSalt, validateSalt } from \"../../entity/key\"\nimport { getEntityNonce } from \"./getEntityNonce\"\n\n/**\n * A key a create will be given, together with the salt that mints it.\n *\n * The two travel as a pair because neither is any use alone: a create defaults to a *random* salt,\n * so the key only comes out as predicted if that same create carries this salt.\n */\nexport type PredictedEntityKey = {\n /** The key the create will be given. */\n key: Hex\n /** The salt the create must carry for its key to come out as {@link PredictedEntityKey.key}. */\n salt: bigint\n}\n\n/** Parameters for {@link predictEntityKeys}. */\nexport type PredictEntityKeysParameters<\n TCount extends number = number,\n TSalts extends readonly bigint[] | undefined = readonly bigint[] | undefined,\n> = {\n /** The account that will sign the creates. Its nonce is what the keys are derived from. */\n owner: Address\n /**\n * How many creates the batch will carry. Ignored when `salts` is given, which already says how\n * many there are.\n *\n * A literal count comes back as a fixed-length tuple, so `count: 2` destructures into two named\n * pairs without a cast.\n */\n count?: TCount | undefined\n /**\n * The salt each create will carry, in batch order. Defaults to `count` fresh random salts —\n * either way each key comes back paired with the salt that mints it.\n */\n salts?: TSalts\n}\n\n/**\n * The keys a batch would mint, in batch order, each paired with its salt.\n *\n * The length follows the request whenever it is known statically: a literal `count`, or a `salts`\n * tuple, gives a fixed-length tuple; a count computed at runtime gives a plain array.\n *\n * `TSalts` is wrapped in a tuple to stop the conditional distributing over it. Left naked, the\n * `readonly bigint[] | undefined` default would take both branches and union a tuple with an array,\n * which widens the length straight back to `number`.\n */\nexport type PredictEntityKeysReturnType<\n TCount extends number = number,\n TSalts extends readonly bigint[] | undefined = readonly bigint[] | undefined,\n> = [TSalts] extends [readonly bigint[]]\n ? { -readonly [Index in keyof TSalts]: PredictedEntityKey }\n : Repeat<PredictedEntityKey, TCount>\n\n/**\n * A tuple of `TLength` × `T`, or a plain array when the length is only known at runtime.\n *\n * Written tail-recursively so TypeScript can build the batch sizes anyone would actually send.\n */\ntype Repeat<T, TLength extends number, TAcc extends T[] = []> = number extends TLength\n ? T[]\n : TAcc[\"length\"] extends TLength\n ? TAcc\n : Repeat<T, TLength, [...TAcc, T]>\n\n/**\n * Works out the keys an account's next creates will be given, before sending them.\n *\n * A key is `keccak256(chainId ++ registry ++ owner ++ nonce ++ salt)`. Everything but the nonce is\n * known to the caller, and the nonce is read here — so a batch can reference a key it is about to\n * mint, storing it as a `key` attribute on a sibling entity created in the same transaction.\n *\n * Each key arrives paired with its salt, and the create must be given that salt: a create left to\n * pick its own salt picks a random one, which mints a different key.\n *\n * The prediction is valid only while nothing else from this owner is in flight. Every create that\n * lands first takes the nonce with it and moves these keys. For a key you can rely on\n * unconditionally, read it back from the create instead — `createEntity` and `mutateEntities`\n * report the keys the engine actually minted.\n *\n * @param parameters - Owner, and either a count or the salts. {@link PredictEntityKeysParameters}\n * @returns One `{ key, salt }` pair per create, in batch order. {@link PredictEntityKeysReturnType}\n *\n * @example A batch whose second entity points at its first.\n * import { key } from \"@arkiv-network/sdk/attr\"\n *\n * const [parent, child] = await client.predictEntityKeys({ owner: account.address, count: 2 })\n * await wallet.mutateEntities({\n * creates: [\n * { payload, contentType, expires, salt: parent.salt },\n * {\n * payload,\n * contentType,\n * expires,\n * salt: child.salt,\n * attributes: { parent: key(parent.key) },\n * },\n * ],\n * })\n */\nexport async function predictEntityKeys<\n const TCount extends number = number,\n const TSalts extends readonly bigint[] | undefined = undefined,\n>(\n client: ArkivClient,\n { owner, count, salts }: PredictEntityKeysParameters<TCount, TSalts>,\n): Promise<PredictEntityKeysReturnType<TCount, TSalts>> {\n const resolvedSalts = resolveSalts(count, salts)\n\n const chainId = client.chain?.id ?? (await getChainId(client))\n const nonce = await getEntityNonce(client, owner)\n\n return resolvedSalts.map((salt, index) => ({\n key: predictEntityKey({ owner, nonce: nonce + BigInt(index), salt, chainId }),\n salt,\n })) as PredictEntityKeysReturnType<TCount, TSalts>\n}\n\n/** The salts to derive from: the ones given, or `count` fresh random ones. */\nfunction resolveSalts(count: number | undefined, salts: readonly bigint[] | undefined): bigint[] {\n if (salts !== undefined) {\n if (salts.length === 0) {\n throw new Error(\"predictEntityKeys: `salts` is empty — there is nothing to predict\")\n }\n return salts.map(validateSalt)\n }\n if (count === undefined) {\n throw new Error(\"predictEntityKeys: pass either `count` or `salts`\")\n }\n if (!Number.isInteger(count) || count <= 0) {\n throw new Error(`predictEntityKeys: \\`count\\` must be a positive whole number, got ${count}`)\n }\n return Array.from({ length: count }, () => randomSalt())\n}\n","import type { ArkivClient } from \"../../clients/baseClient\"\nimport { runQuery } from \"../../query/engine\"\nimport type { Expression } from \"../../query/expression\"\nimport { type SelectArg, toRpcSelect } from \"../../query/selection\"\nimport type { Entity } from \"../../types/entity\"\n\nexport type QueryOptions = {\n /** What to return. Defaults to everything. */\n select?: SelectArg | undefined\n /** Block height to read at. Defaults to the head. */\n atBlock?: bigint | undefined\n /** Page size, up to the node maximum of 200. */\n limit?: number | undefined\n /**\n * Cursor from a previous page. Requires that page's `blockNumber` as {@link atBlock} alongside\n * it — the cursor is bound to the block it was issued at, so persist the two together. A cursor\n * without a block is rejected locally rather than left to fail whenever a block lands mid-walk.\n */\n cursor?: string | undefined\n}\n\nexport type QueryReturnType = {\n entities: Entity[]\n /** The cursor for the next page, or `undefined` when no pages remain. */\n cursor: string | undefined\n /** The block the page was read at. */\n blockNumber: bigint\n}\n\n/**\n * Runs a single query and returns one page, with no builder in between.\n *\n * Takes either an {@link Expression} or a raw query string. The string form is an escape hatch for\n * a query built elsewhere — it goes to the node exactly as written, with none of the name, type or\n * operator checks the expression combinators apply.\n *\n * @throws {QueryError} If the node rejects the query.\n */\nexport function query(\n client: ArkivClient,\n query: Expression | string,\n options: QueryOptions = {},\n): Promise<QueryReturnType> {\n return runQuery(client, {\n query: query.toString(),\n select: toRpcSelect(options.select),\n limit: options.limit,\n cursor: options.cursor,\n atBlock: options.atBlock,\n })\n}\n","import { decodeEventLog, type Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { PublicArkivClient } from \"../../clients/createPublicClient\"\nimport { ARKIV_ADDRESS, BLOCK_TIME } from \"../../consts\"\nimport { ENTITY_EVENTS_ABI } from \"../../entity/events\"\nimport { decodeCreationFlags } from \"../../entity/flags\"\nimport type {\n EntityCreatedEvent,\n EntityDeletedEvent,\n EntityEvent,\n EntityEventContext,\n EntityPatchedEvent,\n ExpiryExtendedEvent,\n OwnershipTransferredEvent,\n} from \"../../types/events\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:public:watch-entity-events\")\n\n/**\n * How often to poll, when the caller does not say.\n *\n * Half a block: fast enough that an event is never a whole block stale, slow enough not to hammer\n * the node. viem's own default is derived from a 12-second Ethereum block and is far too slow here.\n */\nconst DEFAULT_POLLING_INTERVAL = (BLOCK_TIME * 1000) / 2\n\n/**\n * Handlers and options for `client.watchEntityEvents`. Every handler is optional; the watcher does\n * the work for the ones you pass.\n */\nexport type WatchEntityEventsParameters = {\n onEntityCreated?: ((event: EntityCreatedEvent) => void) | undefined\n onEntityPatched?: ((event: EntityPatchedEvent) => void) | undefined\n onExpiryExtended?: ((event: ExpiryExtendedEvent) => void) | undefined\n onOwnershipTransferred?: ((event: OwnershipTransferredEvent) => void) | undefined\n onEntityDeleted?: ((event: EntityDeletedEvent) => void) | undefined\n /**\n * Every event, in application order, whatever its type. Runs *before* the per-event handler for\n * the same event.\n *\n * This is the replay seam: operations apply in batch order and emit one event each, so an\n * off-chain replica that consumes this in order sees exactly what the engine did.\n */\n onEvent?: ((event: EntityEvent) => void) | undefined\n /**\n * Transport failures, logs that will not decode, and anything one of your own handlers throws.\n *\n * Defaults to `console.error`. A watcher whose filter the node dropped otherwise just goes quiet,\n * and a quiet watcher is indistinguishable from a quiet chain.\n */\n onError?: ((error: Error) => void) | undefined\n /** Replay from this block before following the head. Defaults to the head. */\n fromBlock?: bigint | undefined\n /** How often to poll, in milliseconds. Defaults to half a block. */\n pollingInterval?: number | undefined\n}\n\n/**\n * Watches entity events, calling the handlers you pass as they arrive.\n *\n * Every event here is decoded from a log the Arkiv operation address emitted, and carries the\n * block, transaction and log index it came from — so consuming them in order replays exactly what\n * the engine did.\n *\n * @param parameters - Handlers and options. {@link WatchEntityEventsParameters}\n * @returns A function that stops the watcher.\n *\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({ chain: cheesecake, transport: http() })\n *\n * const unwatch = client.watchEntityEvents({\n * onEntityCreated: ({ entityKey, owner, expiresAt }) =>\n * console.log(\"created\", entityKey, \"by\", owner, \"until block\", expiresAt),\n * onEntityDeleted: ({ entityKey }) => console.log(\"deleted\", entityKey),\n * onError: (error) => console.error(error),\n * })\n *\n * unwatch()\n */\nexport function watchEntityEvents(\n client: ArkivClient,\n parameters: WatchEntityEventsParameters,\n): () => void {\n const {\n onEntityCreated,\n onEntityPatched,\n onExpiryExtended,\n onOwnershipTransferred,\n onEntityDeleted,\n onEvent,\n onError,\n fromBlock,\n pollingInterval = DEFAULT_POLLING_INTERVAL,\n } = parameters\n\n const publicClient = client as PublicArkivClient\n const reportError = onError ?? logToConsole\n\n function emit(event: EntityEvent): void {\n deliver(onEvent, event)\n switch (event.type) {\n case \"EntityCreated\":\n deliver(onEntityCreated, event)\n break\n case \"EntityPatched\":\n deliver(onEntityPatched, event)\n break\n case \"ExpiryExtended\":\n deliver(onExpiryExtended, event)\n break\n case \"OwnershipTransferred\":\n deliver(onOwnershipTransferred, event)\n break\n case \"EntityDeleted\":\n deliver(onEntityDeleted, event)\n break\n }\n }\n\n /**\n * Runs one handler, keeping its failure to itself.\n *\n * A handler that throws is the consumer's problem, not the watcher's: letting it escape would\n * reject the poll, drop the rest of the batch, and take down every other handler with it.\n */\n function deliver<TEvent>(handler: ((event: TEvent) => void) | undefined, event: TEvent): void {\n if (handler === undefined) return\n try {\n handler(event)\n } catch (error) {\n reportError(asError(error))\n }\n }\n\n const unwatchLogs = publicClient.watchEvent({\n // Only the Arkiv operation address emits these. Without the filter any contract whose event\n // happens to hash to the same topic lands in `onLogs`, and viem's observer key — which covers\n // the address but not `events` — would make this subscription collide with any other\n // unaddressed `watchEvent` on the same client.\n address: ARKIV_ADDRESS,\n events: ENTITY_EVENTS_ABI,\n pollingInterval,\n ...(fromBlock !== undefined && { fromBlock }),\n onLogs: (logs) => {\n logger(\"logs %o\", logs)\n for (const log of logs) {\n // A log with no position cannot be placed in application order, which is the one thing an\n // event consumer needs from it. Dropping it beats inventing a position it never had.\n if (log.blockNumber === null || log.transactionHash === null || log.logIndex === null) {\n continue\n }\n const context: EntityEventContext = {\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n logIndex: log.logIndex,\n }\n\n // Only the decode is guarded here. Dispatch guards each handler separately, so a consumer's\n // exception is never reported as if the log were the thing that was malformed.\n let event: EntityEvent\n try {\n event = toEntityEvent(log.topics, log.data, context)\n } catch (error) {\n reportError(asError(error))\n continue\n }\n emit(event)\n }\n },\n onError: (error) => reportError(error),\n })\n\n return unwatchLogs\n}\n\n/** The fallback when no `onError` was given — see {@link WatchEntityEventsParameters.onError}. */\nfunction logToConsole(error: Error): void {\n console.error(\"watchEntityEvents error\", error)\n}\n\n/** Handlers take an `Error`, and a `throw` can be anything. */\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error))\n}\n\n/**\n * Decodes one log into the {@link EntityEvent} it carries.\n *\n * @throws If the log does not decode against {@link ENTITY_EVENTS_ABI}.\n */\nfunction toEntityEvent(\n topics: readonly Hex[],\n data: Hex,\n context: EntityEventContext,\n): EntityEvent {\n const decoded = decodeEventLog({\n abi: ENTITY_EVENTS_ABI,\n topics: topics as [Hex, ...Hex[]] | [],\n data,\n })\n\n switch (decoded.eventName) {\n case \"EntityCreated\":\n return {\n type: \"EntityCreated\",\n ...context,\n ...decoded.args,\n creationFlags: decodeCreationFlags(decoded.args.creationFlags),\n }\n case \"EntityPatched\":\n return { type: \"EntityPatched\", ...context, ...decoded.args }\n case \"ExpiryExtended\":\n return { type: \"ExpiryExtended\", ...context, ...decoded.args }\n case \"OwnershipTransferred\":\n return { type: \"OwnershipTransferred\", ...context, ...decoded.args }\n case \"EntityDeleted\":\n return { type: \"EntityDeleted\", ...context, ...decoded.args }\n }\n}\n","import type { Account, Chain, Client, Hash, TransactionReceipt, Transport } from \"viem\"\nimport type {\n BuildMutationOptions,\n BuildMutationReturnType,\n} from \"../../actions/advanced/buildMutation\"\nimport { buildMutation } from \"../../actions/advanced/buildMutation\"\nimport type {\n GetMutationResultReturnType,\n MutationResult,\n} from \"../../actions/advanced/getMutationResult\"\nimport { decodeMutationResult, getMutationResult } from \"../../actions/advanced/getMutationResult\"\nimport type { PingTransactionReturnType } from \"../../actions/advanced/pingTransaction\"\nimport { pingTransaction } from \"../../actions/advanced/pingTransaction\"\nimport type {\n SendMutationOptions,\n SendMutationReturnType,\n} from \"../../actions/advanced/sendMutation\"\nimport { sendMutation } from \"../../actions/advanced/sendMutation\"\nimport type { EntityMutationOps } from \"../../utils/arkivTransactions\"\n\n/**\n * The read-only half of the advanced path — checking on a transaction and decoding its result —\n * which needs no account, so a Public Client carries it too.\n *\n * Every action here costs at most one RPC call, and says exactly which.\n */\nexport type PublicAdvancedActions = {\n /**\n * Asks the chain — once — whether a transaction has landed. Exactly one\n * `eth_getTransactionReceipt`, never a poll: an unmined transaction comes back as\n * `{ status: \"pending\" }` and the schedule stays yours.\n *\n * @param txHash - The transaction hash returned by `sendMutation` (or any other send)\n * @returns `{ status: \"pending\" }`, or `{ status: \"success\" | \"reverted\", blockNumber }`\n *\n * @example\n * const { status } = await client.advanced.pingTransaction(txHash)\n * if (status === \"pending\") scheduleAnotherPing()\n */\n pingTransaction: (txHash: Hash) => Promise<PingTransactionReturnType>\n\n /**\n * Fetches a transaction's receipt — once — and decodes what the mutation did: created keys and\n * expiries, plus the keys of everything patched, deleted, extended or handed over. One\n * `eth_getTransactionReceipt`; `{ status: \"pending\" }` if not mined yet. No revert diagnosis is\n * run on a `reverted` result — that extra call is yours to spend or skip.\n *\n * @param txHash - The transaction hash\n * @returns The decoded {@link MutationResult}, or `{ status: \"pending\" }`\n *\n * @example\n * const result = await client.advanced.getMutationResult(txHash)\n * if (result.status === \"success\") console.log(result.createdEntities)\n */\n getMutationResult: (txHash: Hash) => Promise<GetMutationResultReturnType>\n\n /**\n * Decodes a receipt you already hold into a {@link MutationResult}. **Zero RPC calls** — for\n * receipts that reached you through your own `waitForTransactionReceipt`, a block watcher, or a\n * webhook.\n *\n * @param receipt - The transaction receipt\n * @returns The decoded {@link MutationResult}\n */\n decodeMutationResult: (receipt: TransactionReceipt) => MutationResult\n}\n\n/**\n * The advanced path on a Wallet Client: build, send, ping and read results as separate steps, each\n * costing the minimum number of RPC calls — down to one per transaction when you supply what the\n * SDK would otherwise look up.\n *\n * The everyday actions (`createEntity`, `mutateEntities`, …) bundle send + wait + decode and are\n * the right default. This namespace unbundles them for callers optimising their RPC budget.\n *\n * @example Minimal-call flow: one send, one ping, done.\n * const { txHash } = await client.advanced.sendMutation(\n * { creates: [{ payload, contentType: \"application/json\", expires }] },\n * { currentBlock, txParams: { nonce, gas: 1_000_000n, maxFeePerGas, maxPriorityFeePerGas } },\n * ) // exactly 1 RPC call: eth_sendRawTransaction\n * // ... later, on your own schedule:\n * const result = await client.advanced.getMutationResult(txHash) // 1 RPC call\n * if (result.status === \"success\") console.log(result.createdEntities)\n */\nexport type WalletAdvancedActions = PublicAdvancedActions & {\n /**\n * Encodes a mutation batch without sending anything: zero RPC calls with `currentBlock` supplied\n * (or when no expiry is relative), at most one `eth_blockNumber` otherwise. Returns the\n * operations for `writeContract`, and the `{ to, data }` calldata for offline signing.\n *\n * @param data - The batch (creates, patches, deletes, extensions, ownershipChanges)\n * @param options - Optional `currentBlock` to avoid the `eth_blockNumber` lookup\n */\n buildMutation: (\n data: EntityMutationOps,\n options?: BuildMutationOptions,\n ) => Promise<BuildMutationReturnType>\n\n /**\n * Signs and sends a mutation batch, returning the hash as soon as the transaction is submitted —\n * no waiting, no polling, no revert diagnosis. With `currentBlock` and full `txParams` (nonce,\n * gas, fees) supplied this is exactly one `eth_sendRawTransaction`; each omitted piece adds only\n * the lookup viem needs to fill it.\n *\n * @param data - The batch (creates, patches, deletes, extensions, ownershipChanges)\n * @param options - Optional `currentBlock` and `txParams`\n * @returns The transaction hash and the batch's per-kind operation counts\n *\n * @example\n * const { txHash } = await client.advanced.sendMutation({\n * creates: [{ payload, contentType: \"application/json\", expires: ExpirationTime.atBlock(1_200_000n) }],\n * })\n */\n sendMutation: (\n data: EntityMutationOps,\n options?: SendMutationOptions,\n ) => Promise<SendMutationReturnType>\n}\n\nexport function publicAdvancedActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n>(client: Client<transport, chain, account>): PublicAdvancedActions {\n return {\n pingTransaction: (txHash: Hash) => pingTransaction(client, txHash),\n getMutationResult: (txHash: Hash) => getMutationResult(client, txHash),\n decodeMutationResult: (receipt: TransactionReceipt) => decodeMutationResult(receipt),\n }\n}\n\nexport function walletAdvancedActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n>(client: Client<transport, chain, account>): WalletAdvancedActions {\n return {\n ...publicAdvancedActions(client),\n buildMutation: (data: EntityMutationOps, options?: BuildMutationOptions) =>\n buildMutation(client, data, options),\n sendMutation: (data: EntityMutationOps, options?: SendMutationOptions) =>\n sendMutation(client, data, options),\n }\n}\n","import type { Account, Address, Chain, Client, Hex, PublicActions, Transport } from \"viem\"\nimport { getBlockTiming } from \"../../actions/public/getBlockTiming\"\nimport { getEntity } from \"../../actions/public/getEntity\"\nimport { getEntityCount } from \"../../actions/public/getEntityCount\"\nimport { getEntityNonce } from \"../../actions/public/getEntityNonce\"\nimport {\n type PredictEntityKeysParameters,\n type PredictEntityKeysReturnType,\n predictEntityKeys,\n} from \"../../actions/public/predictEntityKeys\"\nimport { type QueryOptions, type QueryReturnType, query } from \"../../actions/public/query\"\nimport {\n type WatchEntityEventsParameters,\n watchEntityEvents,\n} from \"../../actions/public/watchEntityEvents\"\nimport type { Expression } from \"../../query/expression\"\nimport { SelectQueryBuilder } from \"../../query/queryBuilder\"\nimport type { EntitySelection, FullEntity, ProjectedEntity, SelectArg } from \"../../query/selection\"\nimport type { Entity } from \"../../types/entity\"\nimport { type PublicAdvancedActions, publicAdvancedActions } from \"./arkivAdvanced\"\n\nexport type PublicArkivActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n> = Pick<\n PublicActions<transport, chain, account>,\n | \"getBalance\"\n | \"getBlock\"\n | \"getBlockNumber\"\n | \"getChainId\"\n | \"getLogs\"\n | \"getTransaction\"\n | \"getTransactionCount\"\n | \"getTransactionReceipt\"\n | \"waitForTransactionReceipt\"\n | \"watchEvent\"\n> & {\n /**\n * Returns the entity with the given key.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/public/getEntity\n *\n * @param key - The entity key (hex string)\n * @returns The entity with the given key, with every field populated. {@link FullEntity}\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const entity = await client.getEntity(entityKey)\n * // Entity {\n * // key: \"0x9f2c…\",\n * // owner: \"0xabc…\",\n * // contentType: \"application/json\",\n * // payload: Uint8Array, // entity.toJson() / entity.toText() decode it\n * // attributes: { category: { type: \"str\", value: \"docs\" } },\n * // expiresAt: 1_297_000n,\n * // }\n */\n getEntity: (key: Hex) => Promise<FullEntity>\n\n /**\n * Returns a SelectQueryBuilder for building and executing queries — the recommended way to\n * read entities. You declare up front which parts of an entity you want returned, so results\n * always contain exactly the data you asked for.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/public/query\n *\n * @param selection - What to include in the results. Omit it (or pass `\"*\"`) to select everything,\n * or pass an object to select specific parts (at least one field is required). Every part is\n * opt-in, including the `key`. The selection is flat — each field maps to an entity field.\n * {@link SelectArg}\n * @returns A SelectQueryBuilder instance for building and executing queries. {@link SelectQueryBuilder}\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { eq } from \"@arkiv-network/sdk/query\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * // select everything\n * await client.select().where(eq(\"category\", \"docs\")).fetch()\n * await client.select(\"*\").where(eq(\"category\", \"docs\")).fetch()\n * // only the key\n * await client.select({ key: true }).where(eq(\"category\", \"docs\")).fetch()\n * // select specific fields — result typed { owner: Hex; attributes: Attributes }\n * await client.select({ owner: true, attributes: true }).fetch()\n * // a single field — result typed { owner: Hex }\n * await client.select({ owner: true }).fetch()\n */\n select: {\n /** Select every field. Pass nothing or `\"*\"`; the returned entities contain all fields. */\n (selection?: \"*\"): SelectQueryBuilder<FullEntity>\n /**\n * Pick the entity fields to return. Set the ones you want to `true` (at least one is required);\n * the result is typed to exactly those fields, so reading anything else is a compile error.\n *\n * Available fields: `key`, `owner`, `creator`, `createdAt`, `updatedAt`, `expiresAt`,\n * `creationFlags`, `contentType`, `payload`, `attributeSchema` and `attributes`.\n *\n * `attributes` also takes a map of names, to fetch only those:\n * `select({ key: true, attributes: { projectId: true } })`.\n *\n * Pass the selection inline so its fields stay literal `true`. A selection stored in a `let`/\n * `const` variable widens to `boolean` and the result type can no longer be narrowed — annotate\n * it `as const` (e.g. `const sel = { owner: true } as const`) in that case.\n *\n * @example\n * client.select({ owner: true, attributes: true }) // entities typed { owner, attributes }\n * client.select({ key: true, payload: true }) // includes payload → toText()/toJson() too\n * client.select({ key: true, attributeSchema: true }) // what shape is the data?\n */\n <const S extends EntitySelection>(selection: S): SelectQueryBuilder<ProjectedEntity<S>>\n /**\n * Dynamic selection: accepts a value typed {@link SelectArg} (e.g. built at runtime). The\n * result cannot be narrowed in this case, so the entities are typed as the full entity.\n */\n (selection: SelectArg): SelectQueryBuilder<FullEntity>\n }\n\n /**\n * Runs one query and returns one page, with no builder in between.\n *\n * Use {@link select} for anything typed — this returns full {@link Entity} objects whatever the\n * selection, and takes a raw string as an escape hatch for a query built elsewhere. A raw string\n * goes to the node exactly as written, with none of the name, type or operator checks the\n * expression combinators apply.\n *\n * @param query - An {@link Expression}, or the raw query string.\n * @param queryOptions - Selection, page size, cursor and block. {@link QueryOptions}\n * @returns One page of entities. {@link QueryReturnType}\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { and, eq, gte } from \"@arkiv-network/sdk/query\"\n * import { i32 } from \"@arkiv-network/sdk/attr\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const page = await client.query(and(eq(\"category\", \"docs\"), gte(\"level\", i32(10))), {\n * select: { key: true, attributes: true },\n * limit: 100,\n * })\n * // { entities: [Entity], cursor: \"b64:…\", blockNumber: 32223n }\n *\n * // The raw form, unchecked:\n * await client.query(\"category = str('docs') AND level >= i32(10)\")\n */\n query: (query: Expression | string, queryOptions?: QueryOptions) => Promise<QueryReturnType>\n\n /**\n * Returns the total number of entities on the chain.\n * @returns The number of entities currently stored\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const entityCount = await client.getEntityCount()\n * // entityCount = 0\n */\n getEntityCount: () => Promise<number>\n\n /**\n * Returns how many entities an account has created — its entity-minting nonce.\n *\n * Not the account's transaction nonce: the engine keeps its own counter per creator and mixes it\n * into every key it mints, which is why two identical creates from one account never collide.\n *\n * @param owner - The account whose nonce to read.\n * @returns The nonce the account's next create will use.\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const nonce = await client.getEntityNonce(\"0xabc…\")\n * // 7n — the next entity this account creates is its eighth\n */\n getEntityNonce: (owner: Address) => Promise<bigint>\n\n /**\n * Works out the keys an account's next creates will be given, before sending them.\n *\n * The engine derives a key from the chain, the registry, the owner, the owner's nonce and a\n * salt — everything but the nonce is known to the caller, and the nonce is read here. This is\n * what lets a batch reference an entity it is about to mint.\n *\n * Each key arrives paired with the salt that mints it, because a create defaults to a *random*\n * salt: a predicted key only holds if the create carries the salt it was predicted with. And the\n * prediction holds only while nothing else from this owner is in flight — for a key you can rely\n * on unconditionally, read it back from the create instead.\n *\n * A literal `count` comes back as a fixed-length tuple, so the pairs destructure into names.\n *\n * @param parameters - Owner, and either a count or the salts. {@link PredictEntityKeysParameters}\n * @returns One `{ key, salt }` pair per create, in batch order.\n * {@link PredictEntityKeysReturnType}\n *\n * @example A batch whose second entity points at its first.\n * import { key } from \"@arkiv-network/sdk/attr\"\n *\n * const [parent, child] = await client.predictEntityKeys({ owner: account.address, count: 2 })\n * await wallet.mutateEntities({\n * creates: [\n * { payload, contentType, expires, salt: parent.salt },\n * {\n * payload,\n * contentType,\n * expires,\n * salt: child.salt,\n * attributes: { parent: key(parent.key) },\n * },\n * ],\n * })\n */\n predictEntityKeys: <\n const TCount extends number = number,\n const TSalts extends readonly bigint[] | undefined = undefined,\n >(\n parameters: PredictEntityKeysParameters<TCount, TSalts>,\n ) => Promise<PredictEntityKeysReturnType<TCount, TSalts>>\n\n /**\n * Returns the current block timing.\n * @returns The current block timing. {@link GetBlockTimingReturnType}\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const blockTiming = await client.getBlockTiming()\n * // {\n * // currentBlock: 10n, // block number\n * // currentBlockTime: 1234567890, // block timestamp\n * // blockDuration: 2, // in seconds\n * // }\n */\n getBlockTiming: () => Promise<{\n currentBlock: bigint\n currentBlockTime: number\n blockDuration: number\n }>\n\n /**\n * Watches entity events, calling the handlers you pass as they arrive.\n *\n * All five are decoded from logs — `onEntityCreated`, `onEntityPatched`, `onExpiryExtended`,\n * `onOwnershipTransferred`, `onEntityDeleted` — and each carries the block, transaction and log\n * index it came from, which is the order the operations were applied in. `onEvent` receives all\n * of them, whatever their type.\n *\n * @param parameters - Handlers and options, all optional. {@link WatchEntityEventsParameters}\n * @returns A function that stops the watcher.\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const unwatch = client.watchEntityEvents({\n * onEntityCreated: ({ entityKey, expiresAt }) => console.log(entityKey, \"until\", expiresAt),\n * onError: (error) => console.error(\"watchEntityEvents error\", error),\n * })\n * unwatch() // stop watching\n */\n watchEntityEvents: (parameters: WatchEntityEventsParameters) => () => void\n\n /**\n * The read-only half of the advanced path: check on a transaction and decode its result with at\n * most one RPC call per action — so a process that holds nothing but a transaction hash can\n * follow it without a wallet. {@link PublicAdvancedActions}\n *\n * @example\n * const { status } = await client.advanced.pingTransaction(txHash) // 1 eth_getTransactionReceipt\n */\n advanced: PublicAdvancedActions\n}\n\nexport function publicArkivActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n>(client: Client<transport, chain, account>) {\n return {\n getEntity: (key: Hex) => getEntity(client, key),\n query: (rawQuery: Expression | string, queryOptions?: QueryOptions) =>\n query(client, rawQuery, queryOptions),\n select: (selection?: SelectArg) => new SelectQueryBuilder(client, selection),\n getBlockTiming: () => getBlockTiming(client),\n getEntityCount: () => getEntityCount(client),\n getEntityNonce: (owner: Address) => getEntityNonce(client, owner),\n predictEntityKeys: <\n const TCount extends number = number,\n const TSalts extends readonly bigint[] | undefined = undefined,\n >(\n parameters: PredictEntityKeysParameters<TCount, TSalts>,\n ) => predictEntityKeys(client, parameters),\n watchEntityEvents: (parameters: WatchEntityEventsParameters) =>\n watchEntityEvents(client, parameters),\n advanced: publicAdvancedActions(client),\n }\n}\n","import type {\n Account,\n Address,\n Chain,\n Client,\n ParseAccount,\n Prettify,\n PublicClientConfig,\n RpcSchema,\n Transport,\n} from \"viem\"\nimport { createClient, publicActions } from \"viem\"\nimport type { ArkivRpcSchema } from \"../types/rpcSchema\"\nimport { type PublicArkivActions, publicArkivActions } from \"./decorators/arkivPublic\"\n\nexport type PublicArkivClient<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n accountOrAddress extends Account | undefined = undefined,\n rpcSchema extends RpcSchema | undefined = ArkivRpcSchema,\n> = Prettify<\n Client<transport, chain, accountOrAddress, rpcSchema, PublicArkivActions<transport, chain>>\n>\n\n/**\n * Creates a Public Client with a given [Transport](https://viem.sh/docs/clients/intro) configured for a [Chain](https://viem.sh/docs/clients/chains).\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/clients/public\n *\n * A Public Client is an interface to \"public\" [Ethereum JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/), [Arkiv JSON-RPC API](https://docs.arkiv.network/json-rpc/), and [Cheesecake JSON-RPC API](https://rpc.cheesecake.db-chain.devnet.gobas.me) methods such as retrieving block numbers, transactions, reading from smart contracts, etc through [Public Actions](/docs/actions/public/introduction).\n *\n * @param parameters - Configuration object for the public client (chain, transport, etc.)\n * @returns A Arkiv Public Client. {@link PublicArkivClient}\n *\n * @example\n * import { createPublicClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createPublicClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n */\nexport function createPublicClient<\n transport extends Transport,\n chain extends Chain | undefined = undefined,\n accountOrAddress extends Account | Address | undefined = undefined,\n rpcSchema extends RpcSchema | undefined = ArkivRpcSchema,\n>(\n parameters: PublicClientConfig<transport, chain, accountOrAddress, rpcSchema>,\n): PublicArkivClient<transport, chain, ParseAccount<accountOrAddress>, rpcSchema> {\n const { key = \"public\", name = \"Public Client\" } = parameters\n const client = createClient({\n ...parameters,\n key,\n name,\n })\n\n return client.extend(publicActions).extend(publicArkivActions) as unknown as PublicArkivClient<\n transport,\n chain,\n ParseAccount<accountOrAddress>,\n rpcSchema\n >\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:change-ownership\")\n\n/**\n * Parameters for the changeOwnership function.\n * - entityKey: The key of the entity.\n * - newOwner: The address of the new owner.\n */\nexport type ChangeOwnershipParameters = {\n entityKey: Hex\n newOwner: Hex\n}\n\n/**\n * Return type for the changeOwnership function.\n * - entityKey: The key of the entity.\n * - txHash: The transaction hash.\n */\nexport type ChangeOwnershipReturnType = {\n entityKey: Hex\n txHash: Hash\n}\n\nexport async function changeOwnership(\n client: ArkivClient,\n data: ChangeOwnershipParameters,\n txParams?: TxParams,\n): Promise<ChangeOwnershipReturnType> {\n logger(\"changeOwnership %o\", data)\n const { receipt } = await sendArkivTransaction(client, { ownershipChanges: [data] }, txParams)\n\n logger(\"Receipt from changeOwnership %o\", receipt)\n\n return {\n txHash: receipt.transactionHash,\n entityKey: data.entityKey,\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { AttributeInputs } from \"../../attr\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { CreationFlags, Expiry } from \"../../entity\"\nimport { EntityMutationError } from \"../../errors\"\nimport type { MimeType, TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:create-entity\")\n\n/**\n * Parameters for creating an entity.\n *\n * An entity always carries contents and a type for them, plus a lifetime. Attributes, flags and a\n * salt are optional on top of that.\n *\n * @example\n * const { entityKey } = await client.createEntity({\n * attributes: {\n * level: i32(10),\n * balance: u256(1_000_000n),\n * score: dec(\"3.5\"),\n * name: \"Bob\", // bare string -> str\n * flagged: true, // bare boolean -> bool\n * },\n * payload: jsonToPayload({ hello: \"world\" }),\n * contentType: \"application/json\",\n * expires: ExpirationTime.fromDays(30),\n * flags: { readonly: true },\n * })\n *\n * @example Pin an absolute deadline, but refuse to create something nearly dead:\n * await client.createEntity({\n * payload, contentType: \"application/json\",\n * expires: ExpirationTime.atDate(someDeadline, {\n * atLeast: ExpirationTime.fromDays(1), // ...but live at least a day regardless\n * }),\n * })\n *\n * @example An entity that is nothing but queryable attributes still declares its (empty) contents:\n * await client.createEntity({\n * attributes: { parent: key(parentKey), rank: i32(3) },\n * payload: new Uint8Array(),\n * contentType: \"application/octet-stream\",\n * expires: ExpirationTime.fromDays(30),\n * })\n */\nexport type CreateEntityParameters = {\n /**\n * How long the entity should live, built with {@link ExpirationTime}.\n *\n * `ExpirationTime.fromDays(30)` is the everyday form. `atBlock` / `atDate` pin an absolute\n * deadline instead, and either can carry `{ atLeast }` to guarantee a minimum life on top of it.\n */\n expires: Expiry\n /**\n * The entity's opaque payload. Travels to the engine as the `$payload` system attribute; on this\n * surface it is just the entity's contents.\n *\n * Pass an empty `Uint8Array` for an entity that is nothing but queryable attributes — it is\n * written as an empty payload rather than left unset, so what you pass is what is stored.\n */\n payload: Uint8Array\n /** The payload's MIME type, e.g. `\"application/json\"`. Sent as the `$contentType` cell. */\n contentType: MimeType | (string & {})\n /**\n * The entity's queryable attributes, keyed by name. Values are the tagged constructors from\n * `@arkiv-network/sdk/attr` — `i32`, `u256`, `dec`, `str`, `addr`, `key`, `bytes32`, `bool` — or\n * a bare `boolean`, `number`, `bigint` or `string` where the type is unambiguous.\n *\n * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.\n * @throws {InvalidValueError} If a value does not fit the type it names or defaults to.\n */\n attributes?: AttributeInputs | undefined\n /**\n * Properties fixed at creation: `readonly` and `permissionlessExtension`. No operation changes\n * them afterwards, so an entity is whatever it was created as for life. Both default to `false`.\n */\n flags?: CreationFlags | undefined\n /**\n * The salt mixed into the entity key. Defaults to 128 random bits, which makes the key\n * unpredictable to everyone but the creator.\n *\n * Pass `0n` for a key derived from the owner and nonce alone — predictable by anyone, which is\n * what you want only when a third party must be able to compute the key in advance.\n */\n salt?: bigint | undefined\n}\n\n/**\n * The result of creating an entity.\n */\nexport type CreateEntityReturnType = {\n /** The new entity's key. */\n entityKey: Hex\n txHash: Hash\n /**\n * The block the entity is expected to expire at, resolved against the block the transaction was\n * built on.\n *\n * The engine resolves a duration against the block the transaction actually lands in, so for\n * `ExpirationTime.fromDays(30)` and friends this is a lower bound: the real expiry is later by\n * however many blocks passed between building and inclusion. An `atBlock` deadline is exact.\n */\n expiresAt: bigint\n}\n\nexport async function createEntity(\n client: ArkivClient,\n data: CreateEntityParameters,\n txParams?: TxParams,\n): Promise<CreateEntityReturnType> {\n logger(\"createEntity %o\", data)\n const { receipt, createdEntityKeys, createdExpiries } = await sendArkivTransaction(\n client,\n { creates: [data] },\n txParams,\n )\n\n logger(\"Receipt from createEntity %o\", receipt)\n\n const [entityKey] = createdEntityKeys\n const [expiresAt] = createdExpiries\n if (entityKey === undefined || expiresAt === undefined) {\n throw new EntityMutationError(\n `Transaction ${receipt.transactionHash} succeeded, but the receipt did not carry the expected entity key or expiry.`,\n )\n }\n\n return {\n txHash: receipt.transactionHash as Hash,\n entityKey,\n expiresAt,\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:delete-entity\")\n\n/**\n * Parameters for the deleteEntity function.\n * - entityKey: The key of the entity to delete.\n */\nexport type DeleteEntityParameters = {\n entityKey: Hex\n}\n\n/**\n * Return type for the deleteEntity function.\n * - entityKey: The key of the entity.\n * - txHash: The transaction hash.\n */\nexport type DeleteEntityReturnType = {\n entityKey: Hex\n txHash: Hash\n}\n\nexport async function deleteEntity(\n client: ArkivClient,\n data: DeleteEntityParameters,\n txParams?: TxParams,\n): Promise<DeleteEntityReturnType> {\n logger(\"deleteEntity %o\", data)\n const { receipt } = await sendArkivTransaction(client, { deletes: [data] }, txParams)\n\n logger(\"Receipt from deleteEntity %o\", receipt)\n\n return {\n txHash: receipt.transactionHash as Hash,\n entityKey: data.entityKey,\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { Expiry } from \"../../entity\"\nimport { EntityMutationError } from \"../../errors\"\nimport type { TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:extend-entity\")\n\n/**\n * Parameters for extending an entity's life.\n *\n * An extension **sets a new expiry**; it does not add to the existing one. It is resolved exactly\n * as a create's is — a duration counts from now, not from the entity's current expiry — so\n * `ExpirationTime.fromDays(30)` means \"alive for thirty more days from now\" whatever the entity's\n * remaining life happened to be.\n *\n * The engine rejects an extension that would not move the expiry later, so extending an entity by\n * less than it already has left is an error rather than a silent shortening.\n *\n * @example\n * await client.extendEntity({ entityKey, expires: ExpirationTime.fromDays(30) })\n * await client.extendEntity({ entityKey, expires: ExpirationTime.atBlock(1_200_000n) })\n */\nexport type ExtendEntityParameters = {\n entityKey: Hex\n /** The entity's new lifetime, built with {@link ExpirationTime}. */\n expires: Expiry\n}\n\n/**\n * The result of extending an entity.\n */\nexport type ExtendEntityReturnType = {\n entityKey: Hex\n txHash: Hash\n /**\n * The block the entity is now expected to expire at, resolved against the block the transaction\n * was built on. Durations are approximate, so treat this as the estimate the operation was built\n * from rather than the block the engine settled on.\n */\n expiresAt: bigint\n}\n\nexport async function extendEntity(\n client: ArkivClient,\n data: ExtendEntityParameters,\n txParams?: TxParams,\n): Promise<ExtendEntityReturnType> {\n logger(\"extendEntity %o\", data)\n const { receipt, extendedExpiries } = await sendArkivTransaction(\n client,\n { extensions: [data] },\n txParams,\n )\n\n logger(\"Receipt from extendEntity %o\", receipt)\n\n const [expiresAt] = extendedExpiries\n if (expiresAt === undefined) {\n throw new EntityMutationError(\n `Transaction ${receipt.transactionHash} succeeded, but the receipt did not carry the expected entity expiry.`,\n )\n }\n\n return {\n txHash: receipt.transactionHash as Hash,\n entityKey: data.entityKey,\n expiresAt,\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { TxParams } from \"../../types\"\nimport { type EntityMutationOps, sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:mutate-entities\")\n\n/**\n * Parameters for the mutateEntities function — the same batch shape the advanced path takes\n * ({@link EntityMutationOps}), so the two surfaces cannot drift apart.\n *\n * At least one operation is required; a batch with nothing in it throws rather than spending gas on\n * an empty transaction.\n */\nexport type MutateEntitiesParameters = EntityMutationOps\n\n/** Return type for the mutateEntities function. */\nexport type MutateEntitiesReturnType = {\n /** The transaction hash. */\n txHash: Hash\n /** The keys of the created entities, in batch order. */\n createdEntities: Hex[]\n /** The keys of the patched entities. */\n patchedEntities: Hex[]\n /** The keys of the deleted entities. */\n deletedEntities: Hex[]\n /** The keys of the extended entities. */\n extendedEntities: Hex[]\n /** The keys of the entities handed to a new owner. */\n ownershipChanges: Hex[]\n}\n\nexport async function mutateEntities(\n client: ArkivClient,\n data: MutateEntitiesParameters,\n txParams?: TxParams,\n): Promise<MutateEntitiesReturnType> {\n const { receipt, createdEntityKeys } = await sendArkivTransaction(client, data, txParams)\n\n logger(\"Receipt from mutateEntities %o\", receipt)\n\n return {\n txHash: receipt.transactionHash as Hash,\n createdEntities: createdEntityKeys,\n patchedEntities: (data.patches ?? []).map((p) => p.entityKey),\n deletedEntities: (data.deletes ?? []).map((d) => d.entityKey),\n extendedEntities: (data.extensions ?? []).map((e) => e.entityKey),\n ownershipChanges: (data.ownershipChanges ?? []).map((o) => o.entityKey),\n }\n}\n","import type { Hash, Hex } from \"viem\"\nimport type { AttributeInputs } from \"../../attr\"\nimport type { ArkivClient } from \"../../clients/baseClient\"\nimport type { MimeType, TxParams } from \"../../types\"\nimport { sendArkivTransaction } from \"../../utils/arkivTransactions\"\nimport { getLogger } from \"../../utils/logger\"\n\nconst logger = getLogger(\"actions:wallet:patch-entity\")\n\n/**\n * Parameters for patching an entity.\n *\n * A patch names only what changes. Attributes it does not mention keep whatever value they have, and\n * the payload and content type stay as they are unless given — so a caller can change one field\n * without first reading the entity to learn what the others are, and without racing anyone else who\n * is changing a different field.\n *\n * The entity's identity is fixed: a patch never moves the key, the owner, the creation flags or the\n * expiry. Use `extendEntity` for the expiry and `changeOwnership` for the owner.\n *\n * @example Change one attribute and remove another, leaving the payload alone:\n * await client.patchEntity({\n * entityKey,\n * set: { status: \"published\", level: i32(11) },\n * unset: [\"draft\"],\n * })\n *\n * @example Replace the contents without touching a single attribute:\n * await client.patchEntity({\n * entityKey,\n * payload: jsonToPayload({ hello: \"again\" }),\n * })\n */\nexport type PatchEntityParameters = {\n /** The entity to patch. */\n entityKey: Hex\n /**\n * Attributes to write, keyed by name. An existing attribute is overwritten — including with a\n * different type — and a name the entity does not carry yet is added.\n *\n * Values are the tagged constructors from `@arkiv-network/sdk/attr` — `i32`, `u256`, `dec`, `str`,\n * `addr`, `key`, `bytes32`, `bool` — or a bare `boolean`, `number`, `bigint` or `string` where the\n * type is unambiguous.\n *\n * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.\n * @throws {InvalidValueError} If a value does not fit the type it names or defaults to.\n */\n set?: AttributeInputs | undefined\n /**\n * Attribute names to remove. Naming one the entity does not carry is not an error — the outcome\n * is the same either way, and a caller clearing a field should not have to know whether it was\n * ever set.\n *\n * @throws {ConflictingMutationError} If a name also appears in `set`.\n */\n unset?: readonly string[] | undefined\n /**\n * The entity's new payload. Omit it to leave the current contents untouched; pass an empty\n * `Uint8Array` to replace them with nothing.\n */\n payload?: Uint8Array | undefined\n /**\n * The payload's new MIME type. Omit it to keep the current one — which is what you want when the\n * new payload is the same kind of thing as the old.\n */\n contentType?: MimeType | (string & {}) | undefined\n}\n\n/** The result of patching an entity. */\nexport type PatchEntityReturnType = {\n /** The patched entity's key — unchanged, since a patch never moves it. */\n entityKey: Hex\n txHash: Hash\n}\n\nexport async function patchEntity(\n client: ArkivClient,\n data: PatchEntityParameters,\n txParams?: TxParams,\n): Promise<PatchEntityReturnType> {\n logger(\"patchEntity %o\", data)\n const { receipt } = await sendArkivTransaction(client, { patches: [data] }, txParams)\n\n logger(\"Receipt from patchEntity %o\", receipt)\n\n return {\n txHash: receipt.transactionHash as Hash,\n entityKey: data.entityKey,\n }\n}\n","import type { Account, Chain, Client, PublicActions, Transport, WalletActions } from \"viem\"\nimport type {\n ChangeOwnershipParameters,\n ChangeOwnershipReturnType,\n} from \"../../actions/wallet/changeOwnership\"\nimport { changeOwnership } from \"../../actions/wallet/changeOwnership\"\nimport {\n type CreateEntityParameters,\n type CreateEntityReturnType,\n createEntity,\n} from \"../../actions/wallet/createEntity\"\nimport type {\n DeleteEntityParameters,\n DeleteEntityReturnType,\n} from \"../../actions/wallet/deleteEntity\"\nimport { deleteEntity } from \"../../actions/wallet/deleteEntity\"\nimport type {\n ExtendEntityParameters,\n ExtendEntityReturnType,\n} from \"../../actions/wallet/extendEntity\"\nimport { extendEntity } from \"../../actions/wallet/extendEntity\"\nimport type {\n MutateEntitiesParameters,\n MutateEntitiesReturnType,\n} from \"../../actions/wallet/mutateEntities\"\nimport { mutateEntities } from \"../../actions/wallet/mutateEntities\"\nimport type { PatchEntityParameters, PatchEntityReturnType } from \"../../actions/wallet/patchEntity\"\nimport { patchEntity } from \"../../actions/wallet/patchEntity\"\nimport type { TxParams } from \"../../types\"\nimport { type WalletAdvancedActions, walletAdvancedActions } from \"./arkivAdvanced\"\n\nexport type WalletArkivActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n> = Pick<\n PublicActions<transport, chain, account>,\n \"waitForTransactionReceipt\" | \"call\" | \"simulateContract\" | \"readContract\" | \"getBlockNumber\"\n> &\n Pick<\n WalletActions<chain, account>,\n | \"addChain\"\n | \"sendCalls\"\n | \"waitForCallsStatus\"\n | \"sendTransaction\"\n | \"sendRawTransaction\"\n | \"signMessage\"\n | \"signTransaction\"\n | \"writeContract\"\n > & {\n /**\n * Creates a new entity.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/createEntity\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The entity creation parameters\n * @param txParams - Optional transaction parameters\n * @returns The created entity with transaction hash\n *\n * @throws {InvalidExpiryError} If the expiry exceeds a protocol bound or would leave the\n * entity dead on arrival.\n * @throws {InvalidValueError} If an attribute value does not fit the type it names.\n * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.\n *\n * @example\n * import { createWalletClient, ExpirationTime, jsonToPayload } from \"@arkiv-network/sdk\"\n * import { i32 } from \"@arkiv-network/sdk/attr\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createWalletClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const { entityKey, txHash, expiresAt } = await client.createEntity({\n * payload: jsonToPayload({ entityType: \"testType\", entityId: \"testId\" }),\n * contentType: \"application/json\",\n * attributes: { testKey: \"testValue\", level: i32(3) },\n * expires: ExpirationTime.fromDays(30),\n * })\n */\n createEntity: (\n data: CreateEntityParameters,\n txParams?: TxParams,\n ) => Promise<CreateEntityReturnType>\n\n /**\n * Applies a patch to the entity with the given key: sets some fields, unsets others, and leaves\n * everything it does not name alone.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/patchEntity\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The entity key and the mutations to apply\n * @param txParams - Optional transaction parameters\n * @returns The entity key and the transaction hash\n *\n * @throws {EmptyPatchError} If the patch has nothing to apply.\n * @throws {ConflictingMutationError} If a name appears in both `set` and `unset`.\n * @throws {InvalidValueError} If an attribute value does not fit the type it names.\n * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.\n *\n * @example\n * import { createWalletClient, jsonToPayload } from \"@arkiv-network/sdk\"\n * import { i32 } from \"@arkiv-network/sdk/attr\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createWalletClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * // Publish the entity: one attribute changes, one goes away, the payload is replaced.\n * const { txHash } = await client.patchEntity({\n * entityKey,\n * set: { status: \"published\", revision: i32(2) },\n * unset: [\"draft\"],\n * payload: jsonToPayload({ title: \"Hello\" }),\n * })\n */\n patchEntity: (\n data: PatchEntityParameters,\n txParams?: TxParams,\n ) => Promise<PatchEntityReturnType>\n\n /**\n * Deletes the entity with the given key.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/deleteEntity\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The entity deletion parameters\n * @param txParams - Optional transaction parameters\n * @returns The deleted entity with transaction hash\n *\n * @example\n * import { createWalletClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createWalletClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * // entityKey is the bytes32 key returned by createEntity.\n * const { txHash } = await client.deleteEntity({ entityKey })\n */\n deleteEntity: (\n data: DeleteEntityParameters,\n txParams?: TxParams,\n ) => Promise<DeleteEntityReturnType>\n\n /**\n * Sets a new expiry on the entity with the given key.\n *\n * The new lifetime is resolved the same way a create's is: a duration counts from now rather\n * than adding to what the entity has left, and `atBlock` / `atDate` pin an absolute deadline.\n * The engine rejects an extension that would not move the expiry later.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/extendEntity\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The entity key and its new lifetime\n * @param txParams - Optional transaction parameters\n * @returns The entity key, transaction hash, and the block it is now expected to expire at\n *\n * @throws {InvalidExpiryError} If the expiry is malformed, exceeds a protocol bound, or would\n * leave the entity dead on arrival.\n *\n * @example\n * import { createWalletClient, ExpirationTime } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createWalletClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const { txHash, expiresAt } = await client.extendEntity({\n * entityKey,\n * expires: ExpirationTime.fromDays(30),\n * })\n */\n extendEntity: (\n data: ExtendEntityParameters,\n txParams?: TxParams,\n ) => Promise<ExtendEntityReturnType>\n\n /**\n * Changes the ownership of the entity with the given address.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/changeOwnership\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * @param data - The ownership change parameters\n * @param txParams - Optional transaction parameters\n * @returns The entity with updated ownership and transaction hash\n */\n changeOwnership: (\n data: ChangeOwnershipParameters,\n txParams?: TxParams,\n ) => Promise<ChangeOwnershipReturnType>\n\n /**\n * Mutates the entities with the given keys.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/actions/wallet/mutateEntities\n * - JSON-RPC Methods: [`eth_sendRawTransaction`](https://docs.arkiv.network/dev/json-rpc-api/#mutateEntities)\n *\n * Every operation lands in one transaction, so the whole batch applies or none of it does.\n * At least one operation is required.\n *\n * @param data - The mutation parameters (creates, patches, deletes, extensions, ownershipChanges)\n * @param txParams - Optional transaction parameters\n * @returns The mutation result with transaction hash\n *\n * @throws {InvalidExpiryError} If an expiry exceeds a protocol bound or would leave the entity\n * dead on arrival.\n * @throws {InvalidValueError} If an attribute value does not fit the type it names.\n *\n * @example\n * import { createWalletClient, ExpirationTime, jsonToPayload } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n *\n * const client = createWalletClient({\n * chain: cheesecake,\n * transport: http(),\n * })\n * const { txHash, createdEntities } = await client.mutateEntities({\n * creates: [{\n * payload: jsonToPayload({ entityType: \"testType\", entityId: \"testId\" }),\n * contentType: \"application/json\",\n * attributes: { testKey: \"testValue\" },\n * expires: ExpirationTime.fromDays(30),\n * }],\n * patches: [{ entityKey: keyToRevise, set: { status: \"archived\" }, unset: [\"draft\"] }],\n * deletes: [{ entityKey: staleKey }],\n * extensions: [{\n * entityKey: keyToKeepAlive,\n * expires: ExpirationTime.atBlock(1_200_000n),\n * }],\n * ownershipChanges: [{ entityKey: keyToHandOver, newOwner }],\n * })\n */\n mutateEntities: (\n data: MutateEntitiesParameters,\n txParams?: TxParams,\n ) => Promise<MutateEntitiesReturnType>\n\n /**\n * The advanced path: build, send, ping and read mutation results as separate steps, each\n * costing the minimum number of RPC calls. Use it when you are optimising your RPC budget;\n * the everyday actions above remain the right default. {@link WalletAdvancedActions}\n *\n * @example\n * const { txHash } = await client.advanced.sendMutation({ creates: [entity] }) // no waiting\n * // ... later, one eth_getTransactionReceipt on your own schedule:\n * const result = await client.advanced.getMutationResult(txHash)\n * if (result.status === \"success\") console.log(result.createdEntities)\n */\n advanced: WalletAdvancedActions\n }\n\nexport function walletArkivActions<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n>(client: Client<transport, chain, account>) {\n return {\n createEntity: (data: CreateEntityParameters, txParams?: TxParams) =>\n createEntity(client, data, txParams),\n patchEntity: (data: PatchEntityParameters, txParams?: TxParams) =>\n patchEntity(client, data, txParams),\n deleteEntity: (data: DeleteEntityParameters, txParams?: TxParams) =>\n deleteEntity(client, data, txParams),\n extendEntity: (data: ExtendEntityParameters, txParams?: TxParams) =>\n extendEntity(client, data, txParams),\n changeOwnership: (data: ChangeOwnershipParameters, txParams?: TxParams) =>\n changeOwnership(client, data, txParams),\n mutateEntities: (data: MutateEntitiesParameters, txParams?: TxParams) =>\n mutateEntities(client, data, txParams),\n advanced: walletAdvancedActions(client),\n }\n}\n","import type {\n Account,\n Address,\n Chain,\n Client,\n ParseAccount,\n Prettify,\n RpcSchema,\n Transport,\n WalletClientConfig,\n} from \"viem\"\nimport { createClient, publicActions, walletActions } from \"viem\"\nimport type { ArkivRpcSchema } from \"../types/rpcSchema\"\nimport { type WalletArkivActions, walletArkivActions } from \"./decorators/arkivWallet\"\n\nexport type WalletArkivClient<\n transport extends Transport = Transport,\n chain extends Chain | undefined = Chain | undefined,\n account extends Account | undefined = Account | undefined,\n rpcSchema extends RpcSchema | undefined = ArkivRpcSchema,\n> = Prettify<\n Client<transport, chain, account, rpcSchema, WalletArkivActions<transport, chain, account>>\n>\n\n/**\n * Creates a Wallet Client with a given [Transport](https://viem.sh/docs/clients/intro) configured\n * for a [Chain](https://viem.sh/docs/clients/chains) and an account.\n *\n * - Docs: https://docs.arkiv.network/ts-sdk/clients/wallet\n *\n * A Wallet Client signs and sends transactions, so it carries an `account` and exposes everything\n * that mutates state — `createEntity`, `patchEntity`, `deleteEntity`, `extendEntity`,\n * `changeOwnership` and `mutateEntities` — on top of the read actions a Public Client has.\n *\n * @param parameters - Configuration object for the wallet client (chain, transport, account, etc.)\n * @returns A Arkiv Wallet Client. {@link WalletArkivClient}\n *\n * @example\n * import { createWalletClient } from \"@arkiv-network/sdk\"\n * import { cheesecake } from \"@arkiv-network/sdk/chains\"\n * import { http } from \"viem\"\n * import { privateKeyToAccount } from \"viem/accounts\"\n *\n * const client = createWalletClient({\n * chain: cheesecake,\n * transport: http(),\n * account: privateKeyToAccount(\"0x...\"),\n * })\n */\nexport function createWalletClient<\n transport extends Transport,\n chain extends Chain | undefined = undefined,\n accountOrAddress extends Account | Address | undefined = undefined,\n rpcSchema extends RpcSchema | undefined = ArkivRpcSchema,\n>(\n parameters: WalletClientConfig<transport, chain, accountOrAddress, rpcSchema>,\n): WalletArkivClient<transport, chain, ParseAccount<accountOrAddress>, rpcSchema> {\n const { key = \"wallet\", name = \"Wallet Client\" } = parameters\n const client = createClient({\n ...parameters,\n key,\n name,\n })\n\n return client\n .extend(publicActions)\n .extend(walletActions)\n .extend(walletArkivActions) as unknown as WalletArkivClient<\n transport,\n chain,\n ParseAccount<accountOrAddress>,\n rpcSchema\n >\n}\n","import type { Chain } from \"viem\"\nimport * as chains from \"../chains\"\n\n// Create a lookup map from all exported chains\nconst chainMap = new Map(Object.entries(chains).map(([key, value]) => [key.toLowerCase(), value]))\n\n/**\n * Get a chain from its name\n * @param name - The name of the chain, case insensitive\n * @returns The chain\n * @throws An error if the chain is not found\n */\nexport function chainFromName(name: string): Chain {\n const chain = chainMap.get(name.toLowerCase())\n if (!chain) {\n throw new Error(`Unknown chain: ${name}`)\n }\n return chain as Chain\n}\n"],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import { o as ARKIV_ADDRESS } from "./expiry-BjpxZZQU.js";
2
+ import { i as NoRandomSourceError, r as InvalidSaltError } from "./errors-LTe7bOYS.js";
3
+ import { encodePacked, keccak256, parseAbi } from "viem";
4
+
5
+ //#region src/entity/events.ts
6
+ /**
7
+ * The events the engine emits: one per applied operation, in application order, so an off-chain
8
+ * replica can replay a transaction operation by operation.
9
+ */
10
+ const ENTITY_EVENTS_ABI = parseAbi([
11
+ "event EntityCreated(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt, uint8 creationFlags)",
12
+ "event EntityPatched(bytes32 indexed entityKey, address indexed owner)",
13
+ "event ExpiryExtended(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt)",
14
+ "event OwnershipTransferred(bytes32 indexed entityKey, address indexed previousOwner, address indexed newOwner)",
15
+ "event EntityDeleted(bytes32 indexed entityKey, address indexed owner)"
16
+ ]);
17
+
18
+ //#endregion
19
+ //#region src/entity/key.ts
20
+ /** The widest salt the `uint128` wire field carries. */
21
+ const MAX_SALT = 2n ** 128n - 1n;
22
+ /**
23
+ * A cryptographically random 128-bit salt — what {@link CreateEntityParameters.salt} defaults to.
24
+ *
25
+ * The salt exists for unpredictability, not uniqueness: the per-owner nonce already guarantees
26
+ * distinct keys. Random bits mean only the creator can predict the key of an entity they are about
27
+ * to create, so nobody else can reference or squat it in advance.
28
+ *
29
+ * @throws {NoRandomSourceError} If the runtime has no `crypto.getRandomValues`.
30
+ */
31
+ function randomSalt() {
32
+ const source = globalThis.crypto;
33
+ if (typeof source?.getRandomValues !== "function") throw new NoRandomSourceError();
34
+ const bytes = source.getRandomValues(new Uint8Array(16));
35
+ let salt = 0n;
36
+ for (const byte of bytes) salt = salt << 8n | BigInt(byte);
37
+ return salt;
38
+ }
39
+ /** Validates a caller-supplied salt against the `uint128` wire field. */
40
+ function validateSalt(salt) {
41
+ if (typeof salt !== "bigint" || salt < 0n || salt > MAX_SALT) throw new InvalidSaltError(salt);
42
+ return salt;
43
+ }
44
+ /**
45
+ * The key an entity will be created with, derived exactly as the engine derives it:
46
+ * `keccak256(domain ++ owner ++ nonce ++ salt)`.
47
+ *
48
+ * Deriving it client-side is what lets a batch compose: predict the key of a create, then have a
49
+ * later operation in the same transaction reference it, or store it as a `key` attribute on a
50
+ * sibling entity.
51
+ */
52
+ function predictEntityKey({ owner, nonce, salt, chainId }) {
53
+ return keccak256(encodePacked([
54
+ "uint256",
55
+ "address",
56
+ "address",
57
+ "uint64",
58
+ "uint128"
59
+ ], [
60
+ BigInt(chainId),
61
+ ARKIV_ADDRESS,
62
+ owner,
63
+ nonce,
64
+ validateSalt(salt)
65
+ ]));
66
+ }
67
+
68
+ //#endregion
69
+ export { ENTITY_EVENTS_ABI as a, validateSalt as i, predictEntityKey as n, randomSalt as r, MAX_SALT as t };
70
+ //# sourceMappingURL=key-D1Bh7MF0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-D1Bh7MF0.js","names":[],"sources":["../src/entity/events.ts","../src/entity/key.ts"],"sourcesContent":["import { parseAbi } from \"viem\"\n\n/**\n * The events the engine emits: one per applied operation, in application order, so an off-chain\n * replica can replay a transaction operation by operation.\n */\nexport const ENTITY_EVENTS_ABI = parseAbi([\n \"event EntityCreated(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt, uint8 creationFlags)\",\n \"event EntityPatched(bytes32 indexed entityKey, address indexed owner)\",\n \"event ExpiryExtended(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt)\",\n \"event OwnershipTransferred(bytes32 indexed entityKey, address indexed previousOwner, address indexed newOwner)\",\n \"event EntityDeleted(bytes32 indexed entityKey, address indexed owner)\",\n])\n\n/** The name of each event in {@link ENTITY_EVENTS_ABI}. */\nexport type EntityEventName = (typeof ENTITY_EVENTS_ABI)[number][\"name\"]\n","import { type Address, encodePacked, type Hex, keccak256 } from \"viem\"\nimport { ARKIV_ADDRESS } from \"../consts\"\nimport { InvalidSaltError, NoRandomSourceError } from \"./errors\"\n\n/** The widest salt the `uint128` wire field carries. */\nexport const MAX_SALT = 2n ** 128n - 1n\n\n/**\n * A cryptographically random 128-bit salt — what {@link CreateEntityParameters.salt} defaults to.\n *\n * The salt exists for unpredictability, not uniqueness: the per-owner nonce already guarantees\n * distinct keys. Random bits mean only the creator can predict the key of an entity they are about\n * to create, so nobody else can reference or squat it in advance.\n *\n * @throws {NoRandomSourceError} If the runtime has no `crypto.getRandomValues`.\n */\nexport function randomSalt(): bigint {\n const source = globalThis.crypto\n if (typeof source?.getRandomValues !== \"function\") {\n throw new NoRandomSourceError()\n }\n const bytes = source.getRandomValues(new Uint8Array(16))\n let salt = 0n\n for (const byte of bytes) salt = (salt << 8n) | BigInt(byte)\n return salt\n}\n\n/** Validates a caller-supplied salt against the `uint128` wire field. */\nexport function validateSalt(salt: bigint): bigint {\n if (typeof salt !== \"bigint\" || salt < 0n || salt > MAX_SALT) {\n throw new InvalidSaltError(salt)\n }\n return salt\n}\n\n/**\n * The key an entity will be created with, derived exactly as the engine derives it:\n * `keccak256(domain ++ owner ++ nonce ++ salt)`.\n *\n * Deriving it client-side is what lets a batch compose: predict the key of a create, then have a\n * later operation in the same transaction reference it, or store it as a `key` attribute on a\n * sibling entity.\n */\nexport function predictEntityKey({\n owner,\n nonce,\n salt,\n chainId,\n}: {\n /** The account creating the entity. */\n owner: Address\n /**\n * The owner's entity-nonce at creation time. Each create in a batch consumes one, so the *n*th\n * create in a batch uses `nonce + n`.\n */\n nonce: bigint\n /** The salt the create will carry. */\n salt: bigint\n /** The chain the entity is being created on — half of the derivation domain. */\n chainId: number\n}): Hex {\n return keccak256(\n encodePacked(\n [\"uint256\", \"address\", \"address\", \"uint64\", \"uint128\"],\n [BigInt(chainId), ARKIV_ADDRESS, owner, nonce, validateSalt(salt)],\n ),\n )\n}\n"],"mappings":";;;;;;;;;AAMA,MAAa,oBAAoB,SAAS;CACxC;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;ACPF,MAAa,WAAW,MAAM,OAAO;;;;;;;;;;AAWrC,SAAgB,aAAqB;CACnC,MAAM,SAAS,WAAW;AAC1B,KAAI,OAAO,QAAQ,oBAAoB,WACrC,OAAM,IAAI,qBAAqB;CAEjC,MAAM,QAAQ,OAAO,gBAAgB,IAAI,WAAW,GAAG,CAAC;CACxD,IAAI,OAAO;AACX,MAAK,MAAM,QAAQ,MAAO,QAAQ,QAAQ,KAAM,OAAO,KAAK;AAC5D,QAAO;;;AAIT,SAAgB,aAAa,MAAsB;AACjD,KAAI,OAAO,SAAS,YAAY,OAAO,MAAM,OAAO,SAClD,OAAM,IAAI,iBAAiB,KAAK;AAElC,QAAO;;;;;;;;;;AAWT,SAAgB,iBAAiB,EAC/B,OACA,OACA,MACA,WAaM;AACN,QAAO,UACL,aACE;EAAC;EAAW;EAAW;EAAW;EAAU;EAAU,EACtD;EAAC,OAAO,QAAQ;EAAE;EAAe;EAAO;EAAO,aAAa,KAAK;EAAC,CACnE,CACF"}
@@ -0,0 +1,98 @@
1
+ const require_expiry = require('./expiry-BELY2Kpw.cjs');
2
+ const require_errors = require('./errors-BVbjKVMN.cjs');
3
+ let viem = require("viem");
4
+
5
+ //#region src/entity/events.ts
6
+ /**
7
+ * The events the engine emits: one per applied operation, in application order, so an off-chain
8
+ * replica can replay a transaction operation by operation.
9
+ */
10
+ const ENTITY_EVENTS_ABI = (0, viem.parseAbi)([
11
+ "event EntityCreated(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt, uint8 creationFlags)",
12
+ "event EntityPatched(bytes32 indexed entityKey, address indexed owner)",
13
+ "event ExpiryExtended(bytes32 indexed entityKey, address indexed owner, uint64 expiresAt)",
14
+ "event OwnershipTransferred(bytes32 indexed entityKey, address indexed previousOwner, address indexed newOwner)",
15
+ "event EntityDeleted(bytes32 indexed entityKey, address indexed owner)"
16
+ ]);
17
+
18
+ //#endregion
19
+ //#region src/entity/key.ts
20
+ /** The widest salt the `uint128` wire field carries. */
21
+ const MAX_SALT = 2n ** 128n - 1n;
22
+ /**
23
+ * A cryptographically random 128-bit salt — what {@link CreateEntityParameters.salt} defaults to.
24
+ *
25
+ * The salt exists for unpredictability, not uniqueness: the per-owner nonce already guarantees
26
+ * distinct keys. Random bits mean only the creator can predict the key of an entity they are about
27
+ * to create, so nobody else can reference or squat it in advance.
28
+ *
29
+ * @throws {NoRandomSourceError} If the runtime has no `crypto.getRandomValues`.
30
+ */
31
+ function randomSalt() {
32
+ const source = globalThis.crypto;
33
+ if (typeof source?.getRandomValues !== "function") throw new require_errors.NoRandomSourceError();
34
+ const bytes = source.getRandomValues(new Uint8Array(16));
35
+ let salt = 0n;
36
+ for (const byte of bytes) salt = salt << 8n | BigInt(byte);
37
+ return salt;
38
+ }
39
+ /** Validates a caller-supplied salt against the `uint128` wire field. */
40
+ function validateSalt(salt) {
41
+ if (typeof salt !== "bigint" || salt < 0n || salt > MAX_SALT) throw new require_errors.InvalidSaltError(salt);
42
+ return salt;
43
+ }
44
+ /**
45
+ * The key an entity will be created with, derived exactly as the engine derives it:
46
+ * `keccak256(domain ++ owner ++ nonce ++ salt)`.
47
+ *
48
+ * Deriving it client-side is what lets a batch compose: predict the key of a create, then have a
49
+ * later operation in the same transaction reference it, or store it as a `key` attribute on a
50
+ * sibling entity.
51
+ */
52
+ function predictEntityKey({ owner, nonce, salt, chainId }) {
53
+ return (0, viem.keccak256)((0, viem.encodePacked)([
54
+ "uint256",
55
+ "address",
56
+ "address",
57
+ "uint64",
58
+ "uint128"
59
+ ], [
60
+ BigInt(chainId),
61
+ require_expiry.ARKIV_ADDRESS,
62
+ owner,
63
+ nonce,
64
+ validateSalt(salt)
65
+ ]));
66
+ }
67
+
68
+ //#endregion
69
+ Object.defineProperty(exports, 'ENTITY_EVENTS_ABI', {
70
+ enumerable: true,
71
+ get: function () {
72
+ return ENTITY_EVENTS_ABI;
73
+ }
74
+ });
75
+ Object.defineProperty(exports, 'MAX_SALT', {
76
+ enumerable: true,
77
+ get: function () {
78
+ return MAX_SALT;
79
+ }
80
+ });
81
+ Object.defineProperty(exports, 'predictEntityKey', {
82
+ enumerable: true,
83
+ get: function () {
84
+ return predictEntityKey;
85
+ }
86
+ });
87
+ Object.defineProperty(exports, 'randomSalt', {
88
+ enumerable: true,
89
+ get: function () {
90
+ return randomSalt;
91
+ }
92
+ });
93
+ Object.defineProperty(exports, 'validateSalt', {
94
+ enumerable: true,
95
+ get: function () {
96
+ return validateSalt;
97
+ }
98
+ });