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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/README.md +29 -16
  2. package/dist/attr/index.cjs +34 -0
  3. package/dist/attr/index.d.cts +2 -0
  4. package/dist/attr/index.d.ts +2 -0
  5. package/dist/attr/index.js +3 -0
  6. package/dist/attr-BDZ-APg5.js +809 -0
  7. package/dist/attr-BDZ-APg5.js.map +1 -0
  8. package/dist/attr-BvxHN99W.cjs +1029 -0
  9. package/dist/chains/index.cjs +2 -3
  10. package/dist/chains/index.d.cts +39 -77
  11. package/dist/chains/index.d.cts.map +1 -1
  12. package/dist/chains/index.d.ts +22 -60
  13. package/dist/chains/index.d.ts.map +1 -1
  14. package/dist/chains/index.js +2 -2
  15. package/dist/chains-BJrZs6sG.js +57 -0
  16. package/dist/chains-BJrZs6sG.js.map +1 -0
  17. package/dist/chains-BYRTTipa.cjs +73 -0
  18. package/dist/changeOwnership-B7bEgla4.d.cts +509 -0
  19. package/dist/changeOwnership-B7bEgla4.d.cts.map +1 -0
  20. package/dist/changeOwnership-DwgtdSFc.d.ts +509 -0
  21. package/dist/changeOwnership-DwgtdSFc.d.ts.map +1 -0
  22. package/dist/entity/index.cjs +19 -0
  23. package/dist/entity/index.d.cts +4 -0
  24. package/dist/entity/index.d.ts +4 -0
  25. package/dist/entity/index.js +6 -0
  26. package/dist/entity-B0t6sN7F.cjs +71 -0
  27. package/dist/entity-BIp_df9u.js +67 -0
  28. package/dist/entity-BIp_df9u.js.map +1 -0
  29. package/dist/entity-CFhbAv0R.js +70 -0
  30. package/dist/entity-CFhbAv0R.js.map +1 -0
  31. package/dist/entity-wfBnZd91.cjs +98 -0
  32. package/dist/errors-D-eJkGVc.cjs +56 -0
  33. package/dist/errors-DGB8AgT2.js +33 -0
  34. package/dist/errors-DGB8AgT2.js.map +1 -0
  35. package/dist/expiry-BUYIXTGb.cjs +135 -0
  36. package/dist/expiry-BxOlvVWC.d.ts +79 -0
  37. package/dist/expiry-BxOlvVWC.d.ts.map +1 -0
  38. package/dist/expiry-DGRzrSan.js +95 -0
  39. package/dist/expiry-DGRzrSan.js.map +1 -0
  40. package/dist/expiry-DRV29F1r.d.cts +79 -0
  41. package/dist/expiry-DRV29F1r.d.cts.map +1 -0
  42. package/dist/flags-0Vl5rrHq.d.cts +41 -0
  43. package/dist/flags-0Vl5rrHq.d.cts.map +1 -0
  44. package/dist/flags-Ct8k0gpB.cjs +43 -0
  45. package/dist/flags-ZtlvOIIk.js +33 -0
  46. package/dist/flags-ZtlvOIIk.js.map +1 -0
  47. package/dist/flags-wmcMoAnN.d.ts +41 -0
  48. package/dist/flags-wmcMoAnN.d.ts.map +1 -0
  49. package/dist/index-Cgw1u5aY.d.cts +278 -0
  50. package/dist/index-Cgw1u5aY.d.cts.map +1 -0
  51. package/dist/index-ClgIuxJ8.d.ts +159 -0
  52. package/dist/index-ClgIuxJ8.d.ts.map +1 -0
  53. package/dist/index-D0CmtiWT.d.cts +159 -0
  54. package/dist/index-D0CmtiWT.d.cts.map +1 -0
  55. package/dist/index-D8LZt-3J.d.cts +417 -0
  56. package/dist/index-D8LZt-3J.d.cts.map +1 -0
  57. package/dist/index-DVYFaXNV.d.ts +417 -0
  58. package/dist/index-DVYFaXNV.d.ts.map +1 -0
  59. package/dist/index-VCqgn29D.d.ts +278 -0
  60. package/dist/index-VCqgn29D.d.ts.map +1 -0
  61. package/dist/index.cjs +675 -357
  62. package/dist/index.d.cts +251 -203
  63. package/dist/index.d.cts.map +1 -1
  64. package/dist/index.d.ts +251 -203
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +626 -355
  67. package/dist/index.js.map +1 -1
  68. package/dist/payload-Bnw1hrvb.cjs +83 -0
  69. package/dist/payload-CIxSn_DW.js +67 -0
  70. package/dist/payload-CIxSn_DW.js.map +1 -0
  71. package/dist/payload-Dgx3PQeK.d.ts +94 -0
  72. package/dist/payload-Dgx3PQeK.d.ts.map +1 -0
  73. package/dist/payload-P0nWyjLg.d.cts +94 -0
  74. package/dist/payload-P0nWyjLg.d.cts.map +1 -0
  75. package/dist/query/index.cjs +24 -149
  76. package/dist/query/index.d.cts +5 -3
  77. package/dist/query/index.d.ts +5 -3
  78. package/dist/query/index.js +6 -137
  79. package/dist/queryBuilder-BXDvX1K_.cjs +1123 -0
  80. package/dist/queryBuilder-CbLL4pG5.js +963 -0
  81. package/dist/queryBuilder-CbLL4pG5.js.map +1 -0
  82. package/dist/selection-BvK6yX0g.d.cts +433 -0
  83. package/dist/selection-BvK6yX0g.d.cts.map +1 -0
  84. package/dist/selection-fpmI3ADQ.d.ts +433 -0
  85. package/dist/selection-fpmI3ADQ.d.ts.map +1 -0
  86. package/dist/types/index.cjs +4 -1
  87. package/dist/types/index.d.cts +7 -2
  88. package/dist/types/index.d.ts +7 -2
  89. package/dist/types/index.js +4 -1
  90. package/dist/utils/index.cjs +4 -17
  91. package/dist/utils/index.d.cts +3 -17
  92. package/dist/utils/index.d.ts +3 -17
  93. package/dist/utils/index.js +4 -18
  94. package/package.json +26 -5
  95. package/src/actions/public/getEntity.ts +27 -43
  96. package/src/actions/public/getEntityNonce.ts +30 -0
  97. package/src/actions/public/predictEntityKeys.test.ts +143 -0
  98. package/src/actions/public/predictEntityKeys.ts +138 -0
  99. package/src/actions/public/query.ts +33 -69
  100. package/src/actions/public/watchEntityEvents.test.ts +414 -0
  101. package/src/actions/public/watchEntityEvents.ts +225 -0
  102. package/src/actions/wallet/changeOwnership.ts +8 -8
  103. package/src/actions/wallet/createEntity.ts +104 -26
  104. package/src/actions/wallet/deleteEntity.ts +2 -3
  105. package/src/actions/wallet/extendEntity.ts +39 -16
  106. package/src/actions/wallet/mutateEntities.test.ts +76 -0
  107. package/src/actions/wallet/mutateEntities.ts +29 -74
  108. package/src/actions/wallet/patchEntity.ts +90 -0
  109. package/src/attr/attributes.test.ts +120 -0
  110. package/src/attr/attributes.ts +190 -0
  111. package/src/attr/codec.test.ts +162 -0
  112. package/src/attr/codec.ts +220 -0
  113. package/src/attr/decimal.ts +86 -0
  114. package/src/attr/errors.ts +145 -0
  115. package/src/attr/index.ts +50 -0
  116. package/src/attr/names.ts +106 -0
  117. package/src/attr/types.ts +150 -0
  118. package/src/attr/values.test.ts +271 -0
  119. package/src/attr/values.ts +502 -0
  120. package/src/chains/cheesecake.ts +22 -0
  121. package/src/chains/index.ts +1 -2
  122. package/src/clients/createPublicClient.test.ts +3 -5
  123. package/src/clients/createPublicClient.ts +5 -4
  124. package/src/clients/createWalletClient.test.ts +2 -2
  125. package/src/clients/createWalletClient.ts +13 -7
  126. package/src/clients/decorators/arkivPublic.ts +160 -139
  127. package/src/clients/decorators/arkivWallet.ts +91 -95
  128. package/src/consts.ts +2 -1
  129. package/src/entity/create.test.ts +184 -0
  130. package/src/entity/errors.ts +38 -0
  131. package/src/entity/events.ts +16 -0
  132. package/src/entity/expiry.test.ts +195 -0
  133. package/src/entity/expiry.ts +181 -0
  134. package/src/entity/flags.ts +65 -0
  135. package/src/entity/index.ts +14 -0
  136. package/src/entity/key.ts +68 -0
  137. package/src/entity/operations.ts +134 -0
  138. package/src/entity/params.ts +15 -0
  139. package/src/errors.ts +33 -28
  140. package/src/index.ts +6 -0
  141. package/src/query/engine.ts +59 -134
  142. package/src/query/errors.ts +151 -0
  143. package/src/query/expression.test.ts +286 -0
  144. package/src/query/expression.ts +493 -0
  145. package/src/query/index.ts +40 -4
  146. package/src/query/injection.test.ts +151 -0
  147. package/src/query/queryBuilder.test.ts +322 -637
  148. package/src/query/queryBuilder.ts +126 -359
  149. package/src/query/queryResult.ts +54 -51
  150. package/src/query/selection.test.ts +48 -98
  151. package/src/query/selection.ts +77 -65
  152. package/src/types/entity.test.ts +44 -155
  153. package/src/types/entity.ts +62 -44
  154. package/src/types/events.ts +64 -23
  155. package/src/types/index.ts +20 -16
  156. package/src/types/rpcSchema.ts +70 -33
  157. package/src/utils/arkivTransactions.test.ts +681 -38
  158. package/src/utils/arkivTransactions.ts +249 -104
  159. package/src/utils/chains.test.ts +21 -24
  160. package/src/utils/compression.ts +1 -1
  161. package/src/utils/entities.test.ts +62 -0
  162. package/src/utils/entities.ts +111 -29
  163. package/src/utils/expirationTime.ts +114 -10
  164. package/src/utils/logger.ts +2 -2
  165. package/src/utils/payload.ts +4 -2
  166. package/src/utils/revert.test.ts +99 -0
  167. package/src/utils/revert.ts +145 -0
  168. package/dist/chains-BifaY04V.cjs +0 -108
  169. package/dist/chains-CrtkVbBh.js +0 -86
  170. package/dist/chains-CrtkVbBh.js.map +0 -1
  171. package/dist/consts-AUoL-v42.cjs +0 -18
  172. package/dist/consts-BV4PR-de.js +0 -7
  173. package/dist/consts-BV4PR-de.js.map +0 -1
  174. package/dist/entity-B6g_EPm1.d.cts +0 -382
  175. package/dist/entity-B6g_EPm1.d.cts.map +0 -1
  176. package/dist/entity-qoLMAuuk.d.ts +0 -382
  177. package/dist/entity-qoLMAuuk.d.ts.map +0 -1
  178. package/dist/index-DdspxNAA.d.ts +0 -481
  179. package/dist/index-DdspxNAA.d.ts.map +0 -1
  180. package/dist/index-Ds9dwqb5.d.cts +0 -481
  181. package/dist/index-Ds9dwqb5.d.cts.map +0 -1
  182. package/dist/payload-B2kFJyah.d.ts +0 -6
  183. package/dist/payload-B2kFJyah.d.ts.map +0 -1
  184. package/dist/payload-CJN8fTvX.d.cts +0 -6
  185. package/dist/payload-CJN8fTvX.d.cts.map +0 -1
  186. package/dist/payload-Claf2jUO.js +0 -13
  187. package/dist/payload-Claf2jUO.js.map +0 -1
  188. package/dist/payload-DpA5PA-w.cjs +0 -23
  189. package/dist/query/index.js.map +0 -1
  190. package/dist/queryBuilder-D2uwP9jI.js +0 -704
  191. package/dist/queryBuilder-D2uwP9jI.js.map +0 -1
  192. package/dist/queryBuilder-UW2MCaX4.cjs +0 -792
  193. package/dist/utils/index.d.cts.map +0 -1
  194. package/dist/utils/index.d.ts.map +0 -1
  195. package/dist/utils/index.js.map +0 -1
  196. package/src/actions/public/buildQuery.ts +0 -10
  197. package/src/actions/public/subscribeEntityEvents.ts +0 -119
  198. package/src/actions/wallet/updateEntity.ts +0 -60
  199. package/src/chains/braga.ts +0 -26
  200. package/src/chains/kaolin.ts +0 -29
  201. package/src/query/engine.test.ts +0 -526
  202. package/src/query/predicate.test.ts +0 -461
  203. package/src/query/predicate.ts +0 -144
  204. package/src/query/queryResult.test.ts +0 -270
  205. package/src/query/selectQueryBuilder.test.ts +0 -210
  206. package/src/types/attributes.ts +0 -16
  207. package/src/utils/validation.test.ts +0 -60
  208. package/src/utils/validation.ts +0 -32
  209. /package/dist/{types-H-TSmRpm.js → types-Bx1EKe0v.js} +0 -0
  210. /package/dist/{types-o3zWarRp.cjs → types-CKPddlfS.cjs} +0 -0
