zklicensing 0.1.0-beta.2 → 0.1.0-beta.21
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/README.md +417 -201
- package/build/agent.d.ts +371 -0
- package/build/agent.d.ts.map +1 -0
- package/build/agent.js +553 -0
- package/build/agent.js.map +1 -0
- package/build/agentActions.d.ts +841 -0
- package/build/agentActions.d.ts.map +1 -0
- package/build/agentActions.js +581 -0
- package/build/agentActions.js.map +1 -0
- package/build/agentRecord.d.ts +83 -0
- package/build/agentRecord.d.ts.map +1 -0
- package/build/agentRecord.js +69 -0
- package/build/agentRecord.js.map +1 -0
- package/build/agentVendor.d.ts +220 -0
- package/build/agentVendor.d.ts.map +1 -0
- package/build/agentVendor.js +306 -0
- package/build/agentVendor.js.map +1 -0
- package/build/appsLookup.d.ts +14 -0
- package/build/appsLookup.d.ts.map +1 -0
- package/build/appsLookup.js +12 -0
- package/build/appsLookup.js.map +1 -0
- package/build/archiveBootstrap.d.ts +31 -5
- package/build/archiveBootstrap.d.ts.map +1 -0
- package/build/archiveBootstrap.js +140 -47
- package/build/archiveBootstrap.js.map +1 -0
- package/build/atomicJson.d.ts +5 -0
- package/build/atomicJson.d.ts.map +1 -0
- package/build/atomicJson.js +55 -0
- package/build/atomicJson.js.map +1 -0
- package/build/bindClient.d.ts +85 -0
- package/build/bindClient.d.ts.map +1 -0
- package/build/bindClient.js +187 -0
- package/build/bindClient.js.map +1 -0
- package/build/buyClient.d.ts +27 -4
- package/build/buyClient.d.ts.map +1 -0
- package/build/buyClient.js +72 -26
- package/build/buyClient.js.map +1 -0
- package/build/chainHead.d.ts +61 -0
- package/build/chainHead.d.ts.map +1 -0
- package/build/chainHead.js +88 -0
- package/build/chainHead.js.map +1 -0
- package/build/compactMerkleMap.d.ts +72 -0
- package/build/compactMerkleMap.d.ts.map +1 -0
- package/build/compactMerkleMap.js +224 -0
- package/build/compactMerkleMap.js.map +1 -0
- package/build/contractInterface.d.ts +191 -51
- package/build/contractInterface.d.ts.map +1 -0
- package/build/contractInterface.js +234 -43
- package/build/contractInterface.js.map +1 -0
- package/build/contractTypes.d.ts +9 -0
- package/build/contractTypes.d.ts.map +1 -0
- package/build/contractTypes.js +28 -0
- package/build/contractTypes.js.map +1 -0
- package/build/countryStats.d.ts +12 -3
- package/build/countryStats.d.ts.map +1 -0
- package/build/countryStats.js +87 -23
- package/build/countryStats.js.map +1 -0
- package/build/deployClient.d.ts +138 -24
- package/build/deployClient.d.ts.map +1 -0
- package/build/deployClient.js +91 -31
- package/build/deployClient.js.map +1 -0
- package/build/deviceIdentity.d.ts +68 -0
- package/build/deviceIdentity.d.ts.map +1 -0
- package/build/deviceIdentity.js +209 -0
- package/build/deviceIdentity.js.map +1 -0
- package/build/freezeClient.d.ts +26 -6
- package/build/freezeClient.d.ts.map +1 -0
- package/build/freezeClient.js +30 -6
- package/build/freezeClient.js.map +1 -0
- package/build/generationClient.d.ts +6 -3
- package/build/generationClient.d.ts.map +1 -0
- package/build/generationClient.js +25 -38
- package/build/generationClient.js.map +1 -0
- package/build/holderSecret.d.ts +70 -0
- package/build/holderSecret.d.ts.map +1 -0
- package/build/holderSecret.js +76 -0
- package/build/holderSecret.js.map +1 -0
- package/build/index.d.ts +38 -38
- package/build/index.d.ts.map +1 -0
- package/build/index.js +97 -121
- package/build/index.js.map +1 -0
- package/build/keysClient.d.ts +142 -0
- package/build/keysClient.d.ts.map +1 -0
- package/build/keysClient.js +109 -0
- package/build/keysClient.js.map +1 -0
- package/build/licenseLeaf.d.ts +76 -0
- package/build/licenseLeaf.d.ts.map +1 -0
- package/build/licenseLeaf.js +189 -0
- package/build/licenseLeaf.js.map +1 -0
- package/build/licenseRecord.d.ts +68 -5
- package/build/licenseRecord.d.ts.map +1 -0
- package/build/licenseRecord.js +26 -1
- package/build/licenseRecord.js.map +1 -0
- package/build/licenseStore.d.ts +81 -4
- package/build/licenseStore.d.ts.map +1 -0
- package/build/licenseStore.js +400 -30
- package/build/licenseStore.js.map +1 -0
- package/build/licenseTrustless.d.ts +43 -0
- package/build/licenseTrustless.d.ts.map +1 -0
- package/build/licenseTrustless.js +180 -0
- package/build/licenseTrustless.js.map +1 -0
- package/build/manifestVerify.d.ts +29 -1
- package/build/manifestVerify.d.ts.map +1 -0
- package/build/manifestVerify.js +46 -4
- package/build/manifestVerify.js.map +1 -0
- package/build/minaPriceHistory.d.ts +9 -0
- package/build/minaPriceHistory.d.ts.map +1 -0
- package/build/minaPriceHistory.js +152 -0
- package/build/minaPriceHistory.js.map +1 -0
- package/build/onChainRoot.d.ts +60 -0
- package/build/onChainRoot.d.ts.map +1 -0
- package/build/onChainRoot.js +74 -0
- package/build/onChainRoot.js.map +1 -0
- package/build/ownershipLicenseHash.d.ts +25 -0
- package/build/ownershipLicenseHash.d.ts.map +1 -0
- package/build/ownershipLicenseHash.js +29 -0
- package/build/ownershipLicenseHash.js.map +1 -0
- package/build/ownershipSignature.d.ts +153 -0
- package/build/ownershipSignature.d.ts.map +1 -0
- package/build/ownershipSignature.js +297 -0
- package/build/ownershipSignature.js.map +1 -0
- package/build/permitCheckFlow.d.ts +155 -0
- package/build/permitCheckFlow.d.ts.map +1 -0
- package/build/permitCheckFlow.js +196 -0
- package/build/permitCheckFlow.js.map +1 -0
- package/build/permitDescribe.d.ts +124 -0
- package/build/permitDescribe.d.ts.map +1 -0
- package/build/permitDescribe.js +324 -0
- package/build/permitDescribe.js.map +1 -0
- package/build/permitInterface.d.ts +85 -0
- package/build/permitInterface.d.ts.map +1 -0
- package/build/permitInterface.js +121 -0
- package/build/permitInterface.js.map +1 -0
- package/build/permitMessages.d.ts +313 -0
- package/build/permitMessages.d.ts.map +1 -0
- package/build/permitMessages.js +462 -0
- package/build/permitMessages.js.map +1 -0
- package/build/permitProof.d.ts +108 -0
- package/build/permitProof.d.ts.map +1 -0
- package/build/permitProof.js +202 -0
- package/build/permitProof.js.map +1 -0
- package/build/permitRegistryRebuild.d.ts +166 -0
- package/build/permitRegistryRebuild.d.ts.map +1 -0
- package/build/permitRegistryRebuild.js +347 -0
- package/build/permitRegistryRebuild.js.map +1 -0
- package/build/permitTree.d.ts +88 -0
- package/build/permitTree.d.ts.map +1 -0
- package/build/permitTree.js +230 -0
- package/build/permitTree.js.map +1 -0
- package/build/permitsClient.d.ts +680 -0
- package/build/permitsClient.d.ts.map +1 -0
- package/build/permitsClient.js +597 -0
- package/build/permitsClient.js.map +1 -0
- package/build/proveErrors.d.ts +50 -0
- package/build/proveErrors.d.ts.map +1 -0
- package/build/proveErrors.js +76 -0
- package/build/proveErrors.js.map +1 -0
- package/build/receipt.d.ts +95 -0
- package/build/receipt.d.ts.map +1 -0
- package/build/receipt.js +84 -0
- package/build/receipt.js.map +1 -0
- package/build/refundClient.d.ts +7 -12
- package/build/refundClient.d.ts.map +1 -0
- package/build/refundClient.js +52 -21
- package/build/refundClient.js.map +1 -0
- package/build/registryTrustVerify.d.ts +78 -0
- package/build/registryTrustVerify.d.ts.map +1 -0
- package/build/registryTrustVerify.js +129 -0
- package/build/registryTrustVerify.js.map +1 -0
- package/build/releaseClient.d.ts +26 -0
- package/build/releaseClient.d.ts.map +1 -0
- package/build/releaseClient.js +65 -0
- package/build/releaseClient.js.map +1 -0
- package/build/renewClient.d.ts +28 -2
- package/build/renewClient.d.ts.map +1 -0
- package/build/renewClient.js +31 -27
- package/build/renewClient.js.map +1 -0
- package/build/seatName.d.ts +8 -0
- package/build/seatName.d.ts.map +1 -0
- package/build/seatName.js +136 -0
- package/build/seatName.js.map +1 -0
- package/build/slotConstants.d.ts +15 -0
- package/build/slotConstants.d.ts.map +1 -0
- package/build/slotConstants.js +17 -0
- package/build/slotConstants.js.map +1 -0
- package/build/statsClient.d.ts +61 -7
- package/build/statsClient.d.ts.map +1 -0
- package/build/statsClient.js +44 -5
- package/build/statsClient.js.map +1 -0
- package/build/successorChain.d.ts +35 -0
- package/build/successorChain.d.ts.map +1 -0
- package/build/successorChain.js +69 -0
- package/build/successorChain.js.map +1 -0
- package/build/taxId.d.ts +44 -0
- package/build/taxId.d.ts.map +1 -0
- package/build/taxId.js +212 -0
- package/build/taxId.js.map +1 -0
- package/build/trustAnchorVerify.d.ts +49 -0
- package/build/trustAnchorVerify.d.ts.map +1 -0
- package/build/trustAnchorVerify.js +432 -0
- package/build/trustAnchorVerify.js.map +1 -0
- package/build/trustAnchorVerifyCli.d.ts +45 -0
- package/build/trustAnchorVerifyCli.d.ts.map +1 -0
- package/build/trustAnchorVerifyCli.js +235 -0
- package/build/trustAnchorVerifyCli.js.map +1 -0
- package/build/txBroadcastClient.d.ts +26 -0
- package/build/txBroadcastClient.d.ts.map +1 -0
- package/build/txBroadcastClient.js +20 -0
- package/build/txBroadcastClient.js.map +1 -0
- package/build/unbindClient.d.ts +77 -0
- package/build/unbindClient.d.ts.map +1 -0
- package/build/unbindClient.js +169 -0
- package/build/unbindClient.js.map +1 -0
- package/build/units.d.ts +28 -0
- package/build/units.d.ts.map +1 -0
- package/build/units.js +65 -0
- package/build/units.js.map +1 -0
- package/build/vatRates.d.ts +54 -0
- package/build/vatRates.d.ts.map +1 -0
- package/build/vatRates.js +82 -0
- package/build/vatRates.js.map +1 -0
- package/build/vatRatesData.d.ts +5 -0
- package/build/vatRatesData.d.ts.map +1 -0
- package/build/vatRatesData.js +42 -0
- package/build/vatRatesData.js.map +1 -0
- package/build/vendorAccountClient.d.ts +66 -0
- package/build/vendorAccountClient.d.ts.map +1 -0
- package/build/vendorAccountClient.js +47 -0
- package/build/vendorAccountClient.js.map +1 -0
- package/build/verifyCore.d.ts +4 -1
- package/build/verifyCore.d.ts.map +1 -0
- package/build/verifyCore.js +21 -10
- package/build/verifyCore.js.map +1 -0
- package/build/verifyOffline.d.ts +85 -0
- package/build/verifyOffline.d.ts.map +1 -0
- package/build/verifyOffline.js +139 -0
- package/build/verifyOffline.js.map +1 -0
- package/build/verifyService.d.ts.map +1 -0
- package/build/verifyService.js +571 -501
- package/build/verifyService.js.map +1 -0
- package/build/verifyWithAncestors.d.ts +19 -0
- package/build/verifyWithAncestors.d.ts.map +1 -0
- package/build/verifyWithAncestors.js +127 -0
- package/build/verifyWithAncestors.js.map +1 -0
- package/build/zipToState.d.ts +2 -0
- package/build/zipToState.d.ts.map +1 -0
- package/build/zipToState.js +94 -0
- package/build/zipToState.js.map +1 -0
- package/package.json +141 -16
- package/src/agent.ts +682 -0
- package/src/agentActions.ts +637 -0
- package/src/agentRecord.ts +121 -0
- package/src/agentVendor.ts +356 -0
- package/src/appsLookup.ts +48 -0
- package/src/archiveBootstrap.ts +386 -0
- package/src/atomicJson.ts +53 -0
- package/src/bindClient.ts +297 -0
- package/src/buyClient.ts +344 -0
- package/src/chainHead.ts +106 -0
- package/src/compactMerkleMap.ts +222 -0
- package/src/contractInterface.ts +465 -0
- package/src/contractTypes.ts +31 -0
- package/src/countryStats.ts +200 -0
- package/src/deployClient.ts +517 -0
- package/src/deviceIdentity.ts +249 -0
- package/src/freezeClient.ts +162 -0
- package/src/generationClient.ts +145 -0
- package/src/holderSecret.ts +91 -0
- package/src/index.ts +362 -0
- package/src/keysClient.ts +135 -0
- package/src/licenseLeaf.ts +221 -0
- package/src/licenseRecord.ts +190 -0
- package/src/licenseStore.ts +767 -0
- package/src/licenseTrustless.ts +207 -0
- package/src/manifestVerify.ts +164 -0
- package/src/minaPriceHistory.ts +166 -0
- package/src/onChainRoot.ts +90 -0
- package/src/ownershipLicenseHash.ts +31 -0
- package/src/ownershipSignature.ts +421 -0
- package/src/permitCheckFlow.ts +227 -0
- package/src/permitDescribe.ts +362 -0
- package/src/permitInterface.ts +146 -0
- package/src/permitMessages.ts +572 -0
- package/src/permitProof.ts +230 -0
- package/src/permitRegistryRebuild.ts +423 -0
- package/src/permitTree.ts +232 -0
- package/src/permitsClient.ts +746 -0
- package/src/proveErrors.ts +98 -0
- package/src/receipt.ts +156 -0
- package/src/refundClient.ts +177 -0
- package/src/registryTrustVerify.ts +192 -0
- package/src/releaseClient.ts +101 -0
- package/src/renewClient.ts +234 -0
- package/src/seatName.ts +165 -0
- package/src/slotConstants.ts +18 -0
- package/src/statsClient.ts +249 -0
- package/src/successorChain.ts +87 -0
- package/src/taxId.ts +227 -0
- package/src/trustAnchorVerify.ts +550 -0
- package/src/trustAnchorVerifyCli.ts +234 -0
- package/src/txBroadcastClient.ts +48 -0
- package/src/unbindClient.ts +233 -0
- package/src/units.ts +74 -0
- package/src/vatRates.ts +100 -0
- package/src/vatRatesData.ts +43 -0
- package/src/vendorAccountClient.ts +120 -0
- package/src/verifyCore.ts +100 -0
- package/src/verifyOffline.ts +212 -0
- package/src/verifyService.ts +982 -0
- package/src/verifyWithAncestors.ts +163 -0
- package/src/zipToState.ts +94 -0
- package/build/licenseProof.d.ts +0 -26
- package/build/licenseProof.js +0 -41
- package/build/migrateClient.d.ts +0 -43
- package/build/migrateClient.js +0 -47
- package/build/ownership.d.ts +0 -34
- package/build/ownership.js +0 -147
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copyright (c) 2025-2026 zkLicensing project developers
|
|
3
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
4
|
+
/**
|
|
5
|
+
* trustAnchorVerifyCli.ts
|
|
6
|
+
*
|
|
7
|
+
* Command-line front-end for verifyTrustAnchor(). Ships as the `zklicensing-verify-trust`
|
|
8
|
+
* bin — the sibling of `zklicensing-verify` (which is the verifyService HTTP daemon).
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* zklicensing-verify-trust \
|
|
12
|
+
* --origin https://store.example.com \
|
|
13
|
+
* --address B62q... \
|
|
14
|
+
* --pinned-key <base64-ed25519-pubkey> \
|
|
15
|
+
* [--mina-graphql https://api.minascan.io/node/mainnet/v1/graphql] \
|
|
16
|
+
* [--mina-network-id mainnet|testnet|devnet] \
|
|
17
|
+
* [--skip-chain-checks] \
|
|
18
|
+
* [--json]
|
|
19
|
+
*
|
|
20
|
+
* The manifest lives at `<origin>/.well-known/zklicensing/<address>.json` —
|
|
21
|
+
* one file per generation address, all signed by the same platform key. The
|
|
22
|
+
* appId is read out of the signed payload; callers never need to know it
|
|
23
|
+
* out-of-band, which lets buyers verify from just the address their wallet
|
|
24
|
+
* shows them (including addresses for retired generations).
|
|
25
|
+
*
|
|
26
|
+
* Permit registries:
|
|
27
|
+
* zklicensing-verify-trust --registry B62q... [--origin https://authority.example]
|
|
28
|
+
* [--mina-network-id mainnet|devnet] [--keeper-url https://zklicensing.com/api/keeper]
|
|
29
|
+
* [--no-well-known] [--mina-graphql <url>] [--json]
|
|
30
|
+
* checks the registry's verification key against the published PermitRegistry
|
|
31
|
+
* hashes, its locked permissions and network binding, the authority website
|
|
32
|
+
* written into it at deploy (on the --origin host, when given) and that the
|
|
33
|
+
* website's /.well-known/zkpermits/<address>.json claims it, and (with
|
|
34
|
+
* --keeper-url) that the keeper's authority keys, payout and website match.
|
|
35
|
+
*
|
|
36
|
+
* Exit codes:
|
|
37
|
+
* 0 — every finding passed
|
|
38
|
+
* 1 — one or more findings failed
|
|
39
|
+
* 2 — invalid arguments
|
|
40
|
+
*
|
|
41
|
+
* --pinned-key is required and may be repeated; the CLI ships NO baked-in
|
|
42
|
+
* pin. Source it from https://zklicensing.com/trustanchor.html (published
|
|
43
|
+
* next to each generation's VK hash). See the SDK README for details.
|
|
44
|
+
*/
|
|
45
|
+
import { verifyTrustAnchor } from './trustAnchorVerify.js';
|
|
46
|
+
import { verifyRegistryTrust } from './registryTrustVerify.js';
|
|
47
|
+
const DEFAULT_GRAPHQL = {
|
|
48
|
+
mainnet: 'https://api.minascan.io/node/mainnet/v1/graphql',
|
|
49
|
+
// O1 Labs' devnet-plain node is the reliable public endpoint for freshly
|
|
50
|
+
// deployed accounts — public indexers like Minascan lag by several slots
|
|
51
|
+
// and often return null for a zkApp minutes after landing.
|
|
52
|
+
devnet: 'https://devnet-plain-1.gcp.o1test.net/graphql',
|
|
53
|
+
};
|
|
54
|
+
function usage() {
|
|
55
|
+
return [
|
|
56
|
+
'zklicensing-verify-trust — verify a vendor page + on-chain zkApp mutually bind',
|
|
57
|
+
'',
|
|
58
|
+
'Required:',
|
|
59
|
+
' --origin <url> Vendor origin (https://...)',
|
|
60
|
+
' --address <B62q...> zkApp address (the address your wallet shows you)',
|
|
61
|
+
' --pinned-key <b64> Platform manifest pubkey (repeatable during rotation)',
|
|
62
|
+
'',
|
|
63
|
+
'Or, for a permit registry:',
|
|
64
|
+
' --registry <B62q...> Registry address; checks VK, permissions, network,',
|
|
65
|
+
' the website bound at deploy and its .well-known claim',
|
|
66
|
+
' --origin <url> The authority website you expect (compared by host)',
|
|
67
|
+
' --keeper-url <url> Also compare the keeper\'s authority keys, payout, website',
|
|
68
|
+
' --no-well-known Skip fetching <website>/.well-known/zkpermits/<registry>.json',
|
|
69
|
+
'',
|
|
70
|
+
'Optional:',
|
|
71
|
+
' --mina-graphql <url> Mina GraphQL endpoint (default depends on',
|
|
72
|
+
' --mina-network-id: mainnet →',
|
|
73
|
+
` ${DEFAULT_GRAPHQL.mainnet};`,
|
|
74
|
+
` devnet → ${DEFAULT_GRAPHQL.devnet})`,
|
|
75
|
+
' --mina-network-id <id> mainnet | devnet (default: devnet)',
|
|
76
|
+
' --skip-chain-checks Manifest-only audit — no o1js chain reads',
|
|
77
|
+
' --no-cross-check Skip the platform backend cross-check',
|
|
78
|
+
' (default: on — verifies vendor manifest matches',
|
|
79
|
+
' https://zklicensing.com/apps/by-address/<address>)',
|
|
80
|
+
' --json Emit TrustAnchorReport as JSON on stdout',
|
|
81
|
+
'',
|
|
82
|
+
'Exit: 0 all-ok · 1 any check failed · 2 bad args',
|
|
83
|
+
].join('\n');
|
|
84
|
+
}
|
|
85
|
+
function parseArgs(argv) {
|
|
86
|
+
const args = {
|
|
87
|
+
pinnedKeys: [],
|
|
88
|
+
minaNetworkId: 'devnet',
|
|
89
|
+
skipChainChecks: false,
|
|
90
|
+
// Default on — the platform backend cross-check is cheap and catches
|
|
91
|
+
// vendors whose local manifest has drifted from the signed platform
|
|
92
|
+
// record. Opt out with --no-cross-check for a pure origin+chain audit.
|
|
93
|
+
crossCheck: true,
|
|
94
|
+
wellKnown: true,
|
|
95
|
+
json: false,
|
|
96
|
+
help: false,
|
|
97
|
+
};
|
|
98
|
+
for (let i = 0; i < argv.length; i++) {
|
|
99
|
+
const a = argv[i];
|
|
100
|
+
const next = () => {
|
|
101
|
+
const v = argv[++i];
|
|
102
|
+
if (v === undefined)
|
|
103
|
+
throw new Error(`missing value for ${a}`);
|
|
104
|
+
return v;
|
|
105
|
+
};
|
|
106
|
+
switch (a) {
|
|
107
|
+
case '--origin':
|
|
108
|
+
args.origin = next();
|
|
109
|
+
break;
|
|
110
|
+
case '--address':
|
|
111
|
+
args.address = next();
|
|
112
|
+
break;
|
|
113
|
+
case '--registry':
|
|
114
|
+
args.registry = next();
|
|
115
|
+
break;
|
|
116
|
+
case '--keeper-url':
|
|
117
|
+
args.keeperUrl = next();
|
|
118
|
+
break;
|
|
119
|
+
case '--pinned-key':
|
|
120
|
+
args.pinnedKeys.push(next());
|
|
121
|
+
break;
|
|
122
|
+
case '--mina-graphql':
|
|
123
|
+
args.minaGraphql = next();
|
|
124
|
+
break;
|
|
125
|
+
case '--mina-network-id': {
|
|
126
|
+
const v = next();
|
|
127
|
+
if (v !== 'mainnet' && v !== 'devnet') {
|
|
128
|
+
throw new Error(`--mina-network-id must be mainnet|devnet, got "${v}"`);
|
|
129
|
+
}
|
|
130
|
+
args.minaNetworkId = v;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case '--skip-chain-checks':
|
|
134
|
+
args.skipChainChecks = true;
|
|
135
|
+
break;
|
|
136
|
+
case '--no-well-known':
|
|
137
|
+
args.wellKnown = false;
|
|
138
|
+
break;
|
|
139
|
+
// Kept as a no-op flag so any existing invocation that passed
|
|
140
|
+
// --cross-check keeps working. --no-cross-check opts out.
|
|
141
|
+
case '--cross-check':
|
|
142
|
+
args.crossCheck = true;
|
|
143
|
+
break;
|
|
144
|
+
case '--no-cross-check':
|
|
145
|
+
args.crossCheck = false;
|
|
146
|
+
break;
|
|
147
|
+
case '--json':
|
|
148
|
+
args.json = true;
|
|
149
|
+
break;
|
|
150
|
+
case '-h':
|
|
151
|
+
case '--help':
|
|
152
|
+
args.help = true;
|
|
153
|
+
break;
|
|
154
|
+
default: throw new Error(`unknown argument: ${a}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return args;
|
|
158
|
+
}
|
|
159
|
+
function formatHuman(report) {
|
|
160
|
+
const lines = [];
|
|
161
|
+
const banner = report.ok ? 'TRUST ANCHOR VERIFIED' : 'TRUST ANCHOR FAILED';
|
|
162
|
+
lines.push(banner);
|
|
163
|
+
lines.push(` origin: ${report.origin}`);
|
|
164
|
+
lines.push(` address: ${report.address}`);
|
|
165
|
+
if (report.appId)
|
|
166
|
+
lines.push(` appId: ${report.appId}`);
|
|
167
|
+
if (report.generation !== undefined)
|
|
168
|
+
lines.push(` generation: ${report.generation}`);
|
|
169
|
+
lines.push('');
|
|
170
|
+
for (const f of report.findings) {
|
|
171
|
+
const mark = f.ok ? '[ok] ' : '[FAIL]';
|
|
172
|
+
lines.push(` ${mark} ${f.name} — ${f.detail}`);
|
|
173
|
+
}
|
|
174
|
+
return lines.join('\n');
|
|
175
|
+
}
|
|
176
|
+
async function main() {
|
|
177
|
+
let args;
|
|
178
|
+
try {
|
|
179
|
+
args = parseArgs(process.argv.slice(2));
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
process.stderr.write(`${err.message}\n\n${usage()}\n`);
|
|
183
|
+
return 2;
|
|
184
|
+
}
|
|
185
|
+
if (args.help) {
|
|
186
|
+
process.stdout.write(`${usage()}\n`);
|
|
187
|
+
return 0;
|
|
188
|
+
}
|
|
189
|
+
if (args.registry) {
|
|
190
|
+
const report = await verifyRegistryTrust({
|
|
191
|
+
address: args.registry, network: args.minaNetworkId, minaGraphqlUrl: args.minaGraphql, keeperUrl: args.keeperUrl,
|
|
192
|
+
website: args.origin, checkWellKnown: args.wellKnown,
|
|
193
|
+
});
|
|
194
|
+
if (args.json)
|
|
195
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
196
|
+
else {
|
|
197
|
+
process.stdout.write([report.ok ? 'REGISTRY VERIFIED' : 'REGISTRY FAILED', ` registry: ${report.address}`, ` network: ${report.network}`, '',
|
|
198
|
+
...(report.findings.some(f => f.name === 'website_claims_registry' && !f.ok) ? [` The authority publishes the claim at <website>/.well-known/zkpermits/${report.address}.json`, ''] : []),
|
|
199
|
+
...report.findings.map(f => ` ${f.ok ? '[ok] ' : '[FAIL]'} ${f.name} — ${f.detail}`)].join('\n') + '\n');
|
|
200
|
+
}
|
|
201
|
+
return report.ok ? 0 : 1;
|
|
202
|
+
}
|
|
203
|
+
const missing = [];
|
|
204
|
+
if (!args.origin)
|
|
205
|
+
missing.push('--origin');
|
|
206
|
+
if (!args.address)
|
|
207
|
+
missing.push('--address');
|
|
208
|
+
if (args.pinnedKeys.length === 0)
|
|
209
|
+
missing.push('--pinned-key');
|
|
210
|
+
if (missing.length > 0) {
|
|
211
|
+
process.stderr.write(`missing required argument(s): ${missing.join(', ')}\n\n${usage()}\n`);
|
|
212
|
+
return 2;
|
|
213
|
+
}
|
|
214
|
+
const report = await verifyTrustAnchor({
|
|
215
|
+
origin: args.origin,
|
|
216
|
+
address: args.address,
|
|
217
|
+
pinnedPublicKeysBase64: args.pinnedKeys,
|
|
218
|
+
minaGraphqlUrl: args.minaGraphql ?? DEFAULT_GRAPHQL[args.minaNetworkId],
|
|
219
|
+
minaNetworkId: args.minaNetworkId,
|
|
220
|
+
skipChainChecks: args.skipChainChecks,
|
|
221
|
+
crossCheck: args.crossCheck,
|
|
222
|
+
});
|
|
223
|
+
if (args.json) {
|
|
224
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
process.stdout.write(`${formatHuman(report)}\n`);
|
|
228
|
+
}
|
|
229
|
+
return report.ok ? 0 : 1;
|
|
230
|
+
}
|
|
231
|
+
main().then((code) => process.exit(code), (err) => {
|
|
232
|
+
process.stderr.write(`unexpected error: ${err?.stack ?? err}\n`);
|
|
233
|
+
process.exit(1);
|
|
234
|
+
});
|
|
235
|
+
//# sourceMappingURL=trustAnchorVerifyCli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trustAnchorVerifyCli.js","sourceRoot":"","sources":["../src/trustAnchorVerifyCli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* txBroadcastClient.ts
|
|
3
|
+
*
|
|
4
|
+
* Small helper for POST /tx-broadcast. Called by the buy/renew/migrate
|
|
5
|
+
* flows immediately after the buyer's wallet returns a txHash — signals
|
|
6
|
+
* the backend to extend the app's in-flight slot from the short signing-TTL
|
|
7
|
+
* to the longer landing-TTL, so concurrent buyers on the same app don't
|
|
8
|
+
* think the slot has expired while an honest signed tx is still in the
|
|
9
|
+
* mempool.
|
|
10
|
+
*
|
|
11
|
+
* Fire-and-forget by design: this is a tightening signal, not a
|
|
12
|
+
* correctness dependency. Land-clear in the buy-watcher and the
|
|
13
|
+
* signing-TTL both remain live regardless of whether this call succeeds.
|
|
14
|
+
* Failures are swallowed with an optional log callback so a network blip
|
|
15
|
+
* doesn't surface as a confusing error mid-checkout.
|
|
16
|
+
*/
|
|
17
|
+
export type NotifyBroadcastRequest = {
|
|
18
|
+
keeperUrl: string;
|
|
19
|
+
appId: string;
|
|
20
|
+
txHash: string;
|
|
21
|
+
fetcher?: typeof fetch;
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
onError?: (err: unknown) => void;
|
|
24
|
+
};
|
|
25
|
+
export declare function notifyBroadcast(req: NotifyBroadcastRequest): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=txBroadcastClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txBroadcastClient.d.ts","sourceRoot":"","sources":["../src/txBroadcastClient.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAM,MAAM,CAAC;IAClB,MAAM,EAAK,MAAM,CAAC;IAClB,OAAO,CAAC,EAAG,OAAO,KAAK,CAAC;IACxB,MAAM,CAAC,EAAI,WAAW,CAAC;IAGvB,OAAO,CAAC,EAAG,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACnC,CAAC;AAMF,wBAAsB,eAAe,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright (c) 2025-2026 zkLicensing project developers
|
|
2
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
3
|
+
function baseUrl(url) {
|
|
4
|
+
return url.replace(/\/+$/, '');
|
|
5
|
+
}
|
|
6
|
+
export async function notifyBroadcast(req) {
|
|
7
|
+
const fetcher = req.fetcher ?? fetch;
|
|
8
|
+
try {
|
|
9
|
+
await fetcher(`${baseUrl(req.keeperUrl)}/tx-broadcast`, {
|
|
10
|
+
method: 'POST',
|
|
11
|
+
headers: { 'Content-Type': 'application/json' },
|
|
12
|
+
signal: req.signal,
|
|
13
|
+
body: JSON.stringify({ appId: req.appId, txHash: req.txHash }),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
req.onError?.(err);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=txBroadcastClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txBroadcastClient.js","sourceRoot":"","sources":["../src/txBroadcastClient.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,oCAAoC;AA8BpC,SAAS,OAAO,CAAC,GAAW;IAC1B,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAA2B;IAC/D,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,KAAK,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;SAC/D,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* unbindClient.ts
|
|
3
|
+
*
|
|
4
|
+
* Browser-safe client for the non-custodial device-unbinding flow.
|
|
5
|
+
* Mirrors `bindClient.ts` in shape: signs the unbind message with
|
|
6
|
+
* TAG_UNBINDING, POSTs to /prove/unbind, then /confirm/unbind after
|
|
7
|
+
* the wallet returns a txHash.
|
|
8
|
+
*
|
|
9
|
+
* Notable asymmetry with bind: the unbind message shape carries the
|
|
10
|
+
* deviceCommitment position too, but the backend and circuit both
|
|
11
|
+
* hard-code it to `Field(0)` (the "not about any specific new
|
|
12
|
+
* device" sentinel — the message is about freeing a slot, not
|
|
13
|
+
* introducing a new device). The SDK matches by omitting
|
|
14
|
+
* deviceCommitment from the request and using "0" when computing
|
|
15
|
+
* the signature preimage.
|
|
16
|
+
*
|
|
17
|
+
* Non-custodial invariant: the signature is re-verified in-circuit
|
|
18
|
+
* against the leaf's `licenseHash` (which IS the owner-pubkey
|
|
19
|
+
* commitment — the circuit asserts equality at buy time), so no
|
|
20
|
+
* backend / vendor can unilaterally kick a device — only the
|
|
21
|
+
* passphrase holder can.
|
|
22
|
+
* A user who lost the physical device but still has the passphrase
|
|
23
|
+
* can unbind the missing device's slot from any device that holds
|
|
24
|
+
* the ownership key (the "remote log-off" case).
|
|
25
|
+
*/
|
|
26
|
+
import { PrivateKey } from 'o1js';
|
|
27
|
+
export type ProveUnbindRequest = {
|
|
28
|
+
keeperUrl: string;
|
|
29
|
+
network: 'devnet' | 'mainnet';
|
|
30
|
+
zkAppAddress: string;
|
|
31
|
+
licenseHash: string;
|
|
32
|
+
ownerPrivateKey: PrivateKey;
|
|
33
|
+
slotIndex: number;
|
|
34
|
+
buyerAddress: string;
|
|
35
|
+
nonce?: string;
|
|
36
|
+
slotState?: string;
|
|
37
|
+
expirySlot?: number;
|
|
38
|
+
fetcher?: typeof fetch;
|
|
39
|
+
signal?: AbortSignal;
|
|
40
|
+
};
|
|
41
|
+
export type ProveUnbindResponse = {
|
|
42
|
+
provenTxJson: string;
|
|
43
|
+
licenseHash: string;
|
|
44
|
+
slotIndex: number;
|
|
45
|
+
};
|
|
46
|
+
export type ConfirmUnbindRequest = {
|
|
47
|
+
keeperUrl: string;
|
|
48
|
+
zkAppAddress: string;
|
|
49
|
+
licenseHash: string;
|
|
50
|
+
txHash: string;
|
|
51
|
+
fetcher?: typeof fetch;
|
|
52
|
+
signal?: AbortSignal;
|
|
53
|
+
};
|
|
54
|
+
export declare function proveUnbind(req: ProveUnbindRequest): Promise<ProveUnbindResponse>;
|
|
55
|
+
export declare function confirmUnbind(req: ConfirmUnbindRequest): Promise<{
|
|
56
|
+
ok: true;
|
|
57
|
+
}>;
|
|
58
|
+
export type UnbindStatus = {
|
|
59
|
+
status: 'confirmed' | 'pending' | 'unknown';
|
|
60
|
+
slotIndex?: number;
|
|
61
|
+
deviceCommitment?: string;
|
|
62
|
+
elapsedMs?: number;
|
|
63
|
+
};
|
|
64
|
+
export type PollUnbindStatusOptions = {
|
|
65
|
+
keeperUrl: string;
|
|
66
|
+
network: 'devnet' | 'mainnet';
|
|
67
|
+
zkAppAddress: string;
|
|
68
|
+
licenseHash: string;
|
|
69
|
+
slotIndex: number;
|
|
70
|
+
fetcher?: typeof fetch;
|
|
71
|
+
intervalMs?: number;
|
|
72
|
+
timeoutMs?: number;
|
|
73
|
+
signal?: AbortSignal;
|
|
74
|
+
onTick?: (status: UnbindStatus) => void;
|
|
75
|
+
};
|
|
76
|
+
export declare function pollUnbindStatus(opts: PollUnbindStatusOptions): Promise<UnbindStatus>;
|
|
77
|
+
//# sourceMappingURL=unbindClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unbindClient.d.ts","sourceRoot":"","sources":["../src/unbindClient.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAS,UAAU,EAAwB,MAAM,MAAM,CAAC;AAK/D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAQ,MAAM,CAAC;IACxB,OAAO,EAAU,QAAQ,GAAG,SAAS,CAAC;IACtC,YAAY,EAAK,MAAM,CAAC;IACxB,WAAW,EAAM,MAAM,CAAC;IACxB,eAAe,EAAE,UAAU,CAAC;IAE5B,SAAS,EAAQ,MAAM,CAAC;IACxB,YAAY,EAAK,MAAM,CAAC;IAGxB,KAAK,CAAC,EAAW,MAAM,CAAC;IAGxB,SAAS,CAAC,EAAO,MAAM,CAAC;IACxB,UAAU,CAAC,EAAM,MAAM,CAAC;IACxB,OAAO,CAAC,EAAS,OAAO,KAAK,CAAC;IAC9B,MAAM,CAAC,EAAU,WAAW,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAG,MAAM,CAAC;IACrB,SAAS,EAAK,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAK,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAG,MAAM,CAAC;IACrB,MAAM,EAAQ,MAAM,CAAC;IACrB,OAAO,CAAC,EAAM,OAAO,KAAK,CAAC;IAC3B,MAAM,CAAC,EAAO,WAAW,CAAC;CAC3B,CAAC;AAgCF,wBAAsB,WAAW,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA2CvF;AAGD,wBAAsB,aAAa,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CAAC,CAcpF;AAED,MAAM,MAAM,YAAY,GAAG;IAKzB,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;IAC5C,SAAS,CAAC,EAAS,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAS,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAK,MAAM,CAAC;IACrB,OAAO,EAAO,QAAQ,GAAG,SAAS,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAG,MAAM,CAAC;IACrB,SAAS,EAAK,MAAM,CAAC;IACrB,OAAO,CAAC,EAAM,OAAO,KAAK,CAAC;IAC3B,UAAU,CAAC,EAAG,MAAM,CAAC;IACrB,SAAS,CAAC,EAAI,MAAM,CAAC;IACrB,MAAM,CAAC,EAAO,WAAW,CAAC;IAC1B,MAAM,CAAC,EAAO,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;CAC9C,CAAC;AAKF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4C3F"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// Copyright (c) 2025-2026 zkLicensing project developers
|
|
2
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
3
|
+
/**
|
|
4
|
+
* unbindClient.ts
|
|
5
|
+
*
|
|
6
|
+
* Browser-safe client for the non-custodial device-unbinding flow.
|
|
7
|
+
* Mirrors `bindClient.ts` in shape: signs the unbind message with
|
|
8
|
+
* TAG_UNBINDING, POSTs to /prove/unbind, then /confirm/unbind after
|
|
9
|
+
* the wallet returns a txHash.
|
|
10
|
+
*
|
|
11
|
+
* Notable asymmetry with bind: the unbind message shape carries the
|
|
12
|
+
* deviceCommitment position too, but the backend and circuit both
|
|
13
|
+
* hard-code it to `Field(0)` (the "not about any specific new
|
|
14
|
+
* device" sentinel — the message is about freeing a slot, not
|
|
15
|
+
* introducing a new device). The SDK matches by omitting
|
|
16
|
+
* deviceCommitment from the request and using "0" when computing
|
|
17
|
+
* the signature preimage.
|
|
18
|
+
*
|
|
19
|
+
* Non-custodial invariant: the signature is re-verified in-circuit
|
|
20
|
+
* against the leaf's `licenseHash` (which IS the owner-pubkey
|
|
21
|
+
* commitment — the circuit asserts equality at buy time), so no
|
|
22
|
+
* backend / vendor can unilaterally kick a device — only the
|
|
23
|
+
* passphrase holder can.
|
|
24
|
+
* A user who lost the physical device but still has the passphrase
|
|
25
|
+
* can unbind the missing device's slot from any device that holds
|
|
26
|
+
* the ownership key (the "remote log-off" case).
|
|
27
|
+
*/
|
|
28
|
+
import { Field } from 'o1js';
|
|
29
|
+
import { readErrorBody, tryQueueBusyFromBody, keeperError } from './proveErrors.js';
|
|
30
|
+
import { encodePublicKey, encodeSignature, signUnbinding } from './ownershipSignature.js';
|
|
31
|
+
import { fetchBindingState } from './bindClient.js';
|
|
32
|
+
function baseUrl(url) {
|
|
33
|
+
return url.replace(/\/+$/, '');
|
|
34
|
+
}
|
|
35
|
+
async function readJsonError(resp) {
|
|
36
|
+
try {
|
|
37
|
+
const body = await resp.json();
|
|
38
|
+
if (typeof body.error === 'string')
|
|
39
|
+
return body.error;
|
|
40
|
+
}
|
|
41
|
+
catch { /* body wasn't JSON */ }
|
|
42
|
+
return `HTTP ${resp.status}`;
|
|
43
|
+
}
|
|
44
|
+
function freshNonce() {
|
|
45
|
+
const crypto = globalThis.crypto;
|
|
46
|
+
if (!crypto?.getRandomValues) {
|
|
47
|
+
throw new Error('crypto.getRandomValues unavailable — unbindClient requires Node ≥ 20 or a modern browser');
|
|
48
|
+
}
|
|
49
|
+
const bytes = new Uint8Array(16); // 128 bits
|
|
50
|
+
crypto.getRandomValues(bytes);
|
|
51
|
+
let n = 0n;
|
|
52
|
+
for (const b of bytes)
|
|
53
|
+
n = (n << 8n) | BigInt(b);
|
|
54
|
+
return Field(n).toString();
|
|
55
|
+
}
|
|
56
|
+
// POST /prove/unbind — same retry contract as /prove/bind. Returns
|
|
57
|
+
// 409 `ProveQueueBusyError` when another root-mutating tx for the
|
|
58
|
+
// same app is in flight; the caller retries with the server-supplied
|
|
59
|
+
// `retryAfterMs` cadence.
|
|
60
|
+
export async function proveUnbind(req) {
|
|
61
|
+
const fetcher = req.fetcher ?? fetch;
|
|
62
|
+
const nonce = req.nonce ?? freshNonce();
|
|
63
|
+
const { slotState, expirySlot } = (req.slotState !== undefined && req.expirySlot !== undefined)
|
|
64
|
+
? { slotState: req.slotState, expirySlot: req.expirySlot }
|
|
65
|
+
: await fetchBindingState({ ...req, fetcher });
|
|
66
|
+
const ownerPubKey = req.ownerPrivateKey.toPublicKey();
|
|
67
|
+
// deviceCommitment=0 for the preimage — matches TAG_UNBINDING's
|
|
68
|
+
// circuit-side check (see verifyUnbinding / bindingLikeFields in
|
|
69
|
+
// ownershipSignature.ts).
|
|
70
|
+
const ownerSig = signUnbinding(req.ownerPrivateKey, {
|
|
71
|
+
licenseHash: req.licenseHash,
|
|
72
|
+
deviceCommitment: '0',
|
|
73
|
+
slotIndex: req.slotIndex,
|
|
74
|
+
nonce,
|
|
75
|
+
slotState,
|
|
76
|
+
expirySlot,
|
|
77
|
+
zkAppAddress: req.zkAppAddress,
|
|
78
|
+
});
|
|
79
|
+
const resp = await fetcher(`${baseUrl(req.keeperUrl)}/prove/unbind`, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: { 'Content-Type': 'application/json' },
|
|
82
|
+
signal: req.signal,
|
|
83
|
+
body: JSON.stringify({
|
|
84
|
+
licenseHash: req.licenseHash,
|
|
85
|
+
buyerAddress: req.buyerAddress,
|
|
86
|
+
zkAppAddress: req.zkAppAddress,
|
|
87
|
+
network: req.network,
|
|
88
|
+
ownerPubKey: encodePublicKey(ownerPubKey),
|
|
89
|
+
ownerSig: encodeSignature(ownerSig),
|
|
90
|
+
slotIndex: req.slotIndex,
|
|
91
|
+
nonce,
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
if (!resp.ok) {
|
|
95
|
+
const parsed = await readErrorBody(resp);
|
|
96
|
+
const queueBusy = tryQueueBusyFromBody(parsed);
|
|
97
|
+
if (queueBusy)
|
|
98
|
+
throw queueBusy;
|
|
99
|
+
throw keeperError(parsed);
|
|
100
|
+
}
|
|
101
|
+
return await resp.json();
|
|
102
|
+
}
|
|
103
|
+
// POST /confirm/unbind — pass-through no-op mirror of /confirm/bind.
|
|
104
|
+
export async function confirmUnbind(req) {
|
|
105
|
+
const fetcher = req.fetcher ?? fetch;
|
|
106
|
+
const resp = await fetcher(`${baseUrl(req.keeperUrl)}/confirm/unbind`, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: { 'Content-Type': 'application/json' },
|
|
109
|
+
signal: req.signal,
|
|
110
|
+
body: JSON.stringify({
|
|
111
|
+
zkAppAddress: req.zkAppAddress,
|
|
112
|
+
licenseHash: req.licenseHash,
|
|
113
|
+
txHash: req.txHash,
|
|
114
|
+
}),
|
|
115
|
+
});
|
|
116
|
+
if (!resp.ok)
|
|
117
|
+
throw new Error(await readJsonError(resp));
|
|
118
|
+
return { ok: true };
|
|
119
|
+
}
|
|
120
|
+
// Polls GET /license/:zkAppAddress/:licenseHash until the unbind has
|
|
121
|
+
// landed on-chain (the target slot's commitment is '0') or the timeout
|
|
122
|
+
// fires. Mirrors pollBindStatus in shape.
|
|
123
|
+
export async function pollUnbindStatus(opts) {
|
|
124
|
+
const fetcher = opts.fetcher ?? fetch;
|
|
125
|
+
const interval = opts.intervalMs ?? 10_000;
|
|
126
|
+
const timeout = opts.timeoutMs ?? 20 * 60 * 1000;
|
|
127
|
+
const startedAt = Date.now();
|
|
128
|
+
const deadline = startedAt + timeout;
|
|
129
|
+
const url = `${baseUrl(opts.keeperUrl)}/license/${encodeURIComponent(opts.zkAppAddress)}/${encodeURIComponent(opts.licenseHash)}?network=${opts.network}`;
|
|
130
|
+
while (true) {
|
|
131
|
+
if (opts.signal?.aborted)
|
|
132
|
+
throw new Error('pollUnbindStatus aborted');
|
|
133
|
+
let status = { status: 'unknown', elapsedMs: Date.now() - startedAt };
|
|
134
|
+
try {
|
|
135
|
+
const resp = await fetcher(url, { signal: opts.signal });
|
|
136
|
+
if (resp.ok) {
|
|
137
|
+
const body = await resp.json();
|
|
138
|
+
if (body.found) {
|
|
139
|
+
const slot = (body.devices ?? []).find(d => d.slotIndex === opts.slotIndex);
|
|
140
|
+
const commitment = slot?.deviceCommitment ?? '0';
|
|
141
|
+
if (commitment === '0') {
|
|
142
|
+
status = {
|
|
143
|
+
status: 'confirmed',
|
|
144
|
+
slotIndex: opts.slotIndex,
|
|
145
|
+
deviceCommitment: commitment,
|
|
146
|
+
elapsedMs: Date.now() - startedAt,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
status = {
|
|
151
|
+
status: 'pending',
|
|
152
|
+
slotIndex: opts.slotIndex,
|
|
153
|
+
deviceCommitment: commitment,
|
|
154
|
+
elapsedMs: Date.now() - startedAt,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch { /* transient network — try again on next tick */ }
|
|
161
|
+
opts.onTick?.(status);
|
|
162
|
+
if (status.status === 'confirmed')
|
|
163
|
+
return status;
|
|
164
|
+
if (Date.now() >= deadline)
|
|
165
|
+
return status;
|
|
166
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=unbindClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unbindClient.js","sourceRoot":"","sources":["../src/unbindClient.ts"],"names":[],"mappings":"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"}
|
package/build/units.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type MinaUnit = 'MINA' | 'tMINA';
|
|
2
|
+
/** 'tMINA' on devnet (and any test network), 'MINA' on mainnet. */
|
|
3
|
+
export declare function minaUnit(network: string): MinaUnit;
|
|
4
|
+
/** "12.5 tMINA" / "12.5 MINA" for an amount in MINA (number or decimal string). */
|
|
5
|
+
export declare function formatMina(amountMina: number | string, network: string): string;
|
|
6
|
+
/** "12.5 tMINA" for an amount in nanomina. */
|
|
7
|
+
export declare function formatNanomina(nano: bigint | string | number, network: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* The words that go with a fiat value. Mainnet: "≈ €2.10". Devnet: the same
|
|
10
|
+
* amount of real MINA, said as such ("as MINA ≈ €2.10"), plus a note that
|
|
11
|
+
* tMINA itself has no value.
|
|
12
|
+
*/
|
|
13
|
+
export declare function fiatReference(network: string): {
|
|
14
|
+
prefix: string;
|
|
15
|
+
note: string | null;
|
|
16
|
+
};
|
|
17
|
+
export type FiatCurrency = 'eur' | 'usd' | 'gbp';
|
|
18
|
+
/**
|
|
19
|
+
* Which money a person sees amounts in, by their country: euros in the EU,
|
|
20
|
+
* pounds and euros in the UK, dollars in the US, euros and dollars elsewhere
|
|
21
|
+
* (or when the country is unknown).
|
|
22
|
+
*/
|
|
23
|
+
export declare function fiatCurrencies(country?: string | null): FiatCurrency[];
|
|
24
|
+
/** "€2.10", "-€26.78" for an amount of money. */
|
|
25
|
+
export declare function formatFiat(amount: number | string, currency: FiatCurrency, digits?: number): string;
|
|
26
|
+
/** "€2.10 · $2.30" for the given currencies (a currency without a rate is left out). */
|
|
27
|
+
export declare function formatFiatList(values: Partial<Record<FiatCurrency, number | string>>, currencies: FiatCurrency[], digits?: number): string;
|
|
28
|
+
//# sourceMappingURL=units.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"units.d.ts","sourceRoot":"","sources":["../src/units.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAExC,mEAAmE;AACnE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAElD;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/E;AAED,8CAA8C;AAC9C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMtF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAItF;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAGjD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,EAAE,CAMtE;AAED,iDAAiD;AACjD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAI,GAAG,MAAM,CAG9F;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,MAAM,SAAI,GAAG,MAAM,CAGrI"}
|