@licenseseat/js 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,2014 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // node_modules/@noble/ed25519/index.js
8
+ var ed25519_exports = {};
9
+ __export(ed25519_exports, {
10
+ CURVE: () => ed25519_CURVE,
11
+ ExtendedPoint: () => Point,
12
+ Point: () => Point,
13
+ etc: () => etc,
14
+ getPublicKey: () => getPublicKey,
15
+ getPublicKeyAsync: () => getPublicKeyAsync,
16
+ sign: () => sign,
17
+ signAsync: () => signAsync,
18
+ utils: () => utils,
19
+ verify: () => verify,
20
+ verifyAsync: () => verifyAsync
21
+ });
22
+ var ed25519_CURVE = {
23
+ p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
24
+ n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
25
+ h: 8n,
26
+ a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
27
+ d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
28
+ Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
29
+ Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n
30
+ };
31
+ var { p: P, n: N, Gx, Gy, a: _a, d: _d } = ed25519_CURVE;
32
+ var h = 8n;
33
+ var L = 32;
34
+ var L2 = 64;
35
+ var err = (m = "") => {
36
+ throw new Error(m);
37
+ };
38
+ var isBig = (n) => typeof n === "bigint";
39
+ var isStr = (s) => typeof s === "string";
40
+ var isBytes = (a) => a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
41
+ var abytes = (a, l) => !isBytes(a) || typeof l === "number" && l > 0 && a.length !== l ? err("Uint8Array expected") : a;
42
+ var u8n = (len) => new Uint8Array(len);
43
+ var u8fr = (buf) => Uint8Array.from(buf);
44
+ var padh = (n, pad) => n.toString(16).padStart(pad, "0");
45
+ var bytesToHex = (b) => Array.from(abytes(b)).map((e) => padh(e, 2)).join("");
46
+ var C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
47
+ var _ch = (ch) => {
48
+ if (ch >= C._0 && ch <= C._9)
49
+ return ch - C._0;
50
+ if (ch >= C.A && ch <= C.F)
51
+ return ch - (C.A - 10);
52
+ if (ch >= C.a && ch <= C.f)
53
+ return ch - (C.a - 10);
54
+ return;
55
+ };
56
+ var hexToBytes = (hex) => {
57
+ const e = "hex invalid";
58
+ if (!isStr(hex))
59
+ return err(e);
60
+ const hl = hex.length;
61
+ const al = hl / 2;
62
+ if (hl % 2)
63
+ return err(e);
64
+ const array = u8n(al);
65
+ for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
66
+ const n1 = _ch(hex.charCodeAt(hi));
67
+ const n2 = _ch(hex.charCodeAt(hi + 1));
68
+ if (n1 === void 0 || n2 === void 0)
69
+ return err(e);
70
+ array[ai] = n1 * 16 + n2;
71
+ }
72
+ return array;
73
+ };
74
+ var toU8 = (a, len) => abytes(isStr(a) ? hexToBytes(a) : u8fr(abytes(a)), len);
75
+ var cr = () => globalThis?.crypto;
76
+ var subtle = () => cr()?.subtle ?? err("crypto.subtle must be defined");
77
+ var concatBytes = (...arrs) => {
78
+ const r = u8n(arrs.reduce((sum, a) => sum + abytes(a).length, 0));
79
+ let pad = 0;
80
+ arrs.forEach((a) => {
81
+ r.set(a, pad);
82
+ pad += a.length;
83
+ });
84
+ return r;
85
+ };
86
+ var randomBytes = (len = L) => {
87
+ const c = cr();
88
+ return c.getRandomValues(u8n(len));
89
+ };
90
+ var big = BigInt;
91
+ var arange = (n, min, max, msg = "bad number: out of range") => isBig(n) && min <= n && n < max ? n : err(msg);
92
+ var M = (a, b = P) => {
93
+ const r = a % b;
94
+ return r >= 0n ? r : b + r;
95
+ };
96
+ var modN = (a) => M(a, N);
97
+ var invert = (num, md) => {
98
+ if (num === 0n || md <= 0n)
99
+ err("no inverse n=" + num + " mod=" + md);
100
+ let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;
101
+ while (a !== 0n) {
102
+ const q = b / a, r = b % a;
103
+ const m = x - u * q, n = y - v * q;
104
+ b = a, a = r, x = u, y = v, u = m, v = n;
105
+ }
106
+ return b === 1n ? M(x, md) : err("no inverse");
107
+ };
108
+ var callHash = (name) => {
109
+ const fn = etc[name];
110
+ if (typeof fn !== "function")
111
+ err("hashes." + name + " not set");
112
+ return fn;
113
+ };
114
+ var apoint = (p) => p instanceof Point ? p : err("Point expected");
115
+ var B256 = 2n ** 256n;
116
+ var Point = class _Point {
117
+ static BASE;
118
+ static ZERO;
119
+ ex;
120
+ ey;
121
+ ez;
122
+ et;
123
+ constructor(ex, ey, ez, et) {
124
+ const max = B256;
125
+ this.ex = arange(ex, 0n, max);
126
+ this.ey = arange(ey, 0n, max);
127
+ this.ez = arange(ez, 1n, max);
128
+ this.et = arange(et, 0n, max);
129
+ Object.freeze(this);
130
+ }
131
+ static fromAffine(p) {
132
+ return new _Point(p.x, p.y, 1n, M(p.x * p.y));
133
+ }
134
+ /** RFC8032 5.1.3: Uint8Array to Point. */
135
+ static fromBytes(hex, zip215 = false) {
136
+ const d = _d;
137
+ const normed = u8fr(abytes(hex, L));
138
+ const lastByte = hex[31];
139
+ normed[31] = lastByte & ~128;
140
+ const y = bytesToNumLE(normed);
141
+ const max = zip215 ? B256 : P;
142
+ arange(y, 0n, max);
143
+ const y2 = M(y * y);
144
+ const u = M(y2 - 1n);
145
+ const v = M(d * y2 + 1n);
146
+ let { isValid, value: x } = uvRatio(u, v);
147
+ if (!isValid)
148
+ err("bad point: y not sqrt");
149
+ const isXOdd = (x & 1n) === 1n;
150
+ const isLastByteOdd = (lastByte & 128) !== 0;
151
+ if (!zip215 && x === 0n && isLastByteOdd)
152
+ err("bad point: x==0, isLastByteOdd");
153
+ if (isLastByteOdd !== isXOdd)
154
+ x = M(-x);
155
+ return new _Point(x, y, 1n, M(x * y));
156
+ }
157
+ /** Checks if the point is valid and on-curve. */
158
+ assertValidity() {
159
+ const a = _a;
160
+ const d = _d;
161
+ const p = this;
162
+ if (p.is0())
163
+ throw new Error("bad point: ZERO");
164
+ const { ex: X, ey: Y, ez: Z, et: T } = p;
165
+ const X2 = M(X * X);
166
+ const Y2 = M(Y * Y);
167
+ const Z2 = M(Z * Z);
168
+ const Z4 = M(Z2 * Z2);
169
+ const aX2 = M(X2 * a);
170
+ const left = M(Z2 * M(aX2 + Y2));
171
+ const right = M(Z4 + M(d * M(X2 * Y2)));
172
+ if (left !== right)
173
+ throw new Error("bad point: equation left != right (1)");
174
+ const XY = M(X * Y);
175
+ const ZT = M(Z * T);
176
+ if (XY !== ZT)
177
+ throw new Error("bad point: equation left != right (2)");
178
+ return this;
179
+ }
180
+ /** Equality check: compare points P&Q. */
181
+ equals(other) {
182
+ const { ex: X1, ey: Y1, ez: Z1 } = this;
183
+ const { ex: X2, ey: Y2, ez: Z2 } = apoint(other);
184
+ const X1Z2 = M(X1 * Z2);
185
+ const X2Z1 = M(X2 * Z1);
186
+ const Y1Z2 = M(Y1 * Z2);
187
+ const Y2Z1 = M(Y2 * Z1);
188
+ return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;
189
+ }
190
+ is0() {
191
+ return this.equals(I);
192
+ }
193
+ /** Flip point over y coordinate. */
194
+ negate() {
195
+ return new _Point(M(-this.ex), this.ey, this.ez, M(-this.et));
196
+ }
197
+ /** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */
198
+ double() {
199
+ const { ex: X1, ey: Y1, ez: Z1 } = this;
200
+ const a = _a;
201
+ const A = M(X1 * X1);
202
+ const B = M(Y1 * Y1);
203
+ const C2 = M(2n * M(Z1 * Z1));
204
+ const D = M(a * A);
205
+ const x1y1 = X1 + Y1;
206
+ const E = M(M(x1y1 * x1y1) - A - B);
207
+ const G2 = D + B;
208
+ const F = G2 - C2;
209
+ const H = D - B;
210
+ const X3 = M(E * F);
211
+ const Y3 = M(G2 * H);
212
+ const T3 = M(E * H);
213
+ const Z3 = M(F * G2);
214
+ return new _Point(X3, Y3, Z3, T3);
215
+ }
216
+ /** Point addition. Complete formula. Cost: `8M + 1*k + 8add + 1*2`. */
217
+ add(other) {
218
+ const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this;
219
+ const { ex: X2, ey: Y2, ez: Z2, et: T2 } = apoint(other);
220
+ const a = _a;
221
+ const d = _d;
222
+ const A = M(X1 * X2);
223
+ const B = M(Y1 * Y2);
224
+ const C2 = M(T1 * d * T2);
225
+ const D = M(Z1 * Z2);
226
+ const E = M((X1 + Y1) * (X2 + Y2) - A - B);
227
+ const F = M(D - C2);
228
+ const G2 = M(D + C2);
229
+ const H = M(B - a * A);
230
+ const X3 = M(E * F);
231
+ const Y3 = M(G2 * H);
232
+ const T3 = M(E * H);
233
+ const Z3 = M(F * G2);
234
+ return new _Point(X3, Y3, Z3, T3);
235
+ }
236
+ /**
237
+ * Point-by-scalar multiplication. Scalar must be in range 1 <= n < CURVE.n.
238
+ * Uses {@link wNAF} for base point.
239
+ * Uses fake point to mitigate side-channel leakage.
240
+ * @param n scalar by which point is multiplied
241
+ * @param safe safe mode guards against timing attacks; unsafe mode is faster
242
+ */
243
+ multiply(n, safe = true) {
244
+ if (!safe && (n === 0n || this.is0()))
245
+ return I;
246
+ arange(n, 1n, N);
247
+ if (n === 1n)
248
+ return this;
249
+ if (this.equals(G))
250
+ return wNAF(n).p;
251
+ let p = I;
252
+ let f = G;
253
+ for (let d = this; n > 0n; d = d.double(), n >>= 1n) {
254
+ if (n & 1n)
255
+ p = p.add(d);
256
+ else if (safe)
257
+ f = f.add(d);
258
+ }
259
+ return p;
260
+ }
261
+ /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */
262
+ toAffine() {
263
+ const { ex: x, ey: y, ez: z } = this;
264
+ if (this.equals(I))
265
+ return { x: 0n, y: 1n };
266
+ const iz = invert(z, P);
267
+ if (M(z * iz) !== 1n)
268
+ err("invalid inverse");
269
+ return { x: M(x * iz), y: M(y * iz) };
270
+ }
271
+ toBytes() {
272
+ const { x, y } = this.assertValidity().toAffine();
273
+ const b = numTo32bLE(y);
274
+ b[31] |= x & 1n ? 128 : 0;
275
+ return b;
276
+ }
277
+ toHex() {
278
+ return bytesToHex(this.toBytes());
279
+ }
280
+ // encode to hex string
281
+ clearCofactor() {
282
+ return this.multiply(big(h), false);
283
+ }
284
+ isSmallOrder() {
285
+ return this.clearCofactor().is0();
286
+ }
287
+ isTorsionFree() {
288
+ let p = this.multiply(N / 2n, false).double();
289
+ if (N % 2n)
290
+ p = p.add(this);
291
+ return p.is0();
292
+ }
293
+ static fromHex(hex, zip215) {
294
+ return _Point.fromBytes(toU8(hex), zip215);
295
+ }
296
+ get x() {
297
+ return this.toAffine().x;
298
+ }
299
+ get y() {
300
+ return this.toAffine().y;
301
+ }
302
+ toRawBytes() {
303
+ return this.toBytes();
304
+ }
305
+ };
306
+ var G = new Point(Gx, Gy, 1n, M(Gx * Gy));
307
+ var I = new Point(0n, 1n, 1n, 0n);
308
+ Point.BASE = G;
309
+ Point.ZERO = I;
310
+ var numTo32bLE = (num) => hexToBytes(padh(arange(num, 0n, B256), L2)).reverse();
311
+ var bytesToNumLE = (b) => big("0x" + bytesToHex(u8fr(abytes(b)).reverse()));
312
+ var pow2 = (x, power) => {
313
+ let r = x;
314
+ while (power-- > 0n) {
315
+ r *= r;
316
+ r %= P;
317
+ }
318
+ return r;
319
+ };
320
+ var pow_2_252_3 = (x) => {
321
+ const x2 = x * x % P;
322
+ const b2 = x2 * x % P;
323
+ const b4 = pow2(b2, 2n) * b2 % P;
324
+ const b5 = pow2(b4, 1n) * x % P;
325
+ const b10 = pow2(b5, 5n) * b5 % P;
326
+ const b20 = pow2(b10, 10n) * b10 % P;
327
+ const b40 = pow2(b20, 20n) * b20 % P;
328
+ const b80 = pow2(b40, 40n) * b40 % P;
329
+ const b160 = pow2(b80, 80n) * b80 % P;
330
+ const b240 = pow2(b160, 80n) * b80 % P;
331
+ const b250 = pow2(b240, 10n) * b10 % P;
332
+ const pow_p_5_8 = pow2(b250, 2n) * x % P;
333
+ return { pow_p_5_8, b2 };
334
+ };
335
+ var RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n;
336
+ var uvRatio = (u, v) => {
337
+ const v3 = M(v * v * v);
338
+ const v7 = M(v3 * v3 * v);
339
+ const pow = pow_2_252_3(u * v7).pow_p_5_8;
340
+ let x = M(u * v3 * pow);
341
+ const vx2 = M(v * x * x);
342
+ const root1 = x;
343
+ const root2 = M(x * RM1);
344
+ const useRoot1 = vx2 === u;
345
+ const useRoot2 = vx2 === M(-u);
346
+ const noRoot = vx2 === M(-u * RM1);
347
+ if (useRoot1)
348
+ x = root1;
349
+ if (useRoot2 || noRoot)
350
+ x = root2;
351
+ if ((M(x) & 1n) === 1n)
352
+ x = M(-x);
353
+ return { isValid: useRoot1 || useRoot2, value: x };
354
+ };
355
+ var modL_LE = (hash) => modN(bytesToNumLE(hash));
356
+ var sha512a = (...m) => etc.sha512Async(...m);
357
+ var sha512s = (...m) => callHash("sha512Sync")(...m);
358
+ var hash2extK = (hashed) => {
359
+ const head = hashed.slice(0, L);
360
+ head[0] &= 248;
361
+ head[31] &= 127;
362
+ head[31] |= 64;
363
+ const prefix = hashed.slice(L, L2);
364
+ const scalar = modL_LE(head);
365
+ const point = G.multiply(scalar);
366
+ const pointBytes = point.toBytes();
367
+ return { head, prefix, scalar, point, pointBytes };
368
+ };
369
+ var getExtendedPublicKeyAsync = (priv) => sha512a(toU8(priv, L)).then(hash2extK);
370
+ var getExtendedPublicKey = (priv) => hash2extK(sha512s(toU8(priv, L)));
371
+ var getPublicKeyAsync = (priv) => getExtendedPublicKeyAsync(priv).then((p) => p.pointBytes);
372
+ var getPublicKey = (priv) => getExtendedPublicKey(priv).pointBytes;
373
+ var hashFinishA = (res) => sha512a(res.hashable).then(res.finish);
374
+ var hashFinishS = (res) => res.finish(sha512s(res.hashable));
375
+ var _sign = (e, rBytes, msg) => {
376
+ const { pointBytes: P2, scalar: s } = e;
377
+ const r = modL_LE(rBytes);
378
+ const R = G.multiply(r).toBytes();
379
+ const hashable = concatBytes(R, P2, msg);
380
+ const finish = (hashed) => {
381
+ const S = modN(r + modL_LE(hashed) * s);
382
+ return abytes(concatBytes(R, numTo32bLE(S)), L2);
383
+ };
384
+ return { hashable, finish };
385
+ };
386
+ var signAsync = async (msg, privKey) => {
387
+ const m = toU8(msg);
388
+ const e = await getExtendedPublicKeyAsync(privKey);
389
+ const rBytes = await sha512a(e.prefix, m);
390
+ return hashFinishA(_sign(e, rBytes, m));
391
+ };
392
+ var sign = (msg, privKey) => {
393
+ const m = toU8(msg);
394
+ const e = getExtendedPublicKey(privKey);
395
+ const rBytes = sha512s(e.prefix, m);
396
+ return hashFinishS(_sign(e, rBytes, m));
397
+ };
398
+ var veriOpts = { zip215: true };
399
+ var _verify = (sig, msg, pub, opts = veriOpts) => {
400
+ sig = toU8(sig, L2);
401
+ msg = toU8(msg);
402
+ pub = toU8(pub, L);
403
+ const { zip215 } = opts;
404
+ let A;
405
+ let R;
406
+ let s;
407
+ let SB;
408
+ let hashable = Uint8Array.of();
409
+ try {
410
+ A = Point.fromHex(pub, zip215);
411
+ R = Point.fromHex(sig.slice(0, L), zip215);
412
+ s = bytesToNumLE(sig.slice(L, L2));
413
+ SB = G.multiply(s, false);
414
+ hashable = concatBytes(R.toBytes(), A.toBytes(), msg);
415
+ } catch (error) {
416
+ }
417
+ const finish = (hashed) => {
418
+ if (SB == null)
419
+ return false;
420
+ if (!zip215 && A.isSmallOrder())
421
+ return false;
422
+ const k = modL_LE(hashed);
423
+ const RkA = R.add(A.multiply(k, false));
424
+ return RkA.add(SB.negate()).clearCofactor().is0();
425
+ };
426
+ return { hashable, finish };
427
+ };
428
+ var verifyAsync = async (s, m, p, opts = veriOpts) => hashFinishA(_verify(s, m, p, opts));
429
+ var verify = (s, m, p, opts = veriOpts) => hashFinishS(_verify(s, m, p, opts));
430
+ var etc = {
431
+ sha512Async: async (...messages) => {
432
+ const s = subtle();
433
+ const m = concatBytes(...messages);
434
+ return u8n(await s.digest("SHA-512", m.buffer));
435
+ },
436
+ sha512Sync: void 0,
437
+ bytesToHex,
438
+ hexToBytes,
439
+ concatBytes,
440
+ mod: M,
441
+ invert,
442
+ randomBytes
443
+ };
444
+ var utils = {
445
+ getExtendedPublicKeyAsync,
446
+ getExtendedPublicKey,
447
+ randomPrivateKey: () => randomBytes(L),
448
+ precompute: (w = 8, p = G) => {
449
+ p.multiply(3n);
450
+ w;
451
+ return p;
452
+ }
453
+ // no-op
454
+ };
455
+ var W = 8;
456
+ var scalarBits = 256;
457
+ var pwindows = Math.ceil(scalarBits / W) + 1;
458
+ var pwindowSize = 2 ** (W - 1);
459
+ var precompute = () => {
460
+ const points = [];
461
+ let p = G;
462
+ let b = p;
463
+ for (let w = 0; w < pwindows; w++) {
464
+ b = p;
465
+ points.push(b);
466
+ for (let i = 1; i < pwindowSize; i++) {
467
+ b = b.add(p);
468
+ points.push(b);
469
+ }
470
+ p = b.double();
471
+ }
472
+ return points;
473
+ };
474
+ var Gpows = void 0;
475
+ var ctneg = (cnd, p) => {
476
+ const n = p.negate();
477
+ return cnd ? n : p;
478
+ };
479
+ var wNAF = (n) => {
480
+ const comp = Gpows || (Gpows = precompute());
481
+ let p = I;
482
+ let f = G;
483
+ const pow_2_w = 2 ** W;
484
+ const maxNum = pow_2_w;
485
+ const mask = big(pow_2_w - 1);
486
+ const shiftBy = big(W);
487
+ for (let w = 0; w < pwindows; w++) {
488
+ let wbits = Number(n & mask);
489
+ n >>= shiftBy;
490
+ if (wbits > pwindowSize) {
491
+ wbits -= maxNum;
492
+ n += 1n;
493
+ }
494
+ const off = w * pwindowSize;
495
+ const offF = off;
496
+ const offP = off + Math.abs(wbits) - 1;
497
+ const isEven = w % 2 !== 0;
498
+ const isNeg = wbits < 0;
499
+ if (wbits === 0) {
500
+ f = f.add(ctneg(isEven, comp[offF]));
501
+ } else {
502
+ p = p.add(ctneg(isNeg, comp[offP]));
503
+ }
504
+ }
505
+ return { p, f };
506
+ };
507
+
508
+ // node_modules/@noble/hashes/esm/utils.js
509
+ function isBytes2(a) {
510
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
511
+ }
512
+ function abytes2(b, ...lengths) {
513
+ if (!isBytes2(b))
514
+ throw new Error("Uint8Array expected");
515
+ if (lengths.length > 0 && !lengths.includes(b.length))
516
+ throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
517
+ }
518
+ function aexists(instance, checkFinished = true) {
519
+ if (instance.destroyed)
520
+ throw new Error("Hash instance has been destroyed");
521
+ if (checkFinished && instance.finished)
522
+ throw new Error("Hash#digest() has already been called");
523
+ }
524
+ function aoutput(out, instance) {
525
+ abytes2(out);
526
+ const min = instance.outputLen;
527
+ if (out.length < min) {
528
+ throw new Error("digestInto() expects output buffer of length at least " + min);
529
+ }
530
+ }
531
+ function clean(...arrays) {
532
+ for (let i = 0; i < arrays.length; i++) {
533
+ arrays[i].fill(0);
534
+ }
535
+ }
536
+ function createView(arr) {
537
+ return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
538
+ }
539
+ function utf8ToBytes(str2) {
540
+ if (typeof str2 !== "string")
541
+ throw new Error("string expected");
542
+ return new Uint8Array(new TextEncoder().encode(str2));
543
+ }
544
+ function toBytes(data) {
545
+ if (typeof data === "string")
546
+ data = utf8ToBytes(data);
547
+ abytes2(data);
548
+ return data;
549
+ }
550
+ var Hash = class {
551
+ };
552
+ function createHasher(hashCons) {
553
+ const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
554
+ const tmp = hashCons();
555
+ hashC.outputLen = tmp.outputLen;
556
+ hashC.blockLen = tmp.blockLen;
557
+ hashC.create = () => hashCons();
558
+ return hashC;
559
+ }
560
+
561
+ // node_modules/@noble/hashes/esm/_md.js
562
+ function setBigUint64(view, byteOffset, value, isLE) {
563
+ if (typeof view.setBigUint64 === "function")
564
+ return view.setBigUint64(byteOffset, value, isLE);
565
+ const _32n2 = BigInt(32);
566
+ const _u32_max = BigInt(4294967295);
567
+ const wh = Number(value >> _32n2 & _u32_max);
568
+ const wl = Number(value & _u32_max);
569
+ const h2 = isLE ? 4 : 0;
570
+ const l = isLE ? 0 : 4;
571
+ view.setUint32(byteOffset + h2, wh, isLE);
572
+ view.setUint32(byteOffset + l, wl, isLE);
573
+ }
574
+ var HashMD = class extends Hash {
575
+ constructor(blockLen, outputLen, padOffset, isLE) {
576
+ super();
577
+ this.finished = false;
578
+ this.length = 0;
579
+ this.pos = 0;
580
+ this.destroyed = false;
581
+ this.blockLen = blockLen;
582
+ this.outputLen = outputLen;
583
+ this.padOffset = padOffset;
584
+ this.isLE = isLE;
585
+ this.buffer = new Uint8Array(blockLen);
586
+ this.view = createView(this.buffer);
587
+ }
588
+ update(data) {
589
+ aexists(this);
590
+ data = toBytes(data);
591
+ abytes2(data);
592
+ const { view, buffer, blockLen } = this;
593
+ const len = data.length;
594
+ for (let pos = 0; pos < len; ) {
595
+ const take = Math.min(blockLen - this.pos, len - pos);
596
+ if (take === blockLen) {
597
+ const dataView = createView(data);
598
+ for (; blockLen <= len - pos; pos += blockLen)
599
+ this.process(dataView, pos);
600
+ continue;
601
+ }
602
+ buffer.set(data.subarray(pos, pos + take), this.pos);
603
+ this.pos += take;
604
+ pos += take;
605
+ if (this.pos === blockLen) {
606
+ this.process(view, 0);
607
+ this.pos = 0;
608
+ }
609
+ }
610
+ this.length += data.length;
611
+ this.roundClean();
612
+ return this;
613
+ }
614
+ digestInto(out) {
615
+ aexists(this);
616
+ aoutput(out, this);
617
+ this.finished = true;
618
+ const { buffer, view, blockLen, isLE } = this;
619
+ let { pos } = this;
620
+ buffer[pos++] = 128;
621
+ clean(this.buffer.subarray(pos));
622
+ if (this.padOffset > blockLen - pos) {
623
+ this.process(view, 0);
624
+ pos = 0;
625
+ }
626
+ for (let i = pos; i < blockLen; i++)
627
+ buffer[i] = 0;
628
+ setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
629
+ this.process(view, 0);
630
+ const oview = createView(out);
631
+ const len = this.outputLen;
632
+ if (len % 4)
633
+ throw new Error("_sha2: outputLen should be aligned to 32bit");
634
+ const outLen = len / 4;
635
+ const state = this.get();
636
+ if (outLen > state.length)
637
+ throw new Error("_sha2: outputLen bigger than state");
638
+ for (let i = 0; i < outLen; i++)
639
+ oview.setUint32(4 * i, state[i], isLE);
640
+ }
641
+ digest() {
642
+ const { buffer, outputLen } = this;
643
+ this.digestInto(buffer);
644
+ const res = buffer.slice(0, outputLen);
645
+ this.destroy();
646
+ return res;
647
+ }
648
+ _cloneInto(to) {
649
+ to || (to = new this.constructor());
650
+ to.set(...this.get());
651
+ const { blockLen, buffer, length, finished, destroyed, pos } = this;
652
+ to.destroyed = destroyed;
653
+ to.finished = finished;
654
+ to.length = length;
655
+ to.pos = pos;
656
+ if (length % blockLen)
657
+ to.buffer.set(buffer);
658
+ return to;
659
+ }
660
+ clone() {
661
+ return this._cloneInto();
662
+ }
663
+ };
664
+ var SHA512_IV = /* @__PURE__ */ Uint32Array.from([
665
+ 1779033703,
666
+ 4089235720,
667
+ 3144134277,
668
+ 2227873595,
669
+ 1013904242,
670
+ 4271175723,
671
+ 2773480762,
672
+ 1595750129,
673
+ 1359893119,
674
+ 2917565137,
675
+ 2600822924,
676
+ 725511199,
677
+ 528734635,
678
+ 4215389547,
679
+ 1541459225,
680
+ 327033209
681
+ ]);
682
+
683
+ // node_modules/@noble/hashes/esm/_u64.js
684
+ var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
685
+ var _32n = /* @__PURE__ */ BigInt(32);
686
+ function fromBig(n, le = false) {
687
+ if (le)
688
+ return { h: Number(n & U32_MASK64), l: Number(n >> _32n & U32_MASK64) };
689
+ return { h: Number(n >> _32n & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
690
+ }
691
+ function split(lst, le = false) {
692
+ const len = lst.length;
693
+ let Ah = new Uint32Array(len);
694
+ let Al = new Uint32Array(len);
695
+ for (let i = 0; i < len; i++) {
696
+ const { h: h2, l } = fromBig(lst[i], le);
697
+ [Ah[i], Al[i]] = [h2, l];
698
+ }
699
+ return [Ah, Al];
700
+ }
701
+ var shrSH = (h2, _l, s) => h2 >>> s;
702
+ var shrSL = (h2, l, s) => h2 << 32 - s | l >>> s;
703
+ var rotrSH = (h2, l, s) => h2 >>> s | l << 32 - s;
704
+ var rotrSL = (h2, l, s) => h2 << 32 - s | l >>> s;
705
+ var rotrBH = (h2, l, s) => h2 << 64 - s | l >>> s - 32;
706
+ var rotrBL = (h2, l, s) => h2 >>> s - 32 | l << 64 - s;
707
+ function add(Ah, Al, Bh, Bl) {
708
+ const l = (Al >>> 0) + (Bl >>> 0);
709
+ return { h: Ah + Bh + (l / 2 ** 32 | 0) | 0, l: l | 0 };
710
+ }
711
+ var add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
712
+ var add3H = (low, Ah, Bh, Ch) => Ah + Bh + Ch + (low / 2 ** 32 | 0) | 0;
713
+ var add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);
714
+ var add4H = (low, Ah, Bh, Ch, Dh) => Ah + Bh + Ch + Dh + (low / 2 ** 32 | 0) | 0;
715
+ var add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);
716
+ var add5H = (low, Ah, Bh, Ch, Dh, Eh) => Ah + Bh + Ch + Dh + Eh + (low / 2 ** 32 | 0) | 0;
717
+
718
+ // node_modules/@noble/hashes/esm/sha2.js
719
+ var K512 = /* @__PURE__ */ (() => split([
720
+ "0x428a2f98d728ae22",
721
+ "0x7137449123ef65cd",
722
+ "0xb5c0fbcfec4d3b2f",
723
+ "0xe9b5dba58189dbbc",
724
+ "0x3956c25bf348b538",
725
+ "0x59f111f1b605d019",
726
+ "0x923f82a4af194f9b",
727
+ "0xab1c5ed5da6d8118",
728
+ "0xd807aa98a3030242",
729
+ "0x12835b0145706fbe",
730
+ "0x243185be4ee4b28c",
731
+ "0x550c7dc3d5ffb4e2",
732
+ "0x72be5d74f27b896f",
733
+ "0x80deb1fe3b1696b1",
734
+ "0x9bdc06a725c71235",
735
+ "0xc19bf174cf692694",
736
+ "0xe49b69c19ef14ad2",
737
+ "0xefbe4786384f25e3",
738
+ "0x0fc19dc68b8cd5b5",
739
+ "0x240ca1cc77ac9c65",
740
+ "0x2de92c6f592b0275",
741
+ "0x4a7484aa6ea6e483",
742
+ "0x5cb0a9dcbd41fbd4",
743
+ "0x76f988da831153b5",
744
+ "0x983e5152ee66dfab",
745
+ "0xa831c66d2db43210",
746
+ "0xb00327c898fb213f",
747
+ "0xbf597fc7beef0ee4",
748
+ "0xc6e00bf33da88fc2",
749
+ "0xd5a79147930aa725",
750
+ "0x06ca6351e003826f",
751
+ "0x142929670a0e6e70",
752
+ "0x27b70a8546d22ffc",
753
+ "0x2e1b21385c26c926",
754
+ "0x4d2c6dfc5ac42aed",
755
+ "0x53380d139d95b3df",
756
+ "0x650a73548baf63de",
757
+ "0x766a0abb3c77b2a8",
758
+ "0x81c2c92e47edaee6",
759
+ "0x92722c851482353b",
760
+ "0xa2bfe8a14cf10364",
761
+ "0xa81a664bbc423001",
762
+ "0xc24b8b70d0f89791",
763
+ "0xc76c51a30654be30",
764
+ "0xd192e819d6ef5218",
765
+ "0xd69906245565a910",
766
+ "0xf40e35855771202a",
767
+ "0x106aa07032bbd1b8",
768
+ "0x19a4c116b8d2d0c8",
769
+ "0x1e376c085141ab53",
770
+ "0x2748774cdf8eeb99",
771
+ "0x34b0bcb5e19b48a8",
772
+ "0x391c0cb3c5c95a63",
773
+ "0x4ed8aa4ae3418acb",
774
+ "0x5b9cca4f7763e373",
775
+ "0x682e6ff3d6b2b8a3",
776
+ "0x748f82ee5defb2fc",
777
+ "0x78a5636f43172f60",
778
+ "0x84c87814a1f0ab72",
779
+ "0x8cc702081a6439ec",
780
+ "0x90befffa23631e28",
781
+ "0xa4506cebde82bde9",
782
+ "0xbef9a3f7b2c67915",
783
+ "0xc67178f2e372532b",
784
+ "0xca273eceea26619c",
785
+ "0xd186b8c721c0c207",
786
+ "0xeada7dd6cde0eb1e",
787
+ "0xf57d4f7fee6ed178",
788
+ "0x06f067aa72176fba",
789
+ "0x0a637dc5a2c898a6",
790
+ "0x113f9804bef90dae",
791
+ "0x1b710b35131c471b",
792
+ "0x28db77f523047d84",
793
+ "0x32caab7b40c72493",
794
+ "0x3c9ebe0a15c9bebc",
795
+ "0x431d67c49c100d4c",
796
+ "0x4cc5d4becb3e42b6",
797
+ "0x597f299cfc657e2a",
798
+ "0x5fcb6fab3ad6faec",
799
+ "0x6c44198c4a475817"
800
+ ].map((n) => BigInt(n))))();
801
+ var SHA512_Kh = /* @__PURE__ */ (() => K512[0])();
802
+ var SHA512_Kl = /* @__PURE__ */ (() => K512[1])();
803
+ var SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);
804
+ var SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);
805
+ var SHA512 = class extends HashMD {
806
+ constructor(outputLen = 64) {
807
+ super(128, outputLen, 16, false);
808
+ this.Ah = SHA512_IV[0] | 0;
809
+ this.Al = SHA512_IV[1] | 0;
810
+ this.Bh = SHA512_IV[2] | 0;
811
+ this.Bl = SHA512_IV[3] | 0;
812
+ this.Ch = SHA512_IV[4] | 0;
813
+ this.Cl = SHA512_IV[5] | 0;
814
+ this.Dh = SHA512_IV[6] | 0;
815
+ this.Dl = SHA512_IV[7] | 0;
816
+ this.Eh = SHA512_IV[8] | 0;
817
+ this.El = SHA512_IV[9] | 0;
818
+ this.Fh = SHA512_IV[10] | 0;
819
+ this.Fl = SHA512_IV[11] | 0;
820
+ this.Gh = SHA512_IV[12] | 0;
821
+ this.Gl = SHA512_IV[13] | 0;
822
+ this.Hh = SHA512_IV[14] | 0;
823
+ this.Hl = SHA512_IV[15] | 0;
824
+ }
825
+ // prettier-ignore
826
+ get() {
827
+ const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
828
+ return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];
829
+ }
830
+ // prettier-ignore
831
+ set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {
832
+ this.Ah = Ah | 0;
833
+ this.Al = Al | 0;
834
+ this.Bh = Bh | 0;
835
+ this.Bl = Bl | 0;
836
+ this.Ch = Ch | 0;
837
+ this.Cl = Cl | 0;
838
+ this.Dh = Dh | 0;
839
+ this.Dl = Dl | 0;
840
+ this.Eh = Eh | 0;
841
+ this.El = El | 0;
842
+ this.Fh = Fh | 0;
843
+ this.Fl = Fl | 0;
844
+ this.Gh = Gh | 0;
845
+ this.Gl = Gl | 0;
846
+ this.Hh = Hh | 0;
847
+ this.Hl = Hl | 0;
848
+ }
849
+ process(view, offset) {
850
+ for (let i = 0; i < 16; i++, offset += 4) {
851
+ SHA512_W_H[i] = view.getUint32(offset);
852
+ SHA512_W_L[i] = view.getUint32(offset += 4);
853
+ }
854
+ for (let i = 16; i < 80; i++) {
855
+ const W15h = SHA512_W_H[i - 15] | 0;
856
+ const W15l = SHA512_W_L[i - 15] | 0;
857
+ const s0h = rotrSH(W15h, W15l, 1) ^ rotrSH(W15h, W15l, 8) ^ shrSH(W15h, W15l, 7);
858
+ const s0l = rotrSL(W15h, W15l, 1) ^ rotrSL(W15h, W15l, 8) ^ shrSL(W15h, W15l, 7);
859
+ const W2h = SHA512_W_H[i - 2] | 0;
860
+ const W2l = SHA512_W_L[i - 2] | 0;
861
+ const s1h = rotrSH(W2h, W2l, 19) ^ rotrBH(W2h, W2l, 61) ^ shrSH(W2h, W2l, 6);
862
+ const s1l = rotrSL(W2h, W2l, 19) ^ rotrBL(W2h, W2l, 61) ^ shrSL(W2h, W2l, 6);
863
+ const SUMl = add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);
864
+ const SUMh = add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);
865
+ SHA512_W_H[i] = SUMh | 0;
866
+ SHA512_W_L[i] = SUMl | 0;
867
+ }
868
+ let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
869
+ for (let i = 0; i < 80; i++) {
870
+ const sigma1h = rotrSH(Eh, El, 14) ^ rotrSH(Eh, El, 18) ^ rotrBH(Eh, El, 41);
871
+ const sigma1l = rotrSL(Eh, El, 14) ^ rotrSL(Eh, El, 18) ^ rotrBL(Eh, El, 41);
872
+ const CHIh = Eh & Fh ^ ~Eh & Gh;
873
+ const CHIl = El & Fl ^ ~El & Gl;
874
+ const T1ll = add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);
875
+ const T1h = add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);
876
+ const T1l = T1ll | 0;
877
+ const sigma0h = rotrSH(Ah, Al, 28) ^ rotrBH(Ah, Al, 34) ^ rotrBH(Ah, Al, 39);
878
+ const sigma0l = rotrSL(Ah, Al, 28) ^ rotrBL(Ah, Al, 34) ^ rotrBL(Ah, Al, 39);
879
+ const MAJh = Ah & Bh ^ Ah & Ch ^ Bh & Ch;
880
+ const MAJl = Al & Bl ^ Al & Cl ^ Bl & Cl;
881
+ Hh = Gh | 0;
882
+ Hl = Gl | 0;
883
+ Gh = Fh | 0;
884
+ Gl = Fl | 0;
885
+ Fh = Eh | 0;
886
+ Fl = El | 0;
887
+ ({ h: Eh, l: El } = add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));
888
+ Dh = Ch | 0;
889
+ Dl = Cl | 0;
890
+ Ch = Bh | 0;
891
+ Cl = Bl | 0;
892
+ Bh = Ah | 0;
893
+ Bl = Al | 0;
894
+ const All = add3L(T1l, sigma0l, MAJl);
895
+ Ah = add3H(All, T1h, sigma0h, MAJh);
896
+ Al = All | 0;
897
+ }
898
+ ({ h: Ah, l: Al } = add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));
899
+ ({ h: Bh, l: Bl } = add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));
900
+ ({ h: Ch, l: Cl } = add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));
901
+ ({ h: Dh, l: Dl } = add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));
902
+ ({ h: Eh, l: El } = add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));
903
+ ({ h: Fh, l: Fl } = add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));
904
+ ({ h: Gh, l: Gl } = add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));
905
+ ({ h: Hh, l: Hl } = add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));
906
+ this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);
907
+ }
908
+ roundClean() {
909
+ clean(SHA512_W_H, SHA512_W_L);
910
+ }
911
+ destroy() {
912
+ clean(this.buffer);
913
+ this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
914
+ }
915
+ };
916
+ var sha512 = /* @__PURE__ */ createHasher(() => new SHA512());
917
+
918
+ // node_modules/@noble/hashes/esm/sha512.js
919
+ var sha5122 = sha512;
920
+
921
+ // node_modules/canonical-json/stringify.js
922
+ var gap = "";
923
+ var indent = "";
924
+ var rep;
925
+ var cmp;
926
+ var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
927
+ var meta = { "\b": "\\b", " ": "\\t", "\n": "\\n", "\f": "\\f", "\r": "\\r", '"': '\\"', "\\": "\\\\" };
928
+ function quote(str2) {
929
+ escapable.lastIndex = 0;
930
+ return escapable.test(str2) ? '"' + str2.replace(escapable, (a) => meta[a] || "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4)) + '"' : '"' + str2 + '"';
931
+ }
932
+ function str(key, holder) {
933
+ let value = holder[key];
934
+ if (value && typeof value === "object" && typeof value.toJSON === "function") {
935
+ value = value.toJSON(key);
936
+ }
937
+ if (typeof rep === "function") {
938
+ value = rep.call(holder, key, value);
939
+ }
940
+ switch (typeof value) {
941
+ case "string":
942
+ return quote(value);
943
+ case "number":
944
+ return isFinite(value) ? String(value) : "null";
945
+ case "boolean":
946
+ case "undefined":
947
+ case "object":
948
+ if (value === null)
949
+ return "null";
950
+ const mind = gap;
951
+ gap += indent;
952
+ const partial = [];
953
+ if (Array.isArray(value)) {
954
+ for (let i = 0; i < value.length; i++)
955
+ partial[i] = str(i, value) || "null";
956
+ } else {
957
+ const keys = Object.keys(value).sort(cmp);
958
+ for (const k of keys) {
959
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
960
+ const v2 = str(k, value);
961
+ if (v2)
962
+ partial.push(quote(k) + (gap ? ": " : ":") + v2);
963
+ }
964
+ }
965
+ }
966
+ let v;
967
+ if (Array.isArray(value)) {
968
+ v = partial.length === 0 ? "[]" : gap ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" : "[" + partial.join(",") + "]";
969
+ } else {
970
+ v = partial.length === 0 ? "{}" : gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" : "{" + partial.join(",") + "}";
971
+ }
972
+ gap = mind;
973
+ return v;
974
+ default:
975
+ return String(value);
976
+ }
977
+ }
978
+ function stringify(value, replacer, space, keyCompare) {
979
+ gap = "";
980
+ indent = "";
981
+ rep = replacer;
982
+ cmp = typeof keyCompare === "function" ? keyCompare : void 0;
983
+ if (typeof space === "number") {
984
+ indent = " ".repeat(space);
985
+ } else if (typeof space === "string") {
986
+ indent = space;
987
+ }
988
+ return str("", { "": value });
989
+ }
990
+
991
+ // node_modules/canonical-json/index.js
992
+ var canonical_json_default = stringify;
993
+
994
+ // src/index.js
995
+ var LicenseSeatSDK = class _LicenseSeatSDK {
996
+ constructor(config = {}) {
997
+ this.config = {
998
+ apiBaseUrl: config.apiBaseUrl || "/api",
999
+ storagePrefix: config.storagePrefix || "licenseseat_",
1000
+ autoValidateInterval: config.autoValidateInterval || 36e5,
1001
+ // 1 hour default
1002
+ networkRecheckInterval: config.networkRecheckInterval || 3e4,
1003
+ // 30s while offline
1004
+ maxRetries: config.maxRetries || 3,
1005
+ retryDelay: config.retryDelay || 1e3,
1006
+ apiKey: config.apiKey || null,
1007
+ // Store apiKey
1008
+ debug: config.debug || false,
1009
+ offlineLicenseRefreshInterval: config.offlineLicenseRefreshInterval || 1e3 * 60 * 60 * 72,
1010
+ // 72h
1011
+ offlineFallbackEnabled: config.offlineFallbackEnabled !== false,
1012
+ // default true
1013
+ maxOfflineDays: config.maxOfflineDays || 0,
1014
+ // 0 = disabled
1015
+ maxClockSkewMs: config.maxClockSkewMs || 5 * 60 * 1e3,
1016
+ // 5 minutes
1017
+ ...config
1018
+ };
1019
+ this.eventListeners = {};
1020
+ this.validationTimer = null;
1021
+ this.cache = new LicenseCache(this.config.storagePrefix);
1022
+ this.online = true;
1023
+ this.currentAutoLicenseKey = null;
1024
+ this.connectivityTimer = null;
1025
+ this.offlineRefreshTimer = null;
1026
+ this.lastOfflineValidation = null;
1027
+ if (ed25519_exports && etc && sha5122) {
1028
+ etc.sha512Sync = (...m) => sha5122(etc.concatBytes(...m));
1029
+ } else {
1030
+ console.error(
1031
+ "[LicenseSeat SDK] Noble-ed25519 or Noble-hashes not loaded correctly. Sync crypto methods may fail."
1032
+ );
1033
+ }
1034
+ this.initialize();
1035
+ }
1036
+ initialize() {
1037
+ this.log("LicenseSeat SDK initialized", this.config);
1038
+ const cachedLicense = this.cache.getLicense();
1039
+ if (cachedLicense) {
1040
+ this.emit("license:loaded", cachedLicense);
1041
+ if (this.config.offlineFallbackEnabled) {
1042
+ this.quickVerifyCachedOfflineLocal().then((offlineResult) => {
1043
+ if (offlineResult) {
1044
+ this.cache.updateValidation(offlineResult);
1045
+ if (offlineResult.valid) {
1046
+ this.emit("validation:offline-success", offlineResult);
1047
+ } else {
1048
+ this.emit("validation:offline-failed", offlineResult);
1049
+ }
1050
+ this.lastOfflineValidation = offlineResult;
1051
+ }
1052
+ }).catch(() => {
1053
+ });
1054
+ }
1055
+ if (this.config.apiKey) {
1056
+ this.startAutoValidation(cachedLicense.license_key);
1057
+ }
1058
+ if (this.config.apiKey) {
1059
+ this.validateLicense(cachedLicense.license_key).catch((err2) => {
1060
+ this.log("Background validation failed:", err2);
1061
+ if (err2 instanceof APIError && (err2.status === 401 || err2.status === 501)) {
1062
+ this.log(
1063
+ "Authentication issue during validation, using cached license data"
1064
+ );
1065
+ this.emit("validation:auth-failed", {
1066
+ licenseKey: cachedLicense.license_key,
1067
+ error: err2,
1068
+ cached: true
1069
+ });
1070
+ }
1071
+ });
1072
+ }
1073
+ }
1074
+ }
1075
+ /**
1076
+ * Activate a license
1077
+ * @param {string} licenseKey - The license key to activate
1078
+ * @param {Object} options - Activation options
1079
+ * @param {string} [options.deviceIdentifier] - Optional custom device ID.
1080
+ * @param {string} [options.softwareReleaseDate] - Optional ISO8601 date string for version-aware activation.
1081
+ * @param {Object} [options.metadata] - Optional metadata.
1082
+ * @returns {Promise<Object>} Activation result
1083
+ */
1084
+ async activate(licenseKey, options = {}) {
1085
+ const deviceId = options.deviceIdentifier || this.generateDeviceId();
1086
+ const payload = {
1087
+ license_key: licenseKey,
1088
+ device_identifier: deviceId,
1089
+ metadata: options.metadata || {}
1090
+ };
1091
+ if (options.softwareReleaseDate) {
1092
+ payload.software_release_date = options.softwareReleaseDate;
1093
+ }
1094
+ try {
1095
+ this.emit("activation:start", { licenseKey, deviceId });
1096
+ const response = await this.apiCall("/activations/activate", {
1097
+ method: "POST",
1098
+ body: payload
1099
+ });
1100
+ const licenseData = {
1101
+ license_key: licenseKey,
1102
+ device_identifier: deviceId,
1103
+ activation: response,
1104
+ activated_at: (/* @__PURE__ */ new Date()).toISOString(),
1105
+ last_validated: (/* @__PURE__ */ new Date()).toISOString()
1106
+ };
1107
+ this.cache.setLicense(licenseData);
1108
+ this.cache.updateValidation({ valid: true, optimistic: true });
1109
+ this.startAutoValidation(licenseKey);
1110
+ this.syncOfflineAssets();
1111
+ this.scheduleOfflineRefresh();
1112
+ this.emit("activation:success", licenseData);
1113
+ return licenseData;
1114
+ } catch (error) {
1115
+ this.emit("activation:error", { licenseKey, error });
1116
+ throw error;
1117
+ }
1118
+ }
1119
+ /**
1120
+ * Deactivate the current license
1121
+ * @returns {Promise<Object>} Deactivation result
1122
+ */
1123
+ async deactivate() {
1124
+ const cachedLicense = this.cache.getLicense();
1125
+ if (!cachedLicense) {
1126
+ throw new Error("No active license found");
1127
+ }
1128
+ try {
1129
+ this.emit("deactivation:start", cachedLicense);
1130
+ const response = await this.apiCall("/activations/deactivate", {
1131
+ method: "POST",
1132
+ body: {
1133
+ license_key: cachedLicense.license_key,
1134
+ device_identifier: cachedLicense.device_identifier
1135
+ }
1136
+ });
1137
+ this.cache.clearLicense();
1138
+ this.cache.clearOfflineLicense();
1139
+ this.stopAutoValidation();
1140
+ this.emit("deactivation:success", response);
1141
+ return response;
1142
+ } catch (error) {
1143
+ this.emit("deactivation:error", { error, license: cachedLicense });
1144
+ throw error;
1145
+ }
1146
+ }
1147
+ /**
1148
+ * Validate a license
1149
+ * @param {string} licenseKey - License key to validate
1150
+ * @param {Object} options - Validation options
1151
+ * @returns {Promise<Object>} Validation result
1152
+ */
1153
+ async validateLicense(licenseKey, options = {}) {
1154
+ try {
1155
+ this.emit("validation:start", { licenseKey });
1156
+ const response = await this.apiCall("/licenses/validate", {
1157
+ method: "POST",
1158
+ body: {
1159
+ license_key: licenseKey,
1160
+ device_identifier: options.deviceIdentifier || this.cache.getDeviceId(),
1161
+ product_slug: options.productSlug
1162
+ }
1163
+ });
1164
+ const cachedLicense = this.cache.getLicense();
1165
+ if (cachedLicense && cachedLicense.license_key === licenseKey) {
1166
+ this.cache.updateValidation(response);
1167
+ }
1168
+ if (response.valid) {
1169
+ this.emit("validation:success", response);
1170
+ this.cache.setLastSeenTimestamp(Date.now());
1171
+ } else {
1172
+ this.emit("validation:failed", response);
1173
+ this.stopAutoValidation();
1174
+ this.currentAutoLicenseKey = null;
1175
+ }
1176
+ const isNetworkFailure = response instanceof TypeError && response.message.includes("fetch") || response instanceof APIError && [0, 408].includes(response.status);
1177
+ if (this.config.offlineFallbackEnabled && isNetworkFailure) {
1178
+ const offlineResult = await this.verifyCachedOffline();
1179
+ const duplicateSuccess = offlineResult.valid && this.lastOfflineValidation?.valid === true;
1180
+ const cachedLicense2 = this.cache.getLicense();
1181
+ if (cachedLicense2 && cachedLicense2.license_key === licenseKey) {
1182
+ this.cache.updateValidation(offlineResult);
1183
+ }
1184
+ if (offlineResult.valid) {
1185
+ if (!duplicateSuccess) {
1186
+ this.emit("validation:offline-success", offlineResult);
1187
+ }
1188
+ this.lastOfflineValidation = offlineResult;
1189
+ return offlineResult;
1190
+ } else {
1191
+ this.emit("validation:offline-failed", offlineResult);
1192
+ this.stopAutoValidation();
1193
+ this.currentAutoLicenseKey = null;
1194
+ }
1195
+ }
1196
+ if (response instanceof APIError && response.data) {
1197
+ const cachedLicense2 = this.cache.getLicense();
1198
+ if (cachedLicense2 && cachedLicense2.license_key === licenseKey) {
1199
+ const invalidValidation = {
1200
+ valid: false,
1201
+ ...response.data
1202
+ };
1203
+ this.cache.updateValidation(invalidValidation);
1204
+ }
1205
+ }
1206
+ this.cache.setLastSeenTimestamp(Date.now());
1207
+ return response;
1208
+ } catch (error) {
1209
+ this.emit("validation:error", { licenseKey, error });
1210
+ const isNetworkFailure = error instanceof TypeError && error.message.includes("fetch") || error instanceof APIError && [0, 408].includes(error.status);
1211
+ if (this.config.offlineFallbackEnabled && isNetworkFailure) {
1212
+ const offlineResult = await this.verifyCachedOffline();
1213
+ const cachedLicense = this.cache.getLicense();
1214
+ if (cachedLicense && cachedLicense.license_key === licenseKey) {
1215
+ this.cache.updateValidation(offlineResult);
1216
+ }
1217
+ if (offlineResult.valid) {
1218
+ this.emit("validation:offline-success", offlineResult);
1219
+ return offlineResult;
1220
+ } else {
1221
+ this.emit("validation:offline-failed", offlineResult);
1222
+ this.stopAutoValidation();
1223
+ this.currentAutoLicenseKey = null;
1224
+ }
1225
+ }
1226
+ if (error instanceof APIError && error.data) {
1227
+ const cachedLicense = this.cache.getLicense();
1228
+ if (cachedLicense && cachedLicense.license_key === licenseKey) {
1229
+ const invalidValidation = {
1230
+ valid: false,
1231
+ ...error.data
1232
+ };
1233
+ this.cache.updateValidation(invalidValidation);
1234
+ }
1235
+ if (![0, 408, 429].includes(error.status)) {
1236
+ this.stopAutoValidation();
1237
+ this.currentAutoLicenseKey = null;
1238
+ }
1239
+ }
1240
+ throw error;
1241
+ }
1242
+ }
1243
+ /**
1244
+ * Check if a specific entitlement is active
1245
+ * @param {string} entitlementKey - The entitlement to check
1246
+ * @returns {Object} Entitlement status
1247
+ */
1248
+ checkEntitlement(entitlementKey) {
1249
+ const license = this.cache.getLicense();
1250
+ if (!license || !license.validation) {
1251
+ return { active: false, reason: "no_license" };
1252
+ }
1253
+ const entitlements = license.validation.active_entitlements || [];
1254
+ const entitlement = entitlements.find((e) => e.key === entitlementKey);
1255
+ if (!entitlement) {
1256
+ return { active: false, reason: "not_found" };
1257
+ }
1258
+ if (entitlement.expires_at) {
1259
+ const expiresAt = new Date(entitlement.expires_at);
1260
+ const now = /* @__PURE__ */ new Date();
1261
+ if (expiresAt < now) {
1262
+ return {
1263
+ active: false,
1264
+ reason: "expired",
1265
+ expires_at: entitlement.expires_at
1266
+ };
1267
+ }
1268
+ }
1269
+ return { active: true, entitlement };
1270
+ }
1271
+ /**
1272
+ * Get offline license data for backup.
1273
+ * This fetches the *signed* offline license data from the server.
1274
+ * @returns {Promise<Object>} Signed offline license data (JSON structure with payload and signature).
1275
+ */
1276
+ async getOfflineLicense() {
1277
+ const license = this.cache.getLicense();
1278
+ if (!license || !license.license_key) {
1279
+ const errorMsg = "No active license key found in cache to fetch offline license.";
1280
+ this.emit("sdk:error", { message: errorMsg });
1281
+ throw new Error(errorMsg);
1282
+ }
1283
+ try {
1284
+ this.emit("offlineLicense:fetching", { licenseKey: license.license_key });
1285
+ const path = `/licenses/${license.license_key}/offline_license`;
1286
+ const response = await this.apiCall(path, {
1287
+ method: "POST"
1288
+ });
1289
+ this.emit("offlineLicense:fetched", {
1290
+ licenseKey: license.license_key,
1291
+ data: response
1292
+ });
1293
+ return response;
1294
+ } catch (error) {
1295
+ this.log(
1296
+ `Failed to get offline license for ${license.license_key}:`,
1297
+ error
1298
+ );
1299
+ this.emit("offlineLicense:fetchError", {
1300
+ licenseKey: license.license_key,
1301
+ error
1302
+ });
1303
+ throw error;
1304
+ }
1305
+ }
1306
+ /**
1307
+ * Fetches a public key for a given key ID (kid) from the server.
1308
+ * Assumes an endpoint like /api/public_key/:keyId which returns { key_id: "...", public_key_b64: "..." }
1309
+ * @param {string} keyId - The Key ID (kid) for which to fetch the public key.
1310
+ * @returns {Promise<string>} Base64 encoded public key.
1311
+ */
1312
+ async getPublicKey(keyId) {
1313
+ if (!keyId) {
1314
+ throw new Error("Key ID is required to fetch a public key.");
1315
+ }
1316
+ try {
1317
+ this.log(`Fetching public key for kid: ${keyId}`);
1318
+ const response = await this.apiCall(`/public_keys/${keyId}`, {
1319
+ method: "GET"
1320
+ });
1321
+ if (response && response.public_key_b64) {
1322
+ this.log(`Successfully fetched public key for kid: ${keyId}`);
1323
+ return response.public_key_b64;
1324
+ } else {
1325
+ throw new Error(
1326
+ `Public key not found or invalid response for kid: ${keyId}`
1327
+ );
1328
+ }
1329
+ } catch (error) {
1330
+ this.log(`Failed to fetch public key for kid ${keyId}:`, error);
1331
+ throw error;
1332
+ }
1333
+ }
1334
+ /**
1335
+ * Verifies a signed offline license object client-side.
1336
+ * IMPORTANT: This method requires a JavaScript Ed25519 library (e.g., tweetnacl, noble-ed25519).
1337
+ * The actual crypto verification logic needs to be implemented using such a library.
1338
+ *
1339
+ * @param {Object} signedLicenseData - The signed license data object, typically { payload: Object, signature_b64u: string, kid: string }.
1340
+ * @param {string} publicKeyB64 - The Base64 encoded public Ed25519 key to verify the signature.
1341
+ * @returns {Promise<boolean>} True if verification is successful, false otherwise.
1342
+ * @throws {Error} if crypto library is not available or inputs are invalid.
1343
+ */
1344
+ async verifyOfflineLicense(signedLicenseData, publicKeyB64) {
1345
+ this.log("Attempting to verify offline license client-side.");
1346
+ if (!signedLicenseData || !signedLicenseData.payload || !signedLicenseData.signature_b64u) {
1347
+ throw new Error("Invalid signedLicenseData object provided.");
1348
+ }
1349
+ if (!publicKeyB64) {
1350
+ throw new Error("Public key (Base64 encoded) is required.");
1351
+ }
1352
+ if (!ed25519_exports || !verify || !etc.sha512Sync) {
1353
+ console.error(
1354
+ "Noble-ed25519 not properly initialized or sha512Sync not set. Please check imports and setup."
1355
+ );
1356
+ this.emit("sdk:error", {
1357
+ message: "Client-side verification crypto library (noble-ed25519) not available or configured."
1358
+ });
1359
+ throw new Error(
1360
+ "noble-ed25519 crypto library not available/configured for offline verification."
1361
+ );
1362
+ }
1363
+ try {
1364
+ const payloadString = this.canonicalJsonStringify(
1365
+ signedLicenseData.payload
1366
+ );
1367
+ const messageBytes = new TextEncoder().encode(payloadString);
1368
+ const publicKeyBytes = this.base64UrlDecode(publicKeyB64);
1369
+ const signatureBytes = this.base64UrlDecode(
1370
+ signedLicenseData.signature_b64u
1371
+ );
1372
+ const isValid = verify(
1373
+ signatureBytes,
1374
+ // signature first for noble-ed25519
1375
+ messageBytes,
1376
+ publicKeyBytes
1377
+ );
1378
+ if (isValid) {
1379
+ this.log(
1380
+ "Offline license signature VERIFIED successfully client-side."
1381
+ );
1382
+ this.emit("offlineLicense:verified", {
1383
+ payload: signedLicenseData.payload
1384
+ });
1385
+ } else {
1386
+ this.log("Offline license signature INVALID client-side.");
1387
+ this.emit("offlineLicense:verificationFailed", {
1388
+ payload: signedLicenseData.payload
1389
+ });
1390
+ }
1391
+ return isValid;
1392
+ } catch (error) {
1393
+ this.log("Client-side offline license verification error:", error);
1394
+ this.emit("sdk:error", {
1395
+ message: "Client-side verification failed.",
1396
+ error
1397
+ });
1398
+ throw error;
1399
+ }
1400
+ }
1401
+ /**
1402
+ * Generates a canonical JSON string from an object (keys sorted).
1403
+ * This is crucial for consistent signature verification.
1404
+ * @param {Object} obj - The object to stringify.
1405
+ * @returns {string} Canonical JSON string.
1406
+ */
1407
+ canonicalJsonStringify(obj) {
1408
+ if (!canonical_json_default || typeof canonical_json_default.stringify !== "function") {
1409
+ console.warn(
1410
+ "[LicenseSeat SDK] canonical-json library not loaded correctly. Falling back to basic JSON.stringify. Signature verification might be unreliable if server uses different canonicalization."
1411
+ );
1412
+ try {
1413
+ const sortedObj = {};
1414
+ Object.keys(obj).sort().forEach((key) => {
1415
+ sortedObj[key] = obj[key];
1416
+ });
1417
+ return JSON.stringify(sortedObj);
1418
+ } catch (e) {
1419
+ return JSON.stringify(obj);
1420
+ }
1421
+ }
1422
+ return canonical_json_default.stringify(obj);
1423
+ }
1424
+ /**
1425
+ * Decodes a Base64URL string to a Uint8Array.
1426
+ * @param {string} base64UrlString - The Base64URL encoded string.
1427
+ * @returns {Uint8Array}
1428
+ */
1429
+ base64UrlDecode(base64UrlString) {
1430
+ let base64 = base64UrlString.replace(/-/g, "+").replace(/_/g, "/");
1431
+ while (base64.length % 4) {
1432
+ base64 += "=";
1433
+ }
1434
+ const raw = window.atob(base64);
1435
+ const outputArray = new Uint8Array(raw.length);
1436
+ for (let i = 0; i < raw.length; ++i) {
1437
+ outputArray[i] = raw.charCodeAt(i);
1438
+ }
1439
+ return outputArray;
1440
+ }
1441
+ /**
1442
+ * Start automatic license validation
1443
+ * @private
1444
+ */
1445
+ startAutoValidation(licenseKey) {
1446
+ this.stopAutoValidation();
1447
+ this.currentAutoLicenseKey = licenseKey;
1448
+ const validationInterval = this.config.autoValidateInterval;
1449
+ const performAndReschedule = () => {
1450
+ this.validateLicense(licenseKey).catch((err2) => {
1451
+ this.log("Auto-validation failed:", err2);
1452
+ this.emit("validation:auto-failed", { licenseKey, error: err2 });
1453
+ });
1454
+ this.emit("autovalidation:cycle", {
1455
+ nextRunAt: new Date(Date.now() + validationInterval)
1456
+ });
1457
+ };
1458
+ this.validationTimer = setInterval(
1459
+ performAndReschedule,
1460
+ validationInterval
1461
+ );
1462
+ this.emit("autovalidation:cycle", {
1463
+ nextRunAt: new Date(Date.now() + validationInterval)
1464
+ });
1465
+ }
1466
+ /**
1467
+ * Stop automatic validation
1468
+ * @private
1469
+ */
1470
+ stopAutoValidation() {
1471
+ if (this.validationTimer) {
1472
+ clearInterval(this.validationTimer);
1473
+ this.validationTimer = null;
1474
+ this.emit("autovalidation:stopped");
1475
+ }
1476
+ }
1477
+ /**
1478
+ * Generate a unique device identifier
1479
+ * @private
1480
+ */
1481
+ generateDeviceId() {
1482
+ const nav = window.navigator;
1483
+ const screen = window.screen;
1484
+ const data = [
1485
+ nav.userAgent,
1486
+ nav.language,
1487
+ screen.colorDepth,
1488
+ screen.width + "x" + screen.height,
1489
+ (/* @__PURE__ */ new Date()).getTimezoneOffset(),
1490
+ nav.hardwareConcurrency,
1491
+ this.getCanvasFingerprint()
1492
+ ].join("|");
1493
+ return `web-${this.hashCode(data)}-${Date.now().toString(36)}`;
1494
+ }
1495
+ /**
1496
+ * Get canvas fingerprint for device ID
1497
+ * @private
1498
+ */
1499
+ getCanvasFingerprint() {
1500
+ try {
1501
+ const canvas = document.createElement("canvas");
1502
+ const ctx = canvas.getContext("2d");
1503
+ ctx.textBaseline = "top";
1504
+ ctx.font = "14px Arial";
1505
+ ctx.fillText("LicenseSeat SDK", 2, 2);
1506
+ return canvas.toDataURL().slice(-50);
1507
+ } catch (e) {
1508
+ return "no-canvas";
1509
+ }
1510
+ }
1511
+ /**
1512
+ * Simple hash function
1513
+ * @private
1514
+ */
1515
+ hashCode(str2) {
1516
+ let hash = 0;
1517
+ for (let i = 0; i < str2.length; i++) {
1518
+ const char = str2.charCodeAt(i);
1519
+ hash = (hash << 5) - hash + char;
1520
+ hash = hash & hash;
1521
+ }
1522
+ return Math.abs(hash).toString(36);
1523
+ }
1524
+ /**
1525
+ * Make API call with retry logic
1526
+ * @private
1527
+ */
1528
+ async apiCall(endpoint, options = {}) {
1529
+ const url = `${this.config.apiBaseUrl}${endpoint}`;
1530
+ let lastError;
1531
+ const headers = {
1532
+ "Content-Type": "application/json",
1533
+ Accept: "application/json",
1534
+ ...options.headers
1535
+ };
1536
+ if (this.config.apiKey) {
1537
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
1538
+ } else {
1539
+ this.log(
1540
+ "[Warning] No API key configured for LicenseSeat SDK. Authenticated endpoints will fail."
1541
+ );
1542
+ }
1543
+ for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
1544
+ try {
1545
+ const response = await fetch(url, {
1546
+ method: options.method || "GET",
1547
+ headers,
1548
+ // Use prepared headers
1549
+ body: options.body ? JSON.stringify(options.body) : void 0,
1550
+ credentials: "omit"
1551
+ // Do NOT send cookies (session-agnostic)
1552
+ });
1553
+ const data = await response.json();
1554
+ if (!response.ok) {
1555
+ throw new APIError(
1556
+ data.error || "Request failed",
1557
+ response.status,
1558
+ data
1559
+ );
1560
+ }
1561
+ if (!this.online) {
1562
+ this.online = true;
1563
+ this.emit("network:online");
1564
+ }
1565
+ this.stopConnectivityPolling();
1566
+ if (!this.validationTimer && this.currentAutoLicenseKey) {
1567
+ this.startAutoValidation(this.currentAutoLicenseKey);
1568
+ }
1569
+ return data;
1570
+ } catch (error) {
1571
+ const networkFailure = error instanceof TypeError && error.message.includes("fetch") || error instanceof APIError && error.status === 0;
1572
+ if (networkFailure && this.online) {
1573
+ this.online = false;
1574
+ this.emit("network:offline", { error });
1575
+ this.stopAutoValidation();
1576
+ this.startConnectivityPolling();
1577
+ }
1578
+ lastError = error;
1579
+ const shouldRetry = attempt < this.config.maxRetries && this.shouldRetryError(error);
1580
+ if (shouldRetry) {
1581
+ const delay = this.config.retryDelay * Math.pow(2, attempt);
1582
+ this.log(
1583
+ `Retry attempt ${attempt + 1} after ${delay}ms for error:`,
1584
+ error.message
1585
+ );
1586
+ await this.sleep(delay);
1587
+ } else {
1588
+ throw error;
1589
+ }
1590
+ }
1591
+ }
1592
+ throw lastError;
1593
+ }
1594
+ /**
1595
+ * Determine if an error should be retried
1596
+ * @private
1597
+ */
1598
+ shouldRetryError(error) {
1599
+ if (error instanceof TypeError && error.message.includes("fetch")) {
1600
+ return true;
1601
+ }
1602
+ if (error instanceof APIError) {
1603
+ const status = error.status;
1604
+ if (status >= 502 && status < 600) {
1605
+ return true;
1606
+ }
1607
+ if (status === 0 || status === 408 || status === 429) {
1608
+ return true;
1609
+ }
1610
+ return false;
1611
+ }
1612
+ return false;
1613
+ }
1614
+ /**
1615
+ * Event handling
1616
+ */
1617
+ on(event, callback) {
1618
+ if (!this.eventListeners[event]) {
1619
+ this.eventListeners[event] = [];
1620
+ }
1621
+ this.eventListeners[event].push(callback);
1622
+ return () => this.off(event, callback);
1623
+ }
1624
+ off(event, callback) {
1625
+ if (this.eventListeners[event]) {
1626
+ this.eventListeners[event] = this.eventListeners[event].filter(
1627
+ (cb) => cb !== callback
1628
+ );
1629
+ }
1630
+ }
1631
+ emit(event, data) {
1632
+ this.log(`Event: ${event}`, data);
1633
+ if (this.eventListeners[event]) {
1634
+ this.eventListeners[event].forEach((callback) => {
1635
+ try {
1636
+ callback(data);
1637
+ } catch (error) {
1638
+ console.error(`Error in event listener for ${event}:`, error);
1639
+ }
1640
+ });
1641
+ }
1642
+ }
1643
+ /**
1644
+ * Utilities
1645
+ */
1646
+ getCsrfToken() {
1647
+ const token = document.querySelector('meta[name="csrf-token"]');
1648
+ return token ? token.content : "";
1649
+ }
1650
+ sleep(ms) {
1651
+ return new Promise((resolve) => setTimeout(resolve, ms));
1652
+ }
1653
+ log(...args) {
1654
+ if (this.config.debug) {
1655
+ console.log("[LicenseSeat SDK]", ...args);
1656
+ }
1657
+ }
1658
+ /**
1659
+ * Test server authentication by calling a simple endpoint that requires auth.
1660
+ * Useful for verifying API key/session is valid.
1661
+ * @returns {Promise<Object>} Result from the server
1662
+ */
1663
+ async testAuth() {
1664
+ if (!this.config.apiKey) {
1665
+ const err2 = new Error("API key is required for auth test");
1666
+ this.emit("auth_test:error", { error: err2 });
1667
+ throw err2;
1668
+ }
1669
+ try {
1670
+ this.emit("auth_test:start");
1671
+ const response = await this.apiCall("/auth_test", { method: "GET" });
1672
+ this.emit("auth_test:success", response);
1673
+ return response;
1674
+ } catch (error) {
1675
+ this.emit("auth_test:error", { error });
1676
+ throw error;
1677
+ }
1678
+ }
1679
+ /**
1680
+ * Get current license status
1681
+ */
1682
+ getStatus() {
1683
+ const license = this.cache.getLicense();
1684
+ if (!license) {
1685
+ return { status: "inactive", message: "No license activated" };
1686
+ }
1687
+ const validation = license.validation;
1688
+ if (!validation) {
1689
+ return { status: "pending", message: "License pending validation" };
1690
+ }
1691
+ if (!validation.valid) {
1692
+ if (validation.offline) {
1693
+ return {
1694
+ status: "offline-invalid",
1695
+ message: validation.reason_code || "License invalid (offline)"
1696
+ };
1697
+ }
1698
+ return {
1699
+ status: "invalid",
1700
+ message: validation.reason || "License invalid"
1701
+ };
1702
+ }
1703
+ if (validation.offline) {
1704
+ return {
1705
+ status: "offline-valid",
1706
+ license: license.license_key,
1707
+ device: license.device_identifier,
1708
+ activated_at: license.activated_at,
1709
+ last_validated: license.last_validated,
1710
+ entitlements: validation.active_entitlements || []
1711
+ };
1712
+ }
1713
+ return {
1714
+ status: "active",
1715
+ license: license.license_key,
1716
+ device: license.device_identifier,
1717
+ activated_at: license.activated_at,
1718
+ last_validated: license.last_validated,
1719
+ entitlements: validation.active_entitlements || []
1720
+ };
1721
+ }
1722
+ /**
1723
+ * Clear all data and reset
1724
+ */
1725
+ reset() {
1726
+ this.stopAutoValidation();
1727
+ this.cache.clear();
1728
+ this.lastOfflineValidation = null;
1729
+ this.emit("sdk:reset");
1730
+ }
1731
+ startConnectivityPolling() {
1732
+ if (this.connectivityTimer)
1733
+ return;
1734
+ const heartbeat = async () => {
1735
+ try {
1736
+ await fetch(`${this.config.apiBaseUrl}/heartbeat`, {
1737
+ method: "GET",
1738
+ credentials: "omit"
1739
+ });
1740
+ if (!this.online) {
1741
+ this.online = true;
1742
+ this.emit("network:online");
1743
+ if (this.currentAutoLicenseKey && !this.validationTimer) {
1744
+ this.startAutoValidation(this.currentAutoLicenseKey);
1745
+ }
1746
+ this.syncOfflineAssets();
1747
+ }
1748
+ this.stopConnectivityPolling();
1749
+ } catch (err2) {
1750
+ }
1751
+ };
1752
+ this.connectivityTimer = setInterval(
1753
+ heartbeat,
1754
+ this.config.networkRecheckInterval
1755
+ );
1756
+ }
1757
+ stopConnectivityPolling() {
1758
+ if (this.connectivityTimer) {
1759
+ clearInterval(this.connectivityTimer);
1760
+ this.connectivityTimer = null;
1761
+ }
1762
+ }
1763
+ /**
1764
+ * Fetch & cache offline license + public key so we can verify while offline.
1765
+ * Runs in background; errors are logged but not thrown.
1766
+ * @private
1767
+ */
1768
+ async syncOfflineAssets() {
1769
+ try {
1770
+ const offline = await this.getOfflineLicense();
1771
+ this.cache.setOfflineLicense(offline);
1772
+ const kid = offline.kid || offline.payload?.kid;
1773
+ if (kid) {
1774
+ const existingKey = this.cache.getPublicKey(kid);
1775
+ if (!existingKey) {
1776
+ const pub = await this.getPublicKey(kid);
1777
+ this.cache.setPublicKey(kid, pub);
1778
+ }
1779
+ }
1780
+ this.emit("offlineLicense:ready", {
1781
+ kid: offline.kid || offline.payload?.kid,
1782
+ exp_at: offline.payload?.exp_at
1783
+ });
1784
+ } catch (err2) {
1785
+ this.log("Failed to sync offline assets:", err2);
1786
+ }
1787
+ }
1788
+ /**
1789
+ * Verify cached offline license & return synthetic validation object.
1790
+ * @private
1791
+ */
1792
+ async verifyCachedOffline() {
1793
+ const signed = this.cache.getOfflineLicense();
1794
+ if (!signed) {
1795
+ return { valid: false, offline: true, reason_code: "no_offline_license" };
1796
+ }
1797
+ const kid = signed.kid || signed.payload?.kid;
1798
+ let pub = kid ? this.cache.getPublicKey(kid) : null;
1799
+ if (!pub) {
1800
+ try {
1801
+ pub = await this.getPublicKey(kid);
1802
+ this.cache.setPublicKey(kid, pub);
1803
+ } catch (e) {
1804
+ return { valid: false, offline: true, reason_code: "no_public_key" };
1805
+ }
1806
+ }
1807
+ try {
1808
+ const ok = await this.verifyOfflineLicense(signed, pub);
1809
+ if (!ok) {
1810
+ return {
1811
+ valid: false,
1812
+ offline: true,
1813
+ reason_code: "signature_invalid"
1814
+ };
1815
+ }
1816
+ const payload = signed.payload || {};
1817
+ const cached = this.cache.getLicense();
1818
+ if (!cached || !_LicenseSeatSDK.constantTimeEqual(
1819
+ payload.lic_k || "",
1820
+ cached.license_key || ""
1821
+ )) {
1822
+ return { valid: false, offline: true, reason_code: "license_mismatch" };
1823
+ }
1824
+ const now = Date.now();
1825
+ const expAt = payload.exp_at ? Date.parse(payload.exp_at) : null;
1826
+ if (expAt && expAt < now) {
1827
+ return { valid: false, offline: true, reason_code: "expired" };
1828
+ }
1829
+ if (!expAt && this.config.maxOfflineDays > 0) {
1830
+ const pivot = cached.last_validated || cached.activated_at;
1831
+ if (pivot) {
1832
+ const ageMs = now - new Date(pivot).getTime();
1833
+ if (ageMs > this.config.maxOfflineDays * 24 * 60 * 60 * 1e3) {
1834
+ return {
1835
+ valid: false,
1836
+ offline: true,
1837
+ reason_code: "grace_period_expired"
1838
+ };
1839
+ }
1840
+ }
1841
+ }
1842
+ const lastSeen = this.cache.getLastSeenTimestamp();
1843
+ if (lastSeen && now + this.config.maxClockSkewMs < lastSeen) {
1844
+ return { valid: false, offline: true, reason_code: "clock_tamper" };
1845
+ }
1846
+ this.cache.setLastSeenTimestamp(now);
1847
+ return { valid: true, offline: true };
1848
+ } catch (e) {
1849
+ return { valid: false, offline: true, reason_code: "verification_error" };
1850
+ }
1851
+ }
1852
+ scheduleOfflineRefresh() {
1853
+ if (this.offlineRefreshTimer)
1854
+ clearInterval(this.offlineRefreshTimer);
1855
+ this.offlineRefreshTimer = setInterval(
1856
+ () => this.syncOfflineAssets(),
1857
+ this.config.offlineLicenseRefreshInterval
1858
+ );
1859
+ }
1860
+ // --- Utility: constant-time string comparison to mitigate timing attacks ---
1861
+ static constantTimeEqual(a = "", b = "") {
1862
+ if (a.length !== b.length)
1863
+ return false;
1864
+ let res = 0;
1865
+ for (let i = 0; i < a.length; i++) {
1866
+ res |= a.charCodeAt(i) ^ b.charCodeAt(i);
1867
+ }
1868
+ return res === 0;
1869
+ }
1870
+ /**
1871
+ * Attempt to verify cached offline license using only local data (no network).
1872
+ * Returns validation-like object or null if not possible.
1873
+ * @private
1874
+ */
1875
+ async quickVerifyCachedOfflineLocal() {
1876
+ const signed = this.cache.getOfflineLicense();
1877
+ if (!signed)
1878
+ return null;
1879
+ const kid = signed.kid || signed.payload?.kid;
1880
+ const pub = kid ? this.cache.getPublicKey(kid) : null;
1881
+ if (!pub)
1882
+ return null;
1883
+ try {
1884
+ const ok = await this.verifyOfflineLicense(signed, pub);
1885
+ return ok ? { valid: true, offline: true } : { valid: false, offline: true, reason_code: "signature_invalid" };
1886
+ } catch (_) {
1887
+ return { valid: false, offline: true, reason_code: "verification_error" };
1888
+ }
1889
+ }
1890
+ };
1891
+ var LicenseCache = class {
1892
+ constructor(prefix = "licenseseat_") {
1893
+ this.prefix = prefix;
1894
+ this.publicKeyCacheKey = this.prefix + "public_keys";
1895
+ }
1896
+ getLicense() {
1897
+ try {
1898
+ const data = localStorage.getItem(this.prefix + "license");
1899
+ return data ? JSON.parse(data) : null;
1900
+ } catch (e) {
1901
+ console.error("Failed to read license cache:", e);
1902
+ return null;
1903
+ }
1904
+ }
1905
+ setLicense(data) {
1906
+ try {
1907
+ localStorage.setItem(this.prefix + "license", JSON.stringify(data));
1908
+ } catch (e) {
1909
+ console.error("Failed to cache license:", e);
1910
+ }
1911
+ }
1912
+ updateValidation(validationData) {
1913
+ const license = this.getLicense();
1914
+ if (license) {
1915
+ license.validation = validationData;
1916
+ license.last_validated = (/* @__PURE__ */ new Date()).toISOString();
1917
+ this.setLicense(license);
1918
+ }
1919
+ }
1920
+ getDeviceId() {
1921
+ const license = this.getLicense();
1922
+ return license ? license.device_identifier : null;
1923
+ }
1924
+ clearLicense() {
1925
+ localStorage.removeItem(this.prefix + "license");
1926
+ }
1927
+ // --- Offline license helpers ---
1928
+ getOfflineLicense() {
1929
+ try {
1930
+ const data = localStorage.getItem(this.prefix + "offline_license");
1931
+ return data ? JSON.parse(data) : null;
1932
+ } catch (e) {
1933
+ console.error("Failed to read offline license cache:", e);
1934
+ return null;
1935
+ }
1936
+ }
1937
+ setOfflineLicense(data) {
1938
+ try {
1939
+ localStorage.setItem(
1940
+ this.prefix + "offline_license",
1941
+ JSON.stringify(data)
1942
+ );
1943
+ } catch (e) {
1944
+ console.error("Failed to cache offline license:", e);
1945
+ }
1946
+ }
1947
+ clearOfflineLicense() {
1948
+ localStorage.removeItem(this.prefix + "offline_license");
1949
+ }
1950
+ // Methods for caching public keys
1951
+ getPublicKey(keyId) {
1952
+ try {
1953
+ const cache = JSON.parse(
1954
+ localStorage.getItem(this.publicKeyCacheKey) || "{}"
1955
+ );
1956
+ return cache[keyId] || null;
1957
+ } catch (e) {
1958
+ console.error("Failed to read public key cache:", e);
1959
+ return null;
1960
+ }
1961
+ }
1962
+ setPublicKey(keyId, publicKeyB64) {
1963
+ try {
1964
+ const cache = JSON.parse(
1965
+ localStorage.getItem(this.publicKeyCacheKey) || "{}"
1966
+ );
1967
+ cache[keyId] = publicKeyB64;
1968
+ localStorage.setItem(this.publicKeyCacheKey, JSON.stringify(cache));
1969
+ } catch (e) {
1970
+ console.error("Failed to cache public key:", e);
1971
+ }
1972
+ }
1973
+ // Clears *all* LicenseSeat SDK data for this prefix.
1974
+ clear() {
1975
+ Object.keys(localStorage).forEach((key) => {
1976
+ if (key.startsWith(this.prefix)) {
1977
+ localStorage.removeItem(key);
1978
+ }
1979
+ });
1980
+ this.clearOfflineLicense();
1981
+ localStorage.removeItem(this.prefix + "last_seen_ts");
1982
+ }
1983
+ // --- Time baseline helpers ---
1984
+ getLastSeenTimestamp() {
1985
+ const v = localStorage.getItem(this.prefix + "last_seen_ts");
1986
+ return v ? parseInt(v, 10) : null;
1987
+ }
1988
+ setLastSeenTimestamp(ts) {
1989
+ try {
1990
+ localStorage.setItem(this.prefix + "last_seen_ts", String(ts));
1991
+ } catch (e) {
1992
+ }
1993
+ }
1994
+ };
1995
+ var APIError = class extends Error {
1996
+ constructor(message, status, data) {
1997
+ super(message);
1998
+ this.name = "APIError";
1999
+ this.status = status;
2000
+ this.data = data;
2001
+ }
2002
+ };
2003
+ var src_default = LicenseSeatSDK;
2004
+ export {
2005
+ src_default as default
2006
+ };
2007
+ /*! Bundled license information:
2008
+
2009
+ @noble/ed25519/index.js:
2010
+ (*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
2011
+
2012
+ @noble/hashes/esm/utils.js:
2013
+ (*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
2014
+ */