@unicitylabs/sphere-sdk 0.17.6 → 0.18.0-dev.2

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 (44) hide show
  1. package/dist/connect/chunks/{chunk-T4DZCXWS.js → chunk-FGQ6CKKK.js} +2 -2
  2. package/dist/connect/chunks/{chunk-T4DZCXWS.js.map → chunk-FGQ6CKKK.js.map} +1 -1
  3. package/dist/connect/chunks/{chunk-BRYRG2TL.js → chunk-JYBI36GK.js} +2 -2
  4. package/dist/connect/chunks/{chunk-MA32MTCD.js → chunk-OAAY2JEA.js} +2 -2
  5. package/dist/connect/index.cjs +1 -1
  6. package/dist/connect/index.cjs.map +1 -1
  7. package/dist/connect/index.js +3 -3
  8. package/dist/connect/internal/host.js +2 -2
  9. package/dist/core/index.cjs +304 -47
  10. package/dist/core/index.cjs.map +1 -1
  11. package/dist/core/index.d.cts +392 -320
  12. package/dist/core/index.d.ts +392 -320
  13. package/dist/core/index.js +304 -47
  14. package/dist/core/index.js.map +1 -1
  15. package/dist/impl/browser/connect/index.cjs +1 -1
  16. package/dist/impl/browser/connect/index.cjs.map +1 -1
  17. package/dist/impl/browser/connect/index.js +2 -2
  18. package/dist/impl/wallet-api-v2/index.cjs +2 -0
  19. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  20. package/dist/impl/wallet-api-v2/index.d.cts +30 -30
  21. package/dist/impl/wallet-api-v2/index.d.ts +30 -30
  22. package/dist/impl/wallet-api-v2/index.js +2 -0
  23. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  24. package/dist/index.cjs +304 -47
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +279 -154
  27. package/dist/index.d.ts +279 -154
  28. package/dist/index.js +304 -47
  29. package/dist/index.js.map +1 -1
  30. package/dist/modules/payments-v2/index.cjs +249 -28
  31. package/dist/modules/payments-v2/index.cjs.map +1 -1
  32. package/dist/modules/payments-v2/index.d.cts +252 -166
  33. package/dist/modules/payments-v2/index.d.ts +252 -166
  34. package/dist/modules/payments-v2/index.js +249 -28
  35. package/dist/modules/payments-v2/index.js.map +1 -1
  36. package/dist/token-engine/index.cjs +455 -427
  37. package/dist/token-engine/index.cjs.map +1 -1
  38. package/dist/token-engine/index.d.cts +26 -1
  39. package/dist/token-engine/index.d.ts +26 -1
  40. package/dist/token-engine/index.js +455 -427
  41. package/dist/token-engine/index.js.map +1 -1
  42. package/package.json +1 -1
  43. /package/dist/connect/chunks/{chunk-BRYRG2TL.js.map → chunk-JYBI36GK.js.map} +0 -0
  44. /package/dist/connect/chunks/{chunk-MA32MTCD.js.map → chunk-OAAY2JEA.js.map} +0 -0
