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.
Files changed (317) hide show
  1. package/README.md +417 -201
  2. package/build/agent.d.ts +371 -0
  3. package/build/agent.d.ts.map +1 -0
  4. package/build/agent.js +553 -0
  5. package/build/agent.js.map +1 -0
  6. package/build/agentActions.d.ts +841 -0
  7. package/build/agentActions.d.ts.map +1 -0
  8. package/build/agentActions.js +581 -0
  9. package/build/agentActions.js.map +1 -0
  10. package/build/agentRecord.d.ts +83 -0
  11. package/build/agentRecord.d.ts.map +1 -0
  12. package/build/agentRecord.js +69 -0
  13. package/build/agentRecord.js.map +1 -0
  14. package/build/agentVendor.d.ts +220 -0
  15. package/build/agentVendor.d.ts.map +1 -0
  16. package/build/agentVendor.js +306 -0
  17. package/build/agentVendor.js.map +1 -0
  18. package/build/appsLookup.d.ts +14 -0
  19. package/build/appsLookup.d.ts.map +1 -0
  20. package/build/appsLookup.js +12 -0
  21. package/build/appsLookup.js.map +1 -0
  22. package/build/archiveBootstrap.d.ts +31 -5
  23. package/build/archiveBootstrap.d.ts.map +1 -0
  24. package/build/archiveBootstrap.js +140 -47
  25. package/build/archiveBootstrap.js.map +1 -0
  26. package/build/atomicJson.d.ts +5 -0
  27. package/build/atomicJson.d.ts.map +1 -0
  28. package/build/atomicJson.js +55 -0
  29. package/build/atomicJson.js.map +1 -0
  30. package/build/bindClient.d.ts +85 -0
  31. package/build/bindClient.d.ts.map +1 -0
  32. package/build/bindClient.js +187 -0
  33. package/build/bindClient.js.map +1 -0
  34. package/build/buyClient.d.ts +27 -4
  35. package/build/buyClient.d.ts.map +1 -0
  36. package/build/buyClient.js +72 -26
  37. package/build/buyClient.js.map +1 -0
  38. package/build/chainHead.d.ts +61 -0
  39. package/build/chainHead.d.ts.map +1 -0
  40. package/build/chainHead.js +88 -0
  41. package/build/chainHead.js.map +1 -0
  42. package/build/compactMerkleMap.d.ts +72 -0
  43. package/build/compactMerkleMap.d.ts.map +1 -0
  44. package/build/compactMerkleMap.js +224 -0
  45. package/build/compactMerkleMap.js.map +1 -0
  46. package/build/contractInterface.d.ts +191 -51
  47. package/build/contractInterface.d.ts.map +1 -0
  48. package/build/contractInterface.js +234 -43
  49. package/build/contractInterface.js.map +1 -0
  50. package/build/contractTypes.d.ts +9 -0
  51. package/build/contractTypes.d.ts.map +1 -0
  52. package/build/contractTypes.js +28 -0
  53. package/build/contractTypes.js.map +1 -0
  54. package/build/countryStats.d.ts +12 -3
  55. package/build/countryStats.d.ts.map +1 -0
  56. package/build/countryStats.js +87 -23
  57. package/build/countryStats.js.map +1 -0
  58. package/build/deployClient.d.ts +138 -24
  59. package/build/deployClient.d.ts.map +1 -0
  60. package/build/deployClient.js +91 -31
  61. package/build/deployClient.js.map +1 -0
  62. package/build/deviceIdentity.d.ts +68 -0
  63. package/build/deviceIdentity.d.ts.map +1 -0
  64. package/build/deviceIdentity.js +209 -0
  65. package/build/deviceIdentity.js.map +1 -0
  66. package/build/freezeClient.d.ts +26 -6
  67. package/build/freezeClient.d.ts.map +1 -0
  68. package/build/freezeClient.js +30 -6
  69. package/build/freezeClient.js.map +1 -0
  70. package/build/generationClient.d.ts +6 -3
  71. package/build/generationClient.d.ts.map +1 -0
  72. package/build/generationClient.js +25 -38
  73. package/build/generationClient.js.map +1 -0
  74. package/build/holderSecret.d.ts +70 -0
  75. package/build/holderSecret.d.ts.map +1 -0
  76. package/build/holderSecret.js +76 -0
  77. package/build/holderSecret.js.map +1 -0
  78. package/build/index.d.ts +38 -38
  79. package/build/index.d.ts.map +1 -0
  80. package/build/index.js +97 -121
  81. package/build/index.js.map +1 -0
  82. package/build/keysClient.d.ts +142 -0
  83. package/build/keysClient.d.ts.map +1 -0
  84. package/build/keysClient.js +109 -0
  85. package/build/keysClient.js.map +1 -0
  86. package/build/licenseLeaf.d.ts +76 -0
  87. package/build/licenseLeaf.d.ts.map +1 -0
  88. package/build/licenseLeaf.js +189 -0
  89. package/build/licenseLeaf.js.map +1 -0
  90. package/build/licenseRecord.d.ts +68 -5
  91. package/build/licenseRecord.d.ts.map +1 -0
  92. package/build/licenseRecord.js +26 -1
  93. package/build/licenseRecord.js.map +1 -0
  94. package/build/licenseStore.d.ts +81 -4
  95. package/build/licenseStore.d.ts.map +1 -0
  96. package/build/licenseStore.js +400 -30
  97. package/build/licenseStore.js.map +1 -0
  98. package/build/licenseTrustless.d.ts +43 -0
  99. package/build/licenseTrustless.d.ts.map +1 -0
  100. package/build/licenseTrustless.js +180 -0
  101. package/build/licenseTrustless.js.map +1 -0
  102. package/build/manifestVerify.d.ts +29 -1
  103. package/build/manifestVerify.d.ts.map +1 -0
  104. package/build/manifestVerify.js +46 -4
  105. package/build/manifestVerify.js.map +1 -0
  106. package/build/minaPriceHistory.d.ts +9 -0
  107. package/build/minaPriceHistory.d.ts.map +1 -0
  108. package/build/minaPriceHistory.js +152 -0
  109. package/build/minaPriceHistory.js.map +1 -0
  110. package/build/onChainRoot.d.ts +60 -0
  111. package/build/onChainRoot.d.ts.map +1 -0
  112. package/build/onChainRoot.js +74 -0
  113. package/build/onChainRoot.js.map +1 -0
  114. package/build/ownershipLicenseHash.d.ts +25 -0
  115. package/build/ownershipLicenseHash.d.ts.map +1 -0
  116. package/build/ownershipLicenseHash.js +29 -0
  117. package/build/ownershipLicenseHash.js.map +1 -0
  118. package/build/ownershipSignature.d.ts +153 -0
  119. package/build/ownershipSignature.d.ts.map +1 -0
  120. package/build/ownershipSignature.js +297 -0
  121. package/build/ownershipSignature.js.map +1 -0
  122. package/build/permitCheckFlow.d.ts +155 -0
  123. package/build/permitCheckFlow.d.ts.map +1 -0
  124. package/build/permitCheckFlow.js +196 -0
  125. package/build/permitCheckFlow.js.map +1 -0
  126. package/build/permitDescribe.d.ts +124 -0
  127. package/build/permitDescribe.d.ts.map +1 -0
  128. package/build/permitDescribe.js +324 -0
  129. package/build/permitDescribe.js.map +1 -0
  130. package/build/permitInterface.d.ts +85 -0
  131. package/build/permitInterface.d.ts.map +1 -0
  132. package/build/permitInterface.js +121 -0
  133. package/build/permitInterface.js.map +1 -0
  134. package/build/permitMessages.d.ts +313 -0
  135. package/build/permitMessages.d.ts.map +1 -0
  136. package/build/permitMessages.js +462 -0
  137. package/build/permitMessages.js.map +1 -0
  138. package/build/permitProof.d.ts +108 -0
  139. package/build/permitProof.d.ts.map +1 -0
  140. package/build/permitProof.js +202 -0
  141. package/build/permitProof.js.map +1 -0
  142. package/build/permitRegistryRebuild.d.ts +166 -0
  143. package/build/permitRegistryRebuild.d.ts.map +1 -0
  144. package/build/permitRegistryRebuild.js +347 -0
  145. package/build/permitRegistryRebuild.js.map +1 -0
  146. package/build/permitTree.d.ts +88 -0
  147. package/build/permitTree.d.ts.map +1 -0
  148. package/build/permitTree.js +230 -0
  149. package/build/permitTree.js.map +1 -0
  150. package/build/permitsClient.d.ts +680 -0
  151. package/build/permitsClient.d.ts.map +1 -0
  152. package/build/permitsClient.js +597 -0
  153. package/build/permitsClient.js.map +1 -0
  154. package/build/proveErrors.d.ts +50 -0
  155. package/build/proveErrors.d.ts.map +1 -0
  156. package/build/proveErrors.js +76 -0
  157. package/build/proveErrors.js.map +1 -0
  158. package/build/receipt.d.ts +95 -0
  159. package/build/receipt.d.ts.map +1 -0
  160. package/build/receipt.js +84 -0
  161. package/build/receipt.js.map +1 -0
  162. package/build/refundClient.d.ts +7 -12
  163. package/build/refundClient.d.ts.map +1 -0
  164. package/build/refundClient.js +52 -21
  165. package/build/refundClient.js.map +1 -0
  166. package/build/registryTrustVerify.d.ts +78 -0
  167. package/build/registryTrustVerify.d.ts.map +1 -0
  168. package/build/registryTrustVerify.js +129 -0
  169. package/build/registryTrustVerify.js.map +1 -0
  170. package/build/releaseClient.d.ts +26 -0
  171. package/build/releaseClient.d.ts.map +1 -0
  172. package/build/releaseClient.js +65 -0
  173. package/build/releaseClient.js.map +1 -0
  174. package/build/renewClient.d.ts +28 -2
  175. package/build/renewClient.d.ts.map +1 -0
  176. package/build/renewClient.js +31 -27
  177. package/build/renewClient.js.map +1 -0
  178. package/build/seatName.d.ts +8 -0
  179. package/build/seatName.d.ts.map +1 -0
  180. package/build/seatName.js +136 -0
  181. package/build/seatName.js.map +1 -0
  182. package/build/slotConstants.d.ts +15 -0
  183. package/build/slotConstants.d.ts.map +1 -0
  184. package/build/slotConstants.js +17 -0
  185. package/build/slotConstants.js.map +1 -0
  186. package/build/statsClient.d.ts +61 -7
  187. package/build/statsClient.d.ts.map +1 -0
  188. package/build/statsClient.js +44 -5
  189. package/build/statsClient.js.map +1 -0
  190. package/build/successorChain.d.ts +35 -0
  191. package/build/successorChain.d.ts.map +1 -0
  192. package/build/successorChain.js +69 -0
  193. package/build/successorChain.js.map +1 -0
  194. package/build/taxId.d.ts +44 -0
  195. package/build/taxId.d.ts.map +1 -0
  196. package/build/taxId.js +212 -0
  197. package/build/taxId.js.map +1 -0
  198. package/build/trustAnchorVerify.d.ts +49 -0
  199. package/build/trustAnchorVerify.d.ts.map +1 -0
  200. package/build/trustAnchorVerify.js +432 -0
  201. package/build/trustAnchorVerify.js.map +1 -0
  202. package/build/trustAnchorVerifyCli.d.ts +45 -0
  203. package/build/trustAnchorVerifyCli.d.ts.map +1 -0
  204. package/build/trustAnchorVerifyCli.js +235 -0
  205. package/build/trustAnchorVerifyCli.js.map +1 -0
  206. package/build/txBroadcastClient.d.ts +26 -0
  207. package/build/txBroadcastClient.d.ts.map +1 -0
  208. package/build/txBroadcastClient.js +20 -0
  209. package/build/txBroadcastClient.js.map +1 -0
  210. package/build/unbindClient.d.ts +77 -0
  211. package/build/unbindClient.d.ts.map +1 -0
  212. package/build/unbindClient.js +169 -0
  213. package/build/unbindClient.js.map +1 -0
  214. package/build/units.d.ts +28 -0
  215. package/build/units.d.ts.map +1 -0
  216. package/build/units.js +65 -0
  217. package/build/units.js.map +1 -0
  218. package/build/vatRates.d.ts +54 -0
  219. package/build/vatRates.d.ts.map +1 -0
  220. package/build/vatRates.js +82 -0
  221. package/build/vatRates.js.map +1 -0
  222. package/build/vatRatesData.d.ts +5 -0
  223. package/build/vatRatesData.d.ts.map +1 -0
  224. package/build/vatRatesData.js +42 -0
  225. package/build/vatRatesData.js.map +1 -0
  226. package/build/vendorAccountClient.d.ts +66 -0
  227. package/build/vendorAccountClient.d.ts.map +1 -0
  228. package/build/vendorAccountClient.js +47 -0
  229. package/build/vendorAccountClient.js.map +1 -0
  230. package/build/verifyCore.d.ts +4 -1
  231. package/build/verifyCore.d.ts.map +1 -0
  232. package/build/verifyCore.js +21 -10
  233. package/build/verifyCore.js.map +1 -0
  234. package/build/verifyOffline.d.ts +85 -0
  235. package/build/verifyOffline.d.ts.map +1 -0
  236. package/build/verifyOffline.js +139 -0
  237. package/build/verifyOffline.js.map +1 -0
  238. package/build/verifyService.d.ts.map +1 -0
  239. package/build/verifyService.js +571 -501
  240. package/build/verifyService.js.map +1 -0
  241. package/build/verifyWithAncestors.d.ts +19 -0
  242. package/build/verifyWithAncestors.d.ts.map +1 -0
  243. package/build/verifyWithAncestors.js +127 -0
  244. package/build/verifyWithAncestors.js.map +1 -0
  245. package/build/zipToState.d.ts +2 -0
  246. package/build/zipToState.d.ts.map +1 -0
  247. package/build/zipToState.js +94 -0
  248. package/build/zipToState.js.map +1 -0
  249. package/package.json +141 -16
  250. package/src/agent.ts +682 -0
  251. package/src/agentActions.ts +637 -0
  252. package/src/agentRecord.ts +121 -0
  253. package/src/agentVendor.ts +356 -0
  254. package/src/appsLookup.ts +48 -0
  255. package/src/archiveBootstrap.ts +386 -0
  256. package/src/atomicJson.ts +53 -0
  257. package/src/bindClient.ts +297 -0
  258. package/src/buyClient.ts +344 -0
  259. package/src/chainHead.ts +106 -0
  260. package/src/compactMerkleMap.ts +222 -0
  261. package/src/contractInterface.ts +465 -0
  262. package/src/contractTypes.ts +31 -0
  263. package/src/countryStats.ts +200 -0
  264. package/src/deployClient.ts +517 -0
  265. package/src/deviceIdentity.ts +249 -0
  266. package/src/freezeClient.ts +162 -0
  267. package/src/generationClient.ts +145 -0
  268. package/src/holderSecret.ts +91 -0
  269. package/src/index.ts +362 -0
  270. package/src/keysClient.ts +135 -0
  271. package/src/licenseLeaf.ts +221 -0
  272. package/src/licenseRecord.ts +190 -0
  273. package/src/licenseStore.ts +767 -0
  274. package/src/licenseTrustless.ts +207 -0
  275. package/src/manifestVerify.ts +164 -0
  276. package/src/minaPriceHistory.ts +166 -0
  277. package/src/onChainRoot.ts +90 -0
  278. package/src/ownershipLicenseHash.ts +31 -0
  279. package/src/ownershipSignature.ts +421 -0
  280. package/src/permitCheckFlow.ts +227 -0
  281. package/src/permitDescribe.ts +362 -0
  282. package/src/permitInterface.ts +146 -0
  283. package/src/permitMessages.ts +572 -0
  284. package/src/permitProof.ts +230 -0
  285. package/src/permitRegistryRebuild.ts +423 -0
  286. package/src/permitTree.ts +232 -0
  287. package/src/permitsClient.ts +746 -0
  288. package/src/proveErrors.ts +98 -0
  289. package/src/receipt.ts +156 -0
  290. package/src/refundClient.ts +177 -0
  291. package/src/registryTrustVerify.ts +192 -0
  292. package/src/releaseClient.ts +101 -0
  293. package/src/renewClient.ts +234 -0
  294. package/src/seatName.ts +165 -0
  295. package/src/slotConstants.ts +18 -0
  296. package/src/statsClient.ts +249 -0
  297. package/src/successorChain.ts +87 -0
  298. package/src/taxId.ts +227 -0
  299. package/src/trustAnchorVerify.ts +550 -0
  300. package/src/trustAnchorVerifyCli.ts +234 -0
  301. package/src/txBroadcastClient.ts +48 -0
  302. package/src/unbindClient.ts +233 -0
  303. package/src/units.ts +74 -0
  304. package/src/vatRates.ts +100 -0
  305. package/src/vatRatesData.ts +43 -0
  306. package/src/vendorAccountClient.ts +120 -0
  307. package/src/verifyCore.ts +100 -0
  308. package/src/verifyOffline.ts +212 -0
  309. package/src/verifyService.ts +982 -0
  310. package/src/verifyWithAncestors.ts +163 -0
  311. package/src/zipToState.ts +94 -0
  312. package/build/licenseProof.d.ts +0 -26
  313. package/build/licenseProof.js +0 -41
  314. package/build/migrateClient.d.ts +0 -43
  315. package/build/migrateClient.js +0 -47
  316. package/build/ownership.d.ts +0 -34
  317. package/build/ownership.js +0 -147
