zklicensing 0.1.0-beta.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 (41) hide show
  1. package/LICENSE +104 -0
  2. package/README.md +603 -0
  3. package/build/archiveBootstrap.d.ts +60 -0
  4. package/build/archiveBootstrap.js +234 -0
  5. package/build/buyClient.d.ts +58 -0
  6. package/build/buyClient.js +162 -0
  7. package/build/contractInterface.d.ts +55 -0
  8. package/build/contractInterface.js +213 -0
  9. package/build/countryStats.d.ts +37 -0
  10. package/build/countryStats.js +89 -0
  11. package/build/deployClient.d.ts +168 -0
  12. package/build/deployClient.js +172 -0
  13. package/build/freezeClient.d.ts +44 -0
  14. package/build/freezeClient.js +59 -0
  15. package/build/generationClient.d.ts +54 -0
  16. package/build/generationClient.js +113 -0
  17. package/build/index.d.ts +72 -0
  18. package/build/index.js +258 -0
  19. package/build/licenseProof.d.ts +26 -0
  20. package/build/licenseProof.js +41 -0
  21. package/build/licenseRecord.d.ts +39 -0
  22. package/build/licenseRecord.js +6 -0
  23. package/build/licenseStore.d.ts +49 -0
  24. package/build/licenseStore.js +303 -0
  25. package/build/manifestVerify.d.ts +30 -0
  26. package/build/manifestVerify.js +95 -0
  27. package/build/migrateClient.d.ts +43 -0
  28. package/build/migrateClient.js +47 -0
  29. package/build/ownership.d.ts +34 -0
  30. package/build/ownership.js +147 -0
  31. package/build/refundClient.d.ts +52 -0
  32. package/build/refundClient.js +92 -0
  33. package/build/renewClient.d.ts +49 -0
  34. package/build/renewClient.js +135 -0
  35. package/build/statsClient.d.ts +96 -0
  36. package/build/statsClient.js +28 -0
  37. package/build/verifyCore.d.ts +26 -0
  38. package/build/verifyCore.js +57 -0
  39. package/build/verifyService.d.ts +3 -0
  40. package/build/verifyService.js +690 -0
  41. package/package.json +118 -0
