@arkiv-network/sdk 0.8.1-dev.1 → 0.9.0-next.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 (184) hide show
  1. package/README.md +180 -61
  2. package/dist/chains/index.d.ts +17 -17
  3. package/dist/changeOwnership-Cy9gfyjN.d.cts +1160 -0
  4. package/dist/changeOwnership-Cy9gfyjN.d.cts.map +1 -0
  5. package/dist/changeOwnership-gXf-lBqI.d.ts +1160 -0
  6. package/dist/changeOwnership-gXf-lBqI.d.ts.map +1 -0
  7. package/dist/entity/index.cjs +4 -10
  8. package/dist/entity/index.d.cts +3 -3
  9. package/dist/entity/index.d.ts +3 -3
  10. package/dist/entity/index.js +3 -4
  11. package/dist/entity-BM1unrQf.cjs +41 -0
  12. package/dist/{entity-DJ0Gml9c.cjs → entity-BgaFJSaV.cjs} +4 -4
  13. package/dist/entity-CFAI1KyG.js +36 -0
  14. package/dist/entity-CFAI1KyG.js.map +1 -0
  15. package/dist/{entity-CniBgBSd.js → entity-CGqx_AU0.js} +4 -4
  16. package/dist/entity-CGqx_AU0.js.map +1 -0
  17. package/dist/{payload-AfUfSctb.d.ts → expirationTime-C7PZK49K.d.ts} +8 -37
  18. package/dist/expirationTime-C7PZK49K.d.ts.map +1 -0
  19. package/dist/expirationTime-CkIGNAg8.cjs +140 -0
  20. package/dist/{payload-D167BlJR.d.cts → expirationTime-DOB8V4B8.d.cts} +8 -37
  21. package/dist/expirationTime-DOB8V4B8.d.cts.map +1 -0
  22. package/dist/{expiry-Cgdb_dbq.js → expirationTime-UKPuA-LM.js} +62 -27
  23. package/dist/expirationTime-UKPuA-LM.js.map +1 -0
  24. package/dist/expiry-B48I-yTA.d.cts +40 -0
  25. package/dist/expiry-B48I-yTA.d.cts.map +1 -0
  26. package/dist/expiry-S2PUL8Hg.d.ts +40 -0
  27. package/dist/expiry-S2PUL8Hg.d.ts.map +1 -0
  28. package/dist/index-C-mMF5WZ.d.cts +735 -0
  29. package/dist/index-C-mMF5WZ.d.cts.map +1 -0
  30. package/dist/{index-BkqSnGJH.d.ts → index-C4zZqJ9S.d.ts} +5 -27
  31. package/dist/index-C4zZqJ9S.d.ts.map +1 -0
  32. package/dist/{index-CLhsFyVH.d.cts → index-CcVWYB6v.d.cts} +5 -27
  33. package/dist/index-CcVWYB6v.d.cts.map +1 -0
  34. package/dist/index-DCx2XC6S.d.ts +489 -0
  35. package/dist/index-DCx2XC6S.d.ts.map +1 -0
  36. package/dist/index-DLb7BfIw.d.ts +735 -0
  37. package/dist/index-DLb7BfIw.d.ts.map +1 -0
  38. package/dist/index-DzriOUm8.d.cts +489 -0
  39. package/dist/index-DzriOUm8.d.cts.map +1 -0
  40. package/dist/index.cjs +162 -146
  41. package/dist/index.d.cts +180 -133
  42. package/dist/index.d.cts.map +1 -1
  43. package/dist/index.d.ts +180 -133
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +93 -83
  46. package/dist/index.js.map +1 -1
  47. package/dist/params-BuIrJA9a.cjs +45 -0
  48. package/dist/params-DDJOnsNi.js +22 -0
  49. package/dist/params-DDJOnsNi.js.map +1 -0
  50. package/dist/query/index.cjs +9 -4
  51. package/dist/query/index.d.cts +6 -6
  52. package/dist/query/index.d.ts +6 -6
  53. package/dist/query/index.js +4 -5
  54. package/dist/query-D0KtuFh2.cjs +1625 -0
  55. package/dist/query-DpRDozmj.js +1417 -0
  56. package/dist/query-DpRDozmj.js.map +1 -0
  57. package/dist/schema/index.cjs +46 -0
  58. package/dist/schema/index.d.cts +2 -0
  59. package/dist/schema/index.d.ts +2 -0
  60. package/dist/schema/index.js +3 -0
  61. package/dist/{attr-BXTkpnoc.cjs → schema-B9AyXcgU.cjs} +513 -246
  62. package/dist/{attr-tmyREHtw.js → schema-DY4sqehl.js} +427 -244
  63. package/dist/schema-DY4sqehl.js.map +1 -0
  64. package/dist/types/index.cjs +1 -1
  65. package/dist/types/index.d.cts +5 -5
  66. package/dist/types/index.d.ts +5 -5
  67. package/dist/types/index.js +1 -1
  68. package/dist/utils/index.cjs +3 -5
  69. package/dist/utils/index.d.cts +3 -3
  70. package/dist/utils/index.d.ts +3 -3
  71. package/dist/utils/index.js +3 -3
  72. package/package.json +9 -12
  73. package/src/actions/public/getEntity.test.ts +69 -0
  74. package/src/actions/public/getEntity.ts +34 -20
  75. package/src/actions/public/predictEntityKeys.ts +8 -7
  76. package/src/actions/public/query.test.ts +58 -0
  77. package/src/actions/public/query.ts +41 -13
  78. package/src/actions/wallet/createEntity.ts +34 -63
  79. package/src/actions/wallet/executeBatch.test.ts +38 -0
  80. package/src/actions/wallet/executeBatch.ts +26 -9
  81. package/src/actions/wallet/extendEntity.ts +9 -8
  82. package/src/actions/wallet/patchEntity.ts +43 -52
  83. package/src/clients/createPublicClient.test.ts +10 -2
  84. package/src/clients/createWalletClient.ts +4 -1
  85. package/src/clients/decorators/arkivPublic.ts +123 -80
  86. package/src/clients/decorators/arkivWallet.ts +113 -65
  87. package/src/entity/create.test.ts +25 -21
  88. package/src/entity/expiry.ts +8 -6
  89. package/src/entity/flags.ts +1 -1
  90. package/src/entity/index.ts +2 -4
  91. package/src/entity/key.ts +3 -3
  92. package/src/entity/operations.ts +1 -1
  93. package/src/errors.ts +2 -11
  94. package/src/index.ts +18 -6
  95. package/src/query/builderBase.ts +166 -0
  96. package/src/query/countBuilder.test.ts +91 -0
  97. package/src/query/countBuilder.ts +67 -0
  98. package/src/query/engine.ts +9 -3
  99. package/src/query/errors.ts +24 -14
  100. package/src/query/expression.test.ts +129 -21
  101. package/src/query/expression.ts +323 -94
  102. package/src/query/index.ts +26 -4
  103. package/src/query/injection.test.ts +5 -11
  104. package/src/query/queryBuilder.test.ts +467 -58
  105. package/src/query/queryBuilder.ts +191 -98
  106. package/src/query/queryResult.ts +35 -9
  107. package/src/query/selection.test.ts +278 -24
  108. package/src/query/selection.ts +427 -86
  109. package/src/schema/attributes.test.ts +266 -0
  110. package/src/schema/attributes.ts +212 -0
  111. package/src/{attr → schema}/codec.test.ts +37 -5
  112. package/src/{attr → schema}/codec.ts +40 -11
  113. package/src/schema/column.ts +193 -0
  114. package/src/{attr → schema}/errors.ts +67 -10
  115. package/src/schema/index.ts +76 -0
  116. package/src/{attr → schema}/names.ts +4 -2
  117. package/src/schema/schema.test.ts +171 -0
  118. package/src/schema/schema.ts +250 -0
  119. package/src/{attr → schema}/types.ts +36 -30
  120. package/src/{attr → schema}/values.test.ts +62 -3
  121. package/src/{attr → schema}/values.ts +246 -65
  122. package/src/types/entity.test.ts +1 -44
  123. package/src/types/entity.ts +9 -55
  124. package/src/types/events.ts +1 -1
  125. package/src/types/index.ts +11 -4
  126. package/src/types/rpcSchema.ts +22 -16
  127. package/src/utils/arkivTransactions.test.ts +356 -116
  128. package/src/utils/arkivTransactions.ts +30 -38
  129. package/src/utils/entities.ts +10 -9
  130. package/src/utils/expirationTime.ts +5 -5
  131. package/src/utils/index.ts +0 -1
  132. package/src/utils/logger.test.ts +45 -0
  133. package/src/utils/logger.ts +5 -39
  134. package/src/utils/revert.test.ts +25 -0
  135. package/src/utils/revert.ts +28 -3
  136. package/dist/attr/index.cjs +0 -34
  137. package/dist/attr/index.d.cts +0 -2
  138. package/dist/attr/index.d.ts +0 -2
  139. package/dist/attr/index.js +0 -3
  140. package/dist/attr-tmyREHtw.js.map +0 -1
  141. package/dist/entity-B0t6sN7F.cjs +0 -71
  142. package/dist/entity-BIp_df9u.js +0 -67
  143. package/dist/entity-BIp_df9u.js.map +0 -1
  144. package/dist/entity-CniBgBSd.js.map +0 -1
  145. package/dist/expiry-BxOlvVWC.d.ts +0 -79
  146. package/dist/expiry-BxOlvVWC.d.ts.map +0 -1
  147. package/dist/expiry-CG9GhVXv.cjs +0 -135
  148. package/dist/expiry-Cgdb_dbq.js.map +0 -1
  149. package/dist/expiry-DRV29F1r.d.cts +0 -79
  150. package/dist/expiry-DRV29F1r.d.cts.map +0 -1
  151. package/dist/flags-DCD26uhe.cjs +0 -43
  152. package/dist/flags-DUT2gHEU.js +0 -33
  153. package/dist/flags-DUT2gHEU.js.map +0 -1
  154. package/dist/index-BkqSnGJH.d.ts.map +0 -1
  155. package/dist/index-C7fbakoI.d.cts +0 -278
  156. package/dist/index-C7fbakoI.d.cts.map +0 -1
  157. package/dist/index-CIcHPx2j.d.cts +0 -424
  158. package/dist/index-CIcHPx2j.d.cts.map +0 -1
  159. package/dist/index-CLhsFyVH.d.cts.map +0 -1
  160. package/dist/index-Cd2aaWme.d.ts +0 -424
  161. package/dist/index-Cd2aaWme.d.ts.map +0 -1
  162. package/dist/index-Cq6fa8AI.d.ts +0 -278
  163. package/dist/index-Cq6fa8AI.d.ts.map +0 -1
  164. package/dist/index-DaNeJUw8.d.ts +0 -955
  165. package/dist/index-DaNeJUw8.d.ts.map +0 -1
  166. package/dist/index-Dv16LO2s.d.cts +0 -955
  167. package/dist/index-Dv16LO2s.d.cts.map +0 -1
  168. package/dist/payload-AfUfSctb.d.ts.map +0 -1
  169. package/dist/payload-D167BlJR.d.cts.map +0 -1
  170. package/dist/payload-DE7wMztL.js +0 -92
  171. package/dist/payload-DE7wMztL.js.map +0 -1
  172. package/dist/payload-DqFweqiO.cjs +0 -108
  173. package/dist/query-9oojUdM7.cjs +0 -1128
  174. package/dist/query-Ber-lOJQ.js +0 -968
  175. package/dist/query-Ber-lOJQ.js.map +0 -1
  176. package/src/actions/public/getEntityCount.ts +0 -10
  177. package/src/attr/attributes.test.ts +0 -120
  178. package/src/attr/attributes.ts +0 -196
  179. package/src/attr/index.ts +0 -50
  180. package/src/types/mimeTypes.ts +0 -27
  181. package/src/utils/compression.test.ts +0 -32
  182. package/src/utils/compression.ts +0 -102
  183. package/src/utils/payload.ts +0 -36
  184. /package/src/{attr → schema}/decimal.ts +0 -0
