@axorum/client 0.0.0-stage → 1.0.0

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 (79) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +530 -2
  3. package/dist/agent-uri.d.ts +30 -0
  4. package/dist/agent-uri.d.ts.map +1 -0
  5. package/dist/agent-uri.js +218 -0
  6. package/dist/agent-uri.js.map +1 -0
  7. package/dist/authorize.d.ts +671 -0
  8. package/dist/authorize.d.ts.map +1 -0
  9. package/dist/authorize.js +947 -0
  10. package/dist/authorize.js.map +1 -0
  11. package/dist/capabilities.d.ts +30 -0
  12. package/dist/capabilities.d.ts.map +1 -0
  13. package/dist/capabilities.js +40 -0
  14. package/dist/capabilities.js.map +1 -0
  15. package/dist/chart.d.ts +74 -0
  16. package/dist/chart.d.ts.map +1 -0
  17. package/dist/chart.js +107 -0
  18. package/dist/chart.js.map +1 -0
  19. package/dist/client.d.ts +644 -0
  20. package/dist/client.d.ts.map +1 -0
  21. package/dist/client.js +1302 -0
  22. package/dist/client.js.map +1 -0
  23. package/dist/errors.d.ts +646 -0
  24. package/dist/errors.d.ts.map +1 -0
  25. package/dist/errors.js +928 -0
  26. package/dist/errors.js.map +1 -0
  27. package/dist/failover.d.ts +197 -0
  28. package/dist/failover.d.ts.map +1 -0
  29. package/dist/failover.js +289 -0
  30. package/dist/failover.js.map +1 -0
  31. package/dist/freshness.d.ts +65 -0
  32. package/dist/freshness.d.ts.map +1 -0
  33. package/dist/freshness.js +148 -0
  34. package/dist/freshness.js.map +1 -0
  35. package/dist/generated/agent-plane.d.ts +1863 -0
  36. package/dist/generated/agent-plane.d.ts.map +1 -0
  37. package/dist/generated/agent-plane.js +19 -0
  38. package/dist/generated/agent-plane.js.map +1 -0
  39. package/dist/idempotency.d.ts +160 -0
  40. package/dist/idempotency.d.ts.map +1 -0
  41. package/dist/idempotency.js +208 -0
  42. package/dist/idempotency.js.map +1 -0
  43. package/dist/index.d.ts +89 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +87 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/intent.d.ts +163 -0
  48. package/dist/intent.d.ts.map +1 -0
  49. package/dist/intent.js +82 -0
  50. package/dist/intent.js.map +1 -0
  51. package/dist/json.d.ts +49 -0
  52. package/dist/json.d.ts.map +1 -0
  53. package/dist/json.js +259 -0
  54. package/dist/json.js.map +1 -0
  55. package/dist/key.d.ts +64 -0
  56. package/dist/key.d.ts.map +1 -0
  57. package/dist/key.js +71 -0
  58. package/dist/key.js.map +1 -0
  59. package/dist/payment.d.ts +172 -0
  60. package/dist/payment.d.ts.map +1 -0
  61. package/dist/payment.js +178 -0
  62. package/dist/payment.js.map +1 -0
  63. package/dist/refusal.d.ts +121 -0
  64. package/dist/refusal.d.ts.map +1 -0
  65. package/dist/refusal.js +176 -0
  66. package/dist/refusal.js.map +1 -0
  67. package/dist/retry.d.ts +215 -0
  68. package/dist/retry.d.ts.map +1 -0
  69. package/dist/retry.js +297 -0
  70. package/dist/retry.js.map +1 -0
  71. package/dist/typeid.d.ts +64 -0
  72. package/dist/typeid.d.ts.map +1 -0
  73. package/dist/typeid.js +119 -0
  74. package/dist/typeid.js.map +1 -0
  75. package/dist/types.d.ts +245 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +14 -0
  78. package/dist/types.js.map +1 -0
  79. package/package.json +58 -3