package/build/index.js CHANGED
@@ -1,54 +1,42 @@
1
1
  // Copyright (c) 2025-2026 zkLicensing project developers
2
- // All rights reserved.
2
+ // SPDX-License-Identifier: BUSL-1.1
3
3
  /**
4
4
  * verifyLicense — client SDK.
5
5
  *
6
- * Calls the keeper's GET /verify until the on-chain refund window for the
7
- * license has closed; from that point on returns from a local anchor and
8
- * never touches the network again. The refund-window decision is server-
9
- * side: the keeper returns `refundWindowClosed: boolean` on its /verify
10
- * response, computed from its own record of `purchaseSlot + REFUND_WINDOW_N`
11
- * against the on-chain `currentSlot`. The SDK gates anchor writes on that
12
- * boolean and never trusts a `purchaseSlot` supplied by the local proof
13
- * file, so a user who forges their proof metadata cannot force the offline
14
- * branch prematurely.
6
+ * Calls the licensing service's GET /verify until the on-chain refund
7
+ * window for the license has closed; from that point on returns from a
8
+ * local anchor and never touches the network again. The refund-window
9
+ * decision is server-side: the service returns `refundWindowClosed:
10
+ * boolean` on its /verify response, computed from its own record of
11
+ * `purchaseSlot + REFUND_WINDOW_N` against the on-chain `currentSlot`.
12
+ * The SDK gates anchor writes on that boolean and never trusts a
13
+ * `purchaseSlot` supplied by the local license file, so a user who forges
14
+ * their proof metadata cannot force the offline branch prematurely.
15
15
  *
16
16
  * Anchor purity: every field persisted in the Anchor derives from the
17
- * keeper's /verify response — `anchoredSlot`, `expirySlot`, `ownership`.
18
- * The only client-supplied input to the offline branch is
19
- * `proof.expirySlot`, used solely as the loadAnchor binding key. A
20
- * tampered proof file therefore never gets a wrong answer; it gets no
21
- * offline branch at all and falls through to the keeper on every call.
17
+ * service's /verify response — `anchoredSlot`, `expirySlot`. The only
18
+ * client-supplied input to the offline branch is `proof.expirySlot`,
19
+ * used solely as the loadAnchor binding key. A tampered license file
20
+ * therefore never gets a wrong answer; it gets no offline branch at all
21
+ * and falls through to the licensing service on every call.
22
22
  */