@@ -1,25 +1,6 @@
1
1
  import { n as InvalidExpiryError } from "./errors-D2E1GRjw.js";
2
+ import { i as BLOCK_TIME, t as MAX_EXPIRES_AT } from "./params-DDJOnsNi.js";
2
3
 
3
- //#region src/consts.ts
4
- const ARKIV_ADDRESS = "0x4400000000000000000000000000000000000044";
5
- const BLOCK_TIME = 2;
6
-
7
- //#endregion
8
- //#region src/entity/params.ts
9
- /**
10
- * Max uint64 value
11
- */
12
- const MAX_EXPIRES_AT = 2n ** 64n - 1n;
13
- /** The operation tags of the `execute` ABI's tagged union. */
14
- const OperationType = {
15
- Create: 1,
16
- Patch: 2,
17
- ExtendExpiry: 3,
18
- TransferOwnership: 4,
19
- Delete: 5
20
- };
21
-
22
- //#endregion
23
4
  //#region src/entity/expiry.ts
24
5
  /**
25
6
  * Builds a branded {@link Expiry}.
@@ -36,17 +17,19 @@ function makeExpiry(minLifetime, expiresAt) {
36
17
  /**
37
18
  * Resolves an expiry into the wire pair and the block the entity will expire at.
38
19
  *
39
- * Durations are converted to blocks at the nominal `BLOCK_TIME` (2 seconds), which makes them
40
- * **approximate**: block production is not a clock, so a lifetime asked for in days drifts if the
41
- * chain runs fast or slow. The block it was converted to comes back as
42
- * {@link ResolvedExpiry.target}, so the approximation is always observable rather than assumed.
20
+ * A duration arrives here already in blocks — {@link ExpirationTime} converted it at the nominal
21
+ * `BLOCK_TIME` (2 seconds) through {@link toBlocks} — and a `Date` deadline is placed against
22
+ * `currentBlock` at that same block time here. Both are **approximate**: block production is not a
23
+ * clock, so a lifetime asked for in days drifts if the chain runs fast or slow. The block the
24
+ * expiry resolves to against `currentBlock` comes back as {@link ResolvedExpiry.target}, so the
25
+ * approximation is always observable rather than assumed.
43
26
  *
44
27
  * @throws {InvalidExpiryError} If the expiry is malformed, does not fit the `uint64` the wire
45
28
  * carries, or would leave the entity dead on arrival.
46
29
  */