@@ -0,0 +1,234 @@
1
+ // Copyright (c) 2025-2026 zkLicensing project developers
2
+ // All rights reserved.
3
+ /**
4
+ * archiveBootstrap.ts
5
+ *
6
+ * Two layers:
7
+ * - bootstrapFromArchive() fetches zkApp events and returns them normalized.
8
+ * No writes. Caller decides what to do with the events.
9
+ * - applyEventsToStore() writes the events to licenseStore.
10
+ *
11
+ * Events handled (write side):
12
+ * licenseIssued → applyLicenseIssued
13
+ * licenseIssuedNoEscrow → applyLicenseIssued (escrowless: true)
14
+ * licenseRenewed → updateExpiry
15
+ * licenseMigrated → applyLicenseIssued (escrowless: true, migrated: true)
16
+ * refundIssued → recordRefund
17
+ * fundsReleased → recordRelease
18
+ * priceUpdated → ignored (price-history tracking lives in the private
19
+ * zklicensing-app keeper alongside vendor-stats)
20
+ *
21
+ * Uses LicensingAppEventsContract (from contractInterface) for fetchEvents —
22
+ * this lets the public verify service read events without depending on the
23
+ * private LicensingApp circuit source.
24
+ */
25
+ import { PublicKey, UInt32 } from 'o1js';
26
+ import { LicensingAppEventsContract, MONTHLY_SLOTS_N, ONE_YEAR_SLOTS_N, FIVE_YEAR_SLOTS_N, } from './contractInterface.js';
27
+ import { applyLicenseIssued, updateExpiry, recordRefund, recordRelease, } from './licenseStore.js';
28
+ export const SYNC_CHUNK_SLOTS = 10_000;
29
+ export const MAX_LOOKBACK_SLOTS = 525_600;
30
+ // Back-derive the duration tier from (expirySlot - purchaseSlot). Tolerance
31
+ // of ±2 slots matches the SLOT_TOLERANCE used in the circuit.
32
+ export function tierFromExpiryDelta(slots) {
33
+ const within = (target) => Math.abs(slots - target) <= 2;
34
+ if (within(MONTHLY_SLOTS_N))
35
+ return 'monthly';
36
+ if (within(ONE_YEAR_SLOTS_N))
37
+ return 'yearly';
38
+ if (within(FIVE_YEAR_SLOTS_N))
39
+ return 'fiveYear';
40
+ return null;
41
+ }
42
+ export async function bootstrapFromArchive(zkAppAddress, range = {}) {
43
+ const pubKey = PublicKey.fromBase58(zkAppAddress);
44
+ const zkApp = new LicensingAppEventsContract(pubKey);
45
+ const start = range.from !== undefined ? UInt32.from(range.from) : undefined;
46
+ const end = range.to !== undefined ? UInt32.from(range.to) : undefined;
47
+ const allEvents = await zkApp.fetchEvents(start, end);
48
+ const canonical = [...allEvents]
49
+ .filter(e => e.chainStatus === 'canonical')
50
+ .sort((a, b) => Number(a.globalSlot.toString()) - Number(b.globalSlot.toString()));
51
+ const events = [];
52
+ for (const ev of canonical) {
53
+ const slot = Number(ev.globalSlot.toString());
54
+ switch (ev.type) {
55
+ case 'priceUpdated': {
56
+ const data = ev.event.data;
57
+ events.push({
58
+ kind: 'priceUpdated',
59
+ slot,
60
+ priceMonthly: BigInt(data.priceMonthly.toString()),
61
+ priceYearly: BigInt(data.priceYearly.toString()),
62
+ priceFiveYear: BigInt(data.priceFiveYear.toString()),
63
+ });
64
+ break;
65
+ }
66
+ case 'licenseIssued': {
67
+ const data = ev.event.data;
68
+ events.push({
69
+ kind: 'licenseIssued',
70
+ slot,
71
+ licenseHash: data.licenseHash.toString(),
72
+ amount: BigInt(data.amount.toString()),
73
+ issuedSlot: Number(data.slot.toString()),
74
+ expirySlot: Number(data.expirySlot.toString()),
75
+ });
76
+ break;
77
+ }
78
+ case 'licenseIssuedNoEscrow': {
79
+ const data = ev.event.data;
80
+ events.push({
81
+ kind: 'licenseIssuedNoEscrow',
82
+ slot,
83
+ licenseHash: data.licenseHash.toString(),
84
+ amount: BigInt(data.amount.toString()),
85
+ issuedSlot: Number(data.slot.toString()),
86
+ expirySlot: Number(data.expirySlot.toString()),
87
+ });
88
+ break;
89
+ }
90
+ case 'licenseRenewed': {
91
+ const data = ev.event.data;
92
+ events.push({
93
+ kind: 'licenseRenewed',
94
+ slot,
95
+ licenseHash: data.licenseHash.toString(),
96
+ newExpiry: Number(data.newExpiry.toString()),
97
+ });
98
+ break;
99
+ }
100
+ case 'licenseMigrated': {
101
+ const data = ev.event.data;
102
+ events.push({
103
+ kind: 'licenseMigrated',
104
+ slot,
105
+ licenseHash: data.licenseHash.toString(),
106
+ expirySlot: Number(data.expirySlot.toString()),
107
+ ancestorGen: Number(data.ancestorGen.toString()),
108
+ });
109
+ break;
110
+ }
111
+ case 'refundIssued':
112
+ events.push({ kind: 'refundIssued', slot, licenseHash: ev.event.data.toString() });
113
+ break;
114
+ case 'fundsReleased':
115
+ events.push({ kind: 'fundsReleased', slot, licenseHash: ev.event.data.toString() });
116
+ break;
117
+ }
118
+ }
119
+ const maxSeenSlot = canonical.length === 0
120
+ ? -1
121
+ : Number(canonical[canonical.length - 1].globalSlot.toString());
122
+ return { maxSeenSlot, events };
123
+ }
124
+ export async function applyEventsToStore(zkAppAddress, events) {
125
+ const warnings = [];
126
+ let count = 0;
127
+ for (const ev of events) {
128
+ switch (ev.kind) {
129
+ case 'priceUpdated':
130
+ break;
131
+ case 'licenseIssued': {
132
+ const tier = tierFromExpiryDelta(ev.expirySlot - ev.issuedSlot) ?? undefined;
133
+ await applyLicenseIssued(zkAppAddress, ev.licenseHash, {
134
+ expirySlot: ev.expirySlot,
135
+ purchaseSlot: ev.issuedSlot,
136
+ purchaseAmount: ev.amount.toString(),
137
+ ...(tier ? { tier } : {}),
138
+ });
139
+ count++;
140
+ break;
141
+ }
142
+ case 'licenseIssuedNoEscrow': {
143
+ const tier = tierFromExpiryDelta(ev.expirySlot - ev.issuedSlot) ?? undefined;
144
+ await applyLicenseIssued(zkAppAddress, ev.licenseHash, {
145
+ expirySlot: ev.expirySlot,
146
+ purchaseSlot: ev.issuedSlot,
147
+ purchaseAmount: ev.amount.toString(),
148
+ escrowless: true,
149
+ ...(tier ? { tier } : {}),
150
+ });
151
+ count++;
152
+ break;
153
+ }
154
+ case 'licenseRenewed': {
155
+ const ok = await updateExpiry(zkAppAddress, ev.licenseHash, ev.newExpiry, {
156
+ markRenewed: true,
157
+ });
158
+ if (!ok)
159
+ warnings.push(`renew for unknown license ${ev.licenseHash.slice(0, 16)}…`);
160
+ break;
161
+ }
162
+ case 'licenseMigrated': {
163
+ await applyLicenseIssued(zkAppAddress, ev.licenseHash, {
164
+ expirySlot: ev.expirySlot,
165
+ purchaseSlot: 0,
166
+ purchaseAmount: '0',
167
+ escrowless: true,
168
+ });
169
+ count++;
170
+ break;
171
+ }
172
+ case 'refundIssued': {
173
+ const ok = await recordRefund(zkAppAddress, ev.licenseHash);
174
+ if (!ok)
175
+ warnings.push(`refund for unknown license ${ev.licenseHash.slice(0, 16)}…`);
176
+ break;
177
+ }
178
+ case 'fundsReleased': {
179
+ const ok = await recordRelease(zkAppAddress, ev.licenseHash, ev.slot);
180
+ if (!ok)
181
+ warnings.push(`release for unknown license ${ev.licenseHash.slice(0, 16)}…`);
182
+ break;
183
+ }
184
+ }
185
+ }
186
+ return { count, warnings };
187
+ }
188
+ export async function discoverAppCreatedSlot(zkAppAddress, nowSlot, lookbackSlots = MAX_LOOKBACK_SLOTS) {
189
+ const pubKey = PublicKey.fromBase58(zkAppAddress);
190
+ const zkApp = new LicensingAppEventsContract(pubKey);
191
+ const floor = Math.max(1, nowSlot - lookbackSlots);
192
+ let to = nowSlot;
193
+ while (to >= floor) {
194
+ const from = Math.max(floor, to - SYNC_CHUNK_SLOTS + 1);
195
+ const events = await zkApp.fetchEvents(UInt32.from(from), UInt32.from(to));
196
+ const created = events
197
+ .filter(e => e.chainStatus === 'canonical' && e.type === 'appCreated')
198
+ .sort((a, b) => Number(a.globalSlot.toString()) - Number(b.globalSlot.toString()));
199
+ if (created.length > 0) {
200
+ return Number(created[0].globalSlot.toString());
201
+ }
202
+ if (from <= floor)
203
+ break;
204
+ to = from - 1;
205
+ }
206
+ return null;
207
+ }
208
+ const inFlightBootstraps = new Map();
209
+ export async function lazyBootstrap(zkAppAddress) {
210
+ const existing = inFlightBootstraps.get(zkAppAddress);
211
+ if (existing)
212
+ return existing;
213
+ const short = zkAppAddress.slice(0, 12) + '…';
214
+ const p = (async () => {
215
+ try {
216
+ const { events } = await bootstrapFromArchive(zkAppAddress);
217
+ const { count, warnings } = await applyEventsToStore(zkAppAddress, events);
218
+ for (const w of warnings)
219
+ console.warn(`[lazy-bootstrap] ${short}: ${w}`);
220
+ if (count > 0) {
221
+ console.log(`[lazy-bootstrap] ${short}: replayed ${count} record(s)`);
222
+ }
223
+ }
224
+ catch (e) {
225
+ console.warn(`[lazy-bootstrap] ${short}: ${e?.message ?? e}`);
226
+ }
227
+ finally {
228
+ inFlightBootstraps.delete(zkAppAddress);
229
+ }
230
+ })();
231
+ inFlightBootstraps.set(zkAppAddress, p);
232
+ return p;
233
+ }
234
+ //# sourceMappingURL=archiveBootstrap.js.map
@@ -0,0 +1,58 @@
1
+ export type BuyIdentity = {
2
+ secretHash: string;
3
+ licenseHash: string;
4
+ };
5
+ export declare function deriveBuyIdentity(passphrase: string): BuyIdentity;
6
+ export type ProveBuyRequest = {
7
+ keeperUrl: string;
8
+ licenseHash: string;
9
+ buyerAddress: string;
10
+ zkAppAddress: string;
11
+ duration: 0 | 1 | 2;
12
+ buyerCountry: string;
13
+ refundWaiverAccepted?: boolean;
14
+ freezeAfterSlot?: number | null;
15
+ fetcher?: typeof fetch;
16
+ signal?: AbortSignal;
17
+ };
18
+ export type ProveBuyResponse = {
19
+ provenTxJson: string;
20
+ expirySlot: number;
21
+ licenseHash: string;
22
+ verificationKeyHash: string;
23
+ purchaseSlot: number;
24
+ purchaseAmount: string;
25
+ duration: number;
26
+ durationLabel: string;
27
+ generation: number;
28
+ };
29
+ export type ConfirmBuyRequest = {
30
+ keeperUrl: string;
31
+ zkAppAddress: string;
32
+ licenseHash: string;
33
+ txHash: string;
34
+ fetcher?: typeof fetch;
35
+ signal?: AbortSignal;
36
+ };
37
+ export type BuyStatus = {
38
+ status: 'unknown' | 'pending' | 'confirmed' | 'failed';
39
+ txHash?: string;
40
+ landedAtBlockHeight?: number;
41
+ landedAtSlot?: number;
42
+ elapsedMs?: number;
43
+ };
44
+ export declare function proveBuy(req: ProveBuyRequest): Promise<ProveBuyResponse>;
45
+ export declare function confirmBuy(req: ConfirmBuyRequest): Promise<{
46
+ ok: true;
47
+ }>;
48
+ export type PollBuyStatusOptions = {
49
+ keeperUrl: string;
50
+ licenseHash: string;
51
+ fetcher?: typeof fetch;
52
+ intervalMs?: number;
53
+ timeoutMs?: number;
54
+ signal?: AbortSignal;
55
+ onTick?: (status: BuyStatus) => void;
56
+ };
57
+ export declare function pollBuyStatus(opts: PollBuyStatusOptions): Promise<BuyStatus>;
58
+ //# sourceMappingURL=buyClient.d.ts.map
@@ -0,0 +1,162 @@
1
+ // Copyright (c) 2025-2026 zkLicensing project developers
2
+ // All rights reserved.
3
+ /**
4
+ * buyClient.ts
5
+ *
6
+ * Browser-safe client for the buy flow. Exposes the three keeper roundtrips
7
+ * (derive identity → prove → confirm) as small, individually testable
8
+ * functions plus a `pollBuyStatus` helper. Deliberately does NOT talk to a
9
+ * wallet — the caller drives the wallet step between `proveBuy` and
10
+ * `confirmBuy`, so the SDK stays wallet-agnostic and can be reused by CLI
11
+ * tools, alternate UIs, and third-party integrators.
12
+ *
13
+ * Peer dep: o1js (for Poseidon + Encoding). Consumers of ./buy must have
14
+ * o1js in their dependency graph.
15
+ */
16
+ import { Encoding, Poseidon } from 'o1js';
17
+ import { resolveFreezeState } from './freezeClient.js';
18
+ import { REFUND_WINDOW_N, TOLERANCE_WINDOW_N } from './contractInterface.js';
19
+ // Derive the two hashes the buy flow keys off. Deterministic in the
20
+ // passphrase — same passphrase always maps to the same licenseHash on a
21
+ // given zkApp, so a buyer's passphrase choice locks in their license
22
+ // identity from day one. Only `licenseHash` is sent to the keeper (see
23
+ // proveBuy); `secretHash` stays on the buyer's device and is used only by
24
+ // the client-side LicenseOwnershipProgram challenge/response.
25
+ export function deriveBuyIdentity(passphrase) {
26
+ const secretHash = Poseidon.hash(Encoding.stringToFields(passphrase));
27
+ const licenseHash = Poseidon.hash([secretHash]);
28
+ return { secretHash: secretHash.toString(), licenseHash: licenseHash.toString() };
29
+ }
30
+ function baseUrl(url) {
31
+ return url.replace(/\/+$/, '');
32
+ }
33
+ async function readJsonError(resp) {
34
+ try {
35
+ const body = await resp.json();
36
+ if (typeof body.error === 'string')
37
+ return body.error;
38
+ }
39
+ catch { /* body wasn't JSON */ }
40
+ return `HTTP ${resp.status}`;
41
+ }
42
+ // POST /prove/buy — keeper compiles + proves the buy tx.
43
+ // The buyer's wallet then signs the returned provenTxJson.
44
+ //
45
+ // Pre-network guards:
46
+ // - salesFrozen === true → refuse immediately (keeper would 423 anyway).
47
+ // - freezeAfterSlot announced AND this buy's 14-day refund window would
48
+ // extend past the freeze slot AND refundWaiverAccepted !== true →
49
+ // refuse (buyer must explicitly accept that the scheduled hardfork
50
+ // can truncate their refund window). Buys whose full window ends
51
+ // before the freeze proceed without a waiver.
52
+ //
53
+ // Endpoint routing:
54
+ // - refundWaiverAccepted === true → POST /prove/buy-no-escrow. The no-escrow
55
+ // circuit method pays vendor+platform directly (98/2 split, no escrow
56
+ // tree write). This is chosen either voluntarily by the buyer (opting out
57
+ // of the 14-day statutory right of withdrawal in exchange for immediate
58
+ // delivery) or forced by a freeze overlap.
59
+ // - refundWaiverAccepted !== true → POST /prove/buy (standard escrow path
60
+ // with a 14-day refund window).
61
+ export async function proveBuy(req) {
62
+ const fetcher = req.fetcher ?? fetch;
63
+ const freeze = await resolveFreezeState({
64
+ keeperUrl: req.keeperUrl,
65
+ freezeAfterSlot: req.freezeAfterSlot,
66
+ fetcher,
67
+ signal: req.signal,
68
+ });
69
+ if (freeze.salesFrozen) {
70
+ throw new Error('Sales frozen — new buys refused ahead of scheduled hardfork migration');
71
+ }
72
+ let windowOverlapsFreeze = false;
73
+ if (freeze.freezeAfterSlot !== null) {
74
+ // Waiver required when the refund window would overlap the freeze, or
75
+ // when the current slot is unknown client-side (safe default). The
76
+ // +TOLERANCE_WINDOW_N margin accounts for slot-precondition slop
77
+ // between prove and inclusion: the real inclusion slot can be up to
78
+ // TOLERANCE_WINDOW_N slots past `currentSlot`, so we include that in
79
+ // the overlap comparison rather than let a late inclusion silently
80
+ // push the refund deadline past the freeze without a waiver.
81
+ windowOverlapsFreeze =
82
+ freeze.currentSlot === null ||
83
+ freeze.currentSlot + REFUND_WINDOW_N + TOLERANCE_WINDOW_N > freeze.freezeAfterSlot;
84
+ if (windowOverlapsFreeze && req.refundWaiverAccepted !== true) {
85
+ throw new Error(`refundWaiverAccepted must be true — the scheduled hardfork at slot ${freeze.freezeAfterSlot} can truncate the 14-day refund window`);
86
+ }
87
+ }
88
+ const useNoEscrow = req.refundWaiverAccepted === true;
89
+ const endpoint = useNoEscrow ? '/prove/buy-no-escrow' : '/prove/buy';
90
+ const resp = await fetcher(`${baseUrl(req.keeperUrl)}${endpoint}`, {
91
+ method: 'POST',
92
+ headers: { 'Content-Type': 'application/json' },
93
+ signal: req.signal,
94
+ body: JSON.stringify({
95
+ licenseHash: req.licenseHash,
96
+ buyerAddress: req.buyerAddress,
97
+ zkAppAddress: req.zkAppAddress,
98
+ duration: req.duration,
99
+ buyerCountry: req.buyerCountry,
100
+ ...(req.refundWaiverAccepted === true ? { refundWaiverAccepted: true } : {}),
101
+ }),
102
+ });
103
+ if (!resp.ok) {
104
+ // Distinct guidance for the no-escrow path: a 404 here means the
105
+ // vendor's zkApp was deployed before the no-escrow method existed. Fix
106
+ // is a redeploy through the hardfork-migration flow (§12.13); until
107
+ // then the escrowless (waiver) path is unavailable on this vendor.
108
+ if (useNoEscrow && resp.status === 404) {
109
+ throw new Error('Keeper does not offer /prove/buy-no-escrow — this vendor\'s zkApp does not support the escrowless (waiver) path; vendor must redeploy via the hardfork-migration flow');
110
+ }
111
+ throw new Error(await readJsonError(resp));
112
+ }
113
+ return await resp.json();
114
+ }
115
+ // POST /confirm/buy — promotes the in-memory intent staged by /prove/buy
116
+ // into a persisted (pending: true) LicenseRecord. Call this only after the
117
+ // wallet has actually returned a txHash — a cancelled or dropped signature
118
+ // leaves the intent to expire on its own.
119
+ export async function confirmBuy(req) {
120
+ const fetcher = req.fetcher ?? fetch;
121
+ const resp = await fetcher(`${baseUrl(req.keeperUrl)}/confirm/buy`, {
122
+ method: 'POST',
123
+ headers: { 'Content-Type': 'application/json' },
124
+ signal: req.signal,
125
+ body: JSON.stringify({
126
+ zkAppAddress: req.zkAppAddress,
127
+ licenseHash: req.licenseHash,
128
+ txHash: req.txHash,
129
+ }),
130
+ });
131
+ if (!resp.ok)
132
+ throw new Error(await readJsonError(resp));
133
+ return { ok: true };
134
+ }
135
+ // Polls GET /buy/status until it returns a terminal state ('confirmed' or
136
+ // 'failed') or the timeout fires. Terminal state is resolved via the
137
+ // returned status; 'unknown' just means the keeper hasn't seen the tx yet.
138
+ export async function pollBuyStatus(opts) {
139
+ const fetcher = opts.fetcher ?? fetch;
140
+ const interval = opts.intervalMs ?? 3_000;
141
+ const timeout = opts.timeoutMs ?? 10 * 60 * 1000;
142
+ const deadline = Date.now() + timeout;
143
+ const url = `${baseUrl(opts.keeperUrl)}/buy/status?licenseHash=${encodeURIComponent(opts.licenseHash)}`;
144
+ while (true) {
145
+ if (opts.signal?.aborted)
146
+ throw new Error('pollBuyStatus aborted');
147
+ let status = { status: 'unknown' };
148
+ try {
149
+ const resp = await fetcher(url, { signal: opts.signal });
150
+ if (resp.ok)
151
+ status = await resp.json();
152
+ }
153
+ catch { /* transient network — try again on next tick */ }
154
+ opts.onTick?.(status);
155
+ if (status.status === 'confirmed' || status.status === 'failed')
156
+ return status;
157
+ if (Date.now() >= deadline)
158
+ return status;
159
+ await new Promise((r) => setTimeout(r, interval));
160
+ }
161
+ }
162
+ //# sourceMappingURL=buyClient.js.map
@@ -0,0 +1,55 @@
1
+ // Hand-written declarations for contractInterface.ts.
2
+ // tsc can't emit these automatically because the inferred return types of
3
+ // Struct() and SmartContract reference internal o1js paths outside this
4
+ // package's rootDir, triggering TS2742. Callers get full typing on the
5
+ // methods they actually invoke by importing the corresponding o1js types
6
+ // directly (Field, PublicKey, etc.) in their own code.
7
+
8
+ import type { Field, UInt64 } from 'o1js';
9
+
10
+ export const LicenseIssuedEvent: any;
11
+ export type LicenseIssuedEvent = any;
12
+
13
+ export const ExpiryUpdateEvent: any;
14
+ export type ExpiryUpdateEvent = any;
15
+
16
+ export const PriceUpdatedEvent: any;
17
+ export type PriceUpdatedEvent = any;
18
+
19
+ export const AppCreatedEvent: any;
20
+ export type AppCreatedEvent = any;
21
+
22
+ export const LicenseMigratedEvent: any;
23
+ export type LicenseMigratedEvent = any;
24
+
25
+ export function unpackPrices(packed: Field): { priceMonthly: UInt64; priceYearly: UInt64; priceFiveYear: UInt64 };
26
+
27
+ export const MONTHLY_SLOTS_N: number;
28
+ export const ONE_YEAR_SLOTS_N: number;
29
+ export const FIVE_YEAR_SLOTS_N: number;
30
+ export const REFUND_WINDOW_N: number;
31
+ export const GRACE_PERIOD_N: number;
32
+ export const MS_PER_SLOT_N: number;
33
+ export const SLOTS_PER_DAY_N: number;
34
+ export const TOLERANCE_WINDOW_N: number;
35
+
36
+ export const EMPTY: Field;
37
+ export const EMPTY_ROOT: Field;
38
+
39
+ export const DURATION_LABELS: readonly ['1 Month', '1 Year', '5 Years'];
40
+ export type DurationLabel = '1 Month' | '1 Year' | '5 Years';
41
+ export const DURATION_INDEX: { readonly '1 Month': 0; readonly '1 Year': 1; readonly '5 Years': 2 };
42
+
43
+ export function durationSlotsFromLabel(label?: string | null): number | null;
44
+ export function durationIndexFromLabel(label?: string | null): number | null;
45
+ export function durationLabelFromIndex(idx: number): DurationLabel | null;
46
+
47
+ export const LicensingAppEventsContract: any;
48
+
49
+ export const SUPPORTED_LICENSING_APP_VERSIONS: readonly number[];
50
+ export function fetchLicensingAppVersion(zkAppAddress: string): Promise<number | null>;
51
+
52
+ export const CANONICAL_VK_HASHES: Readonly<Record<number, string>>;
53
+ export const CURRENT_GENERATION: number;
54
+ export const CANONICAL_VK_HASH: string;
55
+ export const CANONICAL_LICENSE_PROOF_VK_HASH: string;