23
- import { REFUND_WINDOW_N, GRACE_PERIOD_N, MS_PER_SLOT_N, SLOTS_PER_DAY_N, } from './contractInterface.js';
23
+ import { REFUND_WINDOW_N, GRACE_PERIOD_N, MS_PER_SLOT_N, SLOTS_PER_DAY_N, } from './slotConstants.js';
24
24
  const MS_PER_SLOT = MS_PER_SLOT_N;
25
25
  const SLOTS_PER_DAY = SLOTS_PER_DAY_N;
26
+ // The one and only verify endpoint. Every issued license routes here
27
+ // regardless of network — the platform verifier resolves devnet vs
28
+ // mainnet from the zkAppAddress (each deployment is unique per network).
29
+ // Tests inject a mock via VerifyOptions.fetcher, not by rewriting this URL.
30
+ export const DEFAULT_VERIFIER_URL = 'https://zklicensing.com/api/verify';
31
+ // Anchor records are keyed by (zkAppAddress, licenseHash). zkAppAddress
32
+ // is generation-scoped by construction: each redeploy puts the
33
+ // LicensingApp at a fresh address (see backend's finalizeRedeploy and
34
+ // AppRecord.deploymentHistory[]), so keying on it implicitly captures
35
+ // generation. An anchor for a retired address is orphaned once the license
36
+ // file names the successor, and re-created cleanly on its next verify.
26
37
  const ANCHOR_KEY_PREFIX = 'zklic_anchor_';
