@empereur-rouge/pms-sdk
v0.3.5
Published
TypeScript SDK for PMS (Planetary Monetary System) — wallet management, transactions, NFTs, and DAG interactions
Downloads
662
Maintainers
Readme
@empereur-rouge/pms-sdk
SDK TypeScript officiel pour interagir avec le réseau PMS (Planetary Monetary System).
Installation
npm install @empereur-rouge/pms-sdk
# ou
yarn add @empereur-rouge/pms-sdk
# ou
pnpm add @empereur-rouge/pms-sdkStructure de l'API
Le SDK est organisé en deux niveaux :
| Import | Usage | Contenu |
|--------|-------|--------|
| @empereur-rouge/pms-sdk | 99% des cas | PmsWallet, PmsClient, utils simples |
| @empereur-rouge/pms-sdk/src/advanced | Power users | computeBlockId, crypto, types bas niveau |
Démarrage Rapide
import { PmsWallet, PmsClient } from "@empereur-rouge/pms-sdk";
// 1. Créer un wallet
const wallet = PmsWallet.generate();
console.log("Mnemonic:", wallet.mnemonic);
console.log("Address:", wallet.address);
// 2. Connecter au réseau (clé API obligatoire)
const client = new PmsClient({
nodeUrl: "https://node.pms.network",
apiKey: "pk_live_votre_cle_ici",
});
// 3. Consulter la balance
const balance = await client.getBalance(wallet.address);
console.log("Balance:", balance);
// 4. Envoyer des tokens
const result = await client.send({
to: "04abc123...",
amount: "10.0",
wallet,
});
console.log("Transaction:", result.block_id);API Reference
PmsWallet - Gestion des Wallets
Le wallet gère les clés cryptographiques (secp256k1) et permet de signer des transactions.
Création de Wallet
// Générer un nouveau wallet (24 mots)
const wallet = PmsWallet.generate();
// Restaurer depuis un mnemonic
const restored = PmsWallet.fromMnemonic("word1 word2 ... word24");
// Importer depuis une clé privée (hex)
const imported = PmsWallet.fromPrivateKey("abc123...");
// Créer depuis une seed (32 bytes)
const seeded = PmsWallet.fromSeed(new Uint8Array(32));Propriétés
| Propriété | Type | Description |
|-----------|------|-------------|
| address | string | Adresse publique (clé publique hex non compressée, commence par 04) |
| publicKeyHex | string | Clé publique en hexadécimal (identique à address) |
| x25519PublicKeyHex | string | Clé publique X25519 pour le chiffrement |
| mnemonic | string \| undefined | Phrase mnémonique (24 mots) si disponible |
Méthodes
// Signer un message
const signature: string = wallet.sign(messageBytes);
// Exporter la clé privée (hex)
const privateKey: string = wallet.exportPrivateKey();
// Vérifier une signature (statique)
const isValid: boolean = PmsWallet.verify(message, signature, publicKeyHex);Validation de Mnemonic
import { isValidMnemonic } from "@empereur-rouge/pms-sdk";
if (isValidMnemonic(userInput)) {
const wallet = PmsWallet.fromMnemonic(userInput);
}PmsClient - Client API
Le client permet d'interagir avec l'API REST des nœuds PMS.
Configuration
const client = new PmsClient({
nodeUrl: "https://node.pms.network", // URL du nœud principal
apiKey: "pk_live_votre_cle_ici", // Clé API (obligatoire)
seedNodes: [ // Optionnel: nœuds de secours
"https://node2.pms.network",
"https://node3.pms.network",
],
networkId: "pms-mainnet", // Défaut: "pms-mainnet"
protocolVersion: 1, // Défaut: 1
timeout: 30000, // Timeout en ms (défaut: 30s)
enableRacing: true, // Racing pattern (défaut: true)
});[!IMPORTANT] La clé API est obligatoire. Obtenez-la depuis votre dashboard PMS ou auprès de l'administrateur du réseau.
Wallet (Custodial — Server-Side)
Ces méthodes créent/restaurent des wallets côté serveur. L'adresse retournée est au format Bech32 (ex: 8e1a...).
// Créer un nouveau wallet (serveur génère les clés)
const wallet = await client.createWallet();
// Réponse (WalletResponse):
// {
// address: "8e1ahpltzjauwev6lf0jql...",
// private_key_b64: "2lM0rVdFXX...",
// private_key_hex: "da5334ad57455d74...",
// public_key_hex: "04593037fa9d4f6ea2...",
// x25519_pub_hex: "266bcd33ab2d20d2...",
// mnemonic_words: ["gain", "space", "color", ...]
// }// Restaurer un wallet depuis un mnemonic (24 mots BIP39)
const restored = await client.restoreFromMnemonic(
"gain space color filter buzz bind side before sauce twist slam history chief patch desk chunk way oblige output turtle purchase scare token rapid"
);
console.log(restored.address); // "8e1ahpltzjauwev6lf0jql..."// Restaurer un wallet depuis une clé privée hex
const imported = await client.restoreFromPrivateKey(
"da5334ad57455d74e5150e4eb06398ce9cf27762b6f29eac7f82f178bee07406"
);
console.log(imported.address); // même adresse que ci-dessus[!NOTE] Le mnemonic et la clé privée produisent exactement la même adresse — la dérivation est déterministe.
Méthodes de Lecture
// Lister les ledgers actifs (avec block_count et symbol par ledger)
const ledgers: LedgerInfo[] = await client.listLedgers();
// Réponse:
// [
// { id: "main", network_id: "mainnet", prefix: "", protocol_version: 1, block_count: 12345, symbol: "PMS" },
// { id: "gaming", network_id: "gaming-net", prefix: "gam_", protocol_version: 1, block_count: 678, symbol: "GAME" }
// ]
// Filtrer par préfixe de nom (starts_with, case-insensitive sur id, network_id ou symbol)
const gaming = await client.listLedgers({ search: "gam" });
// → [{ id: "gaming", ... }]// Récupérer les tips du DAG (blocs les plus récents)
const tips: string[] = await client.getTips();
// Réponse: ["4aa21b8f570005b4088c53149c9afedc528d7a47127e915744a1811c11d5956c", "..."]// Récupérer un bloc par son ID
const block: Block = await client.getBlock(blockId);
// Réponse:
// {
// id: "4aa21b8f570005b4088c53149c9afedc528d7a47127e915744a1811c11d5956c",
// parents: ["abc123...", "def456..."],
// payload: { Plain: { TxUtxo: { ... } } },
// nonce: 12345
// }// Récupérer le supply total
const supply: SupplyInfo = await client.getSupply();
// Réponse:
// {
// circulating: "1000000.00000000",
// utxo_count: 42567
// }// Récupérer les UTXOs d'une adresse
const utxos: Utxo[] = await client.getUtxos(address);
// Réponse:
// [
// {
// address: "04abc123...",
// amount: "50.00000000",
// outpoint: { txid: "tx123...", index: 0 }
// },
// {
// address: "04abc123...",
// amount: "25.50000000",
// outpoint: { txid: "tx456...", index: 1 }
// }
// ]// Récupérer la balance d'une adresse
const balance: string = await client.getBalance(address);
// Réponse: "75.50000000"// Récupérer balance + UTXOs détaillés
const info: BalanceInfo = await client.getBalanceInfo(address);
// Réponse:
// {
// address: "04abc123...",
// balance: "75.50000000",
// utxos: [{ address: "...", amount: "...", outpoint: {...} }, ...]
// }// Récupérer l'historique (Transactions, Mints, Rewards)
const history = await client.getHistory(address, { limit: 50 });
// Réponse:
// {
// address: "04abc123...",
// count: 50,
// items: [
// { block_id: "...", ts_ms: 1700000000000, payload_type: "Reward", payload: { ... } },
// { block_id: "...", ts_ms: 1700000050000, payload_type: "TxUtxo", payload: { ... } }
// ]
// }
// Récupérer l'historique avec déchiffrement automatique des rewards
// (Nécessite le wallet pour déchiffrer les EncryptedRewards)
const historyWithDecrypt = await client.getHistory(address, {
limit: 50,
decryptionWallet: myWallet
});
// Les items "EncryptedReward" déchiffrés apparaîtront comme des "Reward" standardsActivity API
L'Activity API classifie chaque transaction avec un type semantique (fee_received, transfer_in, nft_mint, freeze, etc.), une direction et un montant net. Elle remplace /wallet/history (deprecie).
// Toute l'activite d'un wallet
const activity = await client.getActivity("8eabc...");
// Reponse: { address, items: ActivityItem[], count, has_more, next_after_ts?, next_after_id? }
// Filtrer par type
const fees = await client.getActivity("8eabc...", {
type: ["fee_received", "reward"],
limit: 20,
});
// Pagination
const page2 = await client.getActivity("8eabc...", {
after_ts: activity.next_after_ts,
after_id: activity.next_after_id,
});
// Filtrer par asset
const edeniteActivity = await client.getActivity("8eabc...", {
asset_id: "edenite",
});
// Avec dechiffrement des payloads chiffres (EncryptedReward, Encrypted)
// IMPORTANT: ne passer la cle privee que sur TLS
const decrypted = await client.getActivity("8eabc...", {
x25519_sk_hex: "votre_cle_privee_x25519_hex",
});Streaming temps reel (SSE) :
const stop = client.streamActivity("8eabc...", {
type: ["transfer_in", "fee_received"],
x25519_sk_hex: "votre_cle_privee_x25519_hex", // Optionnel: dechiffrement en temps reel
onActivity: (item) => {
console.log(`${item.activity_type}: ${item.amount} (${item.direction})`);
},
onError: (err) => console.error("SSE error:", err),
onClose: () => console.log("Stream closed"),
});
// Plus tard: fermer la connexion
stop();Methodes d'Ecriture (Transactions)
// Envoyer des tokens
const result = await client.send({
to: "04destinataire...",
amount: "100.0",
wallet: myWallet,
memo: "Paiement optionnel", // Optionnel
});
// Réponse:
// {
// status: "inserted", // ou "already_exists"
// block_id: "7f3a2b1c..."
// }NFT - Non-Fungible Tokens
Le SDK supporte les opérations NFT natives du réseau PMS.
Mint NFT (Standard)
La création de NFT est sécurisée par le Coordinateur.
// Le server (Coordinateur) signe et chiffre le NFT pour vous.
const result = await client.mintNft({
tokenId: "unique-nft-001",
metadata: {
name: "Mon NFT",
description: "Description du NFT",
uri: "ipfs://QmXxx...",
nft_type: "art",
},
wallet: myWallet, // Votre wallet personnel
});
// Réponse:
// {
// status: "inserted",
// token_id: "unique-nft-001",
// block_id: "a1b2c3d4e5f6..."
// }[!NOTE] Les métadonnées sont automatiquement chiffrées par le serveur pour le propriétaire et le Coordinateur.
Mint Cube (NFT avec Rareté)
Les Cubes sont des NFTs spéciaux avec rareté et attributs générés par un backend Authority.
// Mint un cube pour un utilisateur
const result = await client.mintCube({
wallet: myWallet,
generatorUrl: "https://cube-generator.example.com", // Backend Authority
});
// Réponse (MintCubeResponse):
// {
// status: "inserted",
// block_id: "9f8e7d6c5b4a...",
// token_id: "a1b2c3d4e5f6...64chars...",
// rarity: "Legendary",
// roll: 75,
// attributes: {
// weight: 50.5,
// size: 30.2,
// density: 2.5
// }
// }Raretés possibles :
| Rareté | Probabilité | Cubes sur 10M | |--------|-------------|---------------| | Unique | 1/1,000,000 | 10 | | Legendary | 1/100,000 | 100 | | Rare | 1/10,000 | 1,000 | | Uncommon | 1/1,000 | 10,000 | | Common | 1/100 | 100,000 | | Basic | ~99% | ~9,888,890 |
Burn NFT
// Détruit un NFT (seul le propriétaire peut brûler)
const result = await client.burnNft({
tokenId: "nft-to-destroy",
wallet: ownerWallet,
});
// Réponse:
// {
// status: "inserted",
// block_id: "1a2b3c4d5e6f...",
// refund: { // Uniquement pour les Cubes authentiques
// amount: "1.23456789",
// recipient: "04abc123..."
// }
// }[!TIP] Les Cubes avec une signature Authority valide génèrent un remboursement automatique calculé selon leurs attributs.
Batch Burn (Destruction Multiple)
Pour détruire plusieurs NFTs en une seule transaction (économie de frais) :
const result = await client.burnNfts({
tokenIds: ["token-1", "token-2", "token-3"],
wallet: ownerWallet,
});
// Réponse:
// {
// status: "burned",
// token_id: "batch",
// token_ids: ["token-1", "token-2", "token-3"],
// refund: { ... } // Remboursement cumulé
// }API Avancée
Pour les cas d'usage avancés (construction manuelle de blocs, chiffrement custom), importez depuis le module advanced :
import {
computeBlockId,
checkPowBits,
encryptPayload,
decryptPayload,
generateX25519Keypair,
deriveX25519PublicKey,
} from "@empereur-rouge/pms-sdk/src/advanced";
import type {
WireBlock,
PayloadEnvelope,
TxUtxo,
} from "@empereur-rouge/pms-sdk/src/advanced";[!WARNING] L'API avancée peut changer sans préavis. Préférez l'API publique pour la stabilité.
Utilitaires (API Publique)
import {
parseAmount,
formatAmount,
toHex,
fromHex,
} from "@empereur-rouge/pms-sdk";
// Convertir les montants
const sats = parseAmount("10.5"); // -> 1050000000n
const formatted = formatAmount(sats); // -> "10.50000000"
// Conversions hex
const hex = toHex(new Uint8Array([1, 2, 3]));
const bytes = fromHex("010203");Types TypeScript
Tous les types sont exportés et documentés :
import type {
// Configuration
PmsClientConfig,
// Réponses API
SubmitResponse,
BalanceInfo,
SupplyInfo,
WalletResponse,
// NFT
NftMetadata,
MintCubeResponse,
BurnNftResponse,
CubeAttributes,
// Blocs & Transactions (lecture)
Block,
Utxo,
// Historique
WalletHistoryResp,
HistoryItem,
// Activity
ActivityItem,
ActivityResp,
ActivityOptions,
StreamActivityOptions,
ActivityType,
ActivityDirection,
// Ledger
LedgerInfo,
} from "@empereur-rouge/pms-sdk";
// Types bas niveau (API avancée)
import type {
WireBlock,
PayloadEnvelope,
TxUtxo,
OutputRef,
TxOutput,
} from "@empereur-rouge/pms-sdk/src/advanced";Sécurité
Coordinateur et Minting
En production, seul le Coordinateur peut créer de nouveaux NFTs (y compris les Cubes). Cette restriction est appliquée au niveau du backend via la clé coordinator_pk.
Les NFTs authentiques sont identifiés par le creator qui correspond à la clé publique du Coordinateur.
Chiffrement
Le SDK utilise :
- secp256k1 pour les signatures (ECDSA, DER-encoded)
- X25519 pour l'échange de clés
- AES-256-GCM pour le chiffrement symétrique
Bonnes Pratiques
// ✅ Stocker le mnemonic de façon sécurisée
const wallet = PmsWallet.generate();
// Sauvegarder wallet.mnemonic dans un stockage sécurisé
// ✅ Ne jamais exposer la clé privée
const privateKey = wallet.exportPrivateKey();
// Ne pas logger ou transmettre cette valeur
// ✅ Vérifier les signatures avant d'accepter des données
const isValid = PmsWallet.verify(message, signature, senderPubKey);Racing Pattern
Le SDK utilise un "racing pattern" pour la soumission des transactions :
- Le client maintient une liste de nœuds connus
- Lors de
submitBlock(), la transaction est envoyée à tous les nœuds en parallèle - La première réponse positive est retournée
- Les autres requêtes sont annulées
Cela améliore :
- La latence (premier nœud qui répond)
- La fiabilité (tolérance aux pannes)
- La propagation (le bloc atteint plusieurs nœuds rapidement)
// Désactiver si non souhaité
const client = new PmsClient({
nodeUrl: "...",
apiKey: "pk_live_...",
enableRacing: false,
});Tests
# Lancer les tests
npm test
# Mode watch
npm run test:watch
# Couverture
npm run test:coverageLicence
MIT © PMS Team
