@arkiv-network/sdk 0.8.0-advanced.2 → 0.8.0-dev.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 (178) hide show
  1. package/README.md +0 -42
  2. package/dist/attr/index.cjs +33 -34
  3. package/dist/attr/index.d.cts +1 -1
  4. package/dist/attr/index.d.ts +1 -2
  5. package/dist/attr/index.js +1 -2
  6. package/dist/{attributes-Df9IsCVs.cjs → attr-BXTkpnoc.cjs} +13 -3
  7. package/dist/{attributes-BhY5DwJp.js → attr-tmyREHtw.js} +14 -4
  8. package/dist/attr-tmyREHtw.js.map +1 -0
  9. package/dist/chains/index.cjs +1 -1
  10. package/dist/chains/index.d.cts +3 -0
  11. package/dist/chains/index.d.cts.map +1 -1
  12. package/dist/chains/index.d.ts +3 -0
  13. package/dist/chains/index.d.ts.map +1 -1
  14. package/dist/chains/index.js +1 -1
  15. package/dist/{chains-BYRTTipa.cjs → chains-BfNQliHU.cjs} +3 -0
  16. package/dist/{chains-BJrZs6sG.js → chains-Du8tql7I.js} +4 -1
  17. package/dist/chains-Du8tql7I.js.map +1 -0
  18. package/dist/{arkivTransactions-NtGD6uk5.d.ts → changeOwnership-B0ar96ub.d.ts} +74 -123
  19. package/dist/changeOwnership-B0ar96ub.d.ts.map +1 -0
  20. package/dist/{arkivTransactions-D74gERHG.d.cts → changeOwnership-BofkLnXJ.d.cts} +74 -123
  21. package/dist/changeOwnership-BofkLnXJ.d.cts.map +1 -0
  22. package/dist/entity/index.cjs +9 -9
  23. package/dist/entity/index.d.cts +3 -3
  24. package/dist/entity/index.d.ts +4 -5
  25. package/dist/entity/index.js +5 -6
  26. package/dist/{entity-BYQR1uoe.js → entity-BIp_df9u.js} +1 -1
  27. package/dist/{entity-BYQR1uoe.js.map → entity-BIp_df9u.js.map} +1 -1
  28. package/dist/{key-D1Bh7MF0.js → entity-CniBgBSd.js} +31 -19
  29. package/dist/entity-CniBgBSd.js.map +1 -0
  30. package/dist/{key-WKhXnXuU.cjs → entity-DJ0Gml9c.cjs} +37 -19
  31. package/dist/{errors-LTe7bOYS.js → errors-D2E1GRjw.js} +2 -2
  32. package/dist/errors-D2E1GRjw.js.map +1 -0
  33. package/dist/{errors-BVbjKVMN.cjs → errors-DhV00966.cjs} +1 -1
  34. package/dist/{expiry-nDbCgZX4.d.ts → expiry-BxOlvVWC.d.ts} +1 -1
  35. package/dist/{expiry-nDbCgZX4.d.ts.map → expiry-BxOlvVWC.d.ts.map} +1 -1
  36. package/dist/{expiry-BELY2Kpw.cjs → expiry-CG9GhVXv.cjs} +1 -1
  37. package/dist/{expiry-BjpxZZQU.js → expiry-Cgdb_dbq.js} +2 -2
  38. package/dist/expiry-Cgdb_dbq.js.map +1 -0
  39. package/dist/expiry-DRV29F1r.d.cts.map +1 -1
  40. package/dist/{flags-CRjPpoh3.d.cts → flags-0Vl5rrHq.d.cts} +1 -1
  41. package/dist/{flags-CRjPpoh3.d.cts.map → flags-0Vl5rrHq.d.cts.map} +1 -1
  42. package/dist/{flags-kr276q6i.cjs → flags-DCD26uhe.cjs} +1 -1
  43. package/dist/{flags-DFBs2J94.js → flags-DUT2gHEU.js} +2 -2
  44. package/dist/{flags-DFBs2J94.js.map → flags-DUT2gHEU.js.map} +1 -1
  45. package/dist/{flags-5dTNRnow.d.ts → flags-wmcMoAnN.d.ts} +1 -1
  46. package/dist/{flags-5dTNRnow.d.ts.map → flags-wmcMoAnN.d.ts.map} +1 -1
  47. package/dist/{index-fX_XyqLp.d.ts → index-BGp2plHs.d.cts} +15 -13
  48. package/dist/index-BGp2plHs.d.cts.map +1 -0
  49. package/dist/{index-DHDud2hC.d.ts → index-BKB875Um.d.ts} +5 -7
  50. package/dist/{index-DHDud2hC.d.ts.map → index-BKB875Um.d.ts.map} +1 -1
  51. package/dist/{index-DvYvrkdk.d.ts → index-CIcHPx2j.d.cts} +110 -6
  52. package/dist/index-CIcHPx2j.d.cts.map +1 -0
  53. package/dist/{index-CV5zCdpa.d.cts → index-Cd2aaWme.d.ts} +13 -6
  54. package/dist/index-Cd2aaWme.d.ts.map +1 -0
  55. package/dist/{index-CA4V7Pdh.d.cts → index-ezMZ2-JH.d.ts} +15 -13
  56. package/dist/index-ezMZ2-JH.d.ts.map +1 -0
  57. package/dist/{index-BF7Mq9Is.d.cts → index-rINthNuU.d.cts} +5 -7
  58. package/dist/{index-BF7Mq9Is.d.cts.map → index-rINthNuU.d.cts.map} +1 -1
  59. package/dist/index.cjs +433 -139
  60. package/dist/index.d.cts +58 -164
  61. package/dist/index.d.cts.map +1 -1
  62. package/dist/index.d.ts +59 -166
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +376 -75
  65. package/dist/index.js.map +1 -1
  66. package/dist/{payload-CcUj85ys.d.ts → payload-CGvVPZQX.d.ts} +61 -2
  67. package/dist/payload-CGvVPZQX.d.ts.map +1 -0
  68. package/dist/{payload-Bz6651ax.js → payload-DE7wMztL.js} +28 -3
  69. package/dist/payload-DE7wMztL.js.map +1 -0
  70. package/dist/{payload-BNoud2KZ.d.cts → payload-Dfu30njp.d.cts} +60 -1
  71. package/dist/payload-Dfu30njp.d.cts.map +1 -0
  72. package/dist/{payload-KC14SDlN.cjs → payload-DqFweqiO.cjs} +27 -2
  73. package/dist/query/index.cjs +5 -7
  74. package/dist/query/index.d.cts +4 -4
  75. package/dist/query/index.d.ts +4 -5
  76. package/dist/query/index.js +5 -7
  77. package/dist/{queryBuilder-DM6AWCBa.js → queryBuilder-wvA8sn--.js} +169 -23
  78. package/dist/queryBuilder-wvA8sn--.js.map +1 -0
  79. package/dist/{queryBuilder-DbUMEZln.cjs → queryBuilder-zHGhDmaG.cjs} +215 -33
  80. package/dist/{selection-DPg0uyJf.d.cts → selection-Bv8_o-7i.d.cts} +76 -68
  81. package/dist/selection-Bv8_o-7i.d.cts.map +1 -0
  82. package/dist/{selection-C4UhsMOO.d.ts → selection-ox7zdtVm.d.ts} +76 -69
  83. package/dist/selection-ox7zdtVm.d.ts.map +1 -0
  84. package/dist/types/index.cjs +2 -2
  85. package/dist/types/index.d.cts +6 -6
  86. package/dist/types/index.d.ts +7 -8
  87. package/dist/types/index.js +2 -2
  88. package/dist/utils/index.cjs +3 -3
  89. package/dist/utils/index.d.cts +1 -1
  90. package/dist/utils/index.d.ts +2 -2
  91. package/dist/utils/index.js +3 -3
  92. package/package.json +1 -5
  93. package/src/actions/public/getEntity.ts +1 -0
  94. package/src/actions/public/predictEntityKeys.test.ts +17 -1
  95. package/src/actions/public/predictEntityKeys.ts +28 -14
  96. package/src/actions/public/query.ts +1 -5
  97. package/src/actions/wallet/createEntity.ts +7 -6
  98. package/src/actions/wallet/{mutateEntities.test.ts → executeBatch.test.ts} +7 -7
  99. package/src/actions/wallet/{mutateEntities.ts → executeBatch.ts} +26 -11
  100. package/src/actions/wallet/extendEntity.ts +1 -0
  101. package/src/actions/wallet/patchEntity.ts +3 -3
  102. package/src/attr/attributes.ts +8 -2
  103. package/src/attr/errors.ts +2 -2
  104. package/src/attr/types.ts +3 -3
  105. package/src/attr/values.ts +5 -1
  106. package/src/chains/localhost.ts +3 -0
  107. package/src/clients/createPublicClient.test.ts +1 -1
  108. package/src/clients/createPublicClient.ts +5 -5
  109. package/src/clients/createWalletClient.test.ts +2 -2
  110. package/src/clients/createWalletClient.ts +3 -5
  111. package/src/clients/decorators/arkivPublic.ts +13 -24
  112. package/src/clients/decorators/arkivWallet.ts +40 -47
  113. package/src/entity/create.test.ts +20 -1
  114. package/src/entity/errors.ts +4 -3
  115. package/src/entity/expiry.ts +1 -0
  116. package/src/entity/index.ts +2 -2
  117. package/src/entity/key.ts +23 -3
  118. package/src/entity/operations.ts +1 -0
  119. package/src/index.ts +0 -13
  120. package/src/query/engine.ts +0 -11
  121. package/src/query/errors.ts +1 -1
  122. package/src/query/expression.ts +14 -7
  123. package/src/query/queryBuilder.test.ts +1 -21
  124. package/src/query/queryBuilder.ts +3 -10
  125. package/src/types/index.ts +4 -4
  126. package/src/types/rpcSchema.ts +1 -0
  127. package/src/types/txParams.ts +8 -0
  128. package/src/utils/arkivTransactions.test.ts +7 -1
  129. package/src/utils/arkivTransactions.ts +114 -254
  130. package/src/utils/expirationTime.ts +39 -0
  131. package/src/utils/payload.ts +25 -0
  132. package/dist/actions/advanced/index.cjs +0 -13
  133. package/dist/actions/advanced/index.d.cts +0 -8
  134. package/dist/actions/advanced/index.d.ts +0 -9
  135. package/dist/actions/advanced/index.js +0 -9
  136. package/dist/advanced-8ZPTmmaN.js +0 -598
  137. package/dist/advanced-8ZPTmmaN.js.map +0 -1
  138. package/dist/advanced-fPImL6lW.cjs +0 -656
  139. package/dist/arkivTransactions-D74gERHG.d.cts.map +0 -1
  140. package/dist/arkivTransactions-NtGD6uk5.d.ts.map +0 -1
  141. package/dist/attributes-BhY5DwJp.js.map +0 -1
  142. package/dist/chains-BJrZs6sG.js.map +0 -1
  143. package/dist/codec-Car3KkFF.d.ts +0 -102
  144. package/dist/codec-Car3KkFF.d.ts.map +0 -1
  145. package/dist/entity-B7G8q_Eo.cjs +0 -0
  146. package/dist/entity-CD_qFF2M.js +0 -0
  147. package/dist/errors-LTe7bOYS.js.map +0 -1
  148. package/dist/expiry-BjpxZZQU.js.map +0 -1
  149. package/dist/index-B5j76711.d.ts +0 -184
  150. package/dist/index-B5j76711.d.ts.map +0 -1
  151. package/dist/index-CA4V7Pdh.d.cts.map +0 -1
  152. package/dist/index-CV5zCdpa.d.cts.map +0 -1
  153. package/dist/index-DvYvrkdk.d.ts.map +0 -1
  154. package/dist/index-EeUO0nnJ.d.cts +0 -184
  155. package/dist/index-EeUO0nnJ.d.cts.map +0 -1
  156. package/dist/index-fX_XyqLp.d.ts.map +0 -1
  157. package/dist/key-D1Bh7MF0.js.map +0 -1
  158. package/dist/logger-CVpvU8ik.js +0 -153
  159. package/dist/logger-CVpvU8ik.js.map +0 -1
  160. package/dist/logger-Cr15lPAQ.cjs +0 -188
  161. package/dist/payload-BNoud2KZ.d.cts.map +0 -1
  162. package/dist/payload-Bz6651ax.js.map +0 -1
  163. package/dist/payload-CcUj85ys.d.ts.map +0 -1
  164. package/dist/queryBuilder-DM6AWCBa.js.map +0 -1
  165. package/dist/selection-C4UhsMOO.d.ts.map +0 -1
  166. package/dist/selection-DPg0uyJf.d.cts.map +0 -1
  167. package/dist/types-Bu_ZwMbZ.js +0 -0
  168. package/dist/types-NRqymi6S.cjs +0 -0
  169. package/src/actions/advanced/advanced.test.ts +0 -258
  170. package/src/actions/advanced/buildMutation.ts +0 -104
  171. package/src/actions/advanced/getMutationResult.ts +0 -112
  172. package/src/actions/advanced/index.ts +0 -21
  173. package/src/actions/advanced/pingTransaction.ts +0 -43
  174. package/src/actions/advanced/sendMutation.ts +0 -59
  175. package/src/clients/decorators/arkivAdvanced.ts +0 -144
  176. /package/dist/{entity-B00Li04j.cjs → entity-B0t6sN7F.cjs} +0 -0
  177. /package/dist/{attr-DlmErkvR.cjs → types-Bx1EKe0v.js} +0 -0
  178. /package/dist/{attr-GcQKatub.js → types-CKPddlfS.cjs} +0 -0