27
- const ACTIVATION_KEY_PREFIX = 'zklic_activation_';
28
- function activationKey(zkAppAddress, licenseHash) {
29
- return `${ACTIVATION_KEY_PREFIX}${zkAppAddress}_${licenseHash}`;
30
- }
31
- export function loadActivation(storage, zkAppAddress, licenseHash, nowMs = Date.now()) {
32
- try {
33
- const raw = storage.getItem(activationKey(zkAppAddress, licenseHash));
34
- if (!raw)
35
- return null;
36
- const rec = JSON.parse(raw);
37
- if (nowMs > rec.expiresAt)
38
- return null;
39
- return rec;
40
- }
41
- catch {
42
- return null;
43
- }
44
- }
45
- export function saveActivation(storage, zkAppAddress, licenseHash, rec) {
46
- try {
47
- storage.setItem(activationKey(zkAppAddress, licenseHash), JSON.stringify(rec));
48
- }
49
- catch {
50
- /* quota / read-only — non-fatal */
51
- }
38
+ function anchorKey(zkAppAddress, licenseHash) {
39
+ return `${ANCHOR_KEY_PREFIX}${zkAppAddress}_${licenseHash}`;
52
40
  }
53
41
  function defaultStorage() {
54
42
  if (typeof globalThis !== 'undefined' && globalThis.localStorage) {
@@ -56,19 +44,20 @@ function defaultStorage() {
56
44
  }
57
45
  return null;
58
46
  }
59
- function loadAnchor(storage, licenseHash, expirySlot) {
47
+ function loadAnchor(storage, zkAppAddress, licenseHash, expirySlot) {
60
48
  try {
61
- const raw = storage.getItem(ANCHOR_KEY_PREFIX + licenseHash);
49
+ const raw = storage.getItem(anchorKey(zkAppAddress, licenseHash));
62
50
  if (!raw)
63
51
  return null;
64
52
  const a = JSON.parse(raw);
65
- // `a.expirySlot` is the KEEPER's value captured at anchor time; the
66
- // `expirySlot` argument is the LOCAL proof file's value. Match ⇒ local
67
- // file agrees with chain truth as of anchoring ⇒ offline is safe.
68
- // Mismatch has two honest meanings:
53
+ // `a.expirySlot` is the SERVICE's value captured at anchor time;
54
+ // the `expirySlot` argument is the LOCAL license file's value. Match
55
+ // ⇒ local file agrees with chain truth as of anchoring ⇒ offline is
56
+ // safe. Mismatch has two honest meanings:
69
57
  // - renewal: chain moved, local file updated ⇒ re-anchor via chain check
70
- // - forgery: local file edited ⇒ every call falls through to the keeper,
71
- // which reports truth. The forger gets no offline branch at all.
58
+ // - forgery: local file edited ⇒ every call falls through to the
59
+ // licensing service, which reports truth. The forger gets no
60
+ // offline branch at all.
72
61
  if (a.expirySlot !== expirySlot)
73
62
  return null;
74
63
  return a;
@@ -77,9 +66,9 @@ function loadAnchor(storage, licenseHash, expirySlot) {
77
66
  return null;
78
67
  }
79
68
  }
80
- function saveAnchor(storage, licenseHash, anchor) {
69
+ function saveAnchor(storage, zkAppAddress, licenseHash, anchor) {
81
70
  try {
82
- storage.setItem(ANCHOR_KEY_PREFIX + licenseHash, JSON.stringify(anchor));
71
+ storage.setItem(anchorKey(zkAppAddress, licenseHash), JSON.stringify(anchor));
83
72
  }
84
73
  catch {
85
74
  // Storage may be full or read-only; the offline path simply won't activate.
@@ -90,72 +79,38 @@ function computeRemainingDays(expirySlot, currentSlot) {
90
79
  return 0;
91
80
  return Math.floor((expirySlot - currentSlot) / SLOTS_PER_DAY);
92
81
  }
93
- // Renew the activation token when within this window of expiry. Picked so
94
- // that a daily verify call has many chances to refresh before the token dies.
95
- const TOKEN_RENEW_THRESHOLD_MS = 24 * 60 * 60 * 1000;
96
- async function tryActivate(storage, zkAppAddress, licenseHash, current, bootstrapSecretHash, prover, verifierUrl, fetcher, nowMs) {
97
- const secretHash = current?.secretHash ?? bootstrapSecretHash;
98
- if (!secretHash)
99
- return current;
100
- // Existing token still fresh — nothing to do.
101
- if (current?.token && current.expiresAt - nowMs > TOKEN_RENEW_THRESHOLD_MS)
102
- return current;
103
- try {
104
- const base = verifierUrl.replace(/\/+$/, '');
105
- const challengeResp = await fetcher(`${base}/challenge?licenseHash=${encodeURIComponent(licenseHash)}`);
106
- if (!challengeResp.ok)
107
- return current;
108
- const { nonce } = (await challengeResp.json());
109
- const proofJson = await prover({ licenseHash, nonce, secretHash });
110
- const respondResp = await fetcher(`${base}/respond`, {
111
- method: 'POST',
112
- headers: { 'Content-Type': 'application/json' },
113
- body: JSON.stringify({ zkAppAddress, proof: proofJson }),
114
- });
115
- if (!respondResp.ok)
116
- return current;
117
- const { token, expiresAt } = (await respondResp.json());
118
- const next = { token, expiresAt, secretHash };
119
- saveActivation(storage, zkAppAddress, licenseHash, next);
120
- return next;
121
- }
122
- catch {
123
- return current;
124
- }
125
- }
126
82
  function offlineCheck(anchor, nowMs) {
127
83
  const elapsedSlots = Math.max(0, Math.floor((nowMs - anchor.anchoredAtMs) / MS_PER_SLOT));
128
84
  const estCurrentSlot = anchor.anchoredSlot + elapsedSlots;
129
- const expired = estCurrentSlot > anchor.expirySlot + GRACE_PERIOD_N;
130
- const inGracePeriod = !expired && estCurrentSlot > anchor.expirySlot;
131
- const expiresAt = new Date(nowMs + (anchor.expirySlot - estCurrentSlot) * MS_PER_SLOT).toISOString();
85
+ const until = anchor.effectiveExpirySlot ?? anchor.expirySlot;
86
+ const expired = estCurrentSlot > until + GRACE_PERIOD_N;
87
+ const inGracePeriod = !expired && estCurrentSlot > until;
88
+ const expiresAt = new Date(nowMs + (until - estCurrentSlot) * MS_PER_SLOT).toISOString();
132
89
  return {
133
90
  valid: !expired,
134
91
  expirySlot: anchor.expirySlot,
135
92
  expiresAt,
136
93
  currentSlot: estCurrentSlot,
137
94
  inGracePeriod,
138
- remainingDays: computeRemainingDays(anchor.expirySlot, estCurrentSlot),
95
+ remainingDays: computeRemainingDays(until, estCurrentSlot),
139
96
  reason: expired
140
97
  ? 'License has expired'
141
98
  : inGracePeriod
142
99
  ? 'License is in grace period — renew to avoid interruption'
143
100
  : null,
144
101
  source: 'offline',
145
- ownership: anchor.ownership,
146
102
  };
147
103
  }
148
104
  export async function verifyLicense(proof, options = {}) {
149
105
  const storage = options.storage === null ? null : options.storage ?? defaultStorage();
150
106
  const fetcher = options.fetcher ?? (typeof fetch !== 'undefined' ? fetch : undefined);
151
107
  const nowFn = options.now ?? (() => Date.now());
152
- const verifierUrl = options.verifierUrl ?? proof.verifierUrl;
153
108
  if (storage) {
154
- const anchor = loadAnchor(storage, proof.licenseHash, proof.expirySlot);
109
+ const anchor = loadAnchor(storage, proof.zkAppAddress, proof.licenseHash, proof.expirySlot);
155
110
  if (anchor)
156
111
  return offlineCheck(anchor, nowFn());
157
112
  }
158
- if (!verifierUrl || !fetcher) {
113
+ if (!fetcher) {
159
114
  return {
160
115
  valid: false,
161
116
  expirySlot: proof.expirySlot,
@@ -163,24 +118,13 @@ export async function verifyLicense(proof, options = {}) {
163
118
  currentSlot: 0,
164
119
  inGracePeriod: false,
165
120
  remainingDays: 0,
166
- reason: 'No verifier URL or fetcher available; cannot verify',
121
+ reason: 'No fetch implementation available; cannot verify',
167
122
  source: 'chain',
168
- ownership: 'unverified',
169
123
  };
170
124
  }
171
- let activation = storage
172
- ? loadActivation(storage, proof.zkAppAddress, proof.licenseHash, nowFn())
173
- : null;
174
- if (storage && options.prover && (activation || options.secretHash)) {
175
- activation = await tryActivate(storage, proof.zkAppAddress, proof.licenseHash, activation, options.secretHash, options.prover, verifierUrl, fetcher, nowFn());
176
- }
177
- const tokenParam = activation?.token
178
- ? `&token=${encodeURIComponent(activation.token)}`
179
- : '';
180
- const url = `${verifierUrl.replace(/\/+$/, '')}` +
125
+ const url = `${DEFAULT_VERIFIER_URL}` +
181
126
  `?licenseHash=${encodeURIComponent(proof.licenseHash)}` +
182
- `&zkAppAddress=${encodeURIComponent(proof.zkAppAddress)}` +
183
- tokenParam;
127
+ `&zkAppAddress=${encodeURIComponent(proof.zkAppAddress)}`;
184
128
  let data;
185
129
  try {
186
130
  const resp = await fetcher(url);
@@ -194,7 +138,6 @@ export async function verifyLicense(proof, options = {}) {
194
138
  remainingDays: 0,
195
139
  reason: `Verification request failed (HTTP ${resp.status})`,
196
140
  source: 'chain',
197
- ownership: 'unverified',
198
141
  };
199
142
  }
200
143
  data = await resp.json();
@@ -209,13 +152,12 @@ export async function verifyLicense(proof, options = {}) {
209
152
  remainingDays: 0,
210
153
  reason: err?.message ?? 'Verification request errored',
211
154
  source: 'chain',
212
- ownership: 'unverified',
213
155
  };
214
156
  }
215
- // Keeper's authoritative expiry, or null if the response omits it. Only
216
- // the null-safe form may be written into the anchor; the chain-result
217
- // display value below falls back to the local proof file for user-facing
218
- // fields, which is safe (display only).
157
+ // Service's authoritative expiry, or null if the response omits it.
158
+ // Only the null-safe form may be written into the anchor; the
159
+ // chain-result display value below falls back to the local license file
160
+ // for user-facing fields, which is safe (display only).
219
161
  const respExpirySlotStrict = typeof data.expirySlot === 'number' ? data.expirySlot : null;
220
162
  const respExpirySlot = respExpirySlotStrict ?? proof.expirySlot;
221
163
  const respCurrentSlot = typeof data.currentSlot === 'number' ? data.currentSlot : 0;
@@ -230,24 +172,24 @@ export async function verifyLicense(proof, options = {}) {
230
172
  : computeRemainingDays(respExpirySlot, respCurrentSlot),
231
173
  reason: data.reason ?? null,
232
174
  source: 'chain',
233
- ownership: data.ownership === 'verified' ? 'verified' : 'unverified',
234
175
  };
235
- // Anchor gate uses the keeper's own refund-window decision. The keeper
236
- // knows the true purchaseSlot (stored in its LicenseRecord) and the true
237
- // currentSlot; the SDK never trusts a purchaseSlot or expirySlot supplied
238
- // by the local proof file, since that file is client-writable and could
239
- // be forged. If the keeper omits `expirySlot`, we fail-closed on the
240
- // offline path — no anchor written, subsequent calls stay online.
176
+ // Anchor gate uses the service's own refund-window decision. The
177
+ // service knows the true purchaseSlot (stored in its LicenseRecord)
178
+ // and the true currentSlot; the SDK never trusts a purchaseSlot or
179
+ // expirySlot supplied by the local license file, since that file is
180
+ // client-writable and could be forged. If the service omits
181
+ // `expirySlot`, we fail-closed on the offline path — no anchor
182
+ // written, subsequent calls stay online.
241
183
  if (storage &&
242
184
  result.valid &&
243
185
  data.refundWindowClosed === true &&
244
186
  typeof data.currentSlot === 'number' &&
245
187
  respExpirySlotStrict !== null) {
246
- saveAnchor(storage, proof.licenseHash, {
188
+ saveAnchor(storage, proof.zkAppAddress, proof.licenseHash, {
247
189
  anchoredSlot: data.currentSlot,
248
190
  anchoredAtMs: nowFn(),
249
191
  expirySlot: respExpirySlotStrict,
250
- ownership: result.ownership,
192
+ ...(typeof data.effectiveExpirySlot === 'number' ? { effectiveExpirySlot: data.effectiveExpirySlot } : {}),
251
193
  });
252
194
  }
253
195
  return result;
@@ -255,4 +197,38 @@ export async function verifyLicense(proof, options = {}) {
255
197
  // Re-exported so tests and downstream tooling can reference the same values
256
198
  // the SDK uses internally without re-deriving them.
257
199
  export { REFUND_WINDOW_N, GRACE_PERIOD_N, MS_PER_SLOT };
200
+ const bindClient = () => import('./bindClient.js');
201
+ const unbindClient = () => import('./unbindClient.js');
202
+ const deviceIdentityModule = () => import('./deviceIdentity.js');
203
+ export async function proveBind(...a) { return (await bindClient()).proveBind(...a); }
204
+ export async function confirmBind(...a) { return (await bindClient()).confirmBind(...a); }
205
+ export async function pollBindStatus(...a) { return (await bindClient()).pollBindStatus(...a); }
206
+ export async function fetchBindingState(...a) { return (await bindClient()).fetchBindingState(...a); }
207
+ export async function proveUnbind(...a) { return (await unbindClient()).proveUnbind(...a); }
208
+ export async function confirmUnbind(...a) { return (await unbindClient()).confirmUnbind(...a); }
209
+ export async function pollUnbindStatus(...a) { return (await unbindClient()).pollUnbindStatus(...a); }
210
+ export async function getOrCreateDeviceIdentity(...a) { return (await deviceIdentityModule()).getOrCreateDeviceIdentity(...a); }
211
+ // Non-custodial trust anchor for `verifyOffline`. Reads the live
212
+ // `licensesRoot` (zkapp.appState[0]) directly from Mina — pair it with
213
+ // `verifyOffline` when you do not want to trust the licensing service's
214
+ // reported root. Also available at the `zklicensing/on-chain-root`
215
+ // subpath. o1js is imported lazily so callers that skip this helper
216
+ // don't pay the o1js dep cost at load time.
217
+ export { fetchOnChainLicensesRoot, DEFAULT_MINA_GRAPHQL_URLS } from './onChainRoot.js';
218
+ // The receipt file a buyer downloads: `license-<appId>.json`. Look for it
219
+ // under this name in your app's data folder. Also available at the
220
+ // `zklicensing/record` subpath.
221
+ export { licenseFileName, platformFeeNano, vendorShareNano } from './licenseRecord.js';
222
+ // Human-readable seat names for the device-binding UI ("Silent Otter",
223
+ // "Curious Panda"). Deterministic in `licenseHash + slotIndex + boundAtSlot`,
224
+ // so every viewer of the same license computes the same name per slot
225
+ // without a naming sidecar. Also available at the `zklicensing/seat-name`
226
+ // subpath.
227
+ export { seatNameFor, SEAT_NAME_COMBINATIONS } from './seatName.js';
228
+ // Vendor-signed escrow release. The licensing service proves the release tx
229
+ // with the vendor's address as fee payer and returns unsigned tx JSON; the
230
+ // vendor's wallet signs the fee-payer AU and broadcasts. Removes the
231
+ // service's own feepayer key from the release critical path — vendors can
232
+ // release even when the auto-release loop is disabled.
233
+ export { proveVendorRelease, confirmVendorRelease } from './releaseClient.js';
258
234
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * keysClient.ts — key changes on a licensing app, through the keeper.
3
+ *
4
+ * - The keys an app holds on chain (vendor, payout address and a pending
5
+ * change, platform key and treasury).
6
+ * - Payout address: the vendor proposes a new one (their wallet sends it);
7
+ * it takes effect PAYOUT_DELAY_SLOTS_N slots (48 h) later unless
8
+ * cancelled. The keeper applies it then; anyone may (applyPayout).
9
+ * - Vendor account move: the current and the new wallet both sign a text
10
+ * and, for every live deployment, the contract's vendorKeyMessage.
11
+ * - License transfer (resale): the new owner opens it with the public key
12
+ * of their new passphrase (the passphrase never leaves their device), the
13
+ * current owner signs, the new owner signs, and the new owner's wallet
14
+ * sends it. Only once nothing of the purchase is in escrow.
15
+ *
16
+ * Signatures over fields are Mina Schnorr signatures (base58), as an
17
+ * o1js `Signature` or a wallet's `signFields` gives.
18
+ */
19
+ import { type PrivateKey } from 'o1js';
20
+ export type KeysClientOptions = {
21
+ keeperUrl: string;
22
+ fetcher?: typeof fetch;
23
+ };
24
+ export type AppKeys = {
25
+ appId: string;
26
+ network: 'devnet' | 'mainnet';
27
+ zkAppAddress: string;
28
+ slot: number;
29
+ vendor: string;
30
+ vendorNonce: number;
31
+ payout: string;
32
+ pendingPayout: {
33
+ payout: string;
34
+ effectiveSlot: number;
35
+ } | null;
36
+ platform: {
37
+ key: string;
38
+ treasury: string;
39
+ epoch: number;
40
+ };
41
+ };
42
+ export type LicenseTransfer = {
43
+ id: string;
44
+ network: 'devnet' | 'mainnet';
45
+ zkAppAddress: string;
46
+ from: string;
47
+ to: string;
48
+ newOwner: string;
49
+ leafHash: string;
50
+ validUntil: number;
51
+ message: string[];
52
+ oldOwner?: string;
53
+ status: 'signing' | 'ready' | 'sent' | 'done';
54
+ createdAt: string;
55
+ txHash?: string;
56
+ };
57
+ /** A wallet that signs texts and fields (Auro's signMessage / signFields shapes). */
58
+ export type MoveWallet = {
59
+ address: string;
60
+ signMessage(message: string): Promise<{
61
+ field: string;
62
+ scalar: string;
63
+ }>;
64
+ signFields(fields: string[]): Promise<string>;
65
+ };
66
+ export declare class KeysError extends Error {
67
+ readonly status: number;
68
+ readonly code?: string | undefined;
69
+ constructor(message: string, status: number, code?: string | undefined);
70
+ }
71
+ export declare function createKeysClient(opts: KeysClientOptions): {
72
+ /** The keys the app holds on chain. */
73
+ getAppKeys: (zkAppAddress: string) => Promise<AppKeys>;
74
+ /** Proves a payout change for the vendor's wallet to sign and send (its `vendorAddress` must be the app's vendor key). */
75
+ provePayout: (a: {
76
+ zkAppAddress: string;
77
+ vendorAddress: string;
78
+ payout: string;
79
+ }) => Promise<{
80
+ provenTxJson: string;
81
+ payout: string;
82
+ }>;
83
+ /** Proves the cancellation of a pending payout change (vendor's wallet). */
84
+ provePayoutCancel: (a: {
85
+ zkAppAddress: string;
86
+ vendorAddress: string;
87
+ }) => Promise<{
88
+ provenTxJson: string;
89
+ cancelled: string;
90
+ }>;
91
+ /** Proves applying a payout change past its delay, with any fee payer (the keeper does it itself). */
92
+ provePayoutApply: (a: {
93
+ zkAppAddress: string;
94
+ feePayer: string;
95
+ }) => Promise<{
96
+ provenTxJson: string;
97
+ payout: string;
98
+ }>;
99
+ /**
100
+ * Moves the vendor account from `from` to `to`: both wallets sign the
101
+ * move and every live deployment's key change. The keeper's records move
102
+ * at once; it sends the contract changes (or anyone, with /prove/vendor-key).
103
+ * `network` is the one the wallets' text signatures are made on.
104
+ */
105
+ moveVendorAccount(a: {
106
+ network: "devnet" | "mainnet";
107
+ from: MoveWallet;
108
+ to: MoveWallet;
109
+ }): Promise<{
110
+ moved: {
111
+ from: string;
112
+ to: string;
113
+ };
114
+ changes: unknown[];
115
+ keeperSends: boolean;
116
+ }>;
117
+ /** The new owner opens a transfer with the public key of their new passphrase (deriveOwnershipKeypair). */
118
+ openTransfer: (a: {
119
+ zkAppAddress: string;
120
+ licenseHash: string;
121
+ newOwnerPubKey: string;
122
+ }) => Promise<LicenseTransfer>;
123
+ getTransfer: (id: string) => Promise<LicenseTransfer>;
124
+ /**
125
+ * Signs the transfer with an ownership key: the current owner's (`role:
126
+ * 'old'`; from findOwnershipKeypair, since a license carried over from an
127
+ * earlier generation is keyed to that one's address) or the new owner's
128
+ * (`'new'`; deriveOwnershipKeypair with the transfer's zkAppAddress). The message is checked first
129
+ * against the transfer's details.
130
+ */
131
+ signTransfer(id: string, role: "old" | "new", ownerKey: PrivateKey): Promise<LicenseTransfer>;
132
+ /** Both signed: proves the transfer for `feePayer` (the new owner's wallet) to sign and send. */
133
+ proveTransfer: (id: string, feePayer: string) => Promise<{
134
+ provenTxJson: string;
135
+ transferId: string;
136
+ }>;
137
+ confirmTransfer: (id: string, txHash: string) => Promise<{
138
+ ok: true;
139
+ }>;
140
+ };
141
+ export type KeysClient = ReturnType<typeof createKeysClient>;
142
+ //# sourceMappingURL=keysClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keysClient.d.ts","sourceRoot":"","sources":["../src/keysClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ // Copyright (c) 2025-2026 zkLicensing project developers
2
+ // SPDX-License-Identifier: BUSL-1.1
3
+ /**
4
+ * keysClient.ts — key changes on a licensing app, through the keeper.
5
+ *
6
+ * - The keys an app holds on chain (vendor, payout address and a pending
7
+ * change, platform key and treasury).
8
+ * - Payout address: the vendor proposes a new one (their wallet sends it);
9
+ * it takes effect PAYOUT_DELAY_SLOTS_N slots (48 h) later unless
10
+ * cancelled. The keeper applies it then; anyone may (applyPayout).
11
+ * - Vendor account move: the current and the new wallet both sign a text
12
+ * and, for every live deployment, the contract's vendorKeyMessage.
13
+ * - License transfer (resale): the new owner opens it with the public key
14
+ * of their new passphrase (the passphrase never leaves their device), the
15
+ * current owner signs, the new owner signs, and the new owner's wallet
16
+ * sends it. Only once nothing of the purchase is in escrow.
17
+ *
18
+ * Signatures over fields are Mina Schnorr signatures (base58), as an
19
+ * o1js `Signature` or a wallet's `signFields` gives.
20
+ */
21
+ import { Field, PublicKey, Signature, UInt32 } from 'o1js';
22
+ import { licenseTransferMessage, vendorKeyMessage } from './contractInterface.js';
23
+ import { networkField } from './permitMessages.js';
24
+ import { ownerPubKeyHash } from './licenseLeaf.js';
25
+ export class KeysError extends Error {
26
+ status;
27
+ code;
28
+ constructor(message, status, code) {
29
+ super(message);
30
+ this.status = status;
31
+ this.code = code;
32
+ }
33
+ }
34
+ export function createKeysClient(opts) {
35
+ const base = opts.keeperUrl.replace(/\/+$/, '');
36
+ const f = opts.fetcher ?? fetch;
37
+ async function call(method, path, body) {
38
+ const r = await f(base + path, { method, headers: { 'content-type': 'application/json' }, ...(body === undefined ? {} : { body: JSON.stringify(body) }) });
39
+ const json = await r.json().catch(() => null);
40
+ if (!r.ok)
41
+ throw new KeysError(json?.error ?? `${method} ${path} failed (${r.status})`, r.status, json?.code);
42
+ return json;
43
+ }
44
+ return {
45
+ /** The keys the app holds on chain. */
46
+ getAppKeys: (zkAppAddress) => call('GET', `/app-keys?zkAppAddress=${encodeURIComponent(zkAppAddress)}`),
47
+ /** Proves a payout change for the vendor's wallet to sign and send (its `vendorAddress` must be the app's vendor key). */
48
+ provePayout: (a) => call('POST', '/prove/payout', a),
49
+ /** Proves the cancellation of a pending payout change (vendor's wallet). */
50
+ provePayoutCancel: (a) => call('POST', '/prove/payout/cancel', a),
51
+ /** Proves applying a payout change past its delay, with any fee payer (the keeper does it itself). */
52
+ provePayoutApply: (a) => call('POST', '/prove/payout/apply', a),
53
+ /**
54
+ * Moves the vendor account from `from` to `to`: both wallets sign the
55
+ * move and every live deployment's key change. The keeper's records move
56
+ * at once; it sends the contract changes (or anyone, with /prove/vendor-key).
57
+ * `network` is the one the wallets' text signatures are made on.
58
+ */
59
+ async moveVendorAccount(a) {
60
+ const prep = await call('POST', '/vendors/move/prepare', { from: a.from.address, to: a.to.address });
61
+ // Check each message is the key change it says it is before signing.
62
+ for (const c of prep.changes) {
63
+ const expected = vendorKeyMessage({ network: networkField(c.network), app: PublicKey.fromBase58(c.zkAppAddress), nonce: UInt32.from(c.nonce), vendor: PublicKey.fromBase58(a.to.address) }).map(String);
64
+ if (expected.join() !== c.message.join())
65
+ throw new KeysError(`The key change for ${c.zkAppAddress} is not the one asked for: not signing`, 0, 'SIGNATURE_INVALID');
66
+ }
67
+ const changes = [];
68
+ for (const c of prep.changes)
69
+ changes.push({ zkAppAddress: c.zkAppAddress, oldSignature: await a.from.signFields(c.message), newSignature: await a.to.signFields(c.message) });
70
+ return call('POST', '/vendors/move', {
71
+ network: a.network, from: a.from.address, to: a.to.address,
72
+ oldTextSignature: await a.from.signMessage(prep.text), newTextSignature: await a.to.signMessage(prep.text), changes,
73
+ });
74
+ },
75
+ // ── license transfer ────────────────────────────────────────────────────
76
+ /** The new owner opens a transfer with the public key of their new passphrase (deriveOwnershipKeypair). */
77
+ openTransfer: (a) => call('POST', '/transfers', a).then(r => r.transfer),
78
+ getTransfer: (id) => call('GET', `/transfers/${encodeURIComponent(id)}`).then(r => r.transfer),
79
+ /**
80
+ * Signs the transfer with an ownership key: the current owner's (`role:
81
+ * 'old'`; from findOwnershipKeypair, since a license carried over from an
82
+ * earlier generation is keyed to that one's address) or the new owner's
83
+ * (`'new'`; deriveOwnershipKeypair with the transfer's zkAppAddress). The message is checked first
84
+ * against the transfer's details.
85
+ */
86
+ async signTransfer(id, role, ownerKey) {
87
+ const t = await call('GET', `/transfers/${encodeURIComponent(id)}`).then(r => r.transfer);
88
+ const pub = ownerKey.toPublicKey();
89
+ if (role === 'old' && ownerPubKeyHash(pub).toString() !== t.from)
90
+ throw new KeysError('This passphrase does not own the license', 0, 'FORBIDDEN');
91
+ if (role === 'new' && pub.toBase58() !== t.newOwner)
92
+ throw new KeysError('This passphrase is not the one the transfer was opened for', 0, 'FORBIDDEN');
93
+ const expected = licenseTransferMessage({
94
+ network: networkField(t.network), app: PublicKey.fromBase58(t.zkAppAddress), leafHash: Field(t.leafHash), to: Field(t.to), validUntil: UInt32.from(t.validUntil),
95
+ }).map(String);
96
+ if (expected.join() !== t.message.join() || ownerPubKeyHash(PublicKey.fromBase58(t.newOwner)).toString() !== t.to) {
97
+ throw new KeysError('The transfer message does not match its details: not signing', 0, 'SIGNATURE_INVALID');
98
+ }
99
+ const signature = Signature.create(ownerKey, t.message.map(x => Field(x))).toBase58();
100
+ return call('POST', `/transfers/${encodeURIComponent(id)}/signatures`, {
101
+ role, signature, ...(role === 'old' ? { ownerPubKey: pub.toBase58() } : {}),
102
+ }).then(r => r.transfer);
103
+ },
104
+ /** Both signed: proves the transfer for `feePayer` (the new owner's wallet) to sign and send. */
105
+ proveTransfer: (id, feePayer) => call('POST', '/prove/transfer', { id, feePayer }),
106
+ confirmTransfer: (id, txHash) => call('POST', '/confirm/transfer', { id, txHash }),
107
+ };
108
+ }
109
+ //# sourceMappingURL=keysClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keysClient.js","sourceRoot":"","sources":["../src/keysClient.ts"],"names":[],"mappings":"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"}