@unicitylabs/sphere-sdk 0.14.11 → 0.15.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 (46) hide show
  1. package/README.md +55 -17
  2. package/dist/connect/index.cjs +17 -17
  3. package/dist/connect/index.cjs.map +1 -1
  4. package/dist/connect/index.js +17 -17
  5. package/dist/connect/index.js.map +1 -1
  6. package/dist/core/index.cjs +69 -84
  7. package/dist/core/index.cjs.map +1 -1
  8. package/dist/core/index.d.cts +5 -14
  9. package/dist/core/index.d.ts +5 -14
  10. package/dist/core/index.js +69 -84
  11. package/dist/core/index.js.map +1 -1
  12. package/dist/impl/browser/connect/index.cjs +10 -3
  13. package/dist/impl/browser/connect/index.cjs.map +1 -1
  14. package/dist/impl/browser/connect/index.js +10 -3
  15. package/dist/impl/browser/connect/index.js.map +1 -1
  16. package/dist/impl/browser/index.cjs.map +1 -1
  17. package/dist/impl/browser/index.js.map +1 -1
  18. package/dist/impl/nodejs/connect/index.cjs +9 -2
  19. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  20. package/dist/impl/nodejs/connect/index.js +9 -2
  21. package/dist/impl/nodejs/connect/index.js.map +1 -1
  22. package/dist/impl/nodejs/index.cjs.map +1 -1
  23. package/dist/impl/nodejs/index.js.map +1 -1
  24. package/dist/impl/wallet-api-v2/index.cjs +92 -92
  25. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  26. package/dist/impl/wallet-api-v2/index.js +92 -92
  27. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  28. package/dist/index.cjs +69 -84
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +6 -11
  31. package/dist/index.d.ts +6 -11
  32. package/dist/index.js +69 -84
  33. package/dist/index.js.map +1 -1
  34. package/dist/modules/payments-v2/index.cjs +116 -174
  35. package/dist/modules/payments-v2/index.cjs.map +1 -1
  36. package/dist/modules/payments-v2/index.d.cts +3 -5
  37. package/dist/modules/payments-v2/index.d.ts +3 -5
  38. package/dist/modules/payments-v2/index.js +114 -173
  39. package/dist/modules/payments-v2/index.js.map +1 -1
  40. package/dist/token-engine/index.cjs +43 -57
  41. package/dist/token-engine/index.cjs.map +1 -1
  42. package/dist/token-engine/index.d.cts +0 -4
  43. package/dist/token-engine/index.d.ts +0 -4
  44. package/dist/token-engine/index.js +43 -57
  45. package/dist/token-engine/index.js.map +1 -1
  46. package/package.json +3 -2
package/dist/index.cjs CHANGED
@@ -9529,7 +9529,15 @@ function resolveProofTimeoutMs(configured) {
9529
9529
  return configured;
9530
9530
  }
9531
9531
  var TRANSIENT_HTTP_STATUSES = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
9532
+ var TransientSubmitAnswer = class extends Error {
9533
+ constructor(status) {
9534
+ super(`gateway is not ready to certify yet (${status})`);
9535
+ this.status = status;
9536
+ this.name = "TransientSubmitAnswer";
9537
+ }
9538
+ };
9532
9539
  function isTransientGatewayError(err) {
9540
+ if (err instanceof TransientSubmitAnswer) return true;
9533
9541
  return err instanceof import_JsonRpcNetworkError.JsonRpcNetworkError && TRANSIENT_HTTP_STATUSES.has(err.status);
9534
9542
  }
9535
9543
  function pause(ms, signal) {
@@ -9650,37 +9658,9 @@ function certificationFailure(err, failLabel, submitError, submitRejectedCleanly
9650
9658
  );
9651
9659
  }
9652
9660
 