@@ -1,7 +1,13 @@
1
1
  import type { Address, Hex } from "viem"
2
2
  import { getChainId } from "viem/actions"
3
3
  import type { ArkivClient } from "../../clients/baseClient"
4
- import { predictEntityKey, randomSalt, validateSalt } from "../../entity/key"
4
+ import {
5
+ NO_SALT,
6
+ predictEntityKey,
7
+ randomSalt,
8
+ resolveSalt,
9
+ type SaltInput,
10
+ } from "../../entity/key"
5
11
  import { getEntityNonce } from "./getEntityNonce"
6
12
 
7
13
  /**
@@ -13,14 +19,18 @@ import { getEntityNonce } from "./getEntityNonce"
13
19
  export type PredictedEntityKey = {
14
20
  /** The key the create will be given. */
15
21
  key: Hex
16
- /** The salt the create must carry for its key to come out as {@link PredictedEntityKey.key}. */
22
+ /**
23
+ * The salt the create must carry for its key to come out as {@link PredictedEntityKey.key}.
24
+ * Always a plain `uint128` — a requested {@link NO_SALT} comes back as the `0n` it resolves to,
25
+ * which a create accepts just the same.
26
+ */
17
27
  salt: bigint
18
28
  }
19
29
 
20
- /** Parameters for {@link predictEntityKeys}. */
30
+ /** Parameters for `client.predictEntityKeys`. */
21
31
  export type PredictEntityKeysParameters<