package/dist/retry.js ADDED
@@ -0,0 +1,297 @@
1
+ /**
2
+ * The transport retry policy: a mirror of `acton-service-client` 0.2's, which the Rust
3
+ * SDK uses, so both SDKs retry alike.
4
+ *
5
+ * Retries are **off** for a client's own calls unless it is built with a
6
+ * {@link RetryPolicy}. When one is, a request is sent again after a connection failure
7
+ * or a timeout, and after a `429`, `502` or `504` from something in front of the
8
+ * service (or a `423` that says when to come back), honouring `Retry-After`. A status
9
+ * the service documents as an answer (every `4xx` it sends, `421 not_primary`, `503
10
+ * commit_unavailable`) is not retried there: it reaches the caller after one send.
11
+ *
12
+ * `authorize` always retries, under its own policy ({@link AUTHORIZE_RETRY_POLICY}) and
13
+ * one deadline for the whole call ({@link AUTHORIZE_DEADLINE_MS}), and re-sends a `421`
14
+ * and a `503` too ({@link AUTHORIZE_RESENT_STATUSES}).
15
+ *
16
+ * Every function here is pure. `spec/fixtures/retry-v1.json` pins each one to the rows
17
+ * the Rust SDK pins `acton-service-client` itself to.
18
+ *
19
+ * @packageDocumentation
20
+ */
21
+ /**
22
+ * Three sends, 100 ms doubling, capped at 5 s, no jitter, no deadline:
23
+ * `acton-service-client`'s default.
24
+ *
25
+ * ```ts
26
+ * import { AxorumClient, DEFAULT_RETRY_POLICY } from "@axorum/client";
27
+ *
28
+ * const axorum = new AxorumClient({ baseUrl, retry: DEFAULT_RETRY_POLICY });
29
+ * ```
30
+ */
31
+ export const DEFAULT_RETRY_POLICY = Object.freeze({
32
+ maxAttempts: 3,
33
+ baseDelayMs: 100,
34
+ maxDelayMs: 5_000,
35
+ });
36
+ /**
37
+ * The whole budget of one `authorize` call, in milliseconds: the window and pin reads,
38
+ * every submission, every attempt and every pause. The most `authorizeDeadlineMs`
39
+ * accepts, since the attestation minimum is sized for it.
40
+ */
41
+ export const AUTHORIZE_DEADLINE_MS = 15_000;
42
+ /**
43
+ * The response header on `GET /api/openapi.json` in which a clustered service advertises
44
+ * its commit wait (`[cluster] submit_timeout_ms`), in milliseconds: how long it holds a
45
+ * submission before answering `503 commit_unavailable`. A standalone service has no
46
+ * commit wait and sends none.
47
+ */
48
+ export const SUBMIT_TIMEOUT_HEADER = "axorum-submit-timeout-ms";
49
+ /**
50
+ * How much longer than the advertised commit wait an attempt waits, in milliseconds, so
51
+ * the service's own `503 commit_unavailable` arrives before the client gives up.
52
+ */
53
+ export const COMMIT_WAIT_MARGIN_MS = 1_000;
54
+ /**
55
+ * The most one attempt waits, in milliseconds, when the service advertises no commit
56
+ * wait: a standalone service, one older than the header, or an advertisement that could
57
+ * not be read. Also the bound on each of `authorize`'s reads.
58
+ */
59
+ export const SUBMIT_ATTEMPT_FALLBACK_MS = 6_000;
60
+ /**
61
+ * The most one submission attempt waits against a service whose advertised commit wait
62
+ * is `commitWaitMs`: that wait plus {@link COMMIT_WAIT_MARGIN_MS}, or
63
+ * {@link SUBMIT_ATTEMPT_FALLBACK_MS} when none is advertised. Pure.
64
+ *
65
+ * Under `authorize`'s deadline the attempt is further clamped to what is left of it. When
66
+ * that clamp cuts an attempt below the commit wait plus the margin, the service may still
67
+ * be deciding when the client stops waiting, so an attempt that ends that way is honestly
68
+ * `indeterminate`: re-drive the same payment to learn its answer.
69
+ *
70
+ * ```ts
71
+ * submitAttemptTimeout(undefined); // 6000
72
+ * submitAttemptTimeout(9_000); // 10000
73
+ * ```
74
+ */
75
+ export function submitAttemptTimeout(commitWaitMs) {
76
+ return commitWaitMs === undefined ? SUBMIT_ATTEMPT_FALLBACK_MS : commitWaitMs + COMMIT_WAIT_MARGIN_MS;
77
+ }
78
+ /**
79
+ * The timeout a plain submission needs in place of the SDK's default `defaultMs` to
80
+ * outlast an advertised `commitWaitMs`: {@link submitAttemptTimeout} of it, when that is
81
+ * longer. Never shorter, and `undefined` when no wait is advertised. Pure.
82
+ */
83
+ export function liftedSubmitTimeout(defaultMs, commitWaitMs) {
84
+ if (commitWaitMs === undefined) {
85
+ return undefined;
86
+ }
87
+ const needed = submitAttemptTimeout(commitWaitMs);
88
+ return needed > defaultMs ? needed : undefined;
89
+ }
90
+ /**
91
+ * The commit wait, in milliseconds, a {@link SUBMIT_TIMEOUT_HEADER} value states, or
92
+ * `undefined` when it states none: only 1 to 9 ASCII digits, not all zero, state a wait.
93
+ * Anything else (a sign, a space, an exponent, a tenth digit) is treated as no
94
+ * advertisement rather than guessed at, so this client reads the header as the Rust
95
+ * client does (`spec/fixtures/attempt-timeout-v1.json` pins both). Pure.
96
+ */
97
+ export function advertisedCommitWait(value) {
98
+ if (value === null || value === undefined || !/^[0-9]{1,9}$/.test(value)) {
99
+ return undefined;
100
+ }
101
+ const millis = Number(value);
102
+ return millis === 0 ? undefined : millis;
103
+ }
104
+ /**
105
+ * The policy every `authorize` request is sent under: as many attempts as the deadline
106
+ * allows, full jitter floored at 100 ms, capped at 1.6 s. The deadline is not in it: it is
107
+ * an instant, set once per call and shared by all of its requests.
108
+ */
109
+ export const AUTHORIZE_RETRY_POLICY = Object.freeze({
110
+ maxAttempts: 2 ** 32 - 1,
111
+ baseDelayMs: 100,
112
+ maxDelayMs: 1_600,
113
+ jitter: "full",
114
+ });
115
+ /**
116
+ * The status an `authorize` submission is re-sent on beyond the defaults: `421
117
+ * not_primary`, safe to re-send under the same transaction id. A `503` is not here: the
118
+ * transport re-sends on the status alone and reads no body, and only its body tells a
119
+ * `503 idempotency_unseeded`, which wrote nothing, from a `503 commit_unavailable`,
120
+ * which may have committed. So the call sends a `503` again itself, its body read.
121
+ */
122
+ export const AUTHORIZE_RESENT_STATUSES = Object.freeze([421]);
123
+ /** The largest double strictly below 1: the top of the clamped draw range. */
124
+ const DRAW_MAX = 1 - Number.EPSILON / 2;
125
+ /**
126
+ * The exponential ceiling for the pause after send number `attempt` (1-based):
127
+ * `baseDelayMs × 2^(attempt − 1)`, capped at `maxDelayMs`. An attempt below 1 is
128
+ * treated as 1; a huge one saturates to the cap. With no jitter it is the pause. Pure.
129
+ */
130
+ export function backoffDelay(policy, attempt) {
131
+ const exponent = Math.min(Math.max(attempt - 1, 0), 63);
132
+ return Math.min(policy.baseDelayMs * 2 ** exponent, policy.maxDelayMs);
133
+ }
134
+ /**
135
+ * The pause after send number `attempt` (1-based), or `undefined` when it would reach the
136
+ * deadline. Pure.
137
+ *
138
+ * - `draw` is a uniform sample, clamped to `[0, 1)`; a `NaN` counts as 0. Ignored
139
+ * without jitter.
140
+ * - `remainingMs` is the time left before the deadline, or `undefined` for none.
141
+ *
142
+ * With `ceiling = backoffDelay(policy, attempt)` and `floor = min(baseDelayMs, ceiling)`:
143
+ * no jitter pauses `ceiling`; full jitter pauses `floor + ⌊(ceiling − floor) × draw⌋`.
144
+ * Either is refused when `remainingMs` is set and the pause is at least it.
145
+ */
146
+ export function pause(policy, attempt, draw, remainingMs) {
147
+ const ceiling = backoffDelay(policy, attempt);
148
+ let delay = ceiling;
149
+ if (policy.jitter === "full") {
150
+ const floor = Math.min(policy.baseDelayMs, ceiling);
151
+ delay = floor + spread(ceiling - floor, draw);
152
+ }
153
+ return fitsBefore(delay, remainingMs);
154
+ }
155
+ /** Whether another send is allowed after send number `attempt` (1-based). Pure. */
156
+ export function shouldRetry(policy, attempt) {
157
+ return attempt < Math.max(policy.maxAttempts, 1);
158
+ }
159
+ /**
160
+ * The pause before the send after `attempt`, or `undefined` to stop: when `maxAttempts`
161
+ * is spent, or when the pause would reach the deadline. A server's `Retry-After`
162
+ * replaces the computed pause (unjittered, not capped by `maxDelayMs`) but is still
163
+ * refused if it would reach the deadline. Pure.
164
+ */
165
+ export function nextPause(policy, attempt, draw, retryAfterMs, remainingMs) {
166
+ if (!shouldRetry(policy, attempt)) {
167
+ return undefined;
168
+ }
169
+ return retryAfterMs === undefined
170
+ ? pause(policy, attempt, draw, remainingMs)
171
+ : fitsBefore(retryAfterMs, remainingMs);
172
+ }
173
+ /**
174
+ * The timeout for one send, or `undefined` to leave the client's own. Pure.
175
+ *
176
+ * In order: the request's own, the client-wide attempt timeout, then (under a deadline
177
+ * only) the client's timeout, then the time remaining; under a deadline, whichever
178
+ * applies is clamped to what remains.
179
+ */
180
+ export function attemptTimeout(requestMs, clientAttemptMs, clientMs, remainingMs) {
181
+ const configured = requestMs ?? clientAttemptMs;
182
+ if (remainingMs === undefined) {
183
+ return configured;
184
+ }
185
+ const own = configured ?? clientMs;
186
+ return own === undefined ? remainingMs : Math.min(own, remainingMs);
187
+ }
188
+ /**
189
+ * Whether a failing `status` asks for another send. A status listed in `retryOn` always
190
+ * does, checked first; otherwise an accepted (documented) status never does, and any
191
+ * other does when {@link isRetriableStatus} says so. Pure.
192
+ */
193
+ export function wantsRetry(status, hasRetryAfter, accepted, retryOn) {
194
+ return retryOn.includes(status) || (!accepted && isRetriableStatus(status, hasRetryAfter));
195
+ }
196
+ /**
197
+ * Whether a failing status is worth another send: `429`, `502`, `503`, `504`, and `423`
198
+ * only when the server said when to come back. Pure.
199
+ */
200
+ export function isRetriableStatus(status, hasRetryAfter) {
201
+ switch (status) {
202
+ case 429:
203
+ case 502:
204
+ case 503:
205
+ case 504:
206
+ return true;
207
+ case 423:
208
+ return hasRetryAfter;
209
+ default:
210
+ return false;
211
+ }
212
+ }
213
+ /** A reason's label, as the Rust SDK's `RetryReason::label` spells it: `"503"`, `"timeout"`. Pure. */
214
+ export function retryLabel(reason) {
215
+ return reason.kind === "status" ? String(reason.status) : reason.kind;
216
+ }
217
+ /**
218
+ * The pause, if it ends strictly before the deadline `remainingMs` away, or `undefined`
219
+ * when it would reach it: `acton-service-client`'s rule, the boundary included. With no
220
+ * deadline every pause fits. Pure.
221
+ */
222
+ export function fitsBefore(pauseMs, remainingMs) {
223
+ return remainingMs !== undefined && pauseMs >= remainingMs ? undefined : pauseMs;
224
+ }
225
+ /** The largest `Retry-After` the Rust SDK reads: an unsigned 64-bit second count. */
226
+ const MAX_RETRY_AFTER_SECONDS = 2n ** 64n - 1n;
227
+ /**
228
+ * A `Retry-After` header's delay in milliseconds, or `undefined`. Only the
229
+ * delta-seconds form is read, as Rust parses a `u64`: an optional `+`, then digits. An
230
+ * HTTP date, a fraction, a minus sign or an overflow is ignored. Pure.
231
+ */
232
+ export function parseRetryAfter(header) {
233
+ if (header === null) {
234
+ return undefined;
235
+ }
236
+ const trimmed = header.trim();
237
+ if (!/^\+?\d+$/.test(trimmed)) {
238
+ return undefined;
239
+ }
240
+ const seconds = BigInt(trimmed.replace(/^\+/, ""));
241
+ return seconds > MAX_RETRY_AFTER_SECONDS ? undefined : Number(seconds) * 1_000;
242
+ }
243
+ /**
244
+ * Rejects a policy whose counts and delays are not non-negative whole numbers, whose
245
+ * deadline is not a positive whole number, or whose jitter is not one this SDK knows.
246
+ *
247
+ * @throws {RangeError} Naming the bad field.
248
+ */
249
+ export function checkRetryPolicy(policy) {
250
+ for (const [name, value] of [
251
+ ["maxAttempts", policy.maxAttempts],
252
+ ["baseDelayMs", policy.baseDelayMs],
253
+ ["maxDelayMs", policy.maxDelayMs],
254
+ ]) {
255
+ if (!Number.isSafeInteger(value) || value < 0) {
256
+ throw new RangeError(`${name} must be a non-negative whole number, not ${value}`);
257
+ }
258
+ }
259
+ if (policy.deadlineMs !== undefined &&
260
+ (!Number.isSafeInteger(policy.deadlineMs) || policy.deadlineMs <= 0)) {
261
+ throw new RangeError(`deadlineMs must be a positive whole number, not ${policy.deadlineMs}`);
262
+ }
263
+ if (policy.jitter !== undefined && policy.jitter !== "none" && policy.jitter !== "full") {
264
+ throw new RangeError(`jitter must be "none" or "full", not ${String(policy.jitter)}`);
265
+ }
266
+ }
267
+ /** Error codes Node's `fetch` (undici) and its resolver give a connection that never opened. */
268
+ const CONNECT_FAILURE_CODES = new Set([
269
+ "ECONNREFUSED",
270
+ "ENOTFOUND",
271
+ "EAI_AGAIN",
272
+ "EHOSTUNREACH",
273
+ "ENETUNREACH",
274
+ "UND_ERR_CONNECT_TIMEOUT",
275
+ ]);
276
+ /**
277
+ * Whether a `fetch` rejection is a connection that never opened: the counterpart of
278
+ * reqwest's `is_connect`, which is what `acton-service-client` retries (with timeouts).
279
+ * A connection that broke after the request went out is not one. Pure.
280
+ */
281
+ export function isConnectFailure(error) {
282
+ let current = error;
283
+ for (let depth = 0; depth < 4 && current instanceof Error; depth += 1) {
284
+ const code = current.code;
285
+ if (typeof code === "string" && CONNECT_FAILURE_CODES.has(code)) {
286
+ return true;
287
+ }
288
+ current = current.cause;
289
+ }
290
+ return false;
291
+ }
292
+ /** `⌊span × draw⌋` with `draw` clamped to `[0, 1)` (NaN as 0), never above `span`. */
293
+ function spread(span, draw) {
294
+ const clamped = Number.isNaN(draw) ? 0 : Math.min(Math.max(draw, 0), DRAW_MAX);
295
+ return Math.min(Math.floor(span * clamped), span);
296
+ }
297
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * TypeID encoding — how Axorum spells its identifiers on the wire.
3
+ *
4
+ * Every Axorum id is a {@link https://github.com/jetify-com/typeid | TypeID}: a fixed
5
+ * prefix, an underscore, and the 128 bits of a UUID in Crockford base32 —
6
+ * `txn_7w5b4trnc7b2ja027jyyb64395`. The client needs this for exactly one reason:
7
+ * it mints the transaction id, which is the substrate's idempotency key, and it has
8
+ * to spell it the way the ledger reads it.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ /** The TypeID prefix for a transaction id. */
13
+ export declare const TRANSACTION_PREFIX = "txn";
14
+ /**
15
+ * Encodes the 16 bytes of a UUID as a 26-character Crockford base32 TypeID suffix.
16
+ *
17
+ * A pure function of its input: the same UUID always spells the same suffix, which
18
+ * is what makes an id reconstructible rather than merely unique.
19
+ *
20
+ * @param uuid - A canonical UUID string, e.g. `01890a5d-ac96-774b-bcce-b302099a8057`.
21
+ * @returns The 26-character suffix, e.g. `01h455vb4pex5vsknk084sn02q`.
22
+ * @throws {TypeError} If `uuid` is not 32 hex digits with the usual dashes.
23
+ */
24
+ export declare function encodeSuffix(uuid: string): string;
25
+ /**
26
+ * The 128 bits a 26-character TypeID suffix encodes, or `undefined` when it is not one.
27
+ * The inverse of {@link encodeSuffix}. Pure.
28
+ *
29
+ * ```ts
30
+ * decodeSuffix(encodeSuffix("01890a5d-ac96-774b-bcce-b302099a8057")); // 0x01890a5d…n
31
+ * ```
32
+ */
33
+ export declare function decodeSuffix(suffix: string): bigint | undefined;
34
+ /**
35
+ * Mints a fresh transaction id: a UUID v7 minted at `nowMs`, spelled as a `txn_…`
36
+ * TypeID. The id carries its own mint time ({@link v7MintedAtMs}), which every envelope
37
+ * pinned from it sends as `minted_at_ms`.
38
+ *
39
+ * **Mint it once.** The transaction id is the substrate's idempotency key — every
40
+ * retry of a submission must carry the *same* id, so that an attempt which in fact
41
+ * landed replays its stored outcome instead of posting a second time. This is why
42
+ * {@link AxorumClient.submitPinned} mints the id before its first attempt and never
43
+ * again, and why you should hold on to the id you minted rather than mint another.
44
+ *
45
+ * @param nowMs - The minting time; `Date.now()` when omitted.
46
+ * @returns A new transaction id, e.g. `txn_01m3250v3ve008000000000000`.
47
+ */
48
+ export declare function newTransactionId(nowMs?: number): string;
49
+ /**
50
+ * RFC 9562 UUID version 7 from a millisecond timestamp and 16 random bytes (of which
51
+ * the first six are replaced by the timestamp). Pure.
52
+ */
53
+ export declare function uuidV7(unixMs: number, random: Uint8Array): string;
54
+ /**
55
+ * The mint time a UUID v7 transaction id carries: its 48-bit Unix millisecond
56
+ * timestamp. `undefined` for any other version or a malformed id. Pure; the same rule
57
+ * as the Rust SDK's.
58
+ *
59
+ * ```ts
60
+ * v7MintedAtMs(`txn_${encodeSuffix(uuidV7(1_790_000_000_000, new Uint8Array(16)))}`); // 1790000000000
61
+ * ```
62
+ */
63
+ export declare function v7MintedAtMs(transaction: string): number | undefined;
64
+ //# sourceMappingURL=typeid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeid.d.ts","sourceRoot":"","sources":["../src/typeid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,8CAA8C;AAC9C,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAExC;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBjD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAa/D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,MAAmB,GAAG,MAAM,CAEnE;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAWjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUpE"}
package/dist/typeid.js ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * TypeID encoding — how Axorum spells its identifiers on the wire.
3
+ *
4
+ * Every Axorum id is a {@link https://github.com/jetify-com/typeid | TypeID}: a fixed
5
+ * prefix, an underscore, and the 128 bits of a UUID in Crockford base32 —
6
+ * `txn_7w5b4trnc7b2ja027jyyb64395`. The client needs this for exactly one reason:
7
+ * it mints the transaction id, which is the substrate's idempotency key, and it has
8
+ * to spell it the way the ledger reads it.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ /** Crockford's base32 alphabet, lowercase: no `i`, `l`, `o`, or `u`. */
13
+ const ALPHABET = "0123456789abcdefghjkmnpqrstvwxyz";
14
+ /** The number of base32 characters 128 bits encodes to (26 × 5 = 130 ≥ 128). */
15
+ const SUFFIX_LENGTH = 26;
16
+ /** The TypeID prefix for a transaction id. */
17
+ export const TRANSACTION_PREFIX = "txn";
18
+ /**
19
+ * Encodes the 16 bytes of a UUID as a 26-character Crockford base32 TypeID suffix.
20
+ *
21
+ * A pure function of its input: the same UUID always spells the same suffix, which
22
+ * is what makes an id reconstructible rather than merely unique.
23
+ *
24
+ * @param uuid - A canonical UUID string, e.g. `01890a5d-ac96-774b-bcce-b302099a8057`.
25
+ * @returns The 26-character suffix, e.g. `01h455vb4pex5vsknk084sn02q`.
26
+ * @throws {TypeError} If `uuid` is not 32 hex digits with the usual dashes.
27
+ */
28
+ export function encodeSuffix(uuid) {
29
+ const hex = uuid.replaceAll("-", "").toLowerCase();
30
+ if (hex.length !== 32 || !/^[0-9a-f]{32}$/.test(hex)) {
31
+ throw new TypeError(`'${uuid}' is not a UUID`);
32
+ }
33
+ // 128 bits as one integer, then 26 five-bit digits, most significant first. The
34
+ // two bits of headroom land in the leading digit, which is why a TypeID suffix
35
+ // always starts in `0`–`7`.
36
+ let value = BigInt(`0x${hex}`);
37
+ const digits = new Array(SUFFIX_LENGTH);
38
+ for (let index = SUFFIX_LENGTH - 1; index >= 0; index -= 1) {
39
+ digits[index] = ALPHABET[Number(value & 31n)];
40
+ value >>= 5n;
41
+ }
42
+ return digits.join("");
43
+ }
44
+ /**
45
+ * The 128 bits a 26-character TypeID suffix encodes, or `undefined` when it is not one.
46
+ * The inverse of {@link encodeSuffix}. Pure.
47
+ *
48
+ * ```ts
49
+ * decodeSuffix(encodeSuffix("01890a5d-ac96-774b-bcce-b302099a8057")); // 0x01890a5d…n
50
+ * ```
51
+ */
52
+ export function decodeSuffix(suffix) {
53
+ if (suffix.length !== SUFFIX_LENGTH || suffix[0] === undefined || suffix[0] > "7") {
54
+ return undefined;
55
+ }
56
+ let value = 0n;
57
+ for (const digit of suffix) {
58
+ const index = ALPHABET.indexOf(digit);
59
+ if (index < 0) {
60
+ return undefined;
61
+ }
62
+ value = (value << 5n) | BigInt(index);
63
+ }
64
+ return value;
65
+ }
66
+ /**
67
+ * Mints a fresh transaction id: a UUID v7 minted at `nowMs`, spelled as a `txn_…`
68
+ * TypeID. The id carries its own mint time ({@link v7MintedAtMs}), which every envelope
69
+ * pinned from it sends as `minted_at_ms`.
70
+ *
71
+ * **Mint it once.** The transaction id is the substrate's idempotency key — every
72
+ * retry of a submission must carry the *same* id, so that an attempt which in fact
73
+ * landed replays its stored outcome instead of posting a second time. This is why
74
+ * {@link AxorumClient.submitPinned} mints the id before its first attempt and never
75
+ * again, and why you should hold on to the id you minted rather than mint another.
76
+ *
77
+ * @param nowMs - The minting time; `Date.now()` when omitted.
78
+ * @returns A new transaction id, e.g. `txn_01m3250v3ve008000000000000`.
79
+ */
80
+ export function newTransactionId(nowMs = Date.now()) {
81
+ return `${TRANSACTION_PREFIX}_${encodeSuffix(uuidV7(nowMs, crypto.getRandomValues(new Uint8Array(16))))}`;
82
+ }
83
+ /**
84
+ * RFC 9562 UUID version 7 from a millisecond timestamp and 16 random bytes (of which
85
+ * the first six are replaced by the timestamp). Pure.
86
+ */
87
+ export function uuidV7(unixMs, random) {
88
+ const bytes = Uint8Array.from(random.subarray(0, 16));
89
+ let time = BigInt(unixMs);
90
+ for (let index = 5; index >= 0; index -= 1) {
91
+ bytes[index] = Number(time & 0xffn);
92
+ time >>= 8n;
93
+ }
94
+ bytes[6] = (bytes[6] & 0x0f) | 0x70;
95
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
96
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
97
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
98
+ }
99
+ /**
100
+ * The mint time a UUID v7 transaction id carries: its 48-bit Unix millisecond
101
+ * timestamp. `undefined` for any other version or a malformed id. Pure; the same rule
102
+ * as the Rust SDK's.
103
+ *
104
+ * ```ts
105
+ * v7MintedAtMs(`txn_${encodeSuffix(uuidV7(1_790_000_000_000, new Uint8Array(16)))}`); // 1790000000000
106
+ * ```
107
+ */
108
+ export function v7MintedAtMs(transaction) {
109
+ const prefix = `${TRANSACTION_PREFIX}_`;
110
+ if (!transaction.startsWith(prefix)) {
111
+ return undefined;
112
+ }
113
+ const bits = decodeSuffix(transaction.slice(prefix.length));
114
+ if (bits === undefined || ((bits >> 76n) & 0xfn) !== 7n) {
115
+ return undefined;
116
+ }
117
+ return Number(bits >> 80n);
118
+ }
119
+ //# sourceMappingURL=typeid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeid.js","sourceRoot":"","sources":["../src/typeid.ts"],"names":[],"mappings":"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"}