@unicitylabs/sphere-sdk 0.14.11 → 0.15.0-dev.1

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 +10 -17
  3. package/dist/connect/index.cjs.map +1 -1
  4. package/dist/connect/index.js +10 -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 +3 -3
  13. package/dist/impl/browser/connect/index.cjs.map +1 -1
  14. package/dist/impl/browser/connect/index.js +3 -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 +2 -2
  19. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  20. package/dist/impl/nodejs/connect/index.js +2 -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 +2 -2
@@ -9471,7 +9471,15 @@ function resolveProofTimeoutMs(configured) {
9471
9471
  return configured;
9472
9472
  }
9473
9473
  var TRANSIENT_HTTP_STATUSES = /* @__PURE__ */ new Set([408, 425, 429, 500, 502, 503, 504]);
9474
+ var TransientSubmitAnswer = class extends Error {
9475
+ constructor(status) {
9476
+ super(`gateway is not ready to certify yet (${status})`);
9477
+ this.status = status;
9478
+ this.name = "TransientSubmitAnswer";
9479
+ }
9480
+ };
9474
9481
  function isTransientGatewayError(err) {
9482
+ if (err instanceof TransientSubmitAnswer) return true;
9475
9483
  return err instanceof import_JsonRpcNetworkError.JsonRpcNetworkError && TRANSIENT_HTTP_STATUSES.has(err.status);
9476
9484
  }
9477
9485
  function pause(ms, signal) {
@@ -9592,37 +9600,9 @@ function certificationFailure(err, failLabel, submitError, submitRejectedCleanly
9592
9600
  );
9593
9601
  }
9594
9602
 
9595
- // token-engine/token-blob.ts
9596
- var TOKEN_BLOB_TAG = 39051n;
9597
- var TOKEN_BLOB_VERSION = 1;
9598
- function decodeTokenBlob(bytes) {
9599
- const tag = import_CborDeserializer.CborDeserializer.decodeTag(bytes);
9600
- if (tag.tag !== TOKEN_BLOB_TAG) {
9601
- throw new import_CborError.CborError(`Invalid TokenBlob tag: ${tag.tag}`);
9602
- }
9603
- const fields = import_CborDeserializer.CborDeserializer.decodeArray(tag.data, 4);
9604
- const v = Number(import_CborDeserializer.CborDeserializer.decodeUnsignedInteger(fields[0]));
9605
- if (v !== TOKEN_BLOB_VERSION) {
9606
- throw new import_CborError.CborError(`Unsupported TokenBlob version: ${v}`);
9607
- }
9608
- return {
9609
- v,
9610
- network: Number(import_CborDeserializer.CborDeserializer.decodeUnsignedInteger(fields[1])),
9611
- tokenId: import_CborDeserializer.CborDeserializer.decodeTextString(fields[2]),
9612
- token: import_CborDeserializer.CborDeserializer.decodeByteString(fields[3])
9613
- };
9614
- }
9615
- function unwrapTokenBlobBytes(bytes) {
9616
- try {
9617
- return decodeTokenBlob(bytes).token;
9618
- } catch {
9619
- return bytes;
9620
- }
9621
- }
9622
-
9623
9603
  // token-engine/blob-keys.ts
9624
9604
  async function deriveDeliveryKeys(blobBytes) {
9625
- const token = await import_Token.Token.fromCBOR(unwrapTokenBlobBytes(blobBytes));
9605
+ const token = await import_Token.Token.fromCBOR(blobBytes);
9626
9606
  const stateHash = import_HexConverter.HexConverter.encode((await token.latestTransaction.calculateStateHash()).imprint);
9627
9607
  return { tokenId: import_HexConverter.HexConverter.encode(token.id.bytes), stateHash };
9628
9608
  }
@@ -9676,8 +9656,8 @@ function deriveRealization(privKeyHex, transferId, index, field) {
9676
9656
  }
9677
9657
 
9678
9658
  // token-engine/split-checkpoint.ts