22
32
  TCount extends number = number,
23
- TSalts extends readonly bigint[] | undefined = readonly bigint[] | undefined,
33
+ TSalts extends readonly SaltInput[] | undefined = readonly SaltInput[] | undefined,
24
34
  > = {
25
35
  /** The account that will sign the creates. Its nonce is what the keys are derived from. */
26
36
  owner: Address
@@ -34,7 +44,8 @@ export type PredictEntityKeysParameters<
34
44
  count?: TCount | undefined
35
45
  /**
36
46
  * The salt each create will carry, in batch order. Defaults to `count` fresh random salts —
37
- * either way each key comes back paired with the salt that mints it.
47
+ * either way each key comes back paired with the salt that mints it. Pass {@link NO_SALT} in a
48
+ * slot whose create opts out of salting.
38
49
  */
39
50
  salts?: TSalts
40
51
  }
@@ -46,13 +57,13 @@ export type PredictEntityKeysParameters<
46
57
  * tuple, gives a fixed-length tuple; a count computed at runtime gives a plain array.
47
58
  *
48
59
  * `TSalts` is wrapped in a tuple to stop the conditional distributing over it. Left naked, the
49
- * `readonly bigint[] | undefined` default would take both branches and union a tuple with an array,
50
- * which widens the length straight back to `number`.
60
+ * `readonly SaltInput[] | undefined` default would take both branches and union a tuple with an
61
+ * array, which widens the length straight back to `number`.
51
62
  */
52
63
  export type PredictEntityKeysReturnType<
53
64
  TCount extends number = number,
54
- TSalts extends readonly bigint[] | undefined = readonly bigint[] | undefined,
55
- > = [TSalts] extends [readonly bigint[]]
65
+ TSalts extends readonly SaltInput[] | undefined = readonly SaltInput[] | undefined,
66
+ > = [TSalts] extends [readonly SaltInput[]]
56
67
  ? { -readonly [Index in keyof TSalts]: PredictedEntityKey }
