@empereur-rouge/pms-sdk 0.3.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,118 +1,3 @@
1
- /**
2
- * PmsWallet - Wallet pour le réseau PMS.
3
- *
4
- * Supporte:
5
- * - Génération de wallet avec mnémonique 24 mots (BIP39)
6
- * - Import depuis clé privée
7
- * - Signature de messages
8
- * - Export de la phrase mnémonique
9
- *
10
- * @example
11
- * ```typescript
12
- * // Générer un nouveau wallet
13
- * const wallet = PmsWallet.generate();
14
- * console.log(wallet.mnemonic); // 24 mots
15
- *
16
- * // Restaurer depuis mnemonic
17
- * const wallet2 = PmsWallet.fromMnemonic("word1 word2 ...");
18
- *
19
- * // Signer un message
20
- * const sig = await wallet.sign(messageBytes);
21
- * ```
22
- */
23
- /**
24
- * Wallet PMS avec gestion des clés cryptographiques.
25
- */
26
- declare class PmsWallet {
27
- /** Clé privée secp256k1 (32 bytes) - pour signatures */
28
- private readonly _privateKey;
29
- /** Clé publique secp256k1 non compressée (65 bytes: 04 + x + y) */
30
- private readonly _publicKey;
31
- /** Clé privée X25519 (32 bytes) - pour chiffrement */
32
- private readonly _x25519PrivateKey;
33
- /** Clé publique X25519 (32 bytes) */
34
- private readonly _x25519PublicKey;
35
- /** Phrase mnémonique (24 mots) si générée/importée */
36
- private readonly _mnemonic?;
37
- /**
38
- * Constructeur privé - utiliser les méthodes statiques.
39
- */
40
- private constructor();
41
- /**
42
- * Génère un nouveau wallet avec une phrase de 24 mots.
43
- */
44
- static generate(): PmsWallet;
45
- /**
46
- * Crée un wallet à partir d'une phrase mnémonique (12, 15, 18, 21 ou 24 mots).
47
- * @throws Error si la phrase est invalide
48
- */
49
- static fromMnemonic(mnemonic: string): PmsWallet;
50
- /**
51
- * Crée un wallet à partir d'une clé privée hexadécimale.
52
- */
53
- static fromPrivateKey(privateKeyHex: string): PmsWallet;
54
- /**
55
- * Crée un wallet à partir d'une seed (32 bytes).
56
- */
57
- static fromSeed(seed: Uint8Array): PmsWallet;
58
- /**
59
- * Adresse du wallet (clé publique hex).
60
- * Format: "04" + 64 bytes hex = 130 caractères
61
- */
62
- get address(): string;
63
- /**
64
- * Clé publique en bytes.
65
- */
66
- get publicKey(): Uint8Array;
67
- /**
68
- * Clé publique en hex.
69
- */
70
- get publicKeyHex(): string;
71
- /**
72
- * Phrase mnémonique (si disponible).
73
- * @returns undefined si le wallet a été créé depuis une clé privée
74
- */
75
- get mnemonic(): string | undefined;
76
- /**
77
- * Clé publique X25519 en hex (pour chiffrement).
78
- * Utiliser cette clé comme destinataire pour encryptPayload().
79
- */
80
- get x25519PublicKeyHex(): string;
81
- /**
82
- * Clé privée X25519 en hex (pour déchiffrement).
83
- * ⚠️ Ne pas exposer cette clé publiquement !
84
- */
85
- get x25519PrivateKeyHex(): string;
86
- /**
87
- * Signe un message avec la clé privée.
88
- * @param message - Message à signer (sera hashé avec SHA256)
89
- * @returns Signature DER encodée en hex
90
- */
91
- sign(message: Uint8Array): string;
92
- /**
93
- * Signe un message déjà hashé.
94
- * @param hash - Hash 32 bytes du message
95
- * @returns Signature DER encodée en hex
96
- */
97
- signHash(hash: Uint8Array): string;
98
- /**
99
- * Exporte la clé privée en hex.
100
- * ⚠️ À utiliser avec précaution !
101
- */
102
- exportPrivateKey(): string;
103
- /**
104
- * Vérifie une signature.
105
- * @param message - Message original
106
- * @param signature - Signature DER hex
107
- * @param publicKeyHex - Clé publique hex du signataire
108
- */
109
- static verify(message: Uint8Array, signature: string, publicKeyHex: string): boolean;
110
- }
111
- /**
112
- * Vérifie si une phrase mnémonique est valide.
113
- */
114
- declare function isValidMnemonic(mnemonic: string): boolean;
115
-
116
1
  /**
117
2
  * Types TypeScript pour le SDK PMS.
118
3
  *
@@ -125,6 +10,27 @@ interface OutputRef {
125
10
  /** Index de l'output dans la transaction */