9679
- var CHECKPOINT_VERSION = 1;
9680
- var CHECKPOINT_SDK_VERSION = "@unicitylabs/state-transition-sdk@2.0.2";
9659
+ var CHECKPOINT_VERSION = 2;
9660
+ var CHECKPOINT_SDK_VERSION = "@unicitylabs/state-transition-sdk@3.0.1";
9681
9661
  function bytesEqual(a, b) {
9682
9662
  if (a.length !== b.length) return false;
9683
9663
  for (let i = 0; i < a.length; i++) {
@@ -9827,13 +9807,11 @@ var SphereTokenEngine = class {
9827
9807
  const data = params.value ? await SpherePaymentData.fromValue(params.value).encode() : null;
9828
9808
  const transferId = this.resolveTransferId(options);
9829
9809
  const opIndex = this.resolveOpIndex(options);
9830
- const mintTx = await import_MintTransaction.MintTransaction.create(
9831
- this.deps.networkId,
9832
- recipient,
9810
+ const mintTx = await import_MintTransaction.MintTransaction.create(this.deps.networkId, recipient, {
9833
9811
  data,
9834
- new import_TokenType.TokenType(deriveRealization(this.privateKeyHex, transferId, opIndex, "tokenType")),
9835
- import_TokenSalt.TokenSalt.fromBytes(deriveRealization(this.privateKeyHex, transferId, opIndex, "mint"))
9836
- );
9812
+ tokenType: new import_TokenType.TokenType(deriveRealization(this.privateKeyHex, transferId, opIndex, "tokenType")),
9813
+ salt: import_TokenSalt.TokenSalt.fromBytes(deriveRealization(this.privateKeyHex, transferId, opIndex, "mint"))
9814
+ });
9837
9815
  const certificationData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
9838
9816
  const proof = await this.submitAndAwaitProof(
9839
9817
  certificationData,
@@ -9850,7 +9828,7 @@ var SphereTokenEngine = class {
9850
9828
  const recipient = import_SignaturePredicate.SignaturePredicate.create(params.recipientPubkey);
9851
9829
  const tokenType = params.tokenType ? new import_TokenType.TokenType(params.tokenType) : import_TokenType.TokenType.generate();
9852
9830
  const salt = params.salt ? import_TokenSalt.TokenSalt.fromBytes(params.salt) : import_TokenSalt.TokenSalt.generate();
9853
- const mintTx = await import_MintTransaction.MintTransaction.create(this.deps.networkId, recipient, params.data, tokenType, salt);
9831
+ const mintTx = await import_MintTransaction.MintTransaction.create(this.deps.networkId, recipient, { data: params.data, tokenType, salt });
9854
9832
  const certificationData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
9855
9833
  const proof = await this.submitAndAwaitProof(
9856
9834
  certificationData,
@@ -9870,7 +9848,9 @@ var SphereTokenEngine = class {
9870
9848
  const stateMask = import_StateMask.StateMask.fromBytes(
9871
9849
  deriveRealization(this.privateKeyHex, transferId, this.resolveOpIndex(options), "stateMask")
9872
9850
  );
9873
- const transferTx = await import_TransferTransaction.TransferTransaction.create(params.token.sdkToken, recipient, stateMask, params.data ?? null);
9851
+ const transferTx = await import_TransferTransaction.TransferTransaction.create(params.token.sdkToken, recipient, stateMask, {
9852
+ data: params.data ?? null
9853
+ });
9874
9854
  const unlockScript = await import_SignaturePredicateUnlockScript.SignaturePredicateUnlockScript.create(transferTx, this.deps.signingService);
9875
9855
  const certificationData = await import_CertificationData.CertificationData.fromTransaction(transferTx, unlockScript);
9876
9856
  const proof = await this.submitAndAwaitProof(
@@ -9897,12 +9877,11 @@ var SphereTokenEngine = class {
9897
9877
  import_TokenSalt.TokenSalt.fromBytes(deriveRealization(this.privateKeyHex, transferId, i, "salt"))
9898
9878
  )
9899
9879
  );
9900
- const split = await import_TokenSplit.TokenSplit.split(
9901
- params.token.sdkToken,
9902
- decodeSpherePaymentData,
9903
- requests,
9904
- import_StateMask.StateMask.fromBytes(deriveRealization(this.privateKeyHex, transferId, this.resolveOpIndex(options), "burn"))
9905
- );
9880
+ const split = await import_TokenSplit.TokenSplit.split(params.token.sdkToken, decodeSpherePaymentData, requests, {
9881
+ burnStateMask: import_StateMask.StateMask.fromBytes(
9882
+ deriveRealization(this.privateKeyHex, transferId, this.resolveOpIndex(options), "burn")
9883
+ )
9884
+ });
9906
9885
  const burntToken = await this.resolveBurntToken({ params, split, transferId, options });
9907
9886
  const settled = [];
9908
9887
  for (let start = 0; start < split.tokens.length; start += MAX_MINT_CONCURRENCY) {
@@ -9982,9 +9961,14 @@ var SphereTokenEngine = class {
9982
9961
  await Promise.all(
9983
9962
  ctx.split.tokens.map(async (leg) => {
9984
9963
  const data = await leg.paymentData.encode();
9985
- const probe = await import_MintTransaction.MintTransaction.create(leg.networkId, leg.recipient, data, leg.tokenType, leg.salt, null);
9964
+ const probe = await import_MintTransaction.MintTransaction.create(leg.networkId, leg.recipient, {
9965
+ data,
9966
+ tokenType: leg.tokenType,
9967
+ salt: leg.salt,
9968
+ justification: null
9969
+ });
9986
9970
  const response = await this.deps.client.getInclusionProof(await import_StateId.StateId.fromTransaction(probe));
9987
- if (response.inclusionProof.certificationData !== null) {
9971
+ if (response.inclusionProof !== null) {
9988
9972
  throw new SplitCheckpointLostError(
9989
9973
  "a split mint leaf is certified on-chain but no burn checkpoint exists \u2014 outputs are unrecoverable"
9990
9974
  );
@@ -9996,14 +9980,12 @@ var SphereTokenEngine = class {
9996
9980
  async mintSplitOutput(splitToken, burntToken, options) {
9997
9981
  const data = await splitToken.paymentData.encode();
9998
9982
  const justification = import_SplitMintJustification.SplitMintJustification.create(burntToken, splitToken.proofs).toCBOR();
9999
- const mintTx = await import_MintTransaction.MintTransaction.create(
10000
- splitToken.networkId,
10001
- splitToken.recipient,
9983
+ const mintTx = await import_MintTransaction.MintTransaction.create(splitToken.networkId, splitToken.recipient, {
10002
9984
  data,
10003
- splitToken.tokenType,
10004
- splitToken.salt,
9985
+ tokenType: splitToken.tokenType,
9986
+ salt: splitToken.salt,
10005
9987
  justification
10006
- );
9988
+ });
10007
9989
  const certData = await import_CertificationData.CertificationData.fromMintTransaction(mintTx);
10008
9990
  const proof = await this.submitSplitMintLeg(certData, mintTx, options);
10009
9991
  const certified = await mintTx.toCertifiedTransaction(this.deps.trustBase, this.deps.predicateVerifier, this.deps.unicityCertificateVerifier, proof);
@@ -10048,7 +10030,7 @@ var SphereTokenEngine = class {
10048
10030
  );
10049
10031
  const stateId = await import_StateId.StateId.fromTransaction(probe);
10050
10032
  const response = await this.deps.client.getInclusionProof(stateId);
10051
- return response.inclusionProof.certificationData !== null;
10033
+ return response.inclusionProof !== null;
10052
10034
  }
10053
10035
  // ── serialization ────────────────────────────────────────────────────────────
10054
10036
  /** @inheritDoc — SDK-derived (Token.fromCBOR → latestTransaction.calculateStateHash().imprint). */
@@ -10132,7 +10114,13 @@ var SphereTokenEngine = class {
10132
10114
  let submitRejectedCleanly = false;
10133
10115
  try {
10134
10116
  const { value: response, retried } = await retryTransient(
10135
- () => this.deps.client.submitCertificationRequest(certificationData),
10117
+ async () => {
10118
+ const answer = await this.deps.client.submitCertificationRequest(certificationData);
10119
+ if (String(answer.status) === String(import_CertificationResponse.CertificationStatus.SERVICE_NOT_READY)) {
10120
+ throw new TransientSubmitAnswer(String(answer.status));
10121
+ }
10122
+ return answer;
10123
+ },
10136
10124
  signal,
10137
10125
  this.deps.proofPollIntervalMs ?? DEFAULT_PROOF_POLL_INTERVAL_MS
10138
10126
  );
@@ -10187,8 +10175,6 @@ var SphereTokenEngine = class {
10187
10175
  }
10188
10176
  }
10189
10177
  const blob = {
10190
- v: TOKEN_BLOB_VERSION,
10191
- network: sdkToken.genesis.networkId.id,
10192
10178
  tokenId: import_HexConverter.HexConverter.encode(sdkToken.id.bytes),
10193
10179
  token: sdkToken.toCBOR()
10194
10180
  };
@@ -11332,8 +11318,19 @@ function coalesced(run, observe) {
11332
11318
  }
11333
11319
 
11334
11320
  // modules/payments-v2/stores.ts
11321
+ var KV_PREFIX = "pv2g2:";
11322
+ var SUPERSEDED_KV_PREFIXES = ["pv2:"];
11323
+ async function sweepSupersededState(storage) {
11324
+ for (const prefix of SUPERSEDED_KV_PREFIXES) {
11325
+ try {
11326
+ await storage.clear(prefix);
11327
+ } catch (err) {
11328
+ logger.warn("PaymentsV2", `could not clear superseded state under "${prefix}": ${String(err)}`);
11329
+ }
11330
+ }
11331
+ }
11335
11332
  function createScopedKV(storage, network, chainPubkey) {
11336
- const prefix = `pv2:${network}:${chainPubkey}:`;
11333
+ const prefix = `${KV_PREFIX}${network}:${chainPubkey}:`;
11337
11334
  return {
11338
11335
  async get(key) {
11339
11336
  const raw = await storage.get(prefix + key);
@@ -11915,12 +11912,7 @@ var TransferMachine = class {
11915
11912
  let total = 0n;
11916
11913
  for (const outcome of committed) {
11917
11914
  if (outcome.recipientBlob === void 0) continue;
11918
- const token = await engine.decodeToken({
11919
- v: TOKEN_BLOB_VERSION,
11920
- network: 0,
11921
- tokenId: "",
11922
- token: outcome.recipientBlob
11923
- });
11915
+ const token = await engine.decodeToken({ tokenId: "", token: outcome.recipientBlob });
11924
11916
  total += engine.balanceOf(token, coinId);
11925
11917
  }
11926
11918
  return total.toString();
@@ -12036,8 +12028,9 @@ async function fetchSources(deps, jobs) {
12036
12028
  const engine = deps.engine();
12037
12029
  for (const [tokenId, bytes] of blobs) {
12038
12030
  try {
12039
- decoded.set(tokenId, await engine.decodeToken({ v: TOKEN_BLOB_VERSION, network: 0, tokenId, token: bytes }));
12040
- } catch {
12031
+ decoded.set(tokenId, await engine.decodeToken({ tokenId, token: bytes }));
12032
+ } catch (err) {
12033
+ logger.warn("PaymentsV2", `resume: source ${tokenId} did not decode \u2014 ${String(err)}`);
12041
12034
  }
12042
12035
  }
12043
12036
  return decoded;
@@ -13137,13 +13130,9 @@ async function screen(deps, engine, entry) {
13137
13130
  const blobBytes = await entry.fetchBlob();
13138
13131
  let token;
13139
13132
  try {
13140
- token = await engine.decodeToken({
13141
- v: TOKEN_BLOB_VERSION,
13142
- network: 0,
13143
- tokenId: "",
13144
- token: blobBytes
13145
- });
13146
- } catch {
13133
+ token = await engine.decodeToken({ tokenId: "", token: blobBytes });
13134
+ } catch (err) {
13135
+ logger.warn("PaymentsV2", `receive: undecodable blob rejected \u2014 ${String(err)}`);
13147
13136
  return { kind: "ack", ack: rejectAck(entry, "invalid") };
13148
13137
  }
13149
13138
  const verdict = await engine.verify(token);
@@ -14546,7 +14535,7 @@ var PaymentsFacade = class {
14546
14535
  if (bytes === void 0) {
14547
14536
  throw new SphereError(`Selected source ${tokenId} has no blob in storage`, "STORAGE_ERROR");
14548
14537
  }
14549
- const token = await engine.decodeToken({ v: TOKEN_BLOB_VERSION, network: 0, tokenId, token: bytes });
14538
+ const token = await engine.decodeToken({ tokenId, token: bytes });
14550
14539
  const keys = await engine.deliveryKeys(bytes);
14551
14540
  spentStates[tokenId] = { local: keys.stateHash, protocol: keys.stateHash };
14552
14541
  sources.set(tokenId, token);
@@ -15993,6 +15982,7 @@ function composePaymentsV2(spec) {
15993
15982
  const network = spec.composition.network;
15994
15983
  const identitySlice = { privateKey: identity.privateKey, chainPubkey: identity.chainPubkey };
15995
15984
  const kv = createScopedKV(host.storage, network, identity.chainPubkey);
15985
+ void sweepSupersededState(host.storage);
15996
15986
  const fieldKey = deriveFieldEncryptionKey(identity.privateKey);
15997
15987
  const transport = spec.composition.factory({
15998
15988
  identity: identitySlice,
@@ -16284,11 +16274,10 @@ var Sphere = class _Sphere {
16284
16274
  return config;
16285
16275
  }
16286
16276
  /**
16287
- * The ONE sanctioned refusal fossil of the P11 flip (revisit-and-delete after
16288
- * one release): `accounting`/`swap` were public init flags — silently
16289
- * ignoring them would hide that invoices/swaps no longer exist in the SDK.
16290
- * `paymentsV2: true` stays an accepted no-op for the same one release (the
16291
- * live frontend passes it today).
16277
+ * The ONE sanctioned refusal fossil of the P11 flip: `accounting`/`swap` were
16278
+ * public init flags — silently ignoring them would hide that invoices/swaps no
16279
+ * longer exist in the SDK. Kept through 0.15.0, where consumers re-integrate
16280
+ * across the wire break and a silent no-op would be worst.
16292
16281
  */
16293
16282
  static refuseRetiredModuleOptions(options) {
16294
16283
  if (options.accounting) {
@@ -16555,7 +16544,7 @@ var Sphere = class _Sphere {
16555
16544
  }
16556
16545
  /**
16557
16546
  * Clear all SDK-owned wallet data from storage: wallet keys, per-address
16558
- * data, and the payments vertical's `pv2:{network}:{pubkey}:*` scoped KV
16547
+ * data, and the payments vertical's `pv2g2:{network}:{pubkey}:*` scoped KV
16559
16548
  * (refresh token, cursors, journals — all live in the plain StorageProvider,
16560
16549
  * so the full KV wipe below removes them). Tokens are server-custody; the
16561
16550
  * only local token artifacts are orphaned `sphere-token-storage-*` IndexedDB
@@ -16665,10 +16654,6 @@ var Sphere = class _Sphere {
16665
16654
  }
16666
16655
  return facade;
16667
16656
  }
16668
- /** @deprecated Alias of {@link payments} kept for one release (the live frontend calls it). Null when no vertical runs. */
16669
- get paymentsV2() {
16670
- return this._paymentsV2Active?.facade ?? null;
16671
- }
16672
16657
  /** Communications module */
16673
16658
  get communications() {
16674
16659
  this.ensureReady();