57
68
  : Repeat<PredictedEntityKey, TCount>
58
69
 
@@ -79,7 +90,7 @@ type Repeat<T, TLength extends number, TAcc extends T[] = []> = number extends T
79
90
  *
80
91
  * The prediction is valid only while nothing else from this owner is in flight. Every create that
81
92
  * lands first takes the nonce with it and moves these keys. For a key you can rely on
82
- * unconditionally, read it back from the create instead — `createEntity` and `mutateEntities`
93
+ * unconditionally, read it back from the create instead — `createEntity` and `executeBatch`
83
94
  * report the keys the engine actually minted.
84
95
  *
85
96
  * @param parameters - Owner, and either a count or the salts. {@link PredictEntityKeysParameters}
@@ -89,7 +100,7 @@ type Repeat<T, TLength extends number, TAcc extends T[] = []> = number extends T
89
100
  * import { key } from "@arkiv-network/sdk/attr"
90
101
  *
91
102
  * const [parent, child] = await client.predictEntityKeys({ owner: account.address, count: 2 })
92
- * await wallet.mutateEntities({
103
+ * await client.executeBatch({
93
104
  * creates: [
94
105
  * { payload, contentType, expires, salt: parent.salt },
95
106
  * {
@@ -104,7 +115,7 @@ type Repeat<T, TLength extends number, TAcc extends T[] = []> = number extends T
104
115
  */
105
116
  export async function predictEntityKeys<
106
117
  const TCount extends number = number,
107
- const TSalts extends readonly bigint[] | undefined = undefined,
118
+ const TSalts extends readonly SaltInput[] | undefined = undefined,
108
119
  >(
109
120
  client: ArkivClient,
110
121
  { owner, count, salts }: PredictEntityKeysParameters<TCount, TSalts>,
@@ -121,12 +132,15 @@ export async function predictEntityKeys<
121
132
  }
122
133
 
123
134
  /** The salts to derive from: the ones given, or `count` fresh random ones. */
124
- function resolveSalts(count: number | undefined, salts: readonly bigint[] | undefined): bigint[] {
135
+ function resolveSalts(
136
+ count: number | undefined,
137
+ salts: readonly SaltInput[] | undefined,
138
+ ): bigint[] {
125
139
  if (salts !== undefined) {
126
140
  if (salts.length === 0) {
127
141
  throw new Error("predictEntityKeys: `salts` is empty — there is nothing to predict")
128
142
  }
129
- return salts.map(validateSalt)
143
+ return salts.map(resolveSalt)
130
144
  }
131
145
  if (count === undefined) {
132
146
  throw new Error("predictEntityKeys: pass either `count` or `salts`")
@@ -11,11 +11,7 @@ export type QueryOptions = {
11
11
  atBlock?: bigint | undefined
12
12
  /** Page size, up to the node maximum of 200. */
13
13
  limit?: number | undefined
14
- /**
15
- * Cursor from a previous page. Requires that page's `blockNumber` as {@link atBlock} alongside
16
- * it — the cursor is bound to the block it was issued at, so persist the two together. A cursor
17
- * without a block is rejected locally rather than left to fail whenever a block lands mid-walk.
18
- */
14
+ /** Cursor from a previous page. */
19
15
  cursor?: string | undefined
20
16
  }
21
17
 
@@ -1,10 +1,11 @@
1
1
  import type { Hash, Hex } from "viem"
2
2
  import type { AttributeInputs } from "../../attr"
3
3
  import type { ArkivClient } from "../../clients/baseClient"
4
- import type { CreationFlags, Expiry } from "../../entity"
4
+ import type { CreationFlags, Expiry, NO_SALT, SaltInput } from "../../entity"
5
5
  import { EntityMutationError } from "../../errors"
6
6
  import type { MimeType, TxParams } from "../../types"
7
7
  import { sendArkivTransaction } from "../../utils/arkivTransactions"
8
+ import type { ExpirationTime } from "../../utils/expirationTime"
8
9
  import { getLogger } from "../../utils/logger"
9
10
 
10
11
  const logger = getLogger("actions:wallet:create-entity")
@@ -66,8 +67,8 @@ export type CreateEntityParameters = {
66
67
  contentType: MimeType | (string & {})
67
68
  /**
68
69
  * The entity's queryable attributes, keyed by name. Values are the tagged constructors from
69
- * `@arkiv-network/sdk/attr` — `i32`, `u256`, `dec`, `str`, `addr`, `key`, `bytes32`, `bool` — or
70
- * a bare `boolean`, `number`, `bigint` or `string` where the type is unambiguous.
70
+ * `@arkiv-network/sdk/attr` — `i32`, `u64`, `u256`, `dec`, `str`, `addr`, `key`, `bytes32`,
71
+ * `bool` — or a bare `boolean`, `number`, `bigint` or `string` where the type is unambiguous.
71
72
  *
72
73
  * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.
73
74
  * @throws {InvalidValueError} If a value does not fit the type it names or defaults to.
@@ -82,10 +83,10 @@ export type CreateEntityParameters = {
82
83
  * The salt mixed into the entity key. Defaults to 128 random bits, which makes the key
83
84
  * unpredictable to everyone but the creator.
84
85
  *
85
- * Pass `0n` for a key derived from the owner and nonce alone — predictable by anyone, which is
86
- * what you want only when a third party must be able to compute the key in advance.
86
+ * Pass {@link NO_SALT} for a key derived from the owner and nonce alone — predictable by anyone,
87
+ * which is what you want only when a third party must be able to compute the key in advance.
87
88
  */
88
- salt?: bigint | undefined
89
+ salt?: SaltInput | undefined
89
90
  }
90
91
 
91
92
  /**
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it, vi } from "bun:test"
2
2
  import type { ArkivClient } from "../../clients/baseClient"
3
- import { mutateEntities } from "./mutateEntities"
3
+ import { executeBatch } from "./executeBatch"
4
4
 
5
5
  const ENTITY_KEY = `0x${"ab".repeat(32)}` as const
6
6
  const NEW_OWNER = "0x2222222222222222222222222222222222222222"
@@ -29,7 +29,7 @@ describe("the empty-batch guard", () => {
29
29
  // An ownership-only batch is a batch: it used to be rejected because the guard listed
30
30
  // creates/updates/deletes/extensions and forgot ownershipChanges.
31
31
  const { client, writeContract } = makeClient()
32
- const result = await mutateEntities(client, {
32
+ const result = await executeBatch(client, {
33
33
  ownershipChanges: [{ entityKey: ENTITY_KEY, newOwner: NEW_OWNER }],
34
34
  })
35
35
  expect(writeContract).toHaveBeenCalledTimes(1)
@@ -38,9 +38,9 @@ describe("the empty-batch guard", () => {
38
38
 
39
39
  it("rejects a batch with nothing in it", async () => {
40
40
  const { client, writeContract } = makeClient()
41
- await expect(mutateEntities(client, {})).rejects.toThrow(/No operations/)
41
+ await expect(executeBatch(client, {})).rejects.toThrow(/No operations/)
42
42
  // Present but empty is just as empty — the engine would revert with EmptyBatch().
43
- await expect(mutateEntities(client, { deletes: [], ownershipChanges: [] })).rejects.toThrow(
43
+ await expect(executeBatch(client, { deletes: [], ownershipChanges: [] })).rejects.toThrow(
44
44
  /No operations/,
45
45
  )
46
46
  expect(writeContract).not.toHaveBeenCalled()
@@ -52,10 +52,10 @@ describe("the empty-batch guard", () => {
52
52
  // keys would score this batch as non-empty and then drop it on the way to the wire, sending
53
53
  // execute([]) — so the guard counts the five kinds that actually reach the transaction.
54
54
  const stale = { updates: [{ entityKey: ENTITY_KEY, set: { level: 1 } }] } as never
55
- await expect(mutateEntities(client, stale)).rejects.toThrow(/No operations/)
55
+ await expect(executeBatch(client, stale)).rejects.toThrow(/No operations/)
56
56
  // A typo is the same mistake with a different name.
57
57
  await expect(
58
- mutateEntities(client, { delete: [{ entityKey: ENTITY_KEY }] } as never),
58
+ executeBatch(client, { delete: [{ entityKey: ENTITY_KEY }] } as never),
59
59
  ).rejects.toThrow(/No operations/)
60
60
  expect(writeContract).not.toHaveBeenCalled()
61
61
  })
@@ -65,7 +65,7 @@ describe("the empty-batch guard", () => {
65
65
  // The dangerous shape: the creates apply and the transaction succeeds, so nothing surfaces the
66
66
  // fact that the `updates` never happened. The guard cannot catch this one — only the caller's
67
67
  // types can — but the result must at least not claim they did.
68
- const result = await mutateEntities(client, {
68
+ const result = await executeBatch(client, {
69
69
  deletes: [{ entityKey: ENTITY_KEY }],
70
70
  updates: [{ entityKey: ENTITY_KEY, set: { level: 1 } }],
71
71
  } as never)
@@ -1,22 +1,37 @@
1
1
  import type { Hash, Hex } from "viem"
2
2
  import type { ArkivClient } from "../../clients/baseClient"
3
3
  import type { TxParams } from "../../types"
4
- import { type EntityMutationOps, sendArkivTransaction } from "../../utils/arkivTransactions"
4
+ import { sendArkivTransaction } from "../../utils/arkivTransactions"
5
5
  import { getLogger } from "../../utils/logger"
6
+ import type { ChangeOwnershipParameters } from "./changeOwnership"
7
+ import type { CreateEntityParameters } from "./createEntity"
8
+ import type { DeleteEntityParameters } from "./deleteEntity"
9
+ import type { ExtendEntityParameters } from "./extendEntity"
10
+ import type { PatchEntityParameters } from "./patchEntity"
6
11
 
7
- const logger = getLogger("actions:wallet:mutate-entities")
12
+ const logger = getLogger("actions:wallet:execute-batch")
8
13
 
9
14
  /**
10
- * Parameters for the mutateEntities function — the same batch shape the advanced path takes
11
- * ({@link EntityMutationOps}), so the two surfaces cannot drift apart.
15
+ * Parameters for the executeBatch function.
12
16
  *
13
17
  * At least one operation is required; a batch with nothing in it throws rather than spending gas on
14
18
  * an empty transaction.
15
19
  */
16
- export type MutateEntitiesParameters = EntityMutationOps
20
+ export type ExecuteBatchParameters = {
21
+ /** The entities to create. */
22
+ creates?: CreateEntityParameters[]
23
+ /** The patches to apply. */
24
+ patches?: PatchEntityParameters[]
25
+ /** The entities to delete. */
26
+ deletes?: DeleteEntityParameters[]
27
+ /** The expiries to set. */
28
+ extensions?: ExtendEntityParameters[]
29
+ /** The ownership transfers to perform. */
30
+ ownershipChanges?: ChangeOwnershipParameters[]
31
+ }
17
32
 
18
- /** Return type for the mutateEntities function. */
19
- export type MutateEntitiesReturnType = {
33
+ /** Return type for the executeBatch function. */
34
+ export type ExecuteBatchReturnType = {
20
35
  /** The transaction hash. */
21
36
  txHash: Hash
22
37
  /** The keys of the created entities, in batch order. */
@@ -31,14 +46,14 @@ export type MutateEntitiesReturnType = {
31
46
  ownershipChanges: Hex[]
32
47
  }
33
48
 
34
- export async function mutateEntities(
49
+ export async function executeBatch(
35
50
  client: ArkivClient,
36
- data: MutateEntitiesParameters,
51
+ data: ExecuteBatchParameters,
37
52
  txParams?: TxParams,
38
- ): Promise<MutateEntitiesReturnType> {
53
+ ): Promise<ExecuteBatchReturnType> {
39
54
  const { receipt, createdEntityKeys } = await sendArkivTransaction(client, data, txParams)
40
55
 
41
- logger("Receipt from mutateEntities %o", receipt)
56
+ logger("Receipt from executeBatch %o", receipt)
42
57
 
43
58
  return {
44
59
  txHash: receipt.transactionHash as Hash,
@@ -4,6 +4,7 @@ import type { Expiry } from "../../entity"
4
4
  import { EntityMutationError } from "../../errors"
5
5
  import type { TxParams } from "../../types"
6
6
  import { sendArkivTransaction } from "../../utils/arkivTransactions"
7
+ import type { ExpirationTime } from "../../utils/expirationTime"
7
8
  import { getLogger } from "../../utils/logger"
8
9
 
9
10
  const logger = getLogger("actions:wallet:extend-entity")
@@ -38,9 +38,9 @@ export type PatchEntityParameters = {
38
38
  * Attributes to write, keyed by name. An existing attribute is overwritten — including with a
39
39
  * different type — and a name the entity does not carry yet is added.
40
40
  *
41
- * Values are the tagged constructors from `@arkiv-network/sdk/attr` — `i32`, `u256`, `dec`, `str`,
42
- * `addr`, `key`, `bytes32`, `bool` — or a bare `boolean`, `number`, `bigint` or `string` where the
43
- * type is unambiguous.
41
+ * Values are the tagged constructors from `@arkiv-network/sdk/attr` — `i32`, `u64`, `u256`,
42
+ * `dec`, `str`, `addr`, `key`, `bytes32`, `bool` — or a bare `boolean`, `number`, `bigint` or
43
+ * `string` where the type is unambiguous.
44
44
  *
45
45
  * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.
46
46
  * @throws {InvalidValueError} If a value does not fit the type it names or defaults to.
@@ -10,6 +10,10 @@ import { str, toValue, type ValueInput } from "./values"
10
10
  */
11
11
  export const MAX_ATTRIBUTES = 32
12
12
 
13
+ /**
14
+ * The largest payload an entity may carry, in bytes. The payload travels as the `$payload` system
15
+ * cell, so this is a bound on that one attribute rather than on the operation as a whole.
16
+ */
13
17
  export const MAX_PAYLOAD_BYTES = 128 * 1024
14
18
 
15
19
  /** The system attribute holding an entity's opaque payload. */
@@ -20,7 +24,7 @@ const CONTENT_TYPE_CELL = "$contentType"
20
24
  /**
21
25
  * The attributes written on an entity, as a plain object keyed by attribute name.
22
26
  *
23
- * Values may be tagged ({@link ValueInput}) or bare where the type is unambiguous — see
27
+ * Values may be tagged ({@link ArkivValue}) or bare where the type is unambiguous — see
24
28
  * {@link toValue} for the bare-form defaults.
25
29
  *
26
30
  * @example
@@ -141,8 +145,10 @@ export type MutationInputs = SystemCells & {
141
145
  *
142
146
  * @throws {ConflictingMutationError} If a name appears in both `set` and `unset`.
143
147
  * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.
148
+ * @throws {MissingValueError} If a value is `undefined` or `null`.
144
149
  * @throws {InvalidValueError} If a value does not fit its type.
145
- * @throws {TooManyAttributesError} If `set` names more than {@link MAX_ATTRIBUTES} attributes.
150
+ * @throws {TooManyAttributesError} If the mutations exceed {@link MAX_ATTRIBUTES}.
151
+ * @throws {TypeError} If `unset` is not an array.
146
152
  */
147
153
  export function encodeMutations({
148
154
  set,
@@ -32,8 +32,8 @@ export class UntypedValueError extends Error {
32
32
  constructor(input: unknown) {
33
33
  super(
34
34
  `Cannot infer an Arkiv type for ${describe(input)}. ` +
35
- "Attribute values must be a tagged value (i32, u256, dec, str, addr, key, bytes32, bool) " +
36
- "or a bare boolean, number, bigint or string.",
35
+ "Attribute values must be a tagged value (i32, u64, u256, dec, str, addr, key, bytes32, " +
36
+ "bool) or a bare boolean, number, bigint or string.",
37
37
  )
38
38
  this.name = "UntypedValueError"
39
39
  this.input = input
package/src/attr/types.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Address, Hex } from "viem"
2
+ import type { decUnits } from "./values"
2
3
 
3
4
  /**
4
5
  * The protocol's attribute type vocabulary, mapping each short **tag** (the name used by the
@@ -54,8 +55,7 @@ export function isUserSettable(tag: TypeTag): tag is UserTypeTag {
54
55
  /**
55
56
  * Marks a value as having passed its constructor's validation. The symbol is module-private, so a
56
57
  * hand-written object literal is not assignable to {@link ArkivValue} — every value crossing the
57
- * wire has been range-, length- and format-checked by {@link i32}, {@link u256}, {@link dec}, and
58
- * friends.
58
+ * wire has been range-, length- and format-checked by `i32`, `u256`, `dec`, and friends.
59
59
  */
60
60
  declare const validated: unique symbol
61
61
 
@@ -89,7 +89,7 @@ export type U256Value = Value<"u256", bigint>
89
89
  export type DecValue = Value<"dec", string>
90
90
  /** 32 opaque bytes, as lowercase `0x` hex. */
91
91
  export type Bytes32Value = Value<"bytes32", Hex>
92
- /** A UTF-8 string of at most 128 bytes. */
92
+ /** A UTF-8 string of at most 128 bytes, free of C0 control characters and DEL. */
93
93
  export type StrValue = Value<"str", string>
94
94
  /** A 20-byte Ethereum address, as EIP-55 checksummed hex. */
95
95
  export type AddrValue = Value<"addr", Address>
@@ -271,7 +271,11 @@ export function decFromUnits(units: bigint): DecValue {
271
271
  *
272
272
  * The limit is on **bytes**, not characters: a string of 128 emoji does not fit.
273
273
  *
274
- * @throws {InvalidValueError} If the string exceeds 128 UTF-8 bytes.
274
+ * C0 control characters and DEL are rejected: the query language writes a `str` as `str('...')`,
275
+ * whose only escape is a doubled quote, so a control character could be stored but never queried.
276
+ *
277
+ * @throws {InvalidValueError} If the value is not a string, holds a control character, or exceeds
278
+ * 128 UTF-8 bytes.
275
279
  *
276
280
  * @example
277
281
  * str("Bob")
@@ -1,5 +1,8 @@
1
1
  import { defineChain } from "viem"
2
2
 
3
+ /**
4
+ * A node running on the local machine
5
+ */
3
6
  export const localhost = defineChain({
4
7
  id: 1337,
5
8
  name: "Localhost",
@@ -35,5 +35,5 @@ test("creates", () => {
35
35
  expect(client.deleteEntity).not.toBeDefined()
36
36
  expect(client.extendEntity).not.toBeDefined()
37
37
  expect(client.changeOwnership).not.toBeDefined()
38
- expect(client.mutateEntities).not.toBeDefined()
38
+ expect(client.executeBatch).not.toBeDefined()
39
39
  })
@@ -23,14 +23,14 @@ export type PublicArkivClient<
23
23
  >
24
24
 
25
25
  /**
26
- * Creates a Public Client with a given [Transport](https://viem.sh/docs/clients/intro) configured for a [Chain](https://viem.sh/docs/clients/chains).
26
+ * Creates a Public Client with a given [Transport](https://viem.sh/docs/clients/intro) configured for a [Chain](https://viem.sh/docs/chains/introduction).
27
27
  *
28
- * - Docs: https://docs.arkiv.network/ts-sdk/clients/public
29
- *
30
- * 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).
28
+ * A Public Client is an interface to the "public" [Ethereum JSON-RPC API](https://ethereum.org/en/developers/docs/apis/json-rpc/)
29
+ * and the Arkiv JSON-RPC API — retrieving block numbers and transactions, reading from
30
+ * contracts, and querying entities — through {@link PublicArkivActions}.
31
31
  *
32
32
  * @param parameters - Configuration object for the public client (chain, transport, etc.)
33
- * @returns A Arkiv Public Client. {@link PublicArkivClient}
33
+ * @returns An Arkiv Public Client. {@link PublicArkivClient}
34
34
  *
35
35
  * @example
36
36
  * import { createPublicClient } from "@arkiv-network/sdk"
@@ -29,6 +29,6 @@ test("creates", () => {
29
29
  expect(typeof client.extendEntity).toBe("function")
30
30
  expect(client.changeOwnership).toBeDefined()
31
31
  expect(typeof client.changeOwnership).toBe("function")
32
- expect(client.mutateEntities).toBeDefined()
33
- expect(typeof client.mutateEntities).toBe("function")
32
+ expect(client.executeBatch).toBeDefined()
33
+ expect(typeof client.executeBatch).toBe("function")
34
34
  })
@@ -24,16 +24,14 @@ export type WalletArkivClient<
24
24
 
25
25
  /**
26
26
  * Creates a Wallet Client with a given [Transport](https://viem.sh/docs/clients/intro) configured
27
- * for a [Chain](https://viem.sh/docs/clients/chains) and an account.
28
- *
29
- * - Docs: https://docs.arkiv.network/ts-sdk/clients/wallet
27
+ * for a [Chain](https://viem.sh/docs/chains/introduction) and an account.
30
28
  *
31
29
  * A Wallet Client signs and sends transactions, so it carries an `account` and exposes everything
32
30
  * that mutates state — `createEntity`, `patchEntity`, `deleteEntity`, `extendEntity`,
33
- * `changeOwnership` and `mutateEntities` — on top of the read actions a Public Client has.
31
+ * `changeOwnership` and `executeBatch` — on top of the read actions a Public Client has.
34
32
  *
35
33
  * @param parameters - Configuration object for the wallet client (chain, transport, account, etc.)
36
- * @returns A Arkiv Wallet Client. {@link WalletArkivClient}
34
+ * @returns An Arkiv Wallet Client. {@link WalletArkivClient}
37
35
  *
38
36
  * @example
39
37
  * import { createWalletClient } from "@arkiv-network/sdk"
@@ -1,5 +1,5 @@
1
1
  import type { Account, Address, Chain, Client, Hex, PublicActions, Transport } from "viem"
2
- import { getBlockTiming } from "../../actions/public/getBlockTiming"
2
+ import { type GetBlockTimingReturnType, getBlockTiming } from "../../actions/public/getBlockTiming"
3
3
  import { getEntity } from "../../actions/public/getEntity"
4
4
  import { getEntityCount } from "../../actions/public/getEntityCount"
5
5
  import { getEntityNonce } from "../../actions/public/getEntityNonce"
@@ -13,11 +13,11 @@ import {
13
13
  type WatchEntityEventsParameters,
14
14
  watchEntityEvents,
15
15
  } from "../../actions/public/watchEntityEvents"
16
+ import type { SaltInput } from "../../entity/key"
16
17
  import type { Expression } from "../../query/expression"
17
18
  import { SelectQueryBuilder } from "../../query/queryBuilder"
18
19
  import type { EntitySelection, FullEntity, ProjectedEntity, SelectArg } from "../../query/selection"
19
20
  import type { Entity } from "../../types/entity"
20
- import { type PublicAdvancedActions, publicAdvancedActions } from "./arkivAdvanced"
21
21
 
22
22
  export type PublicArkivActions<
23
23
  transport extends Transport = Transport,
@@ -39,11 +39,15 @@ export type PublicArkivActions<
39
39
  /**
40
40
  * Returns the entity with the given key.
41
41
  *
42
- * - Docs: https://docs.arkiv.network/ts-sdk/actions/public/getEntity
42
+ * - JSON-RPC Methods: `arkiv_query`
43
43
  *
44
44
  * @param key - The entity key (hex string)
45
45
  * @returns The entity with the given key, with every field populated. {@link FullEntity}
46
46
  *
47
+ * @throws {InvalidValueError} If the key is not 32 bytes.
48
+ * @throws {NoEntityFoundError} If no live entity has that key — it never existed, or it was
49
+ * deleted or has expired.
50
+ *
47
51
  * @example
48
52
  * import { createPublicClient } from "@arkiv-network/sdk"
49
53
  * import { cheesecake } from "@arkiv-network/sdk/chains"
@@ -70,7 +74,7 @@ export type PublicArkivActions<
70
74
  * read entities. You declare up front which parts of an entity you want returned, so results
71
75
  * always contain exactly the data you asked for.
72
76
  *
73
- * - Docs: https://docs.arkiv.network/ts-sdk/actions/public/query
77
+ * - JSON-RPC Methods: `arkiv_query`
74
78
  *
75
79
  * @param selection - What to include in the results. Omit it (or pass `"*"`) to select everything,
76
80
  * or pass an object to select specific parts (at least one field is required). Every part is
@@ -131,7 +135,7 @@ export type PublicArkivActions<
131
135
  /**
132
136
  * Runs one query and returns one page, with no builder in between.
133
137
  *
134
- * Use {@link select} for anything typed — this returns full {@link Entity} objects whatever the
138
+ * Use {@link PublicArkivActions.select} for anything typed — this returns full {@link Entity} objects whatever the
135
139
  * selection, and takes a raw string as an escape hatch for a query built elsewhere. A raw string
136
140
  * goes to the node exactly as written, with none of the name, type or operator checks the
137
141
  * expression combinators apply.
@@ -225,7 +229,7 @@ export type PublicArkivActions<
225
229
  * import { key } from "@arkiv-network/sdk/attr"
226
230
  *
227
231
  * const [parent, child] = await client.predictEntityKeys({ owner: account.address, count: 2 })
228
- * await wallet.mutateEntities({
232
+ * await wallet.executeBatch({
229
233
  * creates: [
230
234
  * { payload, contentType, expires, salt: parent.salt },
231
235
  * {
@@ -240,7 +244,7 @@ export type PublicArkivActions<
240
244
  */
241
245
  predictEntityKeys: <
242
246
  const TCount extends number = number,
243
- const TSalts extends readonly bigint[] | undefined = undefined,
247
+ const TSalts extends readonly SaltInput[] | undefined = undefined,
244
248
  >(
245
249
  parameters: PredictEntityKeysParameters<TCount, TSalts>,
246
250
  ) => Promise<PredictEntityKeysReturnType<TCount, TSalts>>
@@ -265,11 +269,7 @@ export type PublicArkivActions<
265
269
  * // blockDuration: 2, // in seconds
266
270
  * // }
267
271
  */
268
- getBlockTiming: () => Promise<{
269
- currentBlock: bigint
270
- currentBlockTime: number
271
- blockDuration: number
272
- }>
272
+ getBlockTiming: () => Promise<GetBlockTimingReturnType>
273
273
 
274
274
  /**
275
275
  * Watches entity events, calling the handlers you pass as they arrive.
@@ -298,16 +298,6 @@ export type PublicArkivActions<
298
298
  * unwatch() // stop watching
299
299
  */
300
300
  watchEntityEvents: (parameters: WatchEntityEventsParameters) => () => void
301
-
302
- /**
303
- * The read-only half of the advanced path: check on a transaction and decode its result with at
304
- * most one RPC call per action — so a process that holds nothing but a transaction hash can
305
- * follow it without a wallet. {@link PublicAdvancedActions}
306
- *
307
- * @example
308
- * const { status } = await client.advanced.pingTransaction(txHash) // 1 eth_getTransactionReceipt
309
- */
310
- advanced: PublicAdvancedActions
311
301
  }
312
302
 
313
303
  export function publicArkivActions<
@@ -325,12 +315,11 @@ export function publicArkivActions<
325
315
  getEntityNonce: (owner: Address) => getEntityNonce(client, owner),
326
316
  predictEntityKeys: <
327
317
  const TCount extends number = number,
328
- const TSalts extends readonly bigint[] | undefined = undefined,
318
+ const TSalts extends readonly SaltInput[] | undefined = undefined,
329
319
  >(
330
320
  parameters: PredictEntityKeysParameters<TCount, TSalts>,
331
321
  ) => predictEntityKeys(client, parameters),
332
322
  watchEntityEvents: (parameters: WatchEntityEventsParameters) =>
333
323
  watchEntityEvents(client, parameters),
334
- advanced: publicAdvancedActions(client),
335
324
  }
336
325
  }