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

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 (58) hide show
  1. package/dist/connect/chunks/{chunk-OAAY2JEA.js → chunk-7BZL7HE2.js} +3 -3
  2. package/dist/connect/chunks/{chunk-MQQ3TMHM.js → chunk-CJ4D6M6W.js} +2 -2
  3. package/dist/connect/chunks/{chunk-FGQ6CKKK.js → chunk-LDEOQNG2.js} +2 -2
  4. package/dist/connect/chunks/{chunk-FGQ6CKKK.js.map → chunk-LDEOQNG2.js.map} +1 -1
  5. package/dist/connect/chunks/{chunk-3CYK5SIU.js → chunk-WCKTUB4V.js} +1 -1
  6. package/dist/connect/chunks/chunk-WCKTUB4V.js.map +1 -0
  7. package/dist/connect/chunks/{chunk-JYBI36GK.js → chunk-WL6VYP7G.js} +2 -2
  8. package/dist/connect/index.cjs +1 -1
  9. package/dist/connect/index.cjs.map +1 -1
  10. package/dist/connect/index.js +5 -5
  11. package/dist/connect/internal/host.js +3 -3
  12. package/dist/connect/internal/nft-wire.js +2 -2
  13. package/dist/core/index.cjs +831 -343
  14. package/dist/core/index.cjs.map +1 -1
  15. package/dist/core/index.d.cts +30 -1
  16. package/dist/core/index.d.ts +30 -1
  17. package/dist/core/index.js +831 -343
  18. package/dist/core/index.js.map +1 -1
  19. package/dist/impl/browser/connect/index.cjs +1 -1
  20. package/dist/impl/browser/connect/index.cjs.map +1 -1
  21. package/dist/impl/browser/connect/index.js +2 -2
  22. package/dist/impl/browser/index.cjs.map +1 -1
  23. package/dist/impl/browser/index.js.map +1 -1
  24. package/dist/impl/nodejs/index.cjs.map +1 -1
  25. package/dist/impl/nodejs/index.d.cts +1 -0
  26. package/dist/impl/nodejs/index.d.ts +1 -0
  27. package/dist/impl/nodejs/index.js.map +1 -1
  28. package/dist/impl/shared/wallet-api/index.d.cts +1 -0
  29. package/dist/impl/shared/wallet-api/index.d.ts +1 -0
  30. package/dist/impl/wallet-api-v2/index.cjs +2 -1
  31. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  32. package/dist/impl/wallet-api-v2/index.d.cts +3 -0
  33. package/dist/impl/wallet-api-v2/index.d.ts +3 -0
  34. package/dist/impl/wallet-api-v2/index.js +2 -1
  35. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  36. package/dist/index.cjs +833 -343
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +32 -2
  39. package/dist/index.d.ts +32 -2
  40. package/dist/index.js +832 -343
  41. package/dist/index.js.map +1 -1
  42. package/dist/modules/payments-v2/index.cjs +658 -259
  43. package/dist/modules/payments-v2/index.cjs.map +1 -1
  44. package/dist/modules/payments-v2/index.d.cts +65 -2
  45. package/dist/modules/payments-v2/index.d.ts +65 -2
  46. package/dist/modules/payments-v2/index.js +656 -259
  47. package/dist/modules/payments-v2/index.js.map +1 -1
  48. package/dist/token-engine/index.cjs +185 -65
  49. package/dist/token-engine/index.cjs.map +1 -1
  50. package/dist/token-engine/index.d.cts +20 -3
  51. package/dist/token-engine/index.d.ts +20 -3
  52. package/dist/token-engine/index.js +184 -65
  53. package/dist/token-engine/index.js.map +1 -1
  54. package/package.json +1 -1
  55. package/dist/connect/chunks/chunk-3CYK5SIU.js.map +0 -1
  56. /package/dist/connect/chunks/{chunk-OAAY2JEA.js.map → chunk-7BZL7HE2.js.map} +0 -0
  57. /package/dist/connect/chunks/{chunk-MQQ3TMHM.js.map → chunk-CJ4D6M6W.js.map} +0 -0
  58. /package/dist/connect/chunks/{chunk-JYBI36GK.js.map → chunk-WL6VYP7G.js.map} +0 -0