9653
- // token-engine/token-blob.ts
9654
- var TOKEN_BLOB_TAG = 39051n;
9655
- var TOKEN_BLOB_VERSION = 1;
9656
- function decodeTokenBlob(bytes) {
9657
- const tag = import_CborDeserializer.CborDeserializer.decodeTag(bytes);
9658
- if (tag.tag !== TOKEN_BLOB_TAG) {
9659
- throw new import_CborError.CborError(`Invalid TokenBlob tag: ${tag.tag}`);
9660
- }
9661
- const fields = import_CborDeserializer.CborDeserializer.decodeArray(tag.data, 4);
9662
- const v = Number(import_CborDeserializer.CborDeserializer.decodeUnsignedInteger(fields[0]));
9663
- if (v !== TOKEN_BLOB_VERSION) {
9664
- throw new import_CborError.CborError(`Unsupported TokenBlob version: ${v}`);
9665
- }
9666
- return {
9667
- v,
9668
- network: Number(import_CborDeserializer.CborDeserializer.decodeUnsignedInteger(fields[1])),
9669
- tokenId: import_CborDeserializer.CborDeserializer.decodeTextString(fields[2]),
9670
- token: import_CborDeserializer.CborDeserializer.decodeByteString(fields[3])
9671
- };
9672
- }
9673
- function unwrapTokenBlobBytes(bytes) {
9674
- try {
9675
- return decodeTokenBlob(bytes).token;
9676
- } catch {
9677
- return bytes;
9678
- }
9679
- }
9680
-
9681
9661
  // token-engine/blob-keys.ts
9682
9662
  async function deriveDeliveryKeys(blobBytes) {
9683
- const token = await import_Token.Token.fromCBOR(unwrapTokenBlobBytes(blobBytes));
9663
+ const token = await import_Token.Token.fromCBOR(blobBytes);
9684
9664
  const stateHash = import_HexConverter.HexConverter.encode((await token.latestTransaction.calculateStateHash()).imprint);
9685
9665
  return { tokenId: import_HexConverter.HexConverter.encode(token.id.bytes), stateHash };
9686
9666
  }
@@ -9734,8 +9714,8 @@ function deriveRealization(privKeyHex, transferId, index, field) {
9734
9714
  }
9735
9715
 
9736
9716
  // token-engine/split-checkpoint.ts