@@ -1,3 +1,4 @@
1
+ import { IMintJustificationVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/IMintJustificationVerifier.js';
1
2
  import { Token as Token$1 } from '@unicitylabs/state-transition-sdk/lib/transaction/Token.js';
2
3
 
3
4
  declare const NFT_METADATA_TAG = 39052n;
@@ -173,6 +174,16 @@ interface MintDataTokenParams {
173
174
  readonly tokenType?: Uint8Array;
174
175
  /** Salt bytes; deterministic salt → deterministic (terms-derived) tokenId. */
175
176
  readonly salt?: Uint8Array;
177
+ /** Genesis mint reason (the SDK's `justification`): tagged CBOR a registered verifier validates. */
178
+ readonly justification?: Uint8Array;
179
+ /** Verifiers for this mint's genesis reason, in place of the ones registered on the engine. */
180
+ readonly mintJustificationVerifiers?: readonly IMintJustificationVerifier[];
181
+ }
182
+ /** Spend a token to a burn predicate with the reason bytes as aux data. */
183
+ interface BurnParams {
184
+ readonly token: SphereToken;
185
+ /** The recipient predicate is `BurnPredicate(sha256(reasonBytes))`; the bytes ride in the aux data. */
186
+ readonly reasonBytes: Uint8Array;
176
187
  }
177
188
  /** Plan an NFT mint (#785); `mintDataToken` then mints the plan. */
178
189
  interface BuildNftMintParams {
@@ -245,6 +256,171 @@ interface NftReading {
245
256
  readonly signature: NftSignatureStatus;
246
257
  }
247
258
 
259
+ /**
260
+ * token-engine/engine.ts — the FROZEN public port (ITokenEngine) + its config.
261
+ *
262
+ * This is the contract both migration tracks build against. It is sphere-domain
263
+ * only (see types.ts). The granular, SDK-typed steps (buildMint, submit,
264
+ * awaitProof, certify, …) are an INTERNAL concern of the real adapter and are
265
+ * intentionally NOT part of this public interface.
266
+ */
267
+
268
+ /**
269
+ * Durable, any-device store for a split's burn checkpoint (sdk-changes E.4, sphere-sdk#501
270
+ * option b). The engine passes opaque PLAINTEXT bytes; a transport adapter (the wallet-api
271
+ * provider) is responsible for AAD-encryption and the wallet-api §16 intent-progress round-trip.
272
+ *
273
+ * The store is the resume seed for the one split input the engine cannot re-derive — the burn's
274
+ * aggregator-issued inclusion proof — so the mint justification is rebuilt from stored bytes, not
275
+ * a refetch (the aggregator regenerates proofs per request).
276
+ */
277
+ interface SplitCheckpointStore {
278
+ /**
279
+ * Insert-once, first-write-wins. MUST resolve only AFTER the store acked durability, and MUST
280
+ * resolve with the AUTHORITATIVE stored bytes — the caller's own on a fresh write, or the FIRST
281
+ * writer's when the slot `(transferId, opIndex)` was already taken (the caller adopts those and
282
+ * mints from them, so concurrent resumers converge on one burn proof).
283
+ */
284
+ put(transferId: string, opIndex: number, bytes: Uint8Array): Promise<Uint8Array>;
285
+ /** The stored bytes for the slot, or `null` when none exists. */
286
+ get(transferId: string, opIndex: number): Promise<Uint8Array | null>;
287
+ }
288
+ /** Options common to the long-running, network-bound operations. */
289
+ interface EngineOpOptions {
290
+ /** Cancels the operation (including inclusion-proof polling). */
291
+ readonly signal?: AbortSignal;
292
+ /**
293
+ * Durable burn-checkpoint store for a resumable split (sdk-changes E.4, sphere-sdk#501). When
294
+ * present, `split()` persists the burn's certified proof AND awaits its durable ack BEFORE
295
+ * submitting any mint leg, and rebuilds the mint justification from the stored bytes on resume —
296
+ * so a split resumed after any mint leg certified recovers instead of stranding its outputs.
297
+ *
298
+ * Absent keeps today's behavior (a fresh burn proof per attempt): fine for a mid-split resume
299
+ * with no mint yet certified, but a split resumed AFTER a mint certified cannot recover — a
300
+ * documented residual for fully-local compositions; the live path MUST supply the store.
301
+ */
302
+ readonly checkpointStore?: SplitCheckpointStore;
303
+ /**
304
+ * Realization seed for deterministic transfer/split (Part E, sdk-changes E.1/E.3):
305
+ * a client-generated UUIDv4 in canonical lowercase string form. Every value the
306
+ * transaction binds to (stateMask, per-output salts) is HKDF-derived from the
307
+ * wallet key + this id, so re-calling the op with the same `transferId` and
308
+ * inputs rebuilds the byte-identical transaction and resumes an interrupted
309
+ * attempt instead of losing funds. Persist it BEFORE calling the engine.
310
+ *
311
+ * If absent, the engine generates one internally (`crypto.randomUUID()`) — the
312
+ * derivation path is identical, but the call is NOT resumable (the seed is
313
+ * gone if the process dies mid-op).
314
+ */
315
+ readonly transferId?: string;
316
+ /**
317
+ * Ordinal of this engine op WITHIN one logical send sharing a `transferId`
318
+ * (ARCHITECTURE §7: D whole-token transfers + at most one split under ONE
319
+ * intent). It indexes the op-level HKDF derivations (`stateMask`, the split
320
+ * `burn` mask) so distinct ops never reuse a mask — §8.1's "per-transfer
321
+ * unique". Per-output split salts are indexed by output ordinal in their own
322
+ * `salt` field domain; callers MUST NOT run two splits under one transferId.
323
+ * Default 0 (single-op sends). Resume MUST replay the same (transferId,
324
+ * opIndex) pairing per source.
325
+ */
326
+ readonly opIndex?: number;
327
+ }
328
+ /**
329
+ * The token engine port. The wallet's secp256k1 identity, the target network,
330
+ * the aggregator client and the trust base are all bound at construction
331
+ * (see EngineConfig); operations below take only sphere-domain arguments.
332
+ */
333
+ interface ITokenEngine {
334
+ /** This engine's wallet identity (chain pubkey). Synchronous. */
335
+ getIdentity(): EngineIdentity;
336
+ /**
337
+ * Legacy `DIRECT://` address for the given pubkey (defaults to this engine's
338
+ * identity). This is the ONLY "address" in v2 and is kept stable across the
339
+ * migration (Path A) so Quest XP / Unicity IDs keyed on it survive. Async —
340
+ * the derivation hashes via the SDK.
341
+ */
342
+ deriveIdentityAddress(pubkey?: Uint8Array): Promise<string>;
343
+ /**
344
+ * Genesis-stable token id — 64-char lowercase hex of the v2 TokenId (same
345
+ * across every state). Use for dedup / history / tombstone keys. Synchronous.
346
+ */
347
+ tokenId(token: SphereToken): string;
348
+ /** Decoded value of a token (cached). Synchronous. */
349
+ readValue(token: SphereToken): SphereValue | null;
350
+ /** Balance of a single coin within a token. Synchronous. */
351
+ balanceOf(token: SphereToken, coinId: CoinId): bigint;
352
+ /**
353
+ * The opaque on-chain memo delivered with this token: the latest transfer's
354
+ * data for a transferred token, else the memo in a minted output's value
355
+ * envelope (split). Returns `null` when there is no memo — including for data
356
+ * tokens (no value envelope; use `readTokenData`) and memo-less value tokens.
357
+ * To tell a data token from a value token, check `readValue` (null ⇒
358
+ * data/value-less token). Synchronous.
359
+ */
360
+ readMemo(token: SphereToken): Uint8Array | null;
361
+ /** Raw genesis data of a token (e.g. a data-token's terms). `null` when absent. Synchronous. */
362
+ readTokenData(token: SphereToken): Uint8Array | null;
363
+ /** The genesis mint reason (`justification`) of a token; `null` when it was minted without one. Synchronous. */
364
+ readTokenJustification(token: SphereToken): Uint8Array | null;
365
+ /** Read a token's genesis payload as an NFT. NEVER throws; null = not a recognised NFT. */
366
+ readNft(token: SphereToken): Promise<NftReading | null>;
367
+ /**
368
+ * Mint (issue) a new token to a recipient pubkey. NOT a wallet end-user flow —
369
+ * this is the issuer/developer capability: an app issuing its own tokens
370
+ * (rewards, in-app currency, tickets) to users, or seeding test balances. v2
371
+ * makes standalone mint first-class (Token.mint accepts a genesis with a null
372
+ * justification). Split's per-output mint is a separate, internal path; the
373
+ * Unicity-ID/nametag mint is a distinct identity surface (see migration plan §4.4).
374
+ */
375
+ mint(params: MintParams, options?: EngineOpOptions): Promise<SphereToken>;
376
+ /**
377
+ * Mint a NON-value (data) token: opaque `data` + custom `tokenType` + deterministic
378
+ * `salt` → a stable, terms-derived `tokenId`. The result has `value === null`;
379
+ * read its bytes via `readTokenData`. (Used e.g. for on-chain invoice tokens.)
380
+ */
381
+ mintDataToken(params: MintDataTokenParams, options?: EngineOpOptions): Promise<SphereToken>;
382
+ /** Plan an NFT mint: encode (and optionally sign as this engine's identity) the payload and derive its token id. No chain op. */
383
+ buildNftMint(params: BuildNftMintParams): Promise<NftMintPlan>;
384
+ /** Spend a token wholesale to a recipient pubkey; returns the recipient's finished token. */
385
+ transfer(params: TransferParams, options?: EngineOpOptions): Promise<SphereToken>;
386
+ /** Spend the token to `BurnPredicate(sha256(reasonBytes))` with the reason bytes as aux data. */
387
+ burn(params: BurnParams, options?: EngineOpOptions): Promise<SphereToken>;
388
+ /** Split a token into N value-conserving outputs (burn source + internally mint each output). */
389
+ split(params: SplitParams, options?: EngineOpOptions): Promise<SplitResult>;
390
+ /** Fully verify a token against the trust base. */
391
+ verify(token: SphereToken, options?: EngineOpOptions): Promise<EngineVerifyResult>;
392
+ /** Whether the token's current state has already been spent on the network. */
393
+ isSpent(token: SphereToken, options?: EngineOpOptions): Promise<boolean>;
394
+ /**
395
+ * Whether the token's CURRENT state is locked to `SignaturePredicate(pubkey)`.
396
+ * Local + synchronous (predicate byte-compare, no network). The receive path
397
+ * uses it to reject tokens that are not actually addressed to this wallet.
398
+ */
399
+ isOwnedBy(token: SphereToken, pubkey: Uint8Array): boolean;
400
+ /** Serialize a token for storage/transport. Synchronous. */
401
+ encodeToken(token: SphereToken): TokenBlob;
402
+ /** Reconstruct a token from its blob (decodes embedded payment data). */
403
+ decodeToken(blob: TokenBlob): Promise<SphereToken>;
404
+ /**
405
+ * The backend-true delivery keys for encoded TokenBlob bytes: the
406
+ * genesis-stable tokenId and the SDK's PROTOCOL state hash of the latest
407
+ * state (DataHash imprint, hex). wallet-api keys mailbox entries on exactly
408
+ * this pair (entry_id = SHA-256(tokenId ‖ stateHash); §8.2 step 4 validates
409
+ * a deposit's claimed stateHash against it) — a plain hash over the token
410
+ * bytes is NOT this value and 422s on deposit. Delivery implementations MUST
411
+ * derive their ids through this method, never locally.
412
+ */
413
+ deliveryKeys(blobBytes: Uint8Array): Promise<{
414
+ tokenId: string;
415
+ stateHash: string;
416
+ }>;
417
+ /**
418
+ * Release engine-owned OS resources — today only the verification worker pool.
419
+ * Idempotent; optional because an engine owning none need not define it.
420
+ */
421
+ dispose?(): void;
422
+ }
423
+
248
424
  /**
249
425
  * SDK2 Core Types
250
426
  * Platform-independent type definitions
@@ -434,6 +610,40 @@ interface MintResult {
434
610
  tokenId?: string;
435
611
  error?: string;
436
612
  }
613
+ /** Custom-genesis mint (a TokenPlugin's token), always to this wallet; `assets` = what the payload declares. */
614
+ interface MintCustomRequest {
615
+ readonly tokenType: Uint8Array;
616
+ readonly salt: Uint8Array;
617
+ readonly data: Uint8Array;
618
+ readonly justification?: Uint8Array;
619
+ readonly assets: readonly {
620
+ coinId: string;
621
+ amount: bigint;
622
+ }[];
623
+ readonly mintJustificationVerifiers?: readonly IMintJustificationVerifier[];
624
+ }
625
+ /** Burn a held token to `BurnPredicate(sha256(reasonBytes))` with the bytes as aux data. */
626
+ interface BurnRequest {
627
+ readonly tokenId: string;
628
+ readonly reasonBytes: Uint8Array;
629
+ }
630
+ interface BurnResult {
631
+ success: boolean;
632
+ burnId: string;
633
+ tokenId: string;
634
+ /** The burned blob, the proof of the burn: persist it, then `acknowledgeBurn(burnId)`. */
635
+ burnedToken?: Uint8Array;
636
+ error?: string;
637
+ }
638
+ /** A burn not yet acknowledged: in flight (`burnedToken` null), certified, or settled. */
639
+ interface PendingBurn {
640
+ readonly burnId: string;
641
+ readonly tokenId: string;
642
+ readonly reasonBytes: Uint8Array;
643
+ readonly burnedToken: Uint8Array | null;
644
+ readonly settled: boolean;
645
+ readonly createdAt: number;
646
+ }
437
647
  /** #785: `content` uses ERC-721 field names; `sign` (default true) signs as creator with this wallet's chain key. */
438
648
  interface MintNftRequest {
439
649
  readonly content: NftContent;
@@ -525,6 +735,8 @@ interface PaymentsV2 {
525
735
  }): Token[];
526
736
  coinless(): CoinlessToken[];
527
737
  tokenData(tokenId: string): Promise<Uint8Array | null>;
738
+ /** The genesis mint reason of one held token; null when it was minted without one. Same contract as tokenData. */
739
+ tokenJustification(tokenId: string): Promise<Uint8Array | null>;
528
740
  /** One held token read as an NFT; null = its payload is not a recognised NFT. `creator` is only CLAIMED unless `signature` is 'valid'. Throws VALIDATION_ERROR when not held, STORAGE_ERROR when its blob is missing (same contract as tokenData). */
529
741
  nft(tokenId: string): Promise<NftView | null>;
530
742
  /** Batch read for list views. Ids not held, blobs missing or undecodable, and non-NFT payloads are simply absent from the map. Throws only on a transport failure. */
@@ -539,6 +751,10 @@ interface PaymentsV2 {
539
751
  sendCoinless(req: SendWholeTokenRequest): Promise<TransferResult>;
540
752
  mint(coinId: string, amount: bigint): Promise<MintResult>;
541
753
  mintNft(request: MintNftRequest): Promise<MintResult>;
754
+ mintCustom(request: MintCustomRequest): Promise<MintResult>;
755
+ burn(request: BurnRequest): Promise<BurnResult>;
756
+ pendingBurns(): Promise<PendingBurn[]>;
757
+ acknowledgeBurn(burnId: string): Promise<void>;
542
758
  receive(): Promise<{
543
759
  transfers: IncomingTransfer[];
544
760
  }>;
@@ -806,6 +1022,31 @@ interface NftMintJournalEntry {
806
1022
  tokenTypeHex: string;
807
1023
  createdAt: number;
808
1024
  }
1025
+ interface CustomMintJournalEntry {
1026
+ mintId: string;
1027
+ tokenId: string;
1028
+ dataHex: string;
1029
+ saltHex: string;
1030
+ tokenTypeHex: string;
1031
+ justificationHex: string | null;
1032
+ assets: {
1033
+ coinId: string;
1034
+ amount: string;
1035
+ }[];
1036
+ createdAt: number;
1037
+ }
1038
+ interface BurnJournalEntry {
1039
+ burnId: string;
1040
+ tokenId: string;
1041
+ reasonHex: string;
1042
+ burnedTokenHex: string | null;
1043
+ settled: boolean;
1044
+ assets: {
1045
+ coinId: string;
1046
+ amount: string;
1047
+ }[];
1048
+ createdAt: number;
1049
+ }
809
1050
  interface ShortfallEntry {
810
1051
  transferId: string;
811
1052
  remainingAmount: string;
@@ -831,6 +1072,8 @@ declare const STORE_KEYS: {
831
1072
  readonly deliveryJournal: "delivery-journal";
832
1073
  readonly mintJournal: "mint-journal";
833
1074
  readonly nftMintJournal: "nft-mint-journal";
1075
+ readonly customMintJournal: "custom-mint-journal";
1076
+ readonly burnJournal: "burn-journal";
834
1077
  readonly shortfalls: "shortfalls";
835
1078
  readonly settlingLinks: "settling";
836
1079
  readonly streamCursor: (s: StreamName) => string;
@@ -839,167 +1082,6 @@ declare const STORE_KEYS: {
839
1082
  readonly knownSpends: "known-spends";
840
1083
  };
841
1084
 
842
- /**
843
- * token-engine/engine.ts — the FROZEN public port (ITokenEngine) + its config.
844
- *
845
- * This is the contract both migration tracks build against. It is sphere-domain
846
- * only (see types.ts). The granular, SDK-typed steps (buildMint, submit,
847
- * awaitProof, certify, …) are an INTERNAL concern of the real adapter and are
848
- * intentionally NOT part of this public interface.
849
- */
850
-
851
- /**
852
- * Durable, any-device store for a split's burn checkpoint (sdk-changes E.4, sphere-sdk#501
853
- * option b). The engine passes opaque PLAINTEXT bytes; a transport adapter (the wallet-api
854
- * provider) is responsible for AAD-encryption and the wallet-api §16 intent-progress round-trip.
855
- *
856
- * The store is the resume seed for the one split input the engine cannot re-derive — the burn's
857
- * aggregator-issued inclusion proof — so the mint justification is rebuilt from stored bytes, not
858
- * a refetch (the aggregator regenerates proofs per request).
859
- */
860
- interface SplitCheckpointStore {
861
- /**
862
- * Insert-once, first-write-wins. MUST resolve only AFTER the store acked durability, and MUST
863
- * resolve with the AUTHORITATIVE stored bytes — the caller's own on a fresh write, or the FIRST
864
- * writer's when the slot `(transferId, opIndex)` was already taken (the caller adopts those and
865
- * mints from them, so concurrent resumers converge on one burn proof).
866
- */
867
- put(transferId: string, opIndex: number, bytes: Uint8Array): Promise<Uint8Array>;
868
- /** The stored bytes for the slot, or `null` when none exists. */
869
- get(transferId: string, opIndex: number): Promise<Uint8Array | null>;
870
- }
871
- /** Options common to the long-running, network-bound operations. */
872
- interface EngineOpOptions {
873
- /** Cancels the operation (including inclusion-proof polling). */
874
- readonly signal?: AbortSignal;
875
- /**
876
- * Durable burn-checkpoint store for a resumable split (sdk-changes E.4, sphere-sdk#501). When
877
- * present, `split()` persists the burn's certified proof AND awaits its durable ack BEFORE
878
- * submitting any mint leg, and rebuilds the mint justification from the stored bytes on resume —
879
- * so a split resumed after any mint leg certified recovers instead of stranding its outputs.
880
- *
881
- * Absent keeps today's behavior (a fresh burn proof per attempt): fine for a mid-split resume
882
- * with no mint yet certified, but a split resumed AFTER a mint certified cannot recover — a
883
- * documented residual for fully-local compositions; the live path MUST supply the store.
884
- */
885
- readonly checkpointStore?: SplitCheckpointStore;
886
- /**
887
- * Realization seed for deterministic transfer/split (Part E, sdk-changes E.1/E.3):
888
- * a client-generated UUIDv4 in canonical lowercase string form. Every value the
889
- * transaction binds to (stateMask, per-output salts) is HKDF-derived from the
890
- * wallet key + this id, so re-calling the op with the same `transferId` and
891
- * inputs rebuilds the byte-identical transaction and resumes an interrupted
892
- * attempt instead of losing funds. Persist it BEFORE calling the engine.
893
- *
894
- * If absent, the engine generates one internally (`crypto.randomUUID()`) — the
895
- * derivation path is identical, but the call is NOT resumable (the seed is
896
- * gone if the process dies mid-op).
897
- */
898
- readonly transferId?: string;
899
- /**
900
- * Ordinal of this engine op WITHIN one logical send sharing a `transferId`
901
- * (ARCHITECTURE §7: D whole-token transfers + at most one split under ONE
902
- * intent). It indexes the op-level HKDF derivations (`stateMask`, the split
903
- * `burn` mask) so distinct ops never reuse a mask — §8.1's "per-transfer
904
- * unique". Per-output split salts are indexed by output ordinal in their own
905
- * `salt` field domain; callers MUST NOT run two splits under one transferId.
906
- * Default 0 (single-op sends). Resume MUST replay the same (transferId,
907
- * opIndex) pairing per source.
908
- */
909
- readonly opIndex?: number;
910
- }
911
- /**
912
- * The token engine port. The wallet's secp256k1 identity, the target network,
913
- * the aggregator client and the trust base are all bound at construction
914
- * (see EngineConfig); operations below take only sphere-domain arguments.
915
- */
916
- interface ITokenEngine {
917
- /** This engine's wallet identity (chain pubkey). Synchronous. */
918
- getIdentity(): EngineIdentity;
919
- /**
920
- * Legacy `DIRECT://` address for the given pubkey (defaults to this engine's
921
- * identity). This is the ONLY "address" in v2 and is kept stable across the
922
- * migration (Path A) so Quest XP / Unicity IDs keyed on it survive. Async —
923
- * the derivation hashes via the SDK.
924
- */
925
- deriveIdentityAddress(pubkey?: Uint8Array): Promise<string>;
926
- /**
927
- * Genesis-stable token id — 64-char lowercase hex of the v2 TokenId (same
928
- * across every state). Use for dedup / history / tombstone keys. Synchronous.
929
- */
930
- tokenId(token: SphereToken): string;
931
- /** Decoded value of a token (cached). Synchronous. */
932
- readValue(token: SphereToken): SphereValue | null;
933
- /** Balance of a single coin within a token. Synchronous. */
934
- balanceOf(token: SphereToken, coinId: CoinId): bigint;
935
- /**
936
- * The opaque on-chain memo delivered with this token: the latest transfer's
937
- * data for a transferred token, else the memo in a minted output's value
938
- * envelope (split). Returns `null` when there is no memo — including for data
939
- * tokens (no value envelope; use `readTokenData`) and memo-less value tokens.
940
- * To tell a data token from a value token, check `readValue` (null ⇒
941
- * data/value-less token). Synchronous.
942
- */
943
- readMemo(token: SphereToken): Uint8Array | null;
944
- /** Raw genesis data of a token (e.g. a data-token's terms). `null` when absent. Synchronous. */
945
- readTokenData(token: SphereToken): Uint8Array | null;
946
- /** Read a token's genesis payload as an NFT. NEVER throws; null = not a recognised NFT. */
947
- readNft(token: SphereToken): Promise<NftReading | null>;
948
- /**
949
- * Mint (issue) a new token to a recipient pubkey. NOT a wallet end-user flow —
950
- * this is the issuer/developer capability: an app issuing its own tokens
951
- * (rewards, in-app currency, tickets) to users, or seeding test balances. v2
952
- * makes standalone mint first-class (Token.mint accepts a genesis with a null
953
- * justification). Split's per-output mint is a separate, internal path; the
954
- * Unicity-ID/nametag mint is a distinct identity surface (see migration plan §4.4).
955
- */
956
- mint(params: MintParams, options?: EngineOpOptions): Promise<SphereToken>;
957
- /**
958
- * Mint a NON-value (data) token: opaque `data` + custom `tokenType` + deterministic
959
- * `salt` → a stable, terms-derived `tokenId`. The result has `value === null`;
960
- * read its bytes via `readTokenData`. (Used e.g. for on-chain invoice tokens.)
961
- */
962
- mintDataToken(params: MintDataTokenParams, options?: EngineOpOptions): Promise<SphereToken>;
963
- /** Plan an NFT mint: encode (and optionally sign as this engine's identity) the payload and derive its token id. No chain op. */
964
- buildNftMint(params: BuildNftMintParams): Promise<NftMintPlan>;
965
- /** Spend a token wholesale to a recipient pubkey; returns the recipient's finished token. */
966
- transfer(params: TransferParams, options?: EngineOpOptions): Promise<SphereToken>;
967
- /** Split a token into N value-conserving outputs (burn source + internally mint each output). */
968
- split(params: SplitParams, options?: EngineOpOptions): Promise<SplitResult>;
969
- /** Fully verify a token against the trust base. */
970
- verify(token: SphereToken, options?: EngineOpOptions): Promise<EngineVerifyResult>;
971
- /** Whether the token's current state has already been spent on the network. */
972
- isSpent(token: SphereToken, options?: EngineOpOptions): Promise<boolean>;
973
- /**
974
- * Whether the token's CURRENT state is locked to `SignaturePredicate(pubkey)`.
975
- * Local + synchronous (predicate byte-compare, no network). The receive path
976
- * uses it to reject tokens that are not actually addressed to this wallet.
977
- */
978
- isOwnedBy(token: SphereToken, pubkey: Uint8Array): boolean;
979
- /** Serialize a token for storage/transport. Synchronous. */
980
- encodeToken(token: SphereToken): TokenBlob;
981
- /** Reconstruct a token from its blob (decodes embedded payment data). */
982
- decodeToken(blob: TokenBlob): Promise<SphereToken>;
983
- /**
984
- * The backend-true delivery keys for encoded TokenBlob bytes: the
985
- * genesis-stable tokenId and the SDK's PROTOCOL state hash of the latest
986
- * state (DataHash imprint, hex). wallet-api keys mailbox entries on exactly
987
- * this pair (entry_id = SHA-256(tokenId ‖ stateHash); §8.2 step 4 validates
988
- * a deposit's claimed stateHash against it) — a plain hash over the token
989
- * bytes is NOT this value and 422s on deposit. Delivery implementations MUST
990
- * derive their ids through this method, never locally.
991
- */
992
- deliveryKeys(blobBytes: Uint8Array): Promise<{
993
- tokenId: string;
994
- stateHash: string;
995
- }>;
996
- /**
997
- * Release engine-owned OS resources — today only the verification worker pool.
998
- * Idempotent; optional because an engine owning none need not define it.
999
- */
1000
- dispose?(): void;
1001
- }
1002
-
1003
1085
  interface HistoryWireAsset {
1004
1086
  coinId: string;
1005
1087
  amount: string;
@@ -1368,6 +1450,7 @@ declare class PaymentsFacade implements PaymentsV2 {
1368
1450
  }): Token[];
1369
1451
  coinless(): CoinlessToken[];
1370
1452
  tokenData(tokenId: string): Promise<Uint8Array | null>;
1453
+ tokenJustification(tokenId: string): Promise<Uint8Array | null>;
1371
1454
  nft(tokenId: string): Promise<NftView | null>;
1372
1455
  nfts(tokenIds: readonly string[]): Promise<ReadonlyMap<string, NftView>>;
1373
1456
  private readDeps;
@@ -1391,6 +1474,10 @@ declare class PaymentsFacade implements PaymentsV2 {
1391
1474
  }>;
1392
1475
  mint(coinId: string, amount: bigint): Promise<MintResult>;
1393
1476
  mintNft(request: MintNftRequest): Promise<MintResult>;
1477
+ mintCustom: (request: MintCustomRequest) => Promise<MintResult>;
1478
+ burn: (request: BurnRequest) => Promise<BurnResult>;
1479
+ pendingBurns: () => Promise<PendingBurn[]>;
1480
+ acknowledgeBurn: (burnId: string) => Promise<void>;
1394
1481
  resumeNow(): Promise<void>;
1395
1482
  /** §5.1 restore — awaited by the session latch BEFORE streams resume; never coalesced onto a pre-restore pass. */
1396
1483
  handleEpochChange(_newEpoch: string): Promise<void>;
@@ -1398,7 +1485,7 @@ declare class PaymentsFacade implements PaymentsV2 {
1398
1485
  private runConvergencePass;
1399
1486
  private convergeBody;
1400
1487
  private nowMs;
1401
- /** One snapshot serves the coin and the NFT mint, live and replayed. */
1488
+ /** One snapshot serves the coin, NFT and custom mints and the burn, live and replayed. */
1402
1489
  private mintDeps;
1403
1490
  /** The ONE place a send() outcome is shaped: success emits in finishSend, a
1404
1491
  * CLEAN rejection emits `transfer:updated{status:'failed'}` here (§4). */
@@ -1436,9 +1523,8 @@ declare class PaymentsFacade implements PaymentsV2 {
1436
1523
  /** Nothing delivered → UNWRAPPED; after ≥1 delivered leg every failure surfaces as PartialSendConflictError over the settled set. */
1437
1524
  private softAbort;
1438
1525
  private mintInner;
1439
- /** A live mint under a fresh id — its replay stays hands-off while this attempt runs. */
1440
- private ownedMint;
1441
- private tokenInServerInventory;
1526
+ /** A live money op under a fresh id — its replay stays hands-off while this attempt runs (§7). */
1527
+ private ownedOp;
1442
1528
  private engine;
1443
1529
  private newId;
1444
1530
  private seedHeldStates;
@@ -1449,4 +1535,4 @@ declare class PaymentsFacade implements PaymentsV2 {
1449
1535
  declare const HEARTBEAT_SEED_MS = 5000;
1450
1536
  declare const HEARTBEAT_CAP_MS = 120000;
1451
1537
 
1452
- export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type AckOutcome, type AckRequest, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintNftRequest, type MintResult, NFT_DOCUMENT_MEDIA_TYPE, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintJournalEntry, type NftSignatureContext, type NftSignatureStatus, type NftView, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, type RetryableAckError, STORE_KEYS, type ScopedKV, type SendCoinlessRequest, type SendRequest, type SendWholeTokenRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, encodeNftContent, isNftDocumentLink, isRetryableAckError, parseNftDocument, parseNftPayload, supportsDeterministicMint, sweepSupersededState, verifyNftLinkContent };
1538
+ export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type AckOutcome, type AckRequest, type ApplyDeltaResult, type BurnJournalEntry, type BurnRequest, type BurnResult, type CheckpointReseeder, type ConnectionStatus, type CustomMintJournalEntry, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintCustomRequest, type MintJournalEntry, type MintNftRequest, type MintResult, NFT_DOCUMENT_MEDIA_TYPE, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintJournalEntry, type NftSignatureContext, type NftSignatureStatus, type NftView, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingBurn, type PendingTransfer, type PlannedOp, type RecipientInfo, type RetryableAckError, STORE_KEYS, type ScopedKV, type SendCoinlessRequest, type SendRequest, type SendWholeTokenRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, encodeNftContent, isNftDocumentLink, isRetryableAckError, parseNftDocument, parseNftPayload, supportsDeterministicMint, sweepSupersededState, verifyNftLinkContent };