@@ -1,5 +1,7 @@
1
1
  import { IMintJustificationVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/IMintJustificationVerifier.js';
2
2
  export { IMintJustificationVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/IMintJustificationVerifier.js';
3
+ import { ITokenIssuanceVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/ITokenIssuanceVerifier.js';
4
+ export { ITokenIssuanceVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/ITokenIssuanceVerifier.js';
3
5
  import { DataHash } from '@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHash.js';
4
6
  import { Token } from '@unicitylabs/state-transition-sdk/lib/transaction/Token.js';
5
7
  import { IPaymentData } from '@unicitylabs/state-transition-sdk/lib/payment/IPaymentData.js';
@@ -202,12 +204,21 @@ interface BurnParams {
202
204
  /** The recipient predicate is `BurnPredicate(sha256(reasonBytes))`; the bytes ride in the aux data. */
203
205
  readonly reasonBytes: Uint8Array;
204
206
  }
207
+ /** The issuance rule of one token type, and the coins no other type may carry. */
208
+ interface TokenIssuancePolicy extends ITokenIssuanceVerifier {
209
+ /** A token carrying one of these coins counts only when it is of this type and verified. */
210
+ readonly coinIds: readonly CoinId[];
211
+ /** Must change whenever the proofs this policy accepts change, a fix to its verification code included, so wallets check held tokens again. */
212
+ readonly revision?: string;
213
+ }
205
214
  /** Mint-reason verifiers keyed by CBOR tag, registered at engine construction. */
206
215
  interface TokenPlugin {
207
216
  /** Stable identifier for diagnostics, e.g. `'bridge:tron-usdt'`. */
208
217
  readonly id: string;
209
218
  /** Mint-reason verifiers to register; a duplicate tag across plugins is INVALID_CONFIG. */
210
219
  readonly mintJustificationVerifiers?: readonly IMintJustificationVerifier[];
220
+ /** Issuance policies to register; a duplicate token type or coin across plugins is INVALID_CONFIG. */
221
+ readonly tokenIssuancePolicies?: readonly TokenIssuancePolicy[];
211
222
  }
212
223
  /** Plan an NFT mint (#785); `mintDataToken` then mints the plan. */
213
224
  interface BuildNftMintParams {
@@ -403,6 +414,8 @@ interface ITokenEngine {
403
414
  * read its bytes via `readTokenData`. (Used e.g. for on-chain invoice tokens.)
404
415
  */
405
416
  mintDataToken(params: MintDataTokenParams, options?: EngineOpOptions): Promise<SphereToken>;
417
+ /** Throws VALIDATION_ERROR when `mintDataToken` would refuse `params` before submitting, e.g. a reason tag no registered verifier handles. */
418
+ assertMintable(params: MintDataTokenParams): void;
406
419
  /** Plan an NFT mint: encode (and optionally sign as this engine's identity) the payload and derive its token id. No chain op. */
407
420
  buildNftMint(params: BuildNftMintParams): Promise<NftMintPlan>;
408
421
  /** Spend a token wholesale to a recipient pubkey; returns the recipient's finished token. */
@@ -508,7 +521,7 @@ interface EngineConfig {
508
521
  * terminate the pool.
509
522
  */
510
523
  readonly verification?: VerificationWorkerConfig;
511
- /** Token plugins whose mint-reason verifiers join the engine's verification context. */
524
+ /** Token plugins whose mint-reason verifiers and issuance policies join the engine's verification context. */
512
525
  readonly plugins?: readonly TokenPlugin[];
513
526
  }
514
527
  /** Factory signature for the real adapter (implemented in Track A). */
@@ -571,7 +584,7 @@ declare function createSphereTokenEngine(config: EngineConfig): Promise<ITokenEn
571
584
  * }
572
585
  * ```
573
586
  */
574
- type SphereErrorCode = 'NOT_INITIALIZED' | 'ALREADY_INITIALIZED' | 'INVALID_CONFIG' | 'INVALID_IDENTITY' | 'INSUFFICIENT_BALANCE' | 'INVALID_RECIPIENT' | 'TRANSFER_FAILED' | 'TRANSFER_CONFLICT' | 'CERTIFICATION_UNCONFIRMED' | 'CHECKPOINT_PERSIST_FAILED' | 'SPLIT_CHECKPOINT_LOST' | 'CHECKPOINT_TRUSTBASE_MISMATCH' | 'STORAGE_ERROR' | 'SEND_SYNC_PENDING' | 'SEND_PARTIALLY_COMPLETED' | 'TRANSPORT_ERROR' | 'AGGREGATOR_ERROR' | 'VALIDATION_ERROR' | 'INVALID_AMOUNT' | 'NETWORK_ERROR' | 'TIMEOUT' | 'DECRYPTION_ERROR' | 'MODULE_NOT_AVAILABLE' | 'PAYMENTS_NOT_COMPOSED' | 'SIGNING_ERROR' | 'SEND_QUEUE_TIMEOUT' | 'SEND_INSUFFICIENT_BALANCE' | 'SEND_RESERVATION_CANCELLED' | 'SEND_QUEUE_FULL' | 'MODULE_DESTROYED' | 'REENTRANT_GATE' | 'INVOICE_NO_TARGETS' | 'INVOICE_INVALID_ADDRESS' | 'INVOICE_NO_ASSETS' | 'INVOICE_INVALID_ASSET' | 'INVOICE_INVALID_AMOUNT' | 'INVOICE_INVALID_COIN' | 'INVOICE_INVALID_NFT' | 'INVOICE_PAST_DUE_DATE' | 'INVOICE_DUPLICATE_ADDRESS' | 'INVOICE_DUPLICATE_COIN' | 'INVOICE_DUPLICATE_NFT' | 'INVOICE_MINT_FAILED' | 'INVOICE_INVALID_PROOF' | 'INVOICE_WRONG_TOKEN_TYPE' | 'INVOICE_INVALID_DATA' | 'INVOICE_ALREADY_EXISTS' | 'INVOICE_NOT_FOUND' | 'INVOICE_NOT_TARGET' | 'INVOICE_ALREADY_CLOSED' | 'INVOICE_ALREADY_CANCELLED' | 'INVOICE_ORACLE_REQUIRED' | 'INVOICE_TERMINATED' | 'INVOICE_INVALID_TARGET' | 'INVOICE_INVALID_ASSET_INDEX' | 'INVOICE_RETURN_EXCEEDS_BALANCE' | 'INVOICE_INVALID_DELIVERY_METHOD' | 'INVOICE_INVALID_REFUND_ADDRESS' | 'INVOICE_INVALID_CONTACT' | 'INVOICE_INVALID_ID' | 'INVOICE_TOO_MANY_TARGETS' | 'INVOICE_TOO_MANY_ASSETS' | 'INVOICE_MEMO_TOO_LONG' | 'INVOICE_TERMS_TOO_LARGE' | 'INVOICE_NOT_TERMINATED' | 'INVOICE_NOT_CANCELLED' | 'INVOICE_STORAGE_FAILED' | 'RATE_LIMITED' | 'COMMUNICATIONS_UNAVAILABLE' | 'SWAP_INVALID_DEAL' | 'SWAP_INVALID_MANIFEST' | 'SWAP_NOT_FOUND' | 'SWAP_WRONG_STATE' | 'SWAP_RESOLVE_FAILED' | 'SWAP_DM_SEND_FAILED' | 'SWAP_ESCROW_REJECTED' | 'SWAP_DEPOSIT_FAILED' | 'SWAP_PAYOUT_VERIFICATION_FAILED' | 'SWAP_ALREADY_EXISTS' | 'SWAP_ALREADY_COMPLETED' | 'SWAP_ALREADY_CANCELLED' | 'SWAP_TIMEOUT' | 'SWAP_LIMIT_EXCEEDED' | 'SWAP_ALREADY_INITIALIZED' | 'SWAP_MODULE_DESTROYED' | 'SWAP_NOT_INITIALIZED';
587
+ type SphereErrorCode = 'NOT_INITIALIZED' | 'ALREADY_INITIALIZED' | 'INVALID_CONFIG' | 'INVALID_IDENTITY' | 'INSUFFICIENT_BALANCE' | 'INVALID_RECIPIENT' | 'TRANSFER_FAILED' | 'TRANSFER_CONFLICT' | 'CERTIFICATION_UNCONFIRMED' | 'CHECKPOINT_PERSIST_FAILED' | 'SPLIT_CHECKPOINT_LOST' | 'CHECKPOINT_TRUSTBASE_MISMATCH' | 'MINT_REASON_UNVERIFIABLE' | 'STORAGE_ERROR' | 'SEND_SYNC_PENDING' | 'SEND_PARTIALLY_COMPLETED' | 'TRANSPORT_ERROR' | 'AGGREGATOR_ERROR' | 'VALIDATION_ERROR' | 'INVALID_AMOUNT' | 'NETWORK_ERROR' | 'TIMEOUT' | 'DECRYPTION_ERROR' | 'MODULE_NOT_AVAILABLE' | 'PAYMENTS_NOT_COMPOSED' | 'SIGNING_ERROR' | 'SEND_QUEUE_TIMEOUT' | 'SEND_INSUFFICIENT_BALANCE' | 'SEND_RESERVATION_CANCELLED' | 'SEND_QUEUE_FULL' | 'MODULE_DESTROYED' | 'REENTRANT_GATE' | 'INVOICE_NO_TARGETS' | 'INVOICE_INVALID_ADDRESS' | 'INVOICE_NO_ASSETS' | 'INVOICE_INVALID_ASSET' | 'INVOICE_INVALID_AMOUNT' | 'INVOICE_INVALID_COIN' | 'INVOICE_INVALID_NFT' | 'INVOICE_PAST_DUE_DATE' | 'INVOICE_DUPLICATE_ADDRESS' | 'INVOICE_DUPLICATE_COIN' | 'INVOICE_DUPLICATE_NFT' | 'INVOICE_MINT_FAILED' | 'INVOICE_INVALID_PROOF' | 'INVOICE_WRONG_TOKEN_TYPE' | 'INVOICE_INVALID_DATA' | 'INVOICE_ALREADY_EXISTS' | 'INVOICE_NOT_FOUND' | 'INVOICE_NOT_TARGET' | 'INVOICE_ALREADY_CLOSED' | 'INVOICE_ALREADY_CANCELLED' | 'INVOICE_ORACLE_REQUIRED' | 'INVOICE_TERMINATED' | 'INVOICE_INVALID_TARGET' | 'INVOICE_INVALID_ASSET_INDEX' | 'INVOICE_RETURN_EXCEEDS_BALANCE' | 'INVOICE_INVALID_DELIVERY_METHOD' | 'INVOICE_INVALID_REFUND_ADDRESS' | 'INVOICE_INVALID_CONTACT' | 'INVOICE_INVALID_ID' | 'INVOICE_TOO_MANY_TARGETS' | 'INVOICE_TOO_MANY_ASSETS' | 'INVOICE_MEMO_TOO_LONG' | 'INVOICE_TERMS_TOO_LARGE' | 'INVOICE_NOT_TERMINATED' | 'INVOICE_NOT_CANCELLED' | 'INVOICE_STORAGE_FAILED' | 'RATE_LIMITED' | 'COMMUNICATIONS_UNAVAILABLE' | 'SWAP_INVALID_DEAL' | 'SWAP_INVALID_MANIFEST' | 'SWAP_NOT_FOUND' | 'SWAP_WRONG_STATE' | 'SWAP_RESOLVE_FAILED' | 'SWAP_DM_SEND_FAILED' | 'SWAP_ESCROW_REJECTED' | 'SWAP_DEPOSIT_FAILED' | 'SWAP_PAYOUT_VERIFICATION_FAILED' | 'SWAP_ALREADY_EXISTS' | 'SWAP_ALREADY_COMPLETED' | 'SWAP_ALREADY_CANCELLED' | 'SWAP_TIMEOUT' | 'SWAP_LIMIT_EXCEEDED' | 'SWAP_ALREADY_INITIALIZED' | 'SWAP_MODULE_DESTROYED' | 'SWAP_NOT_INITIALIZED';
575
588
  declare class SphereError extends Error {
576
589
  readonly code: SphereErrorCode;
577
590
  readonly cause?: unknown;
@@ -623,6 +636,10 @@ declare class TransferConflictError extends SphereError {
623
636
  * certified proof + recipient blob, or records the spend if a foreign tx won the
624
637
  * race — never a second on-chain spend (sdk-changes E.2/E.3, #631).
625
638
  */
639
+ /** A token's mint reason cannot be judged yet: no verifier for its tag here, or the plugin could not reach an answer. */
640
+ declare class MintReasonUnverifiableError extends SphereError {
641
+ constructor(message: string, cause?: unknown);
642
+ }
626
643
  declare class ProofUnconfirmedError extends SphereError {
627
644
  readonly mayHaveCertified: true;
628
645
  constructor(message: string, cause?: unknown);
@@ -715,4 +732,4 @@ declare class SpherePaymentData implements IPaymentData {
715
732
  */
716
733
  declare function decodeSpherePaymentData(bytes: Uint8Array): Promise<IPaymentData>;
717
734
 
718
- export { type BuildNftMintParams, type BurnParams, CheckpointPersistFailedError, CheckpointTrustbaseMismatchError, type CoinId, type CreateTokenEngine, type EngineConfig, type EngineIdentity, type EngineOpOptions, type EngineVerifyResult, type ITokenEngine, type MintDataTokenParams, type MintParams, NFT_DOCUMENT_MEDIA_TYPE, NFT_FORMAT_VERSION, NFT_LINK_TAG, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintPlan, type NftReading, type NftSignatureContext, type NftSignatureStatus, type ParsedNft, ProofUnconfirmedError, type SphereAsset, type SphereNetwork, SpherePaymentData, type SphereToken, type SphereValue, SplitCheckpointLostError, type SplitCheckpointStore, type SplitOutput, type SplitParams, type SplitResult, type TokenBlob, type TokenPlugin, TransferConflictError, type TransferParams, type VerificationWorker, type VerificationWorkerConfig, createSphereTokenEngine, decodeSpherePaymentData, deriveDirectAddress, encodeNftContent, encodeNftSigned, isNftDocumentLink, nftSignedDigest, parseNftDocument, parseNftPayload, sphereAssetToSdk, verifyNftLinkContent, verifyNftSignature };
735
+ export { type BuildNftMintParams, type BurnParams, CheckpointPersistFailedError, CheckpointTrustbaseMismatchError, type CoinId, type CreateTokenEngine, type EngineConfig, type EngineIdentity, type EngineOpOptions, type EngineVerifyResult, type ITokenEngine, type MintDataTokenParams, type MintParams, MintReasonUnverifiableError, NFT_DOCUMENT_MEDIA_TYPE, NFT_FORMAT_VERSION, NFT_LINK_TAG, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintPlan, type NftReading, type NftSignatureContext, type NftSignatureStatus, type ParsedNft, ProofUnconfirmedError, type SphereAsset, type SphereNetwork, SpherePaymentData, type SphereToken, type SphereValue, SplitCheckpointLostError, type SplitCheckpointStore, type SplitOutput, type SplitParams, type SplitResult, type TokenBlob, type TokenIssuancePolicy, type TokenPlugin, TransferConflictError, type TransferParams, type VerificationWorker, type VerificationWorkerConfig, createSphereTokenEngine, decodeSpherePaymentData, deriveDirectAddress, encodeNftContent, encodeNftSigned, isNftDocumentLink, nftSignedDigest, parseNftDocument, parseNftPayload, sphereAssetToSdk, verifyNftLinkContent, verifyNftSignature };
@@ -1,5 +1,7 @@
1
1
  import { IMintJustificationVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/IMintJustificationVerifier.js';
2
2
  export { IMintJustificationVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/IMintJustificationVerifier.js';
3
+ import { ITokenIssuanceVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/ITokenIssuanceVerifier.js';
4
+ export { ITokenIssuanceVerifier } from '@unicitylabs/state-transition-sdk/lib/transaction/verification/ITokenIssuanceVerifier.js';
3
5
  import { DataHash } from '@unicitylabs/state-transition-sdk/lib/crypto/hash/DataHash.js';
4
6
  import { Token } from '@unicitylabs/state-transition-sdk/lib/transaction/Token.js';
5
7
  import { IPaymentData } from '@unicitylabs/state-transition-sdk/lib/payment/IPaymentData.js';
@@ -202,12 +204,21 @@ interface BurnParams {
202
204
  /** The recipient predicate is `BurnPredicate(sha256(reasonBytes))`; the bytes ride in the aux data. */
203
205
  readonly reasonBytes: Uint8Array;
204
206
  }
207
+ /** The issuance rule of one token type, and the coins no other type may carry. */
208
+ interface TokenIssuancePolicy extends ITokenIssuanceVerifier {
209
+ /** A token carrying one of these coins counts only when it is of this type and verified. */
210
+ readonly coinIds: readonly CoinId[];
211
+ /** Must change whenever the proofs this policy accepts change, a fix to its verification code included, so wallets check held tokens again. */
212
+ readonly revision?: string;
213
+ }
205
214
  /** Mint-reason verifiers keyed by CBOR tag, registered at engine construction. */
206
215
  interface TokenPlugin {
207
216
  /** Stable identifier for diagnostics, e.g. `'bridge:tron-usdt'`. */
208
217
  readonly id: string;
209
218
  /** Mint-reason verifiers to register; a duplicate tag across plugins is INVALID_CONFIG. */
210
219
  readonly mintJustificationVerifiers?: readonly IMintJustificationVerifier[];
220
+ /** Issuance policies to register; a duplicate token type or coin across plugins is INVALID_CONFIG. */
221
+ readonly tokenIssuancePolicies?: readonly TokenIssuancePolicy[];
211
222
  }
212
223
  /** Plan an NFT mint (#785); `mintDataToken` then mints the plan. */
213
224
  interface BuildNftMintParams {
@@ -403,6 +414,8 @@ interface ITokenEngine {
403
414
  * read its bytes via `readTokenData`. (Used e.g. for on-chain invoice tokens.)
404
415
  */
405
416
  mintDataToken(params: MintDataTokenParams, options?: EngineOpOptions): Promise<SphereToken>;
417
+ /** Throws VALIDATION_ERROR when `mintDataToken` would refuse `params` before submitting, e.g. a reason tag no registered verifier handles. */
418
+ assertMintable(params: MintDataTokenParams): void;
406
419
  /** Plan an NFT mint: encode (and optionally sign as this engine's identity) the payload and derive its token id. No chain op. */
407
420
  buildNftMint(params: BuildNftMintParams): Promise<NftMintPlan>;
408
421
  /** Spend a token wholesale to a recipient pubkey; returns the recipient's finished token. */
@@ -508,7 +521,7 @@ interface EngineConfig {
508
521
  * terminate the pool.
509
522
  */
510
523
  readonly verification?: VerificationWorkerConfig;
511
- /** Token plugins whose mint-reason verifiers join the engine's verification context. */
524
+ /** Token plugins whose mint-reason verifiers and issuance policies join the engine's verification context. */
512
525
  readonly plugins?: readonly TokenPlugin[];
513
526
  }
514
527
  /** Factory signature for the real adapter (implemented in Track A). */
@@ -571,7 +584,7 @@ declare function createSphereTokenEngine(config: EngineConfig): Promise<ITokenEn
571
584
  * }
572
585
  * ```
573
586
  */
574
- type SphereErrorCode = 'NOT_INITIALIZED' | 'ALREADY_INITIALIZED' | 'INVALID_CONFIG' | 'INVALID_IDENTITY' | 'INSUFFICIENT_BALANCE' | 'INVALID_RECIPIENT' | 'TRANSFER_FAILED' | 'TRANSFER_CONFLICT' | 'CERTIFICATION_UNCONFIRMED' | 'CHECKPOINT_PERSIST_FAILED' | 'SPLIT_CHECKPOINT_LOST' | 'CHECKPOINT_TRUSTBASE_MISMATCH' | 'STORAGE_ERROR' | 'SEND_SYNC_PENDING' | 'SEND_PARTIALLY_COMPLETED' | 'TRANSPORT_ERROR' | 'AGGREGATOR_ERROR' | 'VALIDATION_ERROR' | 'INVALID_AMOUNT' | 'NETWORK_ERROR' | 'TIMEOUT' | 'DECRYPTION_ERROR' | 'MODULE_NOT_AVAILABLE' | 'PAYMENTS_NOT_COMPOSED' | 'SIGNING_ERROR' | 'SEND_QUEUE_TIMEOUT' | 'SEND_INSUFFICIENT_BALANCE' | 'SEND_RESERVATION_CANCELLED' | 'SEND_QUEUE_FULL' | 'MODULE_DESTROYED' | 'REENTRANT_GATE' | 'INVOICE_NO_TARGETS' | 'INVOICE_INVALID_ADDRESS' | 'INVOICE_NO_ASSETS' | 'INVOICE_INVALID_ASSET' | 'INVOICE_INVALID_AMOUNT' | 'INVOICE_INVALID_COIN' | 'INVOICE_INVALID_NFT' | 'INVOICE_PAST_DUE_DATE' | 'INVOICE_DUPLICATE_ADDRESS' | 'INVOICE_DUPLICATE_COIN' | 'INVOICE_DUPLICATE_NFT' | 'INVOICE_MINT_FAILED' | 'INVOICE_INVALID_PROOF' | 'INVOICE_WRONG_TOKEN_TYPE' | 'INVOICE_INVALID_DATA' | 'INVOICE_ALREADY_EXISTS' | 'INVOICE_NOT_FOUND' | 'INVOICE_NOT_TARGET' | 'INVOICE_ALREADY_CLOSED' | 'INVOICE_ALREADY_CANCELLED' | 'INVOICE_ORACLE_REQUIRED' | 'INVOICE_TERMINATED' | 'INVOICE_INVALID_TARGET' | 'INVOICE_INVALID_ASSET_INDEX' | 'INVOICE_RETURN_EXCEEDS_BALANCE' | 'INVOICE_INVALID_DELIVERY_METHOD' | 'INVOICE_INVALID_REFUND_ADDRESS' | 'INVOICE_INVALID_CONTACT' | 'INVOICE_INVALID_ID' | 'INVOICE_TOO_MANY_TARGETS' | 'INVOICE_TOO_MANY_ASSETS' | 'INVOICE_MEMO_TOO_LONG' | 'INVOICE_TERMS_TOO_LARGE' | 'INVOICE_NOT_TERMINATED' | 'INVOICE_NOT_CANCELLED' | 'INVOICE_STORAGE_FAILED' | 'RATE_LIMITED' | 'COMMUNICATIONS_UNAVAILABLE' | 'SWAP_INVALID_DEAL' | 'SWAP_INVALID_MANIFEST' | 'SWAP_NOT_FOUND' | 'SWAP_WRONG_STATE' | 'SWAP_RESOLVE_FAILED' | 'SWAP_DM_SEND_FAILED' | 'SWAP_ESCROW_REJECTED' | 'SWAP_DEPOSIT_FAILED' | 'SWAP_PAYOUT_VERIFICATION_FAILED' | 'SWAP_ALREADY_EXISTS' | 'SWAP_ALREADY_COMPLETED' | 'SWAP_ALREADY_CANCELLED' | 'SWAP_TIMEOUT' | 'SWAP_LIMIT_EXCEEDED' | 'SWAP_ALREADY_INITIALIZED' | 'SWAP_MODULE_DESTROYED' | 'SWAP_NOT_INITIALIZED';
587
+ type SphereErrorCode = 'NOT_INITIALIZED' | 'ALREADY_INITIALIZED' | 'INVALID_CONFIG' | 'INVALID_IDENTITY' | 'INSUFFICIENT_BALANCE' | 'INVALID_RECIPIENT' | 'TRANSFER_FAILED' | 'TRANSFER_CONFLICT' | 'CERTIFICATION_UNCONFIRMED' | 'CHECKPOINT_PERSIST_FAILED' | 'SPLIT_CHECKPOINT_LOST' | 'CHECKPOINT_TRUSTBASE_MISMATCH' | 'MINT_REASON_UNVERIFIABLE' | 'STORAGE_ERROR' | 'SEND_SYNC_PENDING' | 'SEND_PARTIALLY_COMPLETED' | 'TRANSPORT_ERROR' | 'AGGREGATOR_ERROR' | 'VALIDATION_ERROR' | 'INVALID_AMOUNT' | 'NETWORK_ERROR' | 'TIMEOUT' | 'DECRYPTION_ERROR' | 'MODULE_NOT_AVAILABLE' | 'PAYMENTS_NOT_COMPOSED' | 'SIGNING_ERROR' | 'SEND_QUEUE_TIMEOUT' | 'SEND_INSUFFICIENT_BALANCE' | 'SEND_RESERVATION_CANCELLED' | 'SEND_QUEUE_FULL' | 'MODULE_DESTROYED' | 'REENTRANT_GATE' | 'INVOICE_NO_TARGETS' | 'INVOICE_INVALID_ADDRESS' | 'INVOICE_NO_ASSETS' | 'INVOICE_INVALID_ASSET' | 'INVOICE_INVALID_AMOUNT' | 'INVOICE_INVALID_COIN' | 'INVOICE_INVALID_NFT' | 'INVOICE_PAST_DUE_DATE' | 'INVOICE_DUPLICATE_ADDRESS' | 'INVOICE_DUPLICATE_COIN' | 'INVOICE_DUPLICATE_NFT' | 'INVOICE_MINT_FAILED' | 'INVOICE_INVALID_PROOF' | 'INVOICE_WRONG_TOKEN_TYPE' | 'INVOICE_INVALID_DATA' | 'INVOICE_ALREADY_EXISTS' | 'INVOICE_NOT_FOUND' | 'INVOICE_NOT_TARGET' | 'INVOICE_ALREADY_CLOSED' | 'INVOICE_ALREADY_CANCELLED' | 'INVOICE_ORACLE_REQUIRED' | 'INVOICE_TERMINATED' | 'INVOICE_INVALID_TARGET' | 'INVOICE_INVALID_ASSET_INDEX' | 'INVOICE_RETURN_EXCEEDS_BALANCE' | 'INVOICE_INVALID_DELIVERY_METHOD' | 'INVOICE_INVALID_REFUND_ADDRESS' | 'INVOICE_INVALID_CONTACT' | 'INVOICE_INVALID_ID' | 'INVOICE_TOO_MANY_TARGETS' | 'INVOICE_TOO_MANY_ASSETS' | 'INVOICE_MEMO_TOO_LONG' | 'INVOICE_TERMS_TOO_LARGE' | 'INVOICE_NOT_TERMINATED' | 'INVOICE_NOT_CANCELLED' | 'INVOICE_STORAGE_FAILED' | 'RATE_LIMITED' | 'COMMUNICATIONS_UNAVAILABLE' | 'SWAP_INVALID_DEAL' | 'SWAP_INVALID_MANIFEST' | 'SWAP_NOT_FOUND' | 'SWAP_WRONG_STATE' | 'SWAP_RESOLVE_FAILED' | 'SWAP_DM_SEND_FAILED' | 'SWAP_ESCROW_REJECTED' | 'SWAP_DEPOSIT_FAILED' | 'SWAP_PAYOUT_VERIFICATION_FAILED' | 'SWAP_ALREADY_EXISTS' | 'SWAP_ALREADY_COMPLETED' | 'SWAP_ALREADY_CANCELLED' | 'SWAP_TIMEOUT' | 'SWAP_LIMIT_EXCEEDED' | 'SWAP_ALREADY_INITIALIZED' | 'SWAP_MODULE_DESTROYED' | 'SWAP_NOT_INITIALIZED';
575
588
  declare class SphereError extends Error {
576
589
  readonly code: SphereErrorCode;
577
590
  readonly cause?: unknown;
@@ -623,6 +636,10 @@ declare class TransferConflictError extends SphereError {
623
636
  * certified proof + recipient blob, or records the spend if a foreign tx won the
624
637
  * race — never a second on-chain spend (sdk-changes E.2/E.3, #631).
625
638
  */
639
+ /** A token's mint reason cannot be judged yet: no verifier for its tag here, or the plugin could not reach an answer. */
640
+ declare class MintReasonUnverifiableError extends SphereError {
641
+ constructor(message: string, cause?: unknown);
642
+ }
626
643
  declare class ProofUnconfirmedError extends SphereError {
627
644
  readonly mayHaveCertified: true;
628
645
  constructor(message: string, cause?: unknown);
@@ -715,4 +732,4 @@ declare class SpherePaymentData implements IPaymentData {
715
732
  */
716
733
  declare function decodeSpherePaymentData(bytes: Uint8Array): Promise<IPaymentData>;
717
734
 
718
- export { type BuildNftMintParams, type BurnParams, CheckpointPersistFailedError, CheckpointTrustbaseMismatchError, type CoinId, type CreateTokenEngine, type EngineConfig, type EngineIdentity, type EngineOpOptions, type EngineVerifyResult, type ITokenEngine, type MintDataTokenParams, type MintParams, NFT_DOCUMENT_MEDIA_TYPE, NFT_FORMAT_VERSION, NFT_LINK_TAG, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintPlan, type NftReading, type NftSignatureContext, type NftSignatureStatus, type ParsedNft, ProofUnconfirmedError, type SphereAsset, type SphereNetwork, SpherePaymentData, type SphereToken, type SphereValue, SplitCheckpointLostError, type SplitCheckpointStore, type SplitOutput, type SplitParams, type SplitResult, type TokenBlob, type TokenPlugin, TransferConflictError, type TransferParams, type VerificationWorker, type VerificationWorkerConfig, createSphereTokenEngine, decodeSpherePaymentData, deriveDirectAddress, encodeNftContent, encodeNftSigned, isNftDocumentLink, nftSignedDigest, parseNftDocument, parseNftPayload, sphereAssetToSdk, verifyNftLinkContent, verifyNftSignature };
735
+ export { type BuildNftMintParams, type BurnParams, CheckpointPersistFailedError, CheckpointTrustbaseMismatchError, type CoinId, type CreateTokenEngine, type EngineConfig, type EngineIdentity, type EngineOpOptions, type EngineVerifyResult, type ITokenEngine, type MintDataTokenParams, type MintParams, MintReasonUnverifiableError, NFT_DOCUMENT_MEDIA_TYPE, NFT_FORMAT_VERSION, NFT_LINK_TAG, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintPlan, type NftReading, type NftSignatureContext, type NftSignatureStatus, type ParsedNft, ProofUnconfirmedError, type SphereAsset, type SphereNetwork, SpherePaymentData, type SphereToken, type SphereValue, SplitCheckpointLostError, type SplitCheckpointStore, type SplitOutput, type SplitParams, type SplitResult, type TokenBlob, type TokenIssuancePolicy, type TokenPlugin, TransferConflictError, type TransferParams, type VerificationWorker, type VerificationWorkerConfig, createSphereTokenEngine, decodeSpherePaymentData, deriveDirectAddress, encodeNftContent, encodeNftSigned, isNftDocumentLink, nftSignedDigest, parseNftDocument, parseNftPayload, sphereAssetToSdk, verifyNftLinkContent, verifyNftSignature };
@@ -203,6 +203,150 @@ var logger = {
203
203
  }
204
204
  };
205
205
 
206
+ // token-engine/claims.ts
207
+ var CoinClaims = class _CoinClaims {
208
+ issuers = /* @__PURE__ */ new Map();
209
+ policies = [];
210
+ static fromPlugins(plugins) {
211
+ const claims = new _CoinClaims();
212
+ for (const plugin of plugins ?? []) {
213
+ for (const policy of plugin.tokenIssuancePolicies ?? []) claims.add(policy);
214
+ }
215
+ return claims;
216
+ }
217
+ add(policy) {
218
+ const tokenType = HexConverter.encode(policy.tokenType.bytes);
219
+ const coinIds = policy.coinIds.map((coinId) => coinId.toLowerCase());
220
+ const taken = coinIds.find((coinId) => this.issuers.has(coinId));
221
+ if (taken !== void 0) throw new Error(`Coin ${taken} is already issued by token type ${this.issuers.get(taken)}.`);
222
+ for (const coinId of coinIds) this.issuers.set(coinId, tokenType);
223
+ this.policies.push(JSON.stringify([tokenType, [...coinIds].sort(), policy.revision ?? ""]));
224
+ }
225
+ fingerprint() {
226
+ return [...this.policies].sort().join("\n");
227
+ }
228
+ issuerOf(coinId) {
229
+ return this.issuers.get(coinId.toLowerCase()) ?? null;
230
+ }
231
+ };
232
+
233
+ // token-engine/errors.ts
234
+ var TransferConflictError = class extends SphereError {
235
+ /**
236
+ * #625: the source token id (the caller's id, e.g. `v2_<genesis>`) whose state was already spent.
237
+ * Set by PaymentsModule at the engine call site so the self-healing retry can demote it and re-plan.
238
+ */
239
+ conflictedSourceId;
240
+ constructor(message, cause) {
241
+ super(message, "TRANSFER_CONFLICT", cause);
242
+ this.name = "TransferConflictError";
243
+ }
244
+ };
245
+ var MintReasonUnverifiableError = class extends SphereError {
246
+ constructor(message, cause) {
247
+ super(message, "MINT_REASON_UNVERIFIABLE", cause);
248
+ this.name = "MintReasonUnverifiableError";
249
+ }
250
+ };
251
+ var ProofUnconfirmedError = class extends SphereError {
252
+ mayHaveCertified = true;
253
+ constructor(message, cause) {
254
+ super(message, "CERTIFICATION_UNCONFIRMED", cause);
255
+ this.name = "ProofUnconfirmedError";
256
+ }
257
+ };
258
+ var CheckpointPersistFailedError = class extends SphereError {
259
+ mayHaveCertified = true;
260
+ constructor(message, cause) {
261
+ super(message, "CHECKPOINT_PERSIST_FAILED", cause);
262
+ this.name = "CheckpointPersistFailedError";
263
+ }
264
+ };
265
+ var SplitCheckpointLostError = class extends SphereError {
266
+ constructor(message, cause) {
267
+ super(message, "SPLIT_CHECKPOINT_LOST", cause);
268
+ this.name = "SplitCheckpointLostError";
269
+ }
270
+ };
271
+ var CheckpointTrustbaseMismatchError = class extends SphereError {
272
+ constructor(message, cause) {
273
+ super(message, "CHECKPOINT_TRUSTBASE_MISMATCH", cause);
274
+ this.name = "CheckpointTrustbaseMismatchError";
275
+ }
276
+ };
277
+ function isKeepOpenSplitError(err) {
278
+ return err instanceof ProofUnconfirmedError || err instanceof CheckpointPersistFailedError || err instanceof SplitCheckpointLostError || err instanceof CheckpointTrustbaseMismatchError;
279
+ }
280
+
281
+ // token-engine/mint-reasons.ts
282
+ var RULE = "MintJustificationVerification";
283
+ var MintReasonRegistry = class _MintReasonRegistry extends MintJustificationVerifierService {
284
+ byTag = /* @__PURE__ */ new Map();
285
+ pluginTags = /* @__PURE__ */ new Set();
286
+ register(verifier) {
287
+ super.register(verifier);
288
+ this.byTag.set(verifier.tag, verifier);
289
+ return this;
290
+ }
291
+ registerPlugin(verifier) {
292
+ this.register(verifier);
293
+ this.pluginTags.add(verifier.tag);
294
+ return this;
295
+ }
296
+ async verify(transaction, nestedTokenCollector) {
297
+ const tag = transaction.justification ? reasonTag(transaction.justification) : null;
298
+ if (tag === null) return super.verify(transaction, nestedTokenCollector);
299
+ const verifier = this.byTag.get(tag);
300
+ if (verifier === void 0) throw new MintReasonUnverifiableError(`No verifier is registered for mint-reason tag ${tag}`);
301
+ if (!this.pluginTags.has(tag)) return super.verify(transaction, nestedTokenCollector);
302
+ return verifyPlugin(verifier, transaction, nestedTokenCollector);
303
+ }
304
+ knows(tag) {
305
+ return this.byTag.has(tag);
306
+ }
307
+ /** `verifiers` replace the registered ones of their tags; a tag this registry lacks is refused. */
308
+ overlaid(verifiers) {
309
+ for (const verifier of verifiers) assertKnown(this, verifier.tag);
310
+ const replaced = new Map(verifiers.map((verifier) => [verifier.tag, verifier]));
311
+ const overlay = new _MintReasonRegistry();
312
+ for (const [tag, verifier] of this.byTag) {
313
+ const perCall = replaced.get(tag);
314
+ if (perCall !== void 0 || this.pluginTags.has(tag)) overlay.registerPlugin(perCall ?? verifier);
315
+ else overlay.register(verifier);
316
+ }
317
+ return overlay;
318
+ }
319
+ assertVerifiable(justification) {
320
+ const tag = reasonTag(justification);
321
+ if (tag === null) throw new SphereError("The mint reason is not tagged CBOR", "VALIDATION_ERROR");
322
+ assertKnown(this, tag);
323
+ }
324
+ };
325
+ function reasonTag(justification) {
326
+ try {
327
+ return BigInt(CborDeserializer.decodeTag(justification).tag);
328
+ } catch {
329
+ return null;
330
+ }
331
+ }
332
+ async function verifyPlugin(verifier, transaction, nestedTokenCollector) {
333
+ let result;
334
+ try {
335
+ result = await verifier.verify(transaction, nestedTokenCollector);
336
+ } catch (err) {
337
+ const why = err instanceof Error ? err.message : String(err);
338
+ throw new MintReasonUnverifiableError(`Mint-reason tag ${verifier.tag} cannot be verified yet: ${why}`, err);
339
+ }
340
+ return result.status === VerificationStatus.OK ? new VerificationResult(RULE, VerificationStatus.OK, "", [result]) : new VerificationResult(RULE, VerificationStatus.FAIL, `Verification failed for tag ${verifier.tag}.`, [result]);
341
+ }
342
+ function assertKnown(registry, tag) {
343
+ if (registry.knows(tag)) return;
344
+ throw new SphereError(
345
+ `No verifier is registered on the engine for mint-reason tag ${tag}, so a replay of this mint could never verify`,
346
+ "VALIDATION_ERROR"
347
+ );
348
+ }
349
+
206
350
  // token-engine/SpherePaymentData.ts
207
351
  var COIN_ID_PATTERN = /^([0-9a-f]{2})+$/;
208
352
  function assertAsset(coinId, amount) {
@@ -723,45 +867,6 @@ async function awaitProofBounded(deps, transaction, signal) {
723
867
  return value;
724
868
  }
725
869
 
726
- // token-engine/errors.ts
727
- var TransferConflictError = class extends SphereError {
728
- /**
729
- * #625: the source token id (the caller's id, e.g. `v2_<genesis>`) whose state was already spent.
730
- * Set by PaymentsModule at the engine call site so the self-healing retry can demote it and re-plan.
731
- */
732
- conflictedSourceId;
733
- constructor(message, cause) {
734
- super(message, "TRANSFER_CONFLICT", cause);
735
- this.name = "TransferConflictError";
736
- }
737
- };
738
- var ProofUnconfirmedError = class extends SphereError {
739
- mayHaveCertified = true;
740
- constructor(message, cause) {
741
- super(message, "CERTIFICATION_UNCONFIRMED", cause);
742
- this.name = "ProofUnconfirmedError";
743
- }
744
- };
745
- var CheckpointPersistFailedError = class extends SphereError {
746
- mayHaveCertified = true;
747
- constructor(message, cause) {
748
- super(message, "CHECKPOINT_PERSIST_FAILED", cause);
749
- this.name = "CheckpointPersistFailedError";
750
- }
751
- };
752
- var SplitCheckpointLostError = class extends SphereError {
753
- constructor(message, cause) {
754
- super(message, "SPLIT_CHECKPOINT_LOST", cause);
755
- this.name = "SplitCheckpointLostError";
756
- }
757
- };
758
- var CheckpointTrustbaseMismatchError = class extends SphereError {
759
- constructor(message, cause) {
760
- super(message, "CHECKPOINT_TRUSTBASE_MISMATCH", cause);
761
- this.name = "CheckpointTrustbaseMismatchError";
762
- }
763
- };
764
-
765
870
  // token-engine/certification-outcome.ts
766
871
  function certificationFailure(err, failLabel, submitError, submitRejectedCleanly) {
767
872
  if (err instanceof Error && err.message === `Invalid inclusion proof status: ${InclusionProofVerificationStatus.TRANSACTION_HASH_MISMATCH}`) {
@@ -1426,15 +1531,17 @@ async function readTokenNft(token) {
1426
1531
  }
1427
1532
 
1428
1533
  // token-engine/plugin-ops.ts
1429
- function contextWithMintVerifiers(base, verifiers) {
1430
- const registry = new MintJustificationVerifierService();
1431
- for (const verifier of verifiers) registry.register(verifier);
1534
+ function mintContext(deps, params) {
1535
+ assertMintableData(params.data);
1536
+ if (params.justification !== void 0) deps.mintJustificationVerifier.assertVerifiable(params.justification);
1537
+ const verifiers = params.mintJustificationVerifiers;
1538
+ if (verifiers === void 0) return deps.verificationContext;
1432
1539
  return new VerificationContext(
1433
- base.trustBase,
1434
- base.predicateVerifier,
1435
- base.unicityCertificateVerifier,
1436
- registry,
1437
- new TokenIssuanceVerifierService(false)
1540
+ deps.trustBase,
1541
+ deps.predicateVerifier,
1542
+ deps.unicityCertificateVerifier,
1543
+ deps.mintJustificationVerifier.overlaid(verifiers),
1544
+ deps.verificationContext.tokenIssuanceVerifier
1438
1545
  );
1439
1546
  }
1440
1547
 
@@ -1522,9 +1629,6 @@ async function burntTokenFromCheckpoint(deps, storedBytes, reDerivedBurnTx, sour
1522
1629
  // token-engine/SphereTokenEngine.ts
1523
1630
  var DEFAULT_PROOF_POLL_INTERVAL_MS = 300;
1524
1631
  var MAX_MINT_CONCURRENCY = 8;
1525
- function isKeepOpenSplitError(err) {
1526
- return err instanceof ProofUnconfirmedError || err instanceof CheckpointPersistFailedError || err instanceof SplitCheckpointLostError || err instanceof CheckpointTrustbaseMismatchError;
1527
- }
1528
1632
  var TRANSFER_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
1529
1633
  var CLEAN_REJECT_STATUSES = /* @__PURE__ */ new Set([
1530
1634
  CertificationStatus.STATE_ID_MISMATCH,
@@ -1614,8 +1718,9 @@ var SphereTokenEngine = class {
1614
1718
  const token = await Token.mint(certified, this.deps.verificationContext);
1615
1719
  return wrapToken(token);
1616
1720
  }
1721
+ assertMintable = (params) => void mintContext(this.deps, params);
1617
1722
  async mintDataToken(params, options) {
1618
- assertMintableData(params.data);
1723
+ const context = mintContext(this.deps, params);
1619
1724
  const recipient = SignaturePredicate.create(params.recipientPubkey);
1620
1725
  const tokenType = params.tokenType ? new TokenType(params.tokenType) : TokenType.generate();
1621
1726
  const salt = params.salt ? TokenSalt.fromBytes(params.salt) : TokenSalt.generate();
@@ -1629,8 +1734,7 @@ var SphereTokenEngine = class {
1629
1734
  options
1630
1735
  );
1631
1736
  const certified = await mintTx.toCertifiedTransaction(this.deps.trustBase, this.deps.predicateVerifier, this.deps.unicityCertificateVerifier, proof);
1632
- const verifiers = params.mintJustificationVerifiers;
1633
- return wrapToken(await Token.mint(certified, verifiers ? contextWithMintVerifiers(this.deps, verifiers) : this.deps.verificationContext));
1737
+ return wrapToken(await Token.mint(certified, context));
1634
1738
  }
1635
1739
  buildNftMint(params) {
1636
1740
  return planNftMint(this.deps, params);
@@ -1967,20 +2071,30 @@ var SphereTokenEngine = class {
1967
2071
 
1968
2072
  // token-engine/factory.ts
1969
2073
  var DEFAULT_VERIFICATION_POOL_SIZE = 4;
1970
- function registerPluginVerifiers(registry, plugins) {
2074
+ function registerPlugins(registries, plugins) {
1971
2075
  for (const plugin of plugins ?? []) {
1972
2076
  for (const verifier of plugin.mintJustificationVerifiers ?? []) {
1973
- try {
1974
- registry.register(verifier);
1975
- } catch (err) {
1976
- throw new SphereError(
1977
- `Token plugin '${plugin.id}' registers mint-reason tag ${verifier.tag} twice or over another plugin's: ` + (err instanceof Error ? err.message : String(err)),
1978
- "INVALID_CONFIG"
1979
- );
1980
- }
2077
+ claim(plugin, `mint-reason tag ${verifier.tag}`, () => registries.reasons.registerPlugin(verifier));
2078
+ }
2079
+ for (const policy of plugin.tokenIssuancePolicies ?? []) {
2080
+ const tokenType = HexConverter.encode(policy.tokenType.bytes);
2081
+ claim(plugin, `an issuance policy for token type ${tokenType}`, () => {
2082
+ registries.claims.add(policy);
2083
+ registries.policies.register(policy);
2084
+ });
1981
2085
  }
1982
2086
  }
1983
2087
  }
2088
+ function claim(plugin, what, register) {
2089
+ try {
2090
+ register();
2091
+ } catch (err) {
2092
+ throw new SphereError(
2093
+ `Token plugin '${plugin.id}' registers ${what} twice or over another plugin's: ` + (err instanceof Error ? err.message : String(err)),
2094
+ "INVALID_CONFIG"
2095
+ );
2096
+ }
2097
+ }
1984
2098
  function disposedError() {
1985
2099
  return new SphereError(
1986
2100
  "Verification worker pool disposed \u2014 the in-flight verification was cancelled",
@@ -2058,11 +2172,15 @@ async function createSphereTokenEngine(config) {
2058
2172
  const unicityCertificateVerifier = new UnicityCertificateVerifier(
2059
2173
  new UnicitySealQuorumSignaturesVerificationRule(new Secp256k1SignatureVerifier(), new VerifiedSealCache(256))
2060
2174
  );
2061
- const mintJustificationVerifier = new MintJustificationVerifierService();
2175
+ const mintJustificationVerifier = new MintReasonRegistry();
2062
2176
  mintJustificationVerifier.register(
2063
2177
  new SplitMintJustificationVerifier(decodeSpherePaymentData)
2064
2178
  );
2065
- registerPluginVerifiers(mintJustificationVerifier, config.plugins);
2179
+ const tokenIssuanceVerifier = new TokenIssuanceVerifierService(false);
2180
+ registerPlugins(
2181
+ { reasons: mintJustificationVerifier, policies: tokenIssuanceVerifier, claims: new CoinClaims() },
2182
+ config.plugins
2183
+ );
2066
2184
  const deps = {
2067
2185
  client: new StateTransitionClient(new AggregatorClient(config.aggregatorUrl, config.apiKey ?? null)),
2068
2186
  trustBase,
@@ -2074,7 +2192,7 @@ async function createSphereTokenEngine(config) {
2074
2192
  predicateVerifier,
2075
2193
  unicityCertificateVerifier,
2076
2194
  mintJustificationVerifier,
2077
- new TokenIssuanceVerifierService(false)
2195
+ tokenIssuanceVerifier
2078
2196
  ),
2079
2197
  signingService: new SigningService(config.privateKey),
2080
2198
  // Also the HKDF ikm for deterministic realization (Part E.1) — the
@@ -2095,6 +2213,7 @@ async function createSphereTokenEngine(config) {
2095
2213
  export {
2096
2214
  CheckpointPersistFailedError,
2097
2215
  CheckpointTrustbaseMismatchError,
2216
+ MintReasonUnverifiableError,
2098
2217
  NFT_DOCUMENT_MEDIA_TYPE,
2099
2218
  NFT_FORMAT_VERSION,
2100
2219
  NFT_LINK_TAG,