9737
- var CHECKPOINT_VERSION = 1;
9738
- var CHECKPOINT_SDK_VERSION = "@unicitylabs/state-transition-sdk@2.0.2";
9717
+ var CHECKPOINT_VERSION = 2;
9718
+ var CHECKPOINT_SDK_VERSION = "@unicitylabs/state-transition-sdk@3.0.1";
9739
9719
  function bytesEqual(a, b) {
9740
9720
  if (a.length !== b.length) return false;
9741
9721
  for (let i = 0; i < a.length; i++) {
@@ -9885,13 +9865,11 @@ var SphereTokenEngine = class {
9885
9865
  const data = params.value ? await SpherePaymentData.fromValue(params.value).encode() : null;
9886
9866
  const transferId = this.resolveTransferId(options);
9887
9867
  const opIndex = this.resolveOpIndex(options);
9888
- const mintTx = await import_MintTransaction.MintTransaction.create(
9889
- this.deps.networkId,
9890
- recipient,
9868
+ const mintTx = await import_MintTransaction.MintTransaction.create(this.deps.networkId, recipient, {
9891
9869
  data,
9892
- new import_TokenType.TokenType(deriveRealization(this.privateKeyHex, transferId, opIndex, "tokenType")),
9893
- import_TokenSalt.TokenSalt.fromBytes(deriveRealization(this.privateKeyHex, transferId, opIndex, "mint"))
9894
- );
9870
+ tokenType: new import_TokenType.TokenType(deriveRealization(this.privateKeyHex, transferId, opIndex, "tokenType")),
9871
+ salt: import_TokenSalt.TokenSalt.fromBytes(deriveRealization(this.privateKeyHex, transferId, opIndex, "mint"))
9872
+ });
9895
9873
  const certificationData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
9896
9874
  const proof = await this.submitAndAwaitProof(
9897
9875
  certificationData,
@@ -9908,7 +9886,7 @@ var SphereTokenEngine = class {
9908
9886
  const recipient = import_SignaturePredicate.SignaturePredicate.create(params.recipientPubkey);
9909
9887
  const tokenType = params.tokenType ? new import_TokenType.TokenType(params.tokenType) : import_TokenType.TokenType.generate();
9910
9888
  const salt = params.salt ? import_TokenSalt.TokenSalt.fromBytes(params.salt) : import_TokenSalt.TokenSalt.generate();
9911
- const mintTx = await import_MintTransaction.MintTransaction.create(this.deps.networkId, recipient, params.data, tokenType, salt);
9889
+ const mintTx = await import_MintTransaction.MintTransaction.create(this.deps.networkId, recipient, { data: params.data, tokenType, salt });
9912
9890
  const certificationData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
9913
9891
  const proof = await this.submitAndAwaitProof(
9914
9892
  certificationData,
@@ -9928,7 +9906,9 @@ var SphereTokenEngine = class {
9928
9906
  const stateMask = import_StateMask.StateMask.fromBytes(
9929
9907
  deriveRealization(this.privateKeyHex, transferId, this.resolveOpIndex(options), "stateMask")
9930
9908
  );
9931
- const transferTx = await import_TransferTransaction.TransferTransaction.create(params.token.sdkToken, recipient, stateMask, params.data ?? null);
9909
+ const transferTx = await import_TransferTransaction.TransferTransaction.create(params.token.sdkToken, recipient, stateMask, {
9910
+ data: params.data ?? null
9911
+ });
9932
9912
  const unlockScript = await import_SignaturePredicateUnlockScript.SignaturePredicateUnlockScript.create(transferTx, this.deps.signingService);
9933
9913
  const certificationData = await import_CertificationData.CertificationData.fromTransaction(transferTx, unlockScript);
9934
9914
  const proof = await this.submitAndAwaitProof(
@@ -9955,12 +9935,11 @@ var SphereTokenEngine = class {
9955
9935
  import_TokenSalt.TokenSalt.fromBytes(deriveRealization(this.privateKeyHex, transferId, i, "salt"))
9956
9936
  )
9957
9937
  );
9958
- const split = await import_TokenSplit.TokenSplit.split(
9959
- params.token.sdkToken,
9960
- decodeSpherePaymentData,
9961
- requests,
9962
- import_StateMask.StateMask.fromBytes(deriveRealization(this.privateKeyHex, transferId, this.resolveOpIndex(options), "burn"))
9963
- );
9938
+ const split = await import_TokenSplit.TokenSplit.split(params.token.sdkToken, decodeSpherePaymentData, requests, {
9939
+ burnStateMask: import_StateMask.StateMask.fromBytes(
9940
+ deriveRealization(this.privateKeyHex, transferId, this.resolveOpIndex(options), "burn")
9941
+ )
9942
+ });
9964
9943
  const burntToken = await this.resolveBurntToken({ params, split, transferId, options });
9965
9944
  const settled = [];
9966
9945
  for (let start = 0; start < split.tokens.length; start += MAX_MINT_CONCURRENCY) {
@@ -10040,9 +10019,14 @@ var SphereTokenEngine = class {
10040
10019
  await Promise.all(
10041
10020
  ctx.split.tokens.map(async (leg) => {
10042
10021
  const data = await leg.paymentData.encode();
10043
- const probe = await import_MintTransaction.MintTransaction.create(leg.networkId, leg.recipient, data, leg.tokenType, leg.salt, null);
10022
+ const probe = await import_MintTransaction.MintTransaction.create(leg.networkId, leg.recipient, {
10023
+ data,
10024
+ tokenType: leg.tokenType,
10025
+ salt: leg.salt,
10026
+ justification: null
10027
+ });
10044
10028
  const response = await this.deps.client.getInclusionProof(await import_StateId.StateId.fromTransaction(probe));
10045
- if (response.inclusionProof.certificationData !== null) {
10029
+ if (response.inclusionProof !== null) {
10046
10030
  throw new SplitCheckpointLostError(
10047
10031
  "a split mint leaf is certified on-chain but no burn checkpoint exists \u2014 outputs are unrecoverable"
10048
10032
  );
@@ -10054,14 +10038,12 @@ var SphereTokenEngine = class {
10054
10038
  async mintSplitOutput(splitToken, burntToken, options) {
10055
10039
  const data = await splitToken.paymentData.encode();
10056
10040
  const justification = import_SplitMintJustification.SplitMintJustification.create(burntToken, splitToken.proofs).toCBOR();
10057
- const mintTx = await import_MintTransaction.MintTransaction.create(
10058
- splitToken.networkId,
10059
- splitToken.recipient,
10041
+ const mintTx = await import_MintTransaction.MintTransaction.create(splitToken.networkId, splitToken.recipient, {
10060
10042
  data,
10061
- splitToken.tokenType,
10062
- splitToken.salt,
10043
+ tokenType: splitToken.tokenType,
10044
+ salt: splitToken.salt,
10063
10045
  justification
10064
- );
10046
+ });
10065
10047
  const certData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
10066
10048
  const proof = await this.submitSplitMintLeg(certData, mintTx, options);
10067
10049
  const certified = await mintTx.toCertifiedTransaction(this.deps.trustBase, this.deps.predicateVerifier, this.deps.unicityCertificateVerifier, proof);
@@ -10106,7 +10088,7 @@ var SphereTokenEngine = class {
10106
10088
  );
10107
10089
  const stateId = await import_StateId.StateId.fromTransaction(probe);
10108
10090
  const response = await this.deps.client.getInclusionProof(stateId);
10109
- return response.inclusionProof.certificationData !== null;
10091
+ return response.inclusionProof !== null;
10110
10092
  }
10111
10093
  // ── serialization ────────────────────────────────────────────────────────────
10112
10094
  /** @inheritDoc — SDK-derived (Token.fromCBOR → latestTransaction.calculateStateHash().imprint). */
@@ -10190,7 +10172,13 @@ var SphereTokenEngine = class {
10190
10172
  let submitRejectedCleanly = false;
10191
10173
  try {
10192
10174
  const { value: response, retried } = await retryTransient(
10193
- () => this.deps.client.submitCertificationRequest(certificationData),
10175
+ async () => {
10176
+ const answer = await this.deps.client.submitCertificationRequest(certificationData);
10177
+ if (String(answer.status) === String(import_CertificationResponse.CertificationStatus.SERVICE_NOT_READY)) {
10178
+ throw new TransientSubmitAnswer(String(answer.status));
10179
+ }
10180
+ return answer;
10181
+ },
10194
10182
  signal,
10195
10183
  this.deps.proofPollIntervalMs ?? DEFAULT_PROOF_POLL_INTERVAL_MS
10196
10184
  );
@@ -10245,8 +10233,6 @@ var SphereTokenEngine = class {
10245
10233
  }
10246
10234
  }
10247
10235
  const blob = {
10248
- v: TOKEN_BLOB_VERSION,
10249
- network: sdkToken.genesis.networkId.id,
10250
10236
  tokenId: import_HexConverter.HexConverter.encode(sdkToken.id.bytes),
10251
10237
  token: sdkToken.toCBOR()
10252
10238
  };
@@ -11390,8 +11376,19 @@ function coalesced(run, observe) {
11390
11376
  }
11391
11377
 
11392
11378
  // modules/payments-v2/stores.ts
11379
+ var KV_PREFIX = "pv2g2:";
11380
+ var SUPERSEDED_KV_PREFIXES = ["pv2:"];
11381
+ async function sweepSupersededState(storage) {
11382
+ for (const prefix of SUPERSEDED_KV_PREFIXES) {
11383
+ try {
11384
+ await storage.clear(prefix);
11385
+ } catch (err) {
11386
+ logger.warn("PaymentsV2", `could not clear superseded state under "${prefix}": ${String(err)}`);
11387
+ }
11388
+ }
11389
+ }
11393
11390
  function createScopedKV(storage, network, chainPubkey) {
11394
- const prefix = `pv2:${network}:${chainPubkey}:`;
11391
+ const prefix = `${KV_PREFIX}${network}:${chainPubkey}:`;
11395
11392
  return {
11396
11393
  async get(key) {
11397
11394
  const raw = await storage.get(prefix + key);
@@ -11973,12 +11970,7 @@ var TransferMachine = class {
11973
11970
  let total = 0n;
11974
11971
  for (const outcome of committed) {
11975
11972
  if (outcome.recipientBlob === void 0) continue;
11976
- const token = await engine.decodeToken({
11977
- v: TOKEN_BLOB_VERSION,
11978
- network: 0,
11979
- tokenId: "",
11980
- token: outcome.recipientBlob
11981
- });
11973
+ const token = await engine.decodeToken({ tokenId: "", token: outcome.recipientBlob });
11982
11974
  total += engine.balanceOf(token, coinId);
11983
11975
  }
11984
11976
  return total.toString();
@@ -12094,8 +12086,9 @@ async function fetchSources(deps, jobs) {
12094
12086
  const engine = deps.engine();
12095
12087
  for (const [tokenId, bytes] of blobs) {
12096
12088
  try {
12097
- decoded.set(tokenId, await engine.decodeToken({ v: TOKEN_BLOB_VERSION, network: 0, tokenId, token: bytes }));
12098
- } catch {
12089
+ decoded.set(tokenId, await engine.decodeToken({ tokenId, token: bytes }));
12090
+ } catch (err) {
12091
+ logger.warn("PaymentsV2", `resume: source ${tokenId} did not decode \u2014 ${String(err)}`);
12099
12092
  }
12100
12093
  }
12101
12094
  return decoded;
@@ -13195,13 +13188,9 @@ async function screen(deps, engine, entry) {
13195
13188
  const blobBytes = await entry.fetchBlob();
13196
13189
  let token;
13197
13190
  try {
13198
- token = await engine.decodeToken({
13199
- v: TOKEN_BLOB_VERSION,
13200
- network: 0,
13201
- tokenId: "",
13202
- token: blobBytes
13203
- });
13204
- } catch {
13191
+ token = await engine.decodeToken({ tokenId: "", token: blobBytes });
13192
+ } catch (err) {
13193
+ logger.warn("PaymentsV2", `receive: undecodable blob rejected \u2014 ${String(err)}`);
13205
13194
  return { kind: "ack", ack: rejectAck(entry, "invalid") };
13206
13195
  }
13207
13196
  const verdict = await engine.verify(token);
@@ -14604,7 +14593,7 @@ var PaymentsFacade = class {
14604
14593
  if (bytes === void 0) {
14605
14594
  throw new SphereError(`Selected source ${tokenId} has no blob in storage`, "STORAGE_ERROR");
14606
14595
  }
14607
- const token = await engine.decodeToken({ v: TOKEN_BLOB_VERSION, network: 0, tokenId, token: bytes });
14596
+ const token = await engine.decodeToken({ tokenId, token: bytes });
14608
14597
  const keys = await engine.deliveryKeys(bytes);
14609
14598
  spentStates[tokenId] = { local: keys.stateHash, protocol: keys.stateHash };
14610
14599
  sources.set(tokenId, token);
@@ -16051,6 +16040,7 @@ function composePaymentsV2(spec) {
16051
16040
  const network = spec.composition.network;
16052
16041
  const identitySlice = { privateKey: identity.privateKey, chainPubkey: identity.chainPubkey };
16053
16042
  const kv = createScopedKV(host.storage, network, identity.chainPubkey);
16043
+ void sweepSupersededState(host.storage);
16054
16044
  const fieldKey = deriveFieldEncryptionKey(identity.privateKey);
16055
16045
  const transport = spec.composition.factory({
16056
16046
  identity: identitySlice,
@@ -16342,11 +16332,10 @@ var Sphere = class _Sphere {
16342
16332
  return config;
16343
16333
  }
16344
16334
  /**
16345
- * The ONE sanctioned refusal fossil of the P11 flip (revisit-and-delete after
16346
- * one release): `accounting`/`swap` were public init flags — silently
16347
- * ignoring them would hide that invoices/swaps no longer exist in the SDK.
16348
- * `paymentsV2: true` stays an accepted no-op for the same one release (the
16349
- * live frontend passes it today).
16335
+ * The ONE sanctioned refusal fossil of the P11 flip: `accounting`/`swap` were
16336
+ * public init flags — silently ignoring them would hide that invoices/swaps no
16337
+ * longer exist in the SDK. Kept through 0.15.0, where consumers re-integrate
16338
+ * across the wire break and a silent no-op would be worst.
16350
16339
  */
16351
16340
  static refuseRetiredModuleOptions(options) {
16352
16341
  if (options.accounting) {
@@ -16613,7 +16602,7 @@ var Sphere = class _Sphere {
16613
16602
  }
16614
16603
  /**
16615
16604
  * Clear all SDK-owned wallet data from storage: wallet keys, per-address
16616
- * data, and the payments vertical's `pv2:{network}:{pubkey}:*` scoped KV
16605
+ * data, and the payments vertical's `pv2g2:{network}:{pubkey}:*` scoped KV
16617
16606
  * (refresh token, cursors, journals — all live in the plain StorageProvider,
16618
16607
  * so the full KV wipe below removes them). Tokens are server-custody; the
16619
16608
  * only local token artifacts are orphaned `sphere-token-storage-*` IndexedDB
@@ -16723,10 +16712,6 @@ var Sphere = class _Sphere {
16723
16712
  }
16724
16713
  return facade;
16725
16714
  }
16726
- /** @deprecated Alias of {@link payments} kept for one release (the live frontend calls it). Null when no vertical runs. */
16727
- get paymentsV2() {
16728
- return this._paymentsV2Active?.facade ?? null;
16729
- }
16730
16715
  /** Communications module */
16731
16716
  get communications() {
16732
16717
  this.ensureReady();