@@ -0,0 +1,1029 @@
1
+ let viem = require("viem");
2
+
3
+ //#region src/attr/errors.ts
4
+ /**
5
+ * A value was rejected by its tagged constructor — out of range, wrong length, bad checksum, too
6
+ * much precision, and so on.
7
+ *
8
+ * The message names the offending value and, where there is one, the type that *would* hold it, so
9
+ * the fix is in the error rather than in the docs.
10
+ */
11
+ var InvalidValueError = class extends Error {
12
+ /** The type tag whose constructor rejected the value. */
13
+ tag;
14
+ /** The rejected input, as given. */
15
+ input;
16
+ constructor(tag, input, reason, hint) {
17
+ super(`Invalid ${tag} value ${describe(input)}: ${reason}.${hint ? ` ${hint}` : ""}`);
18
+ this.name = "InvalidValueError";
19
+ this.tag = tag;
20
+ this.input = input;
21
+ }
22
+ };
23
+ /**
24
+ * A bare JavaScript value could not be given a type. Raised when an attribute or predicate is
25
+ * handed something that is neither a tagged value nor one of the four bare forms
26
+ * (`boolean`, `number`, `bigint`, `string`).
27
+ */
28
+ var UntypedValueError = class extends Error {
29
+ input;
30
+ constructor(input) {
31
+ super(`Cannot infer an Arkiv type for ${describe(input)}. Attribute values must be a tagged value (i32, u256, dec, str, addr, key, bytes32, bool) or a bare boolean, number, bigint or string.`);
32
+ this.name = "UntypedValueError";
33
+ this.input = input;
34
+ }
35
+ };
36
+ /**
37
+ * An attribute was given `undefined` or `null` as its value.
38
+ *
39
+ * There is no such thing as an attribute with no value: an attribute either exists with a type, or
40
+ * is not set. The fix is always to leave the name out of the map rather than to write an empty
41
+ * value, so this is called out separately from {@link UntypedValueError} — the remedy is different.
42
+ */
43
+ var MissingValueError = class extends Error {
44
+ /** The attribute whose value was missing, when raised from an attribute map. */
45
+ attributeName;
46
+ constructor(input, attributeName) {
47
+ const subject = attributeName ? `attribute "${attributeName}"` : "attribute value";
48
+ super(`The ${subject} is ${input === null ? "null" : "undefined"}. An attribute is either set with a value and a type or not set at all, so there is nothing to write here. ` + (attributeName ? `Omit "${attributeName}" from the attributes instead — e.g. build the map conditionally, or drop the key when the value is absent.` : "Omit the attribute instead of giving it an empty value."));
49
+ this.name = "MissingValueError";
50
+ this.attributeName = attributeName;
51
+ }
52
+ };
53
+ /** An attribute name violated the on-chain name grammar. */
54
+ var InvalidAttributeNameError = class extends Error {
55
+ attributeName;
56
+ constructor(attributeName, reason) {
57
+ super(`Invalid attribute name "${attributeName}": ${reason}. Names must be 1-32 bytes, start with a letter, and contain only A-Z, a-z, 0-9, ".", "-" or "_". Names are case-sensitive.`);
58
+ this.name = "InvalidAttributeNameError";
59
+ this.attributeName = attributeName;
60
+ }
61
+ };
62
+ /**
63
+ * One patch tried to both write and remove the same attribute.
64
+ */
65
+ var ConflictingMutationError = class extends Error {
66
+ attributeName;
67
+ constructor(attributeName) {
68
+ super(`The patch both sets and unsets "${attributeName}". A patch applies one mutation per attribute, so say which you mean: drop it from "unset" to write the value, or from "set" to remove the attribute.`);
69
+ this.name = "ConflictingMutationError";
70
+ this.attributeName = attributeName;
71
+ }
72
+ };
73
+ /** More attributes were supplied than an entity operation can carry. */
74
+ var TooManyAttributesError = class extends Error {
75
+ constructor(count, max) {
76
+ super(`An entity may carry at most ${max} attributes, got ${count}.`);
77
+ this.name = "TooManyAttributesError";
78
+ }
79
+ };
80
+ /** The node sent back an attribute this SDK cannot decode. */
81
+ var UnknownAttributeTypeError = class extends Error {
82
+ /** The type as the node named it — a tag over JSON-RPC, a typeId on the wire. */
83
+ type;
84
+ constructor(type) {
85
+ super(`Unknown attribute type ${describe(type)}. The node is using a type this SDK version does not know about — upgrade @arkiv-network/sdk.`);
86
+ this.name = "UnknownAttributeTypeError";
87
+ this.type = type;
88
+ }
89
+ };
90
+ /** Renders an arbitrary input for an error message, without ever throwing. */
91
+ function describe(input) {
92
+ switch (typeof input) {
93
+ case "string": return JSON.stringify(input.length > 64 ? `${input.slice(0, 61)}...` : input);
94
+ case "bigint": return `${input}n`;
95
+ case "object": return input === null ? "null" : safeJson(input);
96
+ case "undefined": return "undefined";
97
+ default: return String(input);
98
+ }
99
+ }
100
+ function safeJson(input) {
101
+ try {
102
+ return JSON.stringify(input) ?? String(input);
103
+ } catch {
104
+ return Object.prototype.toString.call(input);
105
+ }
106
+ }
107
+
108
+ //#endregion
109
+ //#region src/attr/decimal.ts
110
+ /**
111
+ * Decimal places a `dec` value is scaled by. Fixed by the protocol, so any two decimals are
112
+ * directly comparable — and range-indexable — as plain integers.
113
+ */
114
+ const DECIMAL_SCALE = 18;
115
+ /** 10 ** {@link DECIMAL_SCALE} — the scaling factor between a `dec` and its integer units. */
116
+ const DECIMAL_UNIT = 10n ** BigInt(DECIMAL_SCALE);
117
+ /** The widest scaled value an `int256` holds. */
118
+ const INT256_MAX = 2n ** 255n - 1n;
119
+ /** The narrowest scaled value an `int256` holds. */
120
+ const INT256_MIN = -(2n ** 255n);
121
+ /**
122
+ * A decimal literal: an optional sign, at least one integer digit, and an optional fraction of at
123
+ * most {@link DECIMAL_SCALE} digits. Exponents are not part of the grammar — `1e18` is a parse
124
+ * error rather than a silent reinterpretation.
125
+ */
126
+ const DECIMAL_RE = /^([+-]?)(\d+)(?:\.(\d+))?$/;
127
+ /**
128
+ * Parses a decimal literal into its scaled integer units.
129
+ *
130
+ * Excess fractional precision is an **error, never a rounding**: the protocol stores exactly 18
131
+ * decimal places, and silently dropping the 19th digit would make a stored value differ from the
132
+ * one that was written.
133
+ *
134
+ * @param input - The decimal literal, e.g. `"3.5"` or `"-0.000001"`.
135
+ * @returns The value scaled by 10 ** 18.
136
+ * @throws {InvalidValueError} If the literal is malformed, too precise, or out of `int256` range.
137
+ */
138
+ function decimalToUnits(input) {
139
+ const match = DECIMAL_RE.exec(input);
140
+ if (!match) throw new InvalidValueError("dec", input, "not a decimal literal", "Write it as sign, digits, and an optional \".\" with up to 18 fractional digits — e.g. dec(\"3.5\") or dec(\"-0.25\"). Exponents such as \"1e18\" are not accepted.");
141
+ const [, sign, whole, fraction = ""] = match;
142
+ if (fraction.length > DECIMAL_SCALE) throw new InvalidValueError("dec", input, `${fraction.length} fractional digits exceeds the ${DECIMAL_SCALE} the protocol stores`, "Round it yourself before storing — a dec is never rounded for you, so that what you write is exactly what is stored.");
143
+ const digits = BigInt(whole + fraction.padEnd(DECIMAL_SCALE, "0"));
144
+ const units = sign === "-" ? -digits : digits;
145
+ if (units > INT256_MAX || units < INT256_MIN) throw new InvalidValueError("dec", input, "exceeds the int256 range a dec is stored in");
146
+ return units;
147
+ }
148
+ /**
149
+ * Renders scaled integer units back as a canonical decimal string: no leading zeros, no trailing
150
+ * fractional zeros, no `-0`. Parsing the result yields the same units, so this is the inverse of
151
+ * {@link decimalToUnits} on every value it accepts.
152
+ *
153
+ * @param units - The value scaled by 10 ** 18.
154
+ * @returns The canonical decimal string, e.g. `"3.5"`.
155
+ * @throws {InvalidValueError} If the units are outside the `int256` range.
156
+ */
157
+ function unitsToDecimal(units) {
158
+ if (units > INT256_MAX || units < INT256_MIN) throw new InvalidValueError("dec", units, "exceeds the int256 range a dec is stored in");
159
+ const negative = units < 0n;
160
+ const magnitude = negative ? -units : units;
161
+ const whole = magnitude / DECIMAL_UNIT;
162
+ const trimmed = (magnitude % DECIMAL_UNIT).toString().padStart(DECIMAL_SCALE, "0").replace(/0+$/, "");
163
+ const sign = negative ? "-" : "";
164
+ return trimmed ? `${sign}${whole}.${trimmed}` : `${sign}${whole}`;
165
+ }
166
+
167
+ //#endregion
168
+ //#region src/attr/types.ts
169
+ /**
170
+ * The protocol's attribute type vocabulary, mapping each short **tag** (the name used by the
171
+ * client, the query language and this SDK) to its **typeId** (the byte carried on the wire and in
172
+ * the entity record).
173
+ *
174
+ * The typeIds are consensus-critical: they are written into entity records and mixed into index
175
+ * keys, so this table must never drift from the node's `AttributeType`.
176
+ *
177
+ * | tag | typeId | ABI wire type | indexing |
178
+ * | --------- | ------ | ------------------- | ----------------- |
179
+ * | `bool` | 1 | `bool` | equality |
180
+ * | `i32` | 2 | `int32` | equality + range |
181
+ * | `u64` | 3 | `uint64` | equality + range |
182
+ * | `u256` | 4 | `uint256` | equality + range |
183
+ * | `dec` | 5 | `int256` (18 dp) | equality + range |
184
+ * | `bytes32` | 6 | `bytes32` | equality |
185
+ * | `bytes` | 7 | `bytes` | none — system-only |
186
+ * | `str` | 8 | `string` (<= 128 B) | equality + prefix |
187
+ * | `addr` | 9 | `address` | equality |
188
+ * | `key` | 10 | `bytes32` | equality |
189
+ */
190
+ const TYPE_IDS = {
191
+ bool: 1,
192
+ i32: 2,
193
+ u64: 3,
194
+ u256: 4,
195
+ dec: 5,
196
+ bytes32: 6,
197
+ bytes: 7,
198
+ str: 8,
199
+ addr: 9,
200
+ key: 10
201
+ };
202
+ /**
203
+ * Builds a validated value. Module-internal: the constructors in `values.ts` call this **after**
204
+ * validating, which is what makes the {@link validated} brand meaningful.
205
+ */
206
+ function makeValue(type, value) {
207
+ return {
208
+ type,
209
+ value
210
+ };
211
+ }
212
+ /**
213
+ * Whether `input` has the *shape* of an {@link ArkivValue} — a known type tag and a value.
214
+ */
215
+ function isArkivValue(input) {
216
+ return typeof input === "object" && input !== null && "type" in input && "value" in input && typeof input.type === "string" && Object.hasOwn(TYPE_IDS, input.type);
217
+ }
218
+
219
+ //#endregion
220
+ //#region src/attr/values.ts
221
+ /** The widest `i32`. */
222
+ const I32_MAX = 2147483647;
223
+ /** The narrowest `i32`. */
224
+ const I32_MIN = -2147483648;
225
+ /** The widest `u64`. */
226
+ const U64_MAX = 2n ** 64n - 1n;
227
+ /** The widest `u256`. */
228
+ const U256_MAX = 2n ** 256n - 1n;
229
+ /**
230
+ * The longest `str`, in UTF-8 bytes
231
+ */
232
+ const MAX_STRING_BYTES = 128;
233
+ /**
234
+ * Finds the first C0 control or DEL — the characters a `str` may not contain.
235
+ */
236
+ function findControlChar(value) {
237
+ for (let index = 0; index < value.length; index++) {
238
+ const code = value.charCodeAt(index);
239
+ if (code <= 31 || code === 127) return {
240
+ index,
241
+ code
242
+ };
243
+ }
244
+ }
245
+ /**
246
+ * A boolean.
247
+ *
248
+ * `bool` is the one type that may also be written bare — `{ flagged: true }` and
249
+ * `{ flagged: bool(true) }` are the same attribute.
250
+ *
251
+ * @example
252
+ * bool(true) // { type: "bool", value: true }
253
+ */
254
+ function bool(value) {
255
+ if (typeof value !== "boolean") throw new InvalidValueError("bool", value, "not a boolean");
256
+ return makeValue("bool", value);
257
+ }
258
+ /**
259
+ * A 32-bit signed integer, indexed for equality and range queries. This is the default type for a
260
+ * bare number, so `{ level: 10 }` and `{ level: i32(10) }` are the same attribute.
261
+ *
262
+ * @param value - An integer in [-2147483648, 2147483647].
263
+ * @throws {InvalidValueError} If the value is not an integer, or does not fit an `i32`.
264
+ *
265
+ * @example
266
+ * i32(10) // { type: "i32", value: 10 }
267
+ * i32(-42) // negative values are fine — i32 is the signed integer
268
+ */
269
+ function i32(value) {
270
+ if (typeof value === "bigint") {
271
+ if (value > BigInt(I32_MAX) || value < BigInt(I32_MIN)) throw new InvalidValueError("i32", value, outOfI32Range(value >= 0n));
272
+ return makeValue("i32", Number(value));
273
+ }
274
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new InvalidValueError("i32", value, "not a number");
275
+ if (!Number.isInteger(value)) throw new InvalidValueError("i32", value, "not an integer", `Use dec(${JSON.stringify(String(value))}) for a fixed-point decimal.`);
276
+ if (value > I32_MAX || value < I32_MIN) throw new InvalidValueError("i32", value, outOfI32Range(value >= 0));
277
+ return makeValue("i32", value);
278
+ }
279
+ function outOfI32Range(nonNegative) {
280
+ const range = `outside the i32 range [${I32_MIN}, ${I32_MAX}]`;
281
+ return nonNegative ? `${range} — use u64(...) for large counters, timestamps and block heights (Date.now() does not fit an i32), or u256(...) beyond 2**64 - 1` : `${range} — use dec(...) for values that need more range than an i32`;
282
+ }
283
+ /**
284
+ * A 256-bit unsigned integer, indexed for equality and range queries. The type for token amounts
285
+ * and anything else that can outgrow 2⁶⁴ — reach for {@link u64} first for counters, timestamps
286
+ * and block heights.
287
+ *
288
+ * @param value - A non-negative integer, as a `bigint`, a safe `number`, or a decimal or `0x` hex
289
+ * string.
290
+ * @throws {InvalidValueError} If the value is negative, non-integral, or wider than 256 bits.
291
+ *
292
+ * @example
293
+ * u256(1_000_000n)
294
+ * u256(Date.now()) // safe integers are accepted
295
+ * u256("0xf4240") // hex, as it comes back over JSON-RPC
296
+ */
297
+ function u256(value) {
298
+ return makeValue("u256", toUnsigned("u256", value, U256_MAX));
299
+ }
300
+ /**
301
+ * A 64-bit unsigned integer, indexed for equality and range queries.
302
+ *
303
+ * This is the width the protocol counts in: block heights, `$expiresAt` and the entity-nonce are
304
+ * all `u64`, so it is the type to reach for when a value has to line up with one of them. Use
305
+ * {@link u256} for token amounts and anything else that can exceed 2⁶⁴.
306
+ *
307
+ * @param value - A non-negative integer, as a `bigint`, a safe `number`, or a decimal or `0x` hex
308
+ * string.
309
+ * @throws {InvalidValueError} If the value is negative, non-integral, or wider than 64 bits.
310
+ *
311
+ * @example
312
+ * u64(1_200_000n) // a block height
313
+ * u64(Date.now()) // safe integers are accepted
314
+ * u64("0x124f80") // hex, as it comes back over JSON-RPC
315
+ */
316
+ function u64(value) {
317
+ return makeValue("u64", toUnsigned("u64", value, U64_MAX));
318
+ }
319
+ /**
320
+ * Parses and range-checks an unsigned integer for `tag`, whose widest value is `max`.
321
+ *
322
+ * Shared by {@link u64} and {@link u256} so the two differ in exactly one thing — their width —
323
+ * rather than in how they read a string or how they explain a failure.
324
+ */
325
+ function toUnsigned(tag, value, max) {
326
+ const parsed = toUnsignedBigint(tag, value);
327
+ if (parsed < 0n) throw new InvalidValueError(tag, value, `negative — ${tag} is unsigned`, "Use i32(...) for small signed integers, or dec(...) for a signed fixed-point value.");
328
+ if (parsed > max) throw new InvalidValueError(tag, value, `wider than ${tag === "u64" ? 64 : 256} bits`, tag === "u64" ? "Use u256(...) for values beyond 2**64 - 1." : void 0);
329
+ return parsed;
330
+ }
331
+ function toUnsignedBigint(tag, value) {
332
+ if (typeof value === "bigint") return value;
333
+ if (typeof value === "number") {
334
+ if (!Number.isInteger(value)) throw new InvalidValueError(tag, value, "not an integer", `Use dec(${JSON.stringify(String(value))}) for a fixed-point decimal.`);
335
+ if (!Number.isSafeInteger(value)) throw new InvalidValueError(tag, value, "beyond the safe integer range, so it may already have lost precision", "Pass it as a bigint literal (e.g. 12345678901234567890n) or a string instead.");
336
+ return BigInt(value);
337
+ }
338
+ if (typeof value === "string") {
339
+ if (!/^(0x[0-9a-fA-F]+|\d+)$/.test(value)) throw new InvalidValueError(tag, value, "not a decimal or 0x-hex integer");
340
+ return BigInt(value);
341
+ }
342
+ throw new InvalidValueError(tag, value, "not a bigint, number or string");
343
+ }
344
+ /**
345
+ * A signed fixed-point decimal with exactly 18 decimal places, indexed for equality and range
346
+ * queries.
347
+ *
348
+ * Pass fractional values as **strings**. A JavaScript number cannot represent most decimals
349
+ * exactly, so accepting `dec(0.1 + 0.2)` would quietly store `0.30000000000000004`; requiring the
350
+ * string keeps what you write and what is stored the same thing. Excess precision is likewise an
351
+ * error rather than a rounding.
352
+ *
353
+ * @param value - A decimal string, or an integral `number` / `bigint`.
354
+ * @throws {InvalidValueError} If the value is malformed, has more than 18 fractional digits, or
355
+ * falls outside the `int256` range.
356
+ *
357
+ * @example
358
+ * dec("3.5")
359
+ * dec("-0.000000000000000001") // the smallest step
360
+ * dec(5) // integers may be passed bare
361
+ */
362
+ function dec(value) {
363
+ if (typeof value === "string") return makeValue("dec", unitsToDecimal(decimalToUnits(value)));
364
+ if (typeof value === "bigint") return decFromUnits(value * DECIMAL_UNIT);
365
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new InvalidValueError("dec", value, "not a number");
366
+ if (!Number.isInteger(value)) throw new InvalidValueError("dec", value, "a fractional number cannot be represented exactly in binary floating point", `Pass it as a string instead: dec(${JSON.stringify(String(value))}).`);
367
+ return decFromUnits(BigInt(value) * DECIMAL_UNIT);
368
+ }
369
+ /**
370
+ * The exact scaled integer behind a `dec` — the value multiplied by 10 ** 18, which is what the
371
+ * protocol stores and compares. Use it when you need exact arithmetic; JavaScript has no native
372
+ * decimal type, so the SDK carries the canonical string and leaves the maths to you.
373
+ *
374
+ * @example
375
+ * decUnits(dec("3.5")) // 3500000000000000000n
376
+ */
377
+ function decUnits(value) {
378
+ return decimalToUnits(value.value);
379
+ }
380
+ /**
381
+ * A `dec` built from its scaled integer units — the inverse of {@link decUnits}.
382
+ *
383
+ * @example
384
+ * decFromUnits(3_500_000_000_000_000_000n) // dec("3.5")
385
+ */
386
+ function decFromUnits(units) {
387
+ return makeValue("dec", unitsToDecimal(units));
388
+ }
389
+ /**
390
+ * A UTF-8 string of at most 128 bytes, indexed for equality and prefix (`STARTSWITH`) matching.
391
+ *
392
+ * The limit is on **bytes**, not characters: a string of 128 emoji does not fit.
393
+ *
394
+ * @throws {InvalidValueError} If the string exceeds 128 UTF-8 bytes.
395
+ *
396
+ * @example
397
+ * str("Bob")
398
+ */
399
+ function str(value) {
400
+ if (typeof value !== "string") throw new InvalidValueError("str", value, "not a string");
401
+ const control = findControlChar(value);
402
+ if (control !== void 0) throw new InvalidValueError("str", value, `contains the control character U+${control.code.toString(16).padStart(4, "0").toUpperCase()} at index ${control.index}`, "A str is written into a query as str('...'), whose only escape is a doubled quote — there is no spelling for a control character, so this value could be stored but never queried. Free-form text belongs in the entity payload; keep a short, printable key here.");
403
+ const bytes = (0, viem.stringToBytes)(value).length;
404
+ if (bytes > MAX_STRING_BYTES) throw new InvalidValueError("str", value, `${bytes} UTF-8 bytes exceeds the ${MAX_STRING_BYTES}-byte limit on a str`, "Store the long form in the entity payload and keep a short, queryable key here.");
405
+ return makeValue("str", value);
406
+ }
407
+ /**
408
+ * A 20-byte Ethereum address, indexed for equality.
409
+ *
410
+ * All-lowercase and all-uppercase input carries no checksum and is accepted as-is; mixed-case
411
+ * input is checked against its EIP-55 checksum, so a mistyped address is caught here rather than
412
+ * being written to a wrong account. The stored value is always EIP-55 checksummed.
413
+ *
414
+ * @throws {InvalidValueError} If the value is not 20 hex bytes, or fails its EIP-55 checksum.
415
+ *
416
+ * @example
417
+ * addr("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")
418
+ */
419
+ function addr(value) {
420
+ if (typeof value !== "string" || !/^0x[0-9a-fA-F]{40}$/.test(value)) throw new InvalidValueError("addr", value, "not a 20-byte 0x-prefixed hex address");
421
+ const body = value.slice(2);
422
+ if (body !== body.toLowerCase() && body !== body.toUpperCase() && !(0, viem.isAddress)(value, { strict: true })) throw new InvalidValueError("addr", value, "fails its EIP-55 checksum, so a digit is probably mistyped", `If those hex digits are right, the correctly checksummed form is ${(0, viem.checksumAddress)(value)}.`);
423
+ return makeValue("addr", (0, viem.checksumAddress)(value));
424
+ }
425
+ /**
426
+ * A reference to another entity, indexed for equality.
427
+ *
428
+ * References are **weak**: nothing checks that the target exists when you write it, and a
429
+ * reference to a deleted or expired entity is allowed to dangle.
430
+ *
431
+ * @param value - A 32-byte entity key, as `0x` hex or raw bytes.
432
+ * @throws {InvalidValueError} If the value is not exactly 32 bytes.
433
+ *
434
+ * @example
435
+ * key(parentEntityKey)
436
+ */
437
+ function key(value) {
438
+ return makeValue("key", asFixedHex("key", value, 32));
439
+ }
440
+ /**
441
+ * 32 opaque bytes — a hash, a digest, an identifier from another system — indexed for equality.
442
+ *
443
+ * Use {@link key} instead when the bytes are an Arkiv entity key: same wire width, but the
444
+ * distinct type makes the reference visible to readers and to the query language.
445
+ *
446
+ * @param value - 32 bytes, as `0x` hex or raw bytes.
447
+ * @throws {InvalidValueError} If the value is not exactly 32 bytes.
448
+ *
449
+ * @example
450
+ * bytes32(keccak256(toBytes("hello")))
451
+ */
452
+ function bytes32(value) {
453
+ return makeValue("bytes32", asFixedHex("bytes32", value, 32));
454
+ }
455
+ /** Normalizes hex-or-bytes input of a known width into lowercase `0x` hex. */
456
+ function asFixedHex(tag, value, size$1) {
457
+ if (value instanceof Uint8Array) {
458
+ if (value.length !== size$1) throw new InvalidValueError(tag, `<${value.length} bytes>`, `not exactly ${size$1} bytes`);
459
+ return (0, viem.toHex)(value);
460
+ }
461
+ if (typeof value !== "string" || !(0, viem.isHex)(value, { strict: true })) throw new InvalidValueError(tag, value, "not 0x-prefixed hex");
462
+ if (value.length !== 2 + size$1 * 2) throw new InvalidValueError(tag, value, `${(value.length - 2) / 2} bytes, not exactly ${size$1} bytes`);
463
+ return value.toLowerCase();
464
+ }
465
+ /**
466
+ * Resolves a {@link ValueInput} to a typed value, applying the bare-form defaults above. Tagged
467
+ * values pass through untouched.
468
+ *
469
+ * @param input - The value to resolve.
470
+ * @param attributeName - The attribute this value belongs to, used to make errors name it.
471
+ *
472
+ * @throws {MissingValueError} If the input is `undefined` or `null` — an attribute is either set
473
+ * with a value and a type, or not set at all.
474
+ * @throws {UntypedValueError} If the input is not a tagged value or a bare boolean, number, bigint
475
+ * or string.
476
+ * @throws {InvalidValueError} If a bare value does not fit the type it defaults to.
477
+ *
478
+ * @example
479
+ * toValue(10) // i32(10)
480
+ * toValue(10n) // u256(10n)
481
+ * toValue("hello") // str("hello")
482
+ * toValue(dec("3.5")) // unchanged
483
+ */
484
+ function toValue(input, attributeName) {
485
+ if (input === void 0 || input === null) throw new MissingValueError(input, attributeName);
486
+ switch (typeof input) {
487
+ case "boolean": return bool(input);
488
+ case "number": return i32(input);
489
+ case "bigint": return u256(input);
490
+ case "string": return str(input);
491
+ default: {
492
+ const candidate = input;
493
+ if (isArkivValue(candidate)) {
494
+ if (candidate.type === "bytes") throw new InvalidValueError("bytes", candidate.value, "system-only — bytes backs the entity payload and cannot be set as an attribute", "Pass the bytes as the entity payload instead.");
495
+ return revalidate(candidate);
496
+ }
497
+ throw new UntypedValueError(input);
498
+ }
499
+ }
500
+ }
501
+ /**
502
+ * Re-runs a tagged value through its own constructor.
503
+ *
504
+ * {@link isArkivValue} can only check shape — the `validated` brand is a type-level construct with
505
+ * no runtime existence, so a hand-written `{ type: "u256", value: "1000" }` (from `JSON.parse`, a
506
+ * config file, an `as any` boundary) is indistinguishable from a real `u256(1000n)`. Passing it
507
+ * through unchecked was silent corruption rather than an error: the ABI encoder would take the
508
+ * *string* "1000" and write its UTF-8 bytes into the word, storing 2.27e76 on chain.
509
+ *
510
+ * Running the constructor again is what makes the brand's promise — "every value crossing the wire
511
+ * has been range-, length- and format-checked" — true at runtime. For a value that really did come
512
+ * from a constructor it is a no-op that returns an equal value.
513
+ */
514
+ function revalidate(value) {
515
+ switch (value.type) {
516
+ case "bool": return bool(value.value);
517
+ case "i32": return i32(value.value);
518
+ case "u64": return u64(value.value);
519
+ case "u256": return u256(value.value);
520
+ case "dec": return dec(value.value);
521
+ case "bytes32": return bytes32(value.value);
522
+ case "str": return str(value.value);
523
+ case "addr": return addr(value.value);
524
+ case "key": return key(value.value);
525
+ }
526
+ }
527
+
528
+ //#endregion
529
+ //#region src/attr/codec.ts
530
+ function strFromChain(value) {
531
+ return makeValue("str", value);
532
+ }
533
+ /**
534
+ * The `typeId` marking a tombstone — an attribute being unset. It carries a zero-length value and
535
+ * is legal only in a patch's mutation list, never in a create.
536
+ */
537
+ const TOMBSTONE_TYPE_ID = 0;
538
+ /**
539
+ * Encodes a typed value into the `bytes` the ABI carries for it.
540
+ *
541
+ * This and {@link decodeValueBytes} are the only place the value/wire mapping is written down.
542
+ *
543
+ * - Word types (`bool`, `i32`, `u64`, `u256`, `dec`, `bytes32`, `addr`, `key`) become exactly 32
544
+ * bytes, in the encoding Solidity would use — right-aligned, and sign-extended for `i32`.
545
+ * - `str` becomes its raw UTF-8 bytes, and `bytes` its raw bytes: variable length, no padding.
546
+ */
547
+ function encodeValueBytes(value) {
548
+ switch (value.type) {
549
+ case "bool": return (0, viem.pad)(value.value ? "0x01" : "0x00", { size: 32 });
550
+ case "i32": return (0, viem.toHex)(BigInt.asUintN(256, BigInt(value.value)), { size: 32 });
551
+ case "u64":
552
+ case "u256": return (0, viem.toHex)(value.value, { size: 32 });
553
+ case "dec": return (0, viem.toHex)(BigInt.asUintN(256, decUnits(value)), { size: 32 });
554
+ case "bytes32":
555
+ case "key": return value.value;
556
+ case "addr": return (0, viem.pad)(value.value.toLowerCase(), { size: 32 });
557
+ case "str": return (0, viem.toHex)((0, viem.stringToBytes)(value.value));
558
+ case "bytes": return value.value;
559
+ }
560
+ }
561
+ /**
562
+ * Encodes a named, typed attribute into its ABI form.
563
+ *
564
+ * @param name - The attribute name. Assumed already validated, or a system (`$`) name the SDK sets
565
+ * itself.
566
+ */
567
+ function encodeAbiAttribute(name, value) {
568
+ return {
569
+ name: (0, viem.toHex)(name, { size: 32 }),
570
+ typeId: TYPE_IDS[value.type],
571
+ value: encodeValueBytes(value)
572
+ };
573
+ }
574
+ /** Encodes a tombstone — the mutation that unsets `name`. Legal only in a patch. */
575
+ function encodeTombstone(name) {
576
+ return {
577
+ name: (0, viem.toHex)(name, { size: 32 }),
578
+ typeId: TOMBSTONE_TYPE_ID,
579
+ value: "0x"
580
+ };
581
+ }
582
+ /**
583
+ * Decodes an attribute value as it comes back over JSON-RPC.
584
+ *
585
+ * The JSON encoding follows the value's **declared type**, never its magnitude: `bool` is a JSON
586
+ * boolean, `i32` a JSON number, `u64`/`u256` a `0x` QUANTITY, `dec` a decimal string, `str` a
587
+ * string, and
588
+ * the byte-shaped types `0x` DATA. Decimal strings are also accepted for the integer types, so this
589
+ * keeps working against a node that renders them that way.
590
+ *
591
+ * @param type - The type tag the response declared, e.g. `"u256"`.
592
+ * @param value - The JSON value.
593
+ * @throws {UnknownAttributeTypeError} If the tag names no known type.
594
+ * @throws {InvalidValueError} If the value does not parse as that type.
595
+ */
596
+ function decodeRpcValue(type, value) {
597
+ switch (asTypeTag(type)) {
598
+ case "bool": return bool(asBoolean(value));
599
+ case "i32": return i32(Number(asIntegerish("i32", value)));
600
+ case "u64": return u64(asIntegerish("u64", value));
601
+ case "u256": return u256(asIntegerish("u256", value));
602
+ case "dec": return dec(asString("dec", value));
603
+ case "bytes32": return bytes32(asString("bytes32", value));
604
+ case "key": return key(asString("key", value));
605
+ case "addr": return addr(asString("addr", value));
606
+ case "str": return strFromChain(asString("str", value));
607
+ case "bytes": return makeValue("bytes", asString("bytes", value).toLowerCase());
608
+ }
609
+ }
610
+ /**
611
+ * Narrows a type tag as the node spelled it.
612
+ *
613
+ * @throws {UnknownAttributeTypeError} If it names no type this SDK knows.
614
+ */
615
+ function asTypeTag(type) {
616
+ if (typeof type !== "string" || !Object.hasOwn(TYPE_IDS, type)) throw new UnknownAttributeTypeError(type);
617
+ return type;
618
+ }
619
+ function asBoolean(value) {
620
+ if (typeof value === "boolean") return value;
621
+ if (value === "true" || value === "false") return value === "true";
622
+ throw new InvalidValueError("bool", value, "not a boolean");
623
+ }
624
+ function asString(tag, value) {
625
+ if (typeof value !== "string") throw new InvalidValueError(tag, value, `expected a string, got ${typeof value}`);
626
+ return value;
627
+ }
628
+ /** A `0x` QUANTITY, a JSON number, or a decimal string — all of which name one integer. */
629
+ function asIntegerish(tag, value) {
630
+ if (typeof value === "number") {
631
+ if (!Number.isInteger(value)) throw new InvalidValueError(tag, value, "not an integer");
632
+ return BigInt(value);
633
+ }
634
+ if (typeof value === "bigint") return value;
635
+ if (typeof value === "string") {
636
+ if (/^0x[0-9a-fA-F]+$/.test(value)) return BigInt(value);
637
+ if (/^-?\d+$/.test(value)) return BigInt(value);
638
+ }
639
+ throw new InvalidValueError(tag, value, "not an integer");
640
+ }
641
+
642
+ //#endregion
643
+ //#region src/attr/names.ts
644
+ /** The longest attribute name, in bytes — the width of the on-chain `Ident32` name cell. */
645
+ const MAX_NAME_BYTES = 32;
646
+ /**
647
+ * The attribute-name grammar (`Ident32`): a leading letter, then letters, digits, `.`, `-` or `_`.
648
+ *
649
+ * Names are **case-sensitive** — `Level` and `level` are two different attributes.
650
+ *
651
+ * The charset is ASCII-only, so a name's length in characters is also its length in bytes.
652
+ */
653
+ const NAME_RE = /^[A-Za-z][A-Za-z0-9._-]*$/;
654
+ /**
655
+ * Words the query language reserves. They are rejected as attribute names because an attribute
656
+ * named `not` or `str` could be written but never queried — the parser would read the name as an
657
+ * operator or a type tag.
658
+ *
659
+ * Matched **case-insensitively**: query keywords are case-insensitive, so `NOT` and `not` are the
660
+ * same operator, and the type tags are held to the same rule so that what is reserved does not
661
+ * depend on how you happen to capitalise it.
662
+ */
663
+ const RESERVED = new Set([
664
+ "and",
665
+ "or",
666
+ "not",
667
+ "true",
668
+ "false",
669
+ "startswith",
670
+ "exists",
671
+ "typeof",
672
+ "bool",
673
+ "i32",
674
+ "u64",
675
+ "u256",
676
+ "dec",
677
+ "bytes32",
678
+ "bytes",
679
+ "str",
680
+ "addr",
681
+ "key"
682
+ ]);
683
+ /**
684
+ * Validates an attribute name against the engine's `Ident32` grammar and the query language's
685
+ * reserved words.
686
+ *
687
+ * @param name - The attribute name.
688
+ * @throws {InvalidAttributeNameError} If the name is empty, too long, uses characters outside the
689
+ * grammar, or collides with a reserved word.
690
+ */
691
+ function validateAttributeName(name) {
692
+ if (typeof name !== "string" || name.length === 0) throw new InvalidAttributeNameError(String(name), "the name is empty");
693
+ if (name.startsWith("$")) throw new InvalidAttributeNameError(name, "\"$\" is reserved for system attributes, which the engine sets and you cannot write");
694
+ if (!NAME_RE.test(name)) {
695
+ const chars = [...name];
696
+ const at = chars.findIndex((char, index) => !(index === 0 ? /[A-Za-z]/ : /[A-Za-z0-9._-]/).test(char));
697
+ throw new InvalidAttributeNameError(name, at === 0 ? `it starts with "${chars[0]}" rather than a letter` : `it contains "${chars[at]}" at position ${at}`);
698
+ }
699
+ if (name.length > MAX_NAME_BYTES) throw new InvalidAttributeNameError(name, `the name is ${name.length} bytes long`);
700
+ if (name.includes("--")) throw new InvalidAttributeNameError(name, "\"--\" opens a comment in the query language, so everything after it in a query would be discarded — an attribute with this name could be written but never safely queried");
701
+ if (RESERVED.has(name.toLowerCase())) throw new InvalidAttributeNameError(name, `"${name}" is reserved by the query language, so an attribute with this name could never be queried`);
702
+ }
703
+ /** Whether `name` is a valid attribute name — the non-throwing form of {@link validateAttributeName}. */
704
+ function isValidAttributeName(name) {
705
+ try {
706
+ validateAttributeName(name);
707
+ return true;
708
+ } catch {
709
+ return false;
710
+ }
711
+ }
712
+
713
+ //#endregion
714
+ //#region src/attr/attributes.ts
715
+ /**
716
+ * The most attribute cells one operation may carry.
717
+ */
718
+ const MAX_ATTRIBUTES = 32;
719
+ const MAX_PAYLOAD_BYTES = 128 * 1024;
720
+ /** The system attribute holding an entity's opaque payload. */
721
+ const PAYLOAD_CELL = "$payload";
722
+ /** The system attribute holding an entity's content type. */
723
+ const CONTENT_TYPE_CELL = "$contentType";
724
+ /**
725
+ * The typed form of an attribute map: names validated, bare values resolved to their default type.
726
+ *
727
+ * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.
728
+ * @throws {MissingValueError} If a value is `undefined` or `null` — omit the name instead.
729
+ * @throws {InvalidValueError} If a value does not fit the type it names or defaults to.
730
+ * @throws {TooManyAttributesError} If there are more than {@link MAX_ATTRIBUTES} attributes.
731
+ *
732
+ * @example
733
+ * resolveAttributes({ level: 10, name: "Bob" })
734
+ * // { level: { type: "i32", value: 10 }, name: { type: "str", value: "Bob" } }
735
+ */
736
+ function resolveAttributes(attributes) {
737
+ const entries = Object.entries(attributes);
738
+ if (entries.length > MAX_ATTRIBUTES) throw new TooManyAttributesError(entries.length, MAX_ATTRIBUTES);
739
+ const resolved = {};
740
+ for (const [name, input] of entries) {
741
+ validateAttributeName(name);
742
+ resolved[name] = toValue(input, name);
743
+ }
744
+ return resolved;
745
+ }
746
+ /**
747
+ * Encodes an attribute map, plus the payload and content-type system cells, into the ABI attribute
748
+ * array an operation carries.
749
+ *
750
+ * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.
751
+ * @throws {MissingValueError} If a value is `undefined` or `null`.
752
+ * @throws {InvalidValueError} If a value does not fit its type.
753
+ * @throws {TooManyAttributesError} If there are more than {@link MAX_ATTRIBUTES} attributes.
754
+ */
755
+ function encodeAttributes(attributes = {}, system = {}) {
756
+ const cells = Object.entries(resolveAttributes(attributes));
757
+ if (system.payload !== void 0) {
758
+ if (system.payload.length > MAX_PAYLOAD_BYTES) throw new InvalidValueError("bytes", `<${system.payload.length} bytes>`, `${system.payload.length} bytes exceeds the ${MAX_PAYLOAD_BYTES}-byte payload limit`, "Store the bulk elsewhere and keep a reference to it on the entity.");
759
+ cells.push([PAYLOAD_CELL, makeValue("bytes", toHexBytes(system.payload))]);
760
+ }
761
+ if (system.contentType !== void 0) cells.push([CONTENT_TYPE_CELL, str(system.contentType)]);
762
+ if (cells.length > MAX_ATTRIBUTES) throw new TooManyAttributesError(cells.length, MAX_ATTRIBUTES);
763
+ return cells.map(([name, value]) => encodeAbiAttribute(name, value)).sort(byName);
764
+ }
765
+ /**
766
+ * Encodes a patch's mutations into the ABI attribute array the operation carries.
767
+ *
768
+ * @throws {ConflictingMutationError} If a name appears in both `set` and `unset`.
769
+ * @throws {InvalidAttributeNameError} If a name violates the attribute-name grammar.
770
+ * @throws {InvalidValueError} If a value does not fit its type.
771
+ * @throws {TooManyAttributesError} If `set` names more than {@link MAX_ATTRIBUTES} attributes.
772
+ */
773
+ function encodeMutations({ set, unset, payload, contentType }) {
774
+ const written = encodeAttributes(set, {
775
+ payload,
776
+ contentType
777
+ });
778
+ const tombstones = resolveUnset(unset, set).map(encodeTombstone);
779
+ const mutations = [...written, ...tombstones];
780
+ if (mutations.length > MAX_ATTRIBUTES) throw new TooManyAttributesError(mutations.length, MAX_ATTRIBUTES);
781
+ return mutations.sort(byName);
782
+ }
783
+ function resolveUnset(unset = [], set = {}) {
784
+ if (!Array.isArray(unset)) throw new TypeError(`"unset" must be an array of attribute names`);
785
+ const names = new Set(unset);
786
+ for (const name of names) {
787
+ validateAttributeName(name);
788
+ if (Object.hasOwn(set, name)) throw new ConflictingMutationError(name);
789
+ }
790
+ return [...names];
791
+ }
792
+ /**
793
+ * The engine requires attributes **strictly ascending by their `bytes32` name**: that ordering is
794
+ * what the canonical serialization hashes into the state root, and it doubles as the uniqueness
795
+ * check.
796
+ */
797
+ function byName(a, b) {
798
+ return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
799
+ }
800
+ /** Raw bytes as lowercase `0x` hex, without viem's hex-string ambiguity. */
801
+ function toHexBytes(bytes) {
802
+ let out = "0x";
803
+ for (const byte of bytes) out += byte.toString(16).padStart(2, "0");
804
+ return out;
805
+ }
806
+
807
+ //#endregion
808
+ Object.defineProperty(exports, 'ConflictingMutationError', {
809
+ enumerable: true,
810
+ get: function () {
811
+ return ConflictingMutationError;
812
+ }
813
+ });
814
+ Object.defineProperty(exports, 'DECIMAL_SCALE', {
815
+ enumerable: true,
816
+ get: function () {
817
+ return DECIMAL_SCALE;
818
+ }
819
+ });
820
+ Object.defineProperty(exports, 'DECIMAL_UNIT', {
821
+ enumerable: true,
822
+ get: function () {
823
+ return DECIMAL_UNIT;
824
+ }
825
+ });
826
+ Object.defineProperty(exports, 'I32_MAX', {
827
+ enumerable: true,
828
+ get: function () {
829
+ return I32_MAX;
830
+ }
831
+ });
832
+ Object.defineProperty(exports, 'I32_MIN', {
833
+ enumerable: true,
834
+ get: function () {
835
+ return I32_MIN;
836
+ }
837
+ });
838
+ Object.defineProperty(exports, 'InvalidAttributeNameError', {
839
+ enumerable: true,
840
+ get: function () {
841
+ return InvalidAttributeNameError;
842
+ }
843
+ });
844
+ Object.defineProperty(exports, 'InvalidValueError', {
845
+ enumerable: true,
846
+ get: function () {
847
+ return InvalidValueError;
848
+ }
849
+ });
850
+ Object.defineProperty(exports, 'MAX_ATTRIBUTES', {
851
+ enumerable: true,
852
+ get: function () {
853
+ return MAX_ATTRIBUTES;
854
+ }
855
+ });
856
+ Object.defineProperty(exports, 'MAX_NAME_BYTES', {
857
+ enumerable: true,
858
+ get: function () {
859
+ return MAX_NAME_BYTES;
860
+ }
861
+ });
862
+ Object.defineProperty(exports, 'MAX_PAYLOAD_BYTES', {
863
+ enumerable: true,
864
+ get: function () {
865
+ return MAX_PAYLOAD_BYTES;
866
+ }
867
+ });
868
+ Object.defineProperty(exports, 'MAX_STRING_BYTES', {
869
+ enumerable: true,
870
+ get: function () {
871
+ return MAX_STRING_BYTES;
872
+ }
873
+ });
874
+ Object.defineProperty(exports, 'MissingValueError', {
875
+ enumerable: true,
876
+ get: function () {
877
+ return MissingValueError;
878
+ }
879
+ });
880
+ Object.defineProperty(exports, 'TYPE_IDS', {
881
+ enumerable: true,
882
+ get: function () {
883
+ return TYPE_IDS;
884
+ }
885
+ });
886
+ Object.defineProperty(exports, 'TooManyAttributesError', {
887
+ enumerable: true,
888
+ get: function () {
889
+ return TooManyAttributesError;
890
+ }
891
+ });
892
+ Object.defineProperty(exports, 'U256_MAX', {
893
+ enumerable: true,
894
+ get: function () {
895
+ return U256_MAX;
896
+ }
897
+ });
898
+ Object.defineProperty(exports, 'U64_MAX', {
899
+ enumerable: true,
900
+ get: function () {
901
+ return U64_MAX;
902
+ }
903
+ });
904
+ Object.defineProperty(exports, 'UnknownAttributeTypeError', {
905
+ enumerable: true,
906
+ get: function () {
907
+ return UnknownAttributeTypeError;
908
+ }
909
+ });
910
+ Object.defineProperty(exports, 'UntypedValueError', {
911
+ enumerable: true,
912
+ get: function () {
913
+ return UntypedValueError;
914
+ }
915
+ });
916
+ Object.defineProperty(exports, 'addr', {
917
+ enumerable: true,
918
+ get: function () {
919
+ return addr;
920
+ }
921
+ });
922
+ Object.defineProperty(exports, 'asTypeTag', {
923
+ enumerable: true,
924
+ get: function () {
925
+ return asTypeTag;
926
+ }
927
+ });
928
+ Object.defineProperty(exports, 'bool', {
929
+ enumerable: true,
930
+ get: function () {
931
+ return bool;
932
+ }
933
+ });
934
+ Object.defineProperty(exports, 'bytes32', {
935
+ enumerable: true,
936
+ get: function () {
937
+ return bytes32;
938
+ }
939
+ });
940
+ Object.defineProperty(exports, 'dec', {
941
+ enumerable: true,
942
+ get: function () {
943
+ return dec;
944
+ }
945
+ });
946
+ Object.defineProperty(exports, 'decFromUnits', {
947
+ enumerable: true,
948
+ get: function () {
949
+ return decFromUnits;
950
+ }
951
+ });
952
+ Object.defineProperty(exports, 'decUnits', {
953
+ enumerable: true,
954
+ get: function () {
955
+ return decUnits;
956
+ }
957
+ });
958
+ Object.defineProperty(exports, 'decodeRpcValue', {
959
+ enumerable: true,
960
+ get: function () {
961
+ return decodeRpcValue;
962
+ }
963
+ });
964
+ Object.defineProperty(exports, 'encodeAttributes', {
965
+ enumerable: true,
966
+ get: function () {
967
+ return encodeAttributes;
968
+ }
969
+ });
970
+ Object.defineProperty(exports, 'encodeMutations', {
971
+ enumerable: true,
972
+ get: function () {
973
+ return encodeMutations;
974
+ }
975
+ });
976
+ Object.defineProperty(exports, 'i32', {
977
+ enumerable: true,
978
+ get: function () {
979
+ return i32;
980
+ }
981
+ });
982
+ Object.defineProperty(exports, 'isArkivValue', {
983
+ enumerable: true,
984
+ get: function () {
985
+ return isArkivValue;
986
+ }
987
+ });
988
+ Object.defineProperty(exports, 'isValidAttributeName', {
989
+ enumerable: true,
990
+ get: function () {
991
+ return isValidAttributeName;
992
+ }
993
+ });
994
+ Object.defineProperty(exports, 'key', {
995
+ enumerable: true,
996
+ get: function () {
997
+ return key;
998
+ }
999
+ });
1000
+ Object.defineProperty(exports, 'str', {
1001
+ enumerable: true,
1002
+ get: function () {
1003
+ return str;
1004
+ }
1005
+ });
1006
+ Object.defineProperty(exports, 'toValue', {
1007
+ enumerable: true,
1008
+ get: function () {
1009
+ return toValue;
1010
+ }
1011
+ });
1012
+ Object.defineProperty(exports, 'u256', {
1013
+ enumerable: true,
1014
+ get: function () {
1015
+ return u256;
1016
+ }
1017
+ });
1018
+ Object.defineProperty(exports, 'u64', {
1019
+ enumerable: true,
1020
+ get: function () {
1021
+ return u64;
1022
+ }
1023
+ });
1024
+ Object.defineProperty(exports, 'validateAttributeName', {
1025
+ enumerable: true,
1026
+ get: function () {
1027
+ return validateAttributeName;
1028
+ }
1029
+ });