126
11
  index: number;
127
12
  }
13
+ /**
14
+ * Condition de déverrouillage d'un output (protocole 2.2, dag-pms v0.10.0).
15
+ *
16
+ * Sérialisation serde externally-tagged :
17
+ * - variant unit → string JSON `"PubKey"` ;
18
+ * - variants à données → `{ "MultiSig": {...} }` / `{ "HashLock": {...} }`.
19
+ *
20
+ * La condition est figée À LA CRÉATION de l'output. Au spend, le validateur
21
+ * lit la condition depuis l'UTXO STOCKÉ (jamais depuis les données du
22
+ * dépensier).
23
+ */
24
+ type SpendCondition = "PubKey" | {
25
+ MultiSig: {
26
+ m: number;
27
+ pubkeys: string[];
28
+ };
29
+ } | {
30
+ HashLock: {
31
+ hash_hex: string;
32
+ };
33
+ };
128
34
  /** Output de transaction (UTXO) */
129
35
  interface TxOutput {
130
36
  /** Adresse du destinataire */
@@ -133,6 +39,26 @@ interface TxOutput {
133
39
  amount: string;
134
40
  /** Asset ID (undefined/null = PMS natif, "edenite" = token custom) */
135
41
  asset_id?: string;
42
+ /**
43
+ * Time-lock natif (protocole 2.1) : timestamp UNIX **millisecondes**
44
+ * avant lequel l'output est indépensable. Absent = dépensable
45
+ * immédiatement. Entre dans le message signé quand présent.
46
+ */
47
+ locked_until?: number;
48
+ /**
49
+ * Condition de déverrouillage (protocole 2.2). Absent = PubKey simple
50
+ * (binding pubkey↔adresse classique). Pour MultiSig, `address` DOIT être
51
+ * l'adresse canonique de la policy — voir [`multisigAddress`].
52
+ */
53
+ spend_condition?: SpendCondition;
54
+ /**
55
+ * Timestamp de création de l'UTXO (UNIX ms), **assigné par le moteur**
56
+ * au persist — base du calcul de demurrage (protocole 2.5).
57
+ * NE JAMAIS poser ce champ côté client : toute valeur fournie est
58
+ * écrasée par le serveur, et le poser modifie inutilement le message
59
+ * signé. Présent en LECTURE seulement (GET /v1/wallet/{addr}/utxos).
60
+ */
61
+ created_at?: number;
136
62
  }
137
63
  /** UTXO complet avec sa référence */
138
64
  interface Utxo extends TxOutput {
@@ -144,12 +70,31 @@ interface TxInput {
144
70
  /** Référence à l'UTXO dépensé */
145
71
  out: OutputRef;
146
72
  }
73
+ /** Signature additionnelle d'un cosignataire MultiSig (protocole 2.2). */
74
+ interface Cosigner {
75
+ /** Clé publique hex (membre du set MultiSig) */
76
+ pubkey_hex: string;
77
+ /** Signature DER base64 du MÊME message canonique que l'unlock principal */
78
+ signature_b64: string;
79
+ }
147
80
  /** Unlock (signature pour un input) */
148
81
  interface Unlock {
149
82
  /** Clé publique hex */
150
83
  pubkey_hex: string;
151
84
  /** Signature base64 */
152
85
  signature_b64: string;
86
+ /**
87
+ * Cosignatures pour un input sous condition MultiSig : la paire
88
+ * principale compte comme première signature, les cosigners complètent
89
+ * jusqu'à M. Chaque signature porte sur le même message canonique.
90
+ * Les unlocks n'entrent PAS dans le message signé.
91
+ */
92
+ cosigners?: Cosigner[];
93
+ /**
94
+ * Préimage hex pour un input sous condition HashLock :
95
+ * `sha256(bytes(preimage_hex)) == hash_hex` de la condition.
96
+ */
97
+ preimage_hex?: string;
153
98
  }
154
99
  /** Transaction UTXO */
155
100
  interface TxUtxo {
@@ -168,8 +113,14 @@ type PayloadEnvelope = {
168
113
  } | {
169
114
  Encrypted: EncryptedPayload;
170
115
  };
171
- /** Payload en clair */
172
- type PlainPayload = {
116
+ /**
117
+ * Payload en clair.
118
+ *
119
+ * Sérialisation serde externally-tagged : variant unit → string JSON
120
+ * (`"Genesis"`), variant avec données → objet à clé unique
121
+ * (`{"TxUtxo": {...}}`).
122
+ */
123
+ type PlainPayload = "Genesis" | {
173
124
  Mint: MintPayload;
174
125
  } | {
175
126
  TxUtxo: TxUtxo;
@@ -312,6 +263,12 @@ interface TokenMetadata {
312
263
  creator: string;
313
264
  /** Clé publique autorisée à mint ce token */
314
265
  mint_authority: string;
266
+ /**
267
+ * Demurrage opt-in (protocole 2.5) : décote en basis points par JOUR
268
+ * PLEIN écoulé depuis `created_at` de chaque UTXO. Absent/0 = pas de
269
+ * demurrage. Voir [`effectiveValue`] pour le calcul côté client.
270
+ */
271
+ demurrage_bps_per_day?: number;
315
272
  }
316
273
  /** Mise à jour de configuration */
317
274
  type ConfigUpdate = {
@@ -335,6 +292,23 @@ type ConfigUpdate = {
335
292
  enabled: boolean;
336
293
  };
337
294
  };
295
+ /**
296
+ * Dernier snapshot de preuve de réserves ancré (protocole 2.6).
297
+ * `GET /v1/reserves/latest` — le bloc DAG `block_id` est la preuve signée
298
+ * Coordinator ; `state_root` = SHA-256 de l'état UTXO complet.
299
+ */
300
+ interface ReservesLatest {
301
+ /** ID du bloc ReserveSnapshot ancré dans le DAG */
302
+ block_id: string;
303
+ /** Racine d'état SHA-256 (64 hex chars) du set UTXO */
304
+ state_root: string;
305
+ /** Supply totale par asset : [asset_id | null (natif), montant] */
306
+ total_supply: Array<[string | null, string]>;
307
+ /** Nombre d'UTXOs couverts par le root */
308
+ utxo_count: number;
309
+ /** Horodatage du calcul (UNIX ms) */
310
+ computed_at_ms: number;
311
+ }
338
312
  /** Bloc du DAG */
339
313
  interface Block {
340
314
  /** ID unique du bloc (hash) */
@@ -440,13 +414,24 @@ interface UtxoDetail {
440
414
  interface PrepareTxResponse {
441
415
  /** Transaction non-signée (unlocks vide) */
442
416
  unsigned_tx: TxUtxo;
443
- /** Hash SHA256 du message à signer (hex) */
417
+ /** Hash SHA256 du message canonique à signer (hex) */
444
418
  tx_hash: string;
445
- /** Frais calculés */
419
+ /** Frais de gas PMS calculés */
446
420
  fee: string;
421
+ /** Frais de transfert smart contract ("0" si aucun contrat actif) */
422
+ transfer_fee: string;
447
423
  /** Détail des UTXOs sélectionnés */
448
424
  inputs_detail: UtxoDetail[];
449
425
  }
426
+ /** Réponse de POST /v1/wallet/tx/send */
427
+ interface SendTxResponse {
428
+ /** ID du bloc forgé et signé par le serveur (single-writer) */
429
+ id: string;
430
+ /** Statut: "inserted" (201) ou "duplicate" (409) */
431
+ status: string;
432
+ /** Alias de `id` pour compatibilité avec l'ancien SubmitResponse */
433
+ block_id: string;
434
+ }
450
435
  /** Réponse de getNft - informations complètes d'un NFT */
451
436
  interface NftResponse {
452
437
  /** Token ID du NFT */
@@ -522,7 +507,7 @@ interface PmsClientConfig {
522
507
  seedNodes?: string[];
523
508
  /** ID du réseau (défaut: "pms-mainnet") */
524
509
  networkId?: string;
525
- /** Version du protocole (défaut: 1) */
510
+ /** Version du protocole P2P (défaut: 3 — dag-pms v0.10.0) */
526
511
  protocolVersion?: number;
527
512
  /** Timeout en ms (défaut: 30000) */
528
513
  timeout?: number;
@@ -655,6 +640,148 @@ interface NodePublicConfig extends RuntimeConfig {
655
640
  fee_recipient: string;
656
641
  }
657
642
 
643
+ /**
644
+ * PmsWallet - Wallet pour le réseau PMS.
645
+ *
646
+ * Supporte:
647
+ * - Génération de wallet avec mnémonique 24 mots (BIP39)
648
+ * - Import depuis clé privée
649
+ * - Signature de messages
650
+ * - Export de la phrase mnémonique
651
+ *
652
+ * @example
653
+ * ```typescript
654
+ * // Générer un nouveau wallet
655
+ * const wallet = PmsWallet.generate();
656
+ * console.log(wallet.mnemonic); // 24 mots
657
+ *
658
+ * // Restaurer depuis mnemonic
659
+ * const wallet2 = PmsWallet.fromMnemonic("word1 word2 ...");
660
+ *
661
+ * // Signer un message
662
+ * const sig = await wallet.sign(messageBytes);
663
+ * ```
664
+ */
665
+
666
+ /**
667
+ * Wallet PMS avec gestion des clés cryptographiques.
668
+ */
669
+ declare class PmsWallet {
670
+ /** Clé privée secp256k1 (32 bytes) - pour signatures */
671
+ private readonly _privateKey;
672
+ /** Clé publique secp256k1 non compressée (65 bytes: 04 + x + y) */
673
+ private readonly _publicKey;
674
+ /** Clé privée X25519 (32 bytes) - pour chiffrement */
675
+ private readonly _x25519PrivateKey;
676
+ /** Clé publique X25519 (32 bytes) */
677
+ private readonly _x25519PublicKey;
678
+ /** Phrase mnémonique (24 mots) si générée/importée */
679
+ private readonly _mnemonic?;
680
+ /**
681
+ * Constructeur privé - utiliser les méthodes statiques.
682
+ */
683
+ private constructor();
684
+ /**
685
+ * Génère un nouveau wallet avec une phrase de 24 mots.
686
+ */
687
+ static generate(): PmsWallet;
688
+ /**
689
+ * Crée un wallet à partir d'une phrase mnémonique (12, 15, 18, 21 ou 24 mots).
690
+ * @throws Error si la phrase est invalide
691
+ */
692
+ static fromMnemonic(mnemonic: string): PmsWallet;
693
+ /**
694
+ * Crée un wallet à partir d'une clé privée hexadécimale.
695
+ */
696
+ static fromPrivateKey(privateKeyHex: string): PmsWallet;
697
+ /**
698
+ * Crée un wallet à partir d'une seed (32 bytes).
699
+ */
700
+ static fromSeed(seed: Uint8Array): PmsWallet;
701
+ /**
702
+ * Adresse du wallet (clé publique hex).
703
+ * Format: "04" + 64 bytes hex = 130 caractères
704
+ */
705
+ get address(): string;
706
+ /**
707
+ * Clé publique en bytes.
708
+ */
709
+ get publicKey(): Uint8Array;
710
+ /**
711
+ * Clé publique en hex.
712
+ */
713
+ get publicKeyHex(): string;
714
+ /**
715
+ * Phrase mnémonique (si disponible).
716
+ * @returns undefined si le wallet a été créé depuis une clé privée
717
+ */
718
+ get mnemonic(): string | undefined;
719
+ /**
720
+ * Clé publique X25519 en hex (pour chiffrement).
721
+ * Utiliser cette clé comme destinataire pour encryptPayload().
722
+ */
723
+ get x25519PublicKeyHex(): string;
724
+ /**
725
+ * Clé privée X25519 en hex (pour déchiffrement).
726
+ * ⚠️ Ne pas exposer cette clé publiquement !
727
+ */
728
+ get x25519PrivateKeyHex(): string;
729
+ /**
730
+ * Signe un message avec la clé privée.
731
+ * @param message - Message à signer (sera hashé avec SHA256)
732
+ * @returns Signature DER encodée en hex
733
+ */
734
+ sign(message: Uint8Array): string;
735
+ /**
736
+ * Signe un message déjà hashé.
737
+ * @param hash - Hash 32 bytes du message
738
+ * @returns Signature DER encodée en hex
739
+ */
740
+ signHash(hash: Uint8Array): string;
741
+ /**
742
+ * Exporte la clé privée en hex.
743
+ * ⚠️ À utiliser avec précaution !
744
+ */
745
+ exportPrivateKey(): string;
746
+ /**
747
+ * Vérifie une signature.
748
+ * @param message - Message original
749
+ * @param signature - Signature DER hex
750
+ * @param publicKeyHex - Clé publique hex du signataire
751
+ */
752
+ static verify(message: Uint8Array, signature: string, publicKeyHex: string): boolean;
753
+ }
754
+ /**
755
+ * Vérifie si une phrase mnémonique est valide.
756
+ */
757
+ declare function isValidMnemonic(mnemonic: string): boolean;
758
+ /**
759
+ * Construit l'`Unlock` d'un input pour les conditions de dépense du
760
+ * protocole v0.10.0 (MultiSig / HashLock).
761
+ *
762
+ * - 1 signataire, pas d'options → unlock classique (PubKey / binding C-1).
763
+ * - Plusieurs signataires (MultiSig M-of-N) : le premier devient la paire
764
+ * principale, les suivants des `cosigners` — chacun signe le MÊME message
765
+ * canonique (`txSigningMessage`). Le quorum compte les clés DISTINCTES
766
+ * membres du set de la condition.
767
+ * - `preimageHex` (HashLock) : révèle le secret tel que
768
+ * `sha256(bytes(preimage)) == hash_hex` de la condition.
769
+ *
770
+ * @param signers - Wallets signataires (>= 1 ; ordre indifférent pour le quorum)
771
+ * @param txHashHex - Hash hex retourné par `txSigningMessage(...)`
772
+ * @param opts - `preimageHex` pour un input HashLock
773
+ *
774
+ * @example
775
+ * ```typescript
776
+ * const txHash = txSigningMessage(networkId, tx.inputs, tx.outputs, tx.fee);
777
+ * // dépense d'un UTXO MultiSig 2-of-3 :
778
+ * tx.unlocks = tx.inputs.map(() => makeUnlock([alice, carol], txHash));
779
+ * ```
780
+ */
781
+ declare function makeUnlock(signers: PmsWallet[], txHashHex: string, opts?: {
782
+ preimageHex?: string;
783
+ }): Unlock;
784
+
658
785
  /**
659
786
  * PmsClient - Client HTTP pour interagir avec un nœud PMS.
660
787
  *
@@ -741,8 +868,19 @@ declare class PmsClient {
741
868
  getToken(assetId: string): Promise<TokenMetadata>;
742
869
  /**
743
870
  * Récupère les UTXOs d'une adresse.
871
+ *
872
+ * Depuis dag-pms v0.10.0, chaque UTXO expose aussi ses contraintes de
873
+ * dépense : `locked_until` (time-lock), `spend_condition`
874
+ * (MultiSig/HashLock) et `created_at` (base du demurrage). Utiliser
875
+ * [`spendableUtxos`] pour exclure les UTXOs encore verrouillés avant
876
+ * toute sélection de coins côté client.
744
877
  */
745
878
  getUtxos(address: string): Promise<Utxo[]>;
879
+ /**
880
+ * Dernier snapshot de preuve de réserves ancré (protocole 2.6,
881
+ * `GET /v1/reserves/latest`). 404 si aucun snapshot n'a encore été ancré.
882
+ */
883
+ getLatestReserves(): Promise<ReservesLatest>;
746
884
  /**
747
885
  * Crée un nouveau wallet côté serveur (custodial).
748
886
  * Le serveur génère le wallet et retourne toutes les clés + adresse Bech32.
@@ -957,18 +1095,45 @@ declare class PmsClient {
957
1095
  private refreshNodeList;
958
1096
  /**
959
1097
  * Envoie des tokens à une adresse.
960
- * Construit automatiquement la transaction, la signe et la soumet.
1098
+ *
1099
+ * Flux aligné sur dag-pms v0.9.0 (single-writer + vérification des
1100
+ * signatures de transaction par l'engine) :
1101
+ * 1. `POST /v1/tx/prepare` — le serveur sélectionne les UTXOs et calcule
1102
+ * les frais.
1103
+ * 2. Vérification défensive côté client : l'output destinataire demandé
1104
+ * existe bien, et le `tx_hash` retourné correspond au message canonique
1105
+ * recalculé localement (`txSigningMessage`). On ne signe JAMAIS un hash
1106
+ * opaque non vérifié.
1107
+ * 3. Le wallet signe la TRANSACTION (unlocks) — pas le bloc. C'est le
1108
+ * serveur qui forge et signe le bloc (single-writer enforcement).
1109
+ * 4. `POST /v1/wallet/tx/send` avec la TX signée + les clés X25519 des
1110
+ * destinataires pour le chiffrement du payload.
1111
+ *
1112
+ * @param params.to - Adresse destinataire (Bech32m de préférence)
1113
+ * @param params.amount - Montant décimal (ex: "10.0")
1114
+ * @param params.wallet - Wallet signataire (propriétaire des UTXOs)
1115
+ * @param params.assetId - Asset ID optionnel (undefined = PMS natif)
1116
+ * @returns `{id, status, block_id}` — id du bloc forgé par le serveur
961
1117
  */
962
1118
  send(params: {
963
1119
  to: string;
964
1120
  amount: string;
965
1121
  wallet: PmsWallet;
1122
+ assetId?: string;
966
1123
  memo?: string;
967
- }): Promise<SubmitResponse>;
1124
+ }): Promise<SendTxResponse>;
968
1125
  /**
969
1126
  * Transférer un NFT à un autre propriétaire.
970
1127
  * Prend en charge le re-chiffrement des métadonnées via le coordinateur.
971
1128
  *
1129
+ * @deprecated Cette méthode soumet un WireBlock signé par la clé
1130
+ * utilisateur via `/submit/block`. Depuis dag-pms v0.9.0, l'engine tourne
1131
+ * en mode **single-writer** : tout bloc signé par une clé non-coordinateur
1132
+ * est rejeté. Cette méthode ne fonctionne que sur un réseau SANS
1133
+ * single-writer enforcement. Utilisez les flux server-side
1134
+ * (`/v1/nft/transfer/prepare` + endpoints serveur) qui forgent et signent
1135
+ * le bloc côté coordinateur.
1136
+ *
972
1137
  * @param params - Paramètres du transfert
973
1138
  * @param params.tokenId - Identifiant du NFT
974
1139
  * @param params.to - Adresse du nouveau propriétaire
@@ -991,6 +1156,13 @@ declare class PmsClient {
991
1156
  * un remboursement est calculé selon la formule:
992
1157
  * `(weight * size * density) / 10000` PMS
993
1158
  *
1159
+ * @deprecated Cette méthode poste un WireBlock signé par la clé
1160
+ * utilisateur. Depuis dag-pms v0.9.0, l'engine tourne en mode
1161
+ * **single-writer** : tout bloc signé par une clé non-coordinateur est
1162
+ * rejeté. Cette méthode ne fonctionne que sur un réseau SANS single-writer
1163
+ * enforcement. Le flux supporté est le burn server-side
1164
+ * (`/v1/nft/burn-simple`), où le serveur forge et signe le bloc.
1165
+ *
994
1166
  * @param params - Paramètres du burn
995
1167
  * @param params.tokenId - Identifiant du NFT à brûler
996
1168
  * @param params.wallet - Wallet PMS du propriétaire (doit être l'owner actuel)
@@ -1015,6 +1187,13 @@ declare class PmsClient {
1015
1187
  /**
1016
1188
  * Brûle (détruit) plusieurs NFTs en une seule transaction.
1017
1189
  *
1190
+ * @deprecated Cette méthode poste un WireBlock signé par la clé
1191
+ * utilisateur. Depuis dag-pms v0.9.0, l'engine tourne en mode
1192
+ * **single-writer** : tout bloc signé par une clé non-coordinateur est
1193
+ * rejeté. Cette méthode ne fonctionne que sur un réseau SANS single-writer
1194
+ * enforcement. Le flux supporté est le burn server-side
1195
+ * (`/v1/nft/burn-simple`), où le serveur forge et signe le bloc.
1196
+ *
1018
1197
  * @param params - Paramètres du batch burn
1019
1198
  * @param params.tokenIds - Liste des Identifiants des NFTs à brûler
1020
1199
  * @param params.wallet - Wallet PMS du propriétaire
@@ -1059,6 +1238,10 @@ declare class PmsClient {
1059
1238
  private fetchUrl;
1060
1239
  }
1061
1240
 
1241
+ /**
1242
+ * Utilitaires cryptographiques pour le SDK PMS.
1243
+ */
1244
+
1062
1245
  /**
1063
1246
  * Convertit des bytes en hex.
1064
1247
  */
@@ -1067,6 +1250,36 @@ declare function toHex(bytes: Uint8Array): string;
1067
1250
  * Convertit un hex en bytes.
1068
1251
  */
1069
1252
  declare function fromHex(hex: string): Uint8Array;
1253
+ /**
1254
+ * Message canonique de signature de transaction — DOIT matcher
1255
+ * `Transaction::signing_message` du Rust (dag-pms,
1256
+ * crates/pms-types-transaction/src/transaction.rs) :
1257
+ * `hex(SHA256(JSON({network_id, inputs, outputs, fee})))`
1258
+ * Ordre des clés et compacité identiques à serde_json.
1259
+ *
1260
+ * Le `network_id` est inclus dans le message pour empêcher le replay
1261
+ * cross-chain (une TX signée pour le testnet ne valide pas sur mainnet).
1262
+ *
1263
+ * Les inputs/outputs sont re-canonicalisés défensivement :
1264
+ * - `TxInput` → `{out: {txid, index}}` (ordre de clés serde).
1265
+ * - `TxOutput` → `{address, amount[, asset_id][, locked_until]
1266
+ * [, spend_condition][, created_at]}` — l'ORDRE des clés est celui de la
1267
+ * struct Rust et chaque clé optionnelle est OMISE quand undefined/null
1268
+ * (équivalent serde `skip_serializing_if`), jamais sérialisée à `null`.
1269
+ * `created_at` est système : ne le posez jamais côté client (géré ici
1270
+ * uniquement par fidélité de hash si un serveur l'echo).
1271
+ *
1272
+ * La signature côté wallet : `wallet.sign(encodeUtf8(msgHex))` —
1273
+ * `wallet.sign` fait SHA256(message) puis ECDSA, ce qui correspond
1274
+ * exactement au verify Rust (k256 hash la hex-string du message).
1275
+ *
1276
+ * @param networkId - Network ID de la chaîne cible (ex: "pms-testnet-v1")
1277
+ * @param inputs - Inputs de la transaction
1278
+ * @param outputs - Outputs de la transaction
1279
+ * @param fee - Frais (string décimale, ex: "0.1")
1280
+ * @returns Hash hex (64 chars) du message canonique
1281
+ */
1282
+ declare function txSigningMessage(networkId: string, inputs: TxInput[], outputs: TxOutput[], fee: string): string;
1070
1283
  /**
1071
1284
  * Parse un montant décimal en satoshis (8 décimales).
1072
1285
  */
@@ -1075,6 +1288,64 @@ declare function parseAmount(amount: string): bigint;
1075
1288
  * Formate des satoshis en montant décimal.
1076
1289
  */
1077
1290
  declare function formatAmount(sats: bigint): string;
1291
+ /** Millisecondes par jour — base du demurrage (protocole 2.5). */
1292
+ declare const DAY_MS = 86400000;
1293
+ /**
1294
+ * Dérive l'adresse multisig CANONIQUE d'une policy M-of-N (protocole 2.2).
1295
+ *
1296
+ * DOIT matcher `multisig_address` du Rust
1297
+ * (crates/pms-core/src/validations/conditions.rs) :
1298
+ * `"msig1" + hex(SHA256("pms-multisig-v1" || m || n || pk_1 || … || pk_n)[..20])`
1299
+ * où les pubkeys sont normalisées (trim, sans `0x`, lowercase) puis TRIÉES —
1300
+ * ordre et casse de déclaration indifférents.
1301
+ *
1302
+ * Tout output sous condition MultiSig DOIT porter cette adresse, sinon le
1303
+ * moteur rejette la création (`InvalidSpendCondition`).
1304
+ *
1305
+ * @param m - Quorum requis (1..=N)
1306
+ * @param pubkeys - Clés publiques secp256k1 hex des membres (N <= 16)
1307
+ */
1308
+ declare function multisigAddress(m: number, pubkeys: string[]): string;
1309
+ /**
1310
+ * Hash SHA-256 hex d'un préimage HashLock (protocole 2.2).
1311
+ * À poser dans `SpendCondition.HashLock.hash_hex` à la création de l'output ;
1312
+ * le dépensier fournira `hex(preimage)` dans `Unlock.preimage_hex`.
1313
+ *
1314
+ * @param preimage - Le secret, en bytes ou string UTF-8
1315
+ */
1316
+ declare function hashlockHash(preimage: Uint8Array | string): string;
1317
+ /**
1318
+ * Valeur effective d'un UTXO d'un asset à demurrage (protocole 2.5),
1319
+ * **plancher au satoshi** (8 décimales).
1320
+ *
1321
+ * Formule moteur (Rust `effective_value`, Decimal exact) :
1322
+ * `effective = amount − amount × bps × jours_pleins / 10_000` (plancher 0),
1323
+ * `jours_pleins = floor((now − created_at) / 24h)`.
1324
+ *
1325
+ * La conservation moteur est `sum(outputs) <= sum(effective_inputs)` :
1326
+ * arrondir VERS LE BAS au satoshi est donc toujours sûr (le résidu
1327
+ * sub-satoshi est brûlé avec la décote). Retourne le montant maximal
1328
+ * dépensable, en string décimale 8 dp.
1329
+ *
1330
+ * - `createdAtMs` undefined (UTXO pré-v0.10.0) → valeur nominale intacte.
1331
+ * - `bpsPerDay` 0/undefined → valeur nominale intacte.
1332
+ *
1333
+ * @param amount - Montant nominal (string décimale)
1334
+ * @param createdAtMs - `created_at` de l'UTXO (UNIX ms), tel que lu de l'API
1335
+ * @param nowMs - Horloge courante (UNIX ms)
1336
+ * @param bpsPerDay - `TokenMetadata.demurrage_bps_per_day` de l'asset
1337
+ */
1338
+ declare function effectiveValue(amount: string, createdAtMs: number | undefined, nowMs: number, bpsPerDay: number | undefined): string;
1339
+ /**
1340
+ * Filtre les UTXOs dépensables MAINTENANT : exclut ceux dont le time-lock
1341
+ * (`locked_until`, protocole 2.1) est encore dans le futur. Le moteur
1342
+ * rejetterait leur dépense (`OutputTimeLocked`) — à appliquer avant toute
1343
+ * sélection de coins côté client.
1344
+ *
1345
+ * @param utxos - UTXOs tels que retournés par `GET /v1/wallet/{addr}/utxos`
1346
+ * @param nowMs - Horloge courante (défaut: Date.now())
1347
+ */
1348
+ declare function spendableUtxos<T extends Utxo>(utxos: T[], nowMs?: number): T[];
1078
1349
 
1079
1350
  /**
1080
1351
  * Fonctions de chiffrement pour le SDK PMS.
@@ -1105,4 +1376,4 @@ declare function formatAmount(sats: bigint): string;
1105
1376
  */
1106
1377
  declare function decryptPayload(encrypted: EncryptedPayload, recipientPrivateKeyHex: string): string;
1107
1378
 
1108
- export { type ActivityDirection, type ActivityItem, type ActivityOptions, type ActivityResp, type ActivityType, type BalanceInfo, type Block, type BurnNftResponse, type CoordinatorInfoResponse, type CubeAttributes, type HistoryItem, type LedgerInfo, type ListLedgersOptions, type MintCubeResponse, type NftMetadata, type NftResponse, PmsClient, type PmsClientConfig, PmsWallet, type PrepareTxRequest, type PrepareTxResponse, type RuntimeConfig, type StreamActivityOptions, type SubmitResponse, type SupplyInfo, type TokenMetadata, type Utxo, type UtxoDetail, type WalletHistoryResp, type WalletResponse, decryptPayload, formatAmount, fromHex, isValidMnemonic, parseAmount, toHex };
1379
+ export { type ActivityDirection, type ActivityItem, type ActivityOptions, type ActivityResp, type ActivityType, type BalanceInfo, type Block, type BurnNftResponse, type CoordinatorInfoResponse, type Cosigner, type CubeAttributes, DAY_MS, type HistoryItem, type LedgerInfo, type ListLedgersOptions, type MintCubeResponse, type NftMetadata, type NftResponse, PmsClient, type PmsClientConfig, PmsWallet, type PrepareTxRequest, type PrepareTxResponse, type ReservesLatest, type RuntimeConfig, type SendTxResponse, type SpendCondition, type StreamActivityOptions, type SubmitResponse, type SupplyInfo, type TokenMetadata, type TxInput, type TxOutput, type TxUtxo, type Unlock, type Utxo, type UtxoDetail, type WalletHistoryResp, type WalletResponse, decryptPayload, effectiveValue, formatAmount, fromHex, hashlockHash, isValidMnemonic, makeUnlock, multisigAddress, parseAmount, spendableUtxos, toHex, txSigningMessage };