47
30
  function resolveExpiry(expiry, context) {
48
31
  const { currentBlock } = context;
49
- if (typeof expiry?.minLifetime !== "bigint" || expiry.expiresAt === void 0) throw new InvalidExpiryError("expires must be built with ExpirationTime, e.g. ExpirationTime.fromDays(30) or ExpirationTime.atBlock(1_200_000n)");
32
+ if (typeof expiry?.minLifetime !== "bigint" || expiry.expiresAt === void 0) throw new InvalidExpiryError("expiration must be built with ExpirationTime, e.g. ExpirationTime.fromDays(30) or ExpirationTime.atBlock(1_200_000n)");
50
33
  const { minLifetime } = expiry;
51
34
  const absolute = typeof expiry.expiresAt === "bigint" ? expiry.expiresAt : blockAtDate(expiry.expiresAt, currentBlock);
52
35
  if (minLifetime === 0n && absolute === 0n) throw new InvalidExpiryError("no expiry given. Pass ExpirationTime.fromDays(30) for a lifetime, ExpirationTime.atBlock(n) for an absolute deadline, or a deadline with { atLeast } to take whichever is later.");
@@ -91,5 +74,57 @@ function blockAtDate(date, currentBlock) {
91
74
  }
92
75
 
93
76
  //#endregion
94
- export { OperationType as a, MAX_EXPIRES_AT as i, resolveExpiry as n, ARKIV_ADDRESS as o, toBlocks as r, BLOCK_TIME as s, makeExpiry as t };
95
- //# sourceMappingURL=expiry-Cgdb_dbq.js.map
77
+ //#region src/utils/expirationTime.ts
78
+ function lifetimeOf(seconds) {
79
+ return makeExpiry(toBlocks(seconds), 0n);
80
+ }
81
+ function deadlineOf(expiresAt, options) {
82
+ return makeExpiry(options?.atLeast?.minLifetime ?? 0n, expiresAt);
83
+ }
84
+ /**
85
+ * Builds the `expiration` of a create or an extension.
86
+ *
87
+ * Every helper returns the `{ minLifetime, expiresAt }` pair the ABI carries, so what you write is
88
+ * what goes on the wire. The `from*` helpers fill `minLifetime` and leave `expiresAt` at `0n`;
89
+ * {@link ExpirationTime.atBlock} and {@link ExpirationTime.atDate} do the reverse. The engine takes
90
+ * whichever comes later, which is why a deadline can also carry a floor.
91
+ *
92
+ * Values are plain data — no methods, no prototype — so they log, clone and compare like any other
93
+ * object.
94
+ *
95
+ * @example The 90% case: a duration, and nothing else to think about.
96
+ * await client.createEntity(Posts, values, { expiration: ExpirationTime.fromDays(30) })
97
+ *
98
+ * @example An exact block, or a wall-clock date.
99
+ * expiration: ExpirationTime.atBlock(1_200_000n)
100
+ * expiration: ExpirationTime.atDate(new Date("2027-01-01"))
101
+ *
102
+ * @example A deadline that still guarantees a minimum life.
103
+ * expiration: ExpirationTime.atBlock(1_200_000n, { atLeast: ExpirationTime.fromDays(1) })
104
+ */
105
+ const ExpirationTime = {
106
+ fromSeconds: (seconds) => lifetimeOf(seconds),
107
+ fromMinutes: (minutes) => lifetimeOf(minutes * 60),
108
+ fromHours: (hours) => lifetimeOf(hours * 60 * 60),
109
+ fromDays: (days) => lifetimeOf(days * 24 * 60 * 60),
110
+ fromWeeks: (weeks) => lifetimeOf(weeks * 7 * 24 * 60 * 60),
111
+ fromMonths: (months) => lifetimeOf(months * 30 * 24 * 60 * 60),
112
+ fromYears: (years) => lifetimeOf(years * 365 * 24 * 60 * 60),
113
+ fromBlocks: (blocks) => {
114
+ if (!Number.isInteger(blocks) || blocks <= 0) throw new InvalidExpiryError(`a lifetime must be a positive whole number of blocks, got ${blocks}`);
115
+ return makeExpiry(BigInt(blocks), 0n);
116
+ },
117
+ atBlock: (block, options) => {
118
+ if (typeof block !== "bigint" || block < 0n) throw new InvalidExpiryError(`a deadline must be a non-negative block height, got ${block}`);
119
+ return deadlineOf(block, options);
120
+ },
121
+ atDate: (date, options) => {
122
+ if (!(date instanceof Date) || Number.isNaN(date.getTime())) throw new InvalidExpiryError(`a deadline must be a valid Date, got ${String(date)}`);
123
+ return deadlineOf(date, options);
124
+ },
125
+ permanent: () => deadlineOf(MAX_EXPIRES_AT)
126
+ };
127
+
128
+ //#endregion
129
+ export { resolveExpiry as n, ExpirationTime as t };
130
+ //# sourceMappingURL=expirationTime-UKPuA-LM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expirationTime-UKPuA-LM.js","names":[],"sources":["../src/entity/expiry.ts","../src/utils/expirationTime.ts"],"sourcesContent":["import { BLOCK_TIME } from \"../consts\"\nimport type { ExpirationTime } from \"../utils/expirationTime\"\nimport { InvalidExpiryError } from \"./errors\"\nimport { MAX_EXPIRES_AT } from \"./params\"\n\n/**\n * The brand. Module-private and never exported, so the only way to obtain an {@link Expiry} is to\n * build one with {@link ExpirationTime} — a hand-written `{ minLifetime, expiresAt }` literal will\n * not typecheck, and neither will a bare number of seconds.\n */\ndeclare const validated: unique symbol\n\n/**\n * How long an entity should live.\n *\n * This is the pair the ABI carries, and the engine resolves it as\n * `max(expiresAt, currentBlock + minLifetime)` — whichever is later. Build one with\n * {@link ExpirationTime}; there is no other way to make one.\n *\n * Which slot a value lands in also decides which rules govern it. `minLifetime` is a duration, so\n * it must come to a whole number of blocks. `expiresAt` is a block height, which is a whole number\n * by construction, so a wall-clock date rounds into it rather than being rejected.\n */\nexport type Expiry = {\n /** Lifetime floor in blocks, counted from the block the transaction lands in. `0n` if unset. */\n readonly minLifetime: bigint\n /**\n * Absolute deadline: a block height, or a `Date` still to be placed against the current block.\n * `0n` if unset.\n */\n readonly expiresAt: bigint | Date\n readonly [validated]: true\n}\n\n/**\n * An expiry that is nothing but a duration — what the `ExpirationTime.from*` helpers return.\n *\n * Distinguished from a full {@link Expiry} by its `expiresAt` being the literal `0n`, which is what\n * keeps `atBlock(x, { atLeast: atBlock(y) })` from compiling: a deadline is not a floor.\n */\nexport type Lifetime = Expiry & { readonly expiresAt: 0n }\n\n/**\n * Builds a branded {@link Expiry}.\n *\n * Internal seam for {@link ExpirationTime}, which is the only thing that should call it — it is not\n * part of the package's public surface.\n */\nexport function makeExpiry(minLifetime: bigint, expiresAt: bigint | Date): Expiry {\n return { minLifetime, expiresAt } as Expiry\n}\n\n/** The two `uint64` values the ABI carries, with every `Date` already placed. */\nexport type EncodedExpiry = {\n /** Absolute target block height, or `0n` for a purely relative lifetime. */\n expiresAt: bigint\n /** Relative floor in blocks, or `0n` for a purely absolute expiry. */\n minLifetime: bigint\n}\n\n/** What an expiry resolves to, given the chain's current block. */\nexport type ResolvedExpiry = EncodedExpiry & {\n /** The block the entity will expire at — `max(expiresAt, currentBlock + minLifetime)`. */\n target: bigint\n}\n\n/** What the SDK needs to know about the chain to resolve an expiry. */\nexport type ExpiryContext = {\n currentBlock: bigint\n}\n\n/**\n * Resolves an expiry into the wire pair and the block the entity will expire at.\n *\n * A duration arrives here already in blocks — {@link ExpirationTime} converted it at the nominal\n * `BLOCK_TIME` (2 seconds) through {@link toBlocks} — and a `Date` deadline is placed against\n * `currentBlock` at that same block time here. Both are **approximate**: block production is not a\n * clock, so a lifetime asked for in days drifts if the chain runs fast or slow. The block the\n * expiry resolves to against `currentBlock` comes back as {@link ResolvedExpiry.target}, so the\n * approximation is always observable rather than assumed.\n *\n * @throws {InvalidExpiryError} If the expiry is malformed, does not fit the `uint64` the wire\n * carries, or would leave the entity dead on arrival.\n */\nexport function resolveExpiry(expiry: Expiry, context: ExpiryContext): ResolvedExpiry {\n const { currentBlock } = context\n\n if (typeof expiry?.minLifetime !== \"bigint\" || expiry.expiresAt === undefined) {\n throw new InvalidExpiryError(\n \"expiration must be built with ExpirationTime, e.g. ExpirationTime.fromDays(30) or \" +\n \"ExpirationTime.atBlock(1_200_000n)\",\n )\n }\n\n const { minLifetime } = expiry\n const absolute =\n typeof expiry.expiresAt === \"bigint\"\n ? expiry.expiresAt\n : blockAtDate(expiry.expiresAt, currentBlock)\n\n if (minLifetime === 0n && absolute === 0n) {\n throw new InvalidExpiryError(\n \"no expiry given. Pass ExpirationTime.fromDays(30) for a lifetime, \" +\n \"ExpirationTime.atBlock(n) for an absolute deadline, or a deadline with \" +\n \"{ atLeast } to take whichever is later.\",\n )\n }\n\n if (absolute > MAX_EXPIRES_AT) {\n throw new InvalidExpiryError(\n `expiresAt resolves to block ${absolute}, which does not fit the uint64 the wire carries ` +\n `(max ${MAX_EXPIRES_AT}). Use ExpirationTime.permanent() for an entity that should not ` +\n \"expire.\",\n )\n }\n if (minLifetime > MAX_EXPIRES_AT) {\n throw new InvalidExpiryError(\n `the lifetime is ${minLifetime} blocks, which does not fit the uint64 the wire carries ` +\n `(max ${MAX_EXPIRES_AT})`,\n )\n }\n\n const relative = minLifetime === 0n ? 0n : currentBlock + minLifetime\n const target = absolute > relative ? absolute : relative\n\n if (target <= currentBlock) {\n throw new InvalidExpiryError(\n `the entity would expire at block ${target}, which is not after the current block ` +\n `${currentBlock}, so it would be dead on arrival`,\n )\n }\n if (target > MAX_EXPIRES_AT) {\n throw new InvalidExpiryError(\n `a lifetime of ${minLifetime} blocks from block ${currentBlock} lands at ${target}, past ` +\n `the largest expiry the wire carries (${MAX_EXPIRES_AT})`,\n )\n }\n\n return { expiresAt: absolute, minLifetime, target }\n}\n\n/**\n * A duration in seconds as a whole number of blocks.\n *\n * Arkiv counts lifetimes in blocks, so a duration that is not a whole number of them does not\n * describe anything the chain can store. Rather than silently round a caller's `3` up to two blocks\n * — four seconds, not what they asked for — this rejects it: a duration must be a positive multiple\n * of `BLOCK_TIME` (2 seconds). The {@link ExpirationTime} helpers all produce such multiples.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive whole number of blocks' seconds.\n */\nexport function toBlocks(seconds: number): bigint {\n if (!Number.isInteger(seconds) || seconds <= 0) {\n throw new InvalidExpiryError(\n `a lifetime must be a positive whole number of seconds, got ${seconds}. Use the ` +\n \"ExpirationTime helpers, e.g. ExpirationTime.fromDays(30).\",\n )\n }\n if (seconds % BLOCK_TIME !== 0) {\n throw new InvalidExpiryError(\n `a lifetime must be a multiple of the ${BLOCK_TIME}s block time, got ${seconds}, which is ` +\n `${seconds / BLOCK_TIME} blocks. Try ${seconds - (seconds % BLOCK_TIME)} or ` +\n `${seconds + BLOCK_TIME - (seconds % BLOCK_TIME)}, or ExpirationTime.fromBlocks(n).`,\n )\n }\n return BigInt(seconds / BLOCK_TIME)\n}\n\n/**\n * The block a wall-clock instant lands on.\n *\n * Rounds **up**: a date almost never falls on a block boundary, and unlike a duration — which the\n * caller states and can state exactly — there is nothing here to reject, so the entity lives until\n * at least the instant asked for.\n */\nfunction blockAtDate(date: Date, currentBlock: bigint): bigint {\n const secondsAway = (date.getTime() - Date.now()) / 1000\n if (secondsAway <= 0) {\n throw new InvalidExpiryError(\n `the deadline ${date.toISOString()} is in the past, so the entity would be dead on arrival`,\n )\n }\n return currentBlock + BigInt(Math.ceil(secondsAway / BLOCK_TIME))\n}\n","import { InvalidExpiryError } from \"../entity/errors\"\nimport { type Expiry, type Lifetime, makeExpiry, toBlocks } from \"../entity/expiry\"\nimport { MAX_EXPIRES_AT } from \"../entity/params\"\n\n/**\n * The optional floor a deadline can carry.\n *\n * `atLeast` takes a duration — one of the `from*` helpers — and never another deadline, so\n * `atBlock(x, { atLeast: atBlock(y) })` does not compile. Two deadlines are not a thing the engine\n * can resolve.\n */\nexport type DeadlineOptions = {\n /** Live at least this long from now, even if the deadline is sooner. */\n atLeast?: Lifetime | undefined\n}\n\nfunction lifetimeOf(seconds: number): Lifetime {\n return makeExpiry(toBlocks(seconds), 0n) as Lifetime\n}\n\nfunction deadlineOf(expiresAt: bigint | Date, options?: DeadlineOptions): Expiry {\n return makeExpiry(options?.atLeast?.minLifetime ?? 0n, expiresAt)\n}\n\n/**\n * Builds the `expiration` of a create or an extension.\n *\n * Every helper returns the `{ minLifetime, expiresAt }` pair the ABI carries, so what you write is\n * what goes on the wire. The `from*` helpers fill `minLifetime` and leave `expiresAt` at `0n`;\n * {@link ExpirationTime.atBlock} and {@link ExpirationTime.atDate} do the reverse. The engine takes\n * whichever comes later, which is why a deadline can also carry a floor.\n *\n * Values are plain data — no methods, no prototype — so they log, clone and compare like any other\n * object.\n *\n * @example The 90% case: a duration, and nothing else to think about.\n * await client.createEntity(Posts, values, { expiration: ExpirationTime.fromDays(30) })\n *\n * @example An exact block, or a wall-clock date.\n * expiration: ExpirationTime.atBlock(1_200_000n)\n * expiration: ExpirationTime.atDate(new Date(\"2027-01-01\"))\n *\n * @example A deadline that still guarantees a minimum life.\n * expiration: ExpirationTime.atBlock(1_200_000n, { atLeast: ExpirationTime.fromDays(1) })\n */\nexport const ExpirationTime = {\n /**\n * A raw number of seconds. Must be a whole number of blocks' worth — see the other helpers, which\n * all produce one by construction.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.\n */\n fromSeconds: (seconds: number): Lifetime => lifetimeOf(seconds),\n /**\n * A number of minutes.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.\n */\n fromMinutes: (minutes: number): Lifetime => lifetimeOf(minutes * 60),\n\n /**\n * A number of hours.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.\n */\n fromHours: (hours: number): Lifetime => lifetimeOf(hours * 60 * 60),\n\n /**\n * A number of days. The everyday form — `fromDays(30)` is what most creates want.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.\n */\n fromDays: (days: number): Lifetime => lifetimeOf(days * 24 * 60 * 60),\n\n /**\n * A number of weeks, each of 7 days.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.\n */\n fromWeeks: (weeks: number): Lifetime => lifetimeOf(weeks * 7 * 24 * 60 * 60),\n\n /**\n * A number of months, each of exactly **30 days** — calendar months are not all the same length,\n * and a lifetime is a duration rather than a date. Use {@link ExpirationTime.atDate} when the\n * expiry has to land on a particular calendar day.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.\n */\n fromMonths: (months: number): Lifetime => lifetimeOf(months * 30 * 24 * 60 * 60),\n\n /**\n * A number of years, each of exactly **365 days** — leap days are not counted, so `fromYears(4)`\n * is a day short of four calendar years. Use {@link ExpirationTime.atDate} for a calendar\n * deadline.\n *\n * @throws {InvalidExpiryError} If the duration is not a positive multiple of the block time.\n */\n fromYears: (years: number): Lifetime => lifetimeOf(years * 365 * 24 * 60 * 60),\n\n /**\n * A number of blocks, for callers who think in the chain's own unit. Always exact — there is no\n * conversion to be approximate about.\n *\n * @throws {InvalidExpiryError} If the count is not a positive whole number.\n */\n fromBlocks: (blocks: number): Lifetime => {\n if (!Number.isInteger(blocks) || blocks <= 0) {\n throw new InvalidExpiryError(\n `a lifetime must be a positive whole number of blocks, got ${blocks}`,\n )\n }\n return makeExpiry(BigInt(blocks), 0n) as Lifetime\n },\n\n /**\n * An absolute block height.\n *\n * @param block - The block the entity expires at.\n * @param options - Optionally, a floor: `{ atLeast: ExpirationTime.fromDays(1) }`.\n * @throws {InvalidExpiryError} If the height is negative.\n */\n atBlock: (block: bigint, options?: DeadlineOptions): Expiry => {\n if (typeof block !== \"bigint\" || block < 0n) {\n throw new InvalidExpiryError(`a deadline must be a non-negative block height, got ${block}`)\n }\n return deadlineOf(block, options)\n },\n\n /**\n * A wall-clock instant, placed against the block the transaction is built on.\n *\n * A date cannot land on a block boundary in general, so it rounds **up** to the next block: the\n * entity lives until at least the instant asked for. This is why a date is never rejected for\n * \"not being a whole number of blocks\" the way a duration is — it becomes a block height, not a\n * duration.\n *\n * @param date - When the entity should expire.\n * @param options - Optionally, a floor: `{ atLeast: ExpirationTime.fromDays(1) }`.\n * @throws {InvalidExpiryError} If the value is not a valid `Date`.\n */\n atDate: (date: Date, options?: DeadlineOptions): Expiry => {\n if (!(date instanceof Date) || Number.isNaN(date.getTime())) {\n throw new InvalidExpiryError(`a deadline must be a valid Date, got ${String(date)}`)\n }\n return deadlineOf(date, options)\n },\n\n /**\n * An entity that should never expire.\n *\n * This is `atBlock(MAX_EXPIRES_AT)` — the largest expiry the `uint64` field holds — and the\n * engine treats it as an ordinary deadline rather than a special case. There is no permanence\n * flag; a block height no chain will reach is what permanence is.\n */\n permanent: (): Expiry => deadlineOf(MAX_EXPIRES_AT),\n}\n"],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ //#region src/entity/expiry.d.ts
2
+ /**
3
+ * The brand. Module-private and never exported, so the only way to obtain an {@link Expiry} is to
4
+ * build one with {@link ExpirationTime} — a hand-written `{ minLifetime, expiresAt }` literal will
5
+ * not typecheck, and neither will a bare number of seconds.
6
+ */
7
+ declare const validated: unique symbol;
8
+ /**
9
+ * How long an entity should live.
10
+ *
11
+ * This is the pair the ABI carries, and the engine resolves it as
12
+ * `max(expiresAt, currentBlock + minLifetime)` — whichever is later. Build one with
13
+ * {@link ExpirationTime}; there is no other way to make one.
14
+ *
15
+ * Which slot a value lands in also decides which rules govern it. `minLifetime` is a duration, so
16
+ * it must come to a whole number of blocks. `expiresAt` is a block height, which is a whole number
17
+ * by construction, so a wall-clock date rounds into it rather than being rejected.
18
+ */
19
+ type Expiry = {
20
+ /** Lifetime floor in blocks, counted from the block the transaction lands in. `0n` if unset. */
21
+ readonly minLifetime: bigint;
22
+ /**
23
+ * Absolute deadline: a block height, or a `Date` still to be placed against the current block.
24
+ * `0n` if unset.
25
+ */
26
+ readonly expiresAt: bigint | Date;
27
+ readonly [validated]: true;
28
+ };
29
+ /**
30
+ * An expiry that is nothing but a duration — what the `ExpirationTime.from*` helpers return.
31
+ *
32
+ * Distinguished from a full {@link Expiry} by its `expiresAt` being the literal `0n`, which is what
33
+ * keeps `atBlock(x, { atLeast: atBlock(y) })` from compiling: a deadline is not a floor.
34
+ */
35
+ type Lifetime = Expiry & {
36
+ readonly expiresAt: 0n;
37
+ };
38
+ //#endregion
39
+ export { Lifetime as n, Expiry as t };
40
+ //# sourceMappingURL=expiry-B48I-yTA.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expiry-B48I-yTA.d.cts","names":[],"sources":["../src/entity/expiry.ts"],"sourcesContent":[],"mappings":";;;AAuBA;AAiBA;;cA9Bc;;;;;;;;;;;;KAaF,MAAA;;;;;;;+BAOmB;YACnB,SAAA;;;;;;;;KASA,QAAA,GAAW"}
@@ -0,0 +1,40 @@
1
+ //#region src/entity/expiry.d.ts
2
+ /**
3
+ * The brand. Module-private and never exported, so the only way to obtain an {@link Expiry} is to
4
+ * build one with {@link ExpirationTime} — a hand-written `{ minLifetime, expiresAt }` literal will
5
+ * not typecheck, and neither will a bare number of seconds.
6
+ */
7
+ declare const validated: unique symbol;
8
+ /**
9
+ * How long an entity should live.
10
+ *
11
+ * This is the pair the ABI carries, and the engine resolves it as
12
+ * `max(expiresAt, currentBlock + minLifetime)` — whichever is later. Build one with
13
+ * {@link ExpirationTime}; there is no other way to make one.
14
+ *
15
+ * Which slot a value lands in also decides which rules govern it. `minLifetime` is a duration, so
16
+ * it must come to a whole number of blocks. `expiresAt` is a block height, which is a whole number
17
+ * by construction, so a wall-clock date rounds into it rather than being rejected.
18
+ */
19
+ type Expiry = {
20
+ /** Lifetime floor in blocks, counted from the block the transaction lands in. `0n` if unset. */
21
+ readonly minLifetime: bigint;
22
+ /**
23
+ * Absolute deadline: a block height, or a `Date` still to be placed against the current block.
24
+ * `0n` if unset.
25
+ */
26
+ readonly expiresAt: bigint | Date;
27
+ readonly [validated]: true;
28
+ };
29
+ /**
30
+ * An expiry that is nothing but a duration — what the `ExpirationTime.from*` helpers return.
31
+ *
32
+ * Distinguished from a full {@link Expiry} by its `expiresAt` being the literal `0n`, which is what
33
+ * keeps `atBlock(x, { atLeast: atBlock(y) })` from compiling: a deadline is not a floor.
34
+ */
35
+ type Lifetime = Expiry & {
36
+ readonly expiresAt: 0n;
37
+ };
38
+ //#endregion
39
+ export { Lifetime as n, Expiry as t };
40
+ //# sourceMappingURL=expiry-S2PUL8Hg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expiry-S2PUL8Hg.d.ts","names":[],"sources":["../src/entity/expiry.ts"],"sourcesContent":[],"mappings":";;;AAuBA;AAiBA;;cA9Bc;;;;;;;;;;;;KAaF,MAAA;;;;;;;+BAOmB;YACnB,SAAA;;;;;;;;KASA,QAAA,GAAW"}