RGB - Développement

Guide développeur pour intégrer RGB dans vos applications : SDK, API, et bonnes pratiques.

💡

🚀 Solutions DazNode

DazNode simplifie votre parcours Bitcoin/Lightning avec des solutions clé en main.

  • Setup automatisé en 1-clic
  • Support expert inclus
  • ROI optimisé garanti

RGB - Développement 💻

Temps de lecture estimé : 25 minutes

Vue d'Ensemble 🌍

Ce guide vous accompagne dans l'intégration de RGB dans vos applications, depuis les concepts de base jusqu'aux implémentations avancées.

Architecture de Développement 🏗️

┌───────────────────┐
│   Votre Application    │
├───────────────────┤
│     RGB SDK/API       │
├───────────────────┤
│     RGB Core          │
├───────────────────┤
│   Bitcoin Network     │
└───────────────────┘

Installation des Outils 🛠️

RGB SDK pour Rust

# Cargo.toml
[dependencies]
rgb-sdk = "0.10"
rgb-core = "0.10"
rgb-wallet = "0.10"
bitcoin = "0.30"
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }

RGB SDK pour JavaScript/TypeScript

# Installation via npm
npm install @rgb-protocol/rgb-sdk
npm install @rgb-protocol/bitcoin-js

# Ou via yarn
yarn add @rgb-protocol/rgb-sdk @rgb-protocol/bitcoin-js

RGB SDK pour Python

# Installation via pip
pip install rgb-python
pip install bitcoin-python

# Installation depuis les sources
git clone https://github.com/RGB-WG/rgb-python
cd rgb-python && pip install -e .

Premiers Pas avec l'API 🚀

Configuration Initiale (Rust)

use rgb_sdk::*;
use bitcoin::Network;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Configuration du client RGB
    let config = RgbConfig {
        network: Network::Testnet,
        data_dir: "./rgb-data".into(),
        electrum_server: "electrum.example.com:50002".into(),
    };
    
    // Initialisation du client
    let client = RgbClient::new(config).await?;
    
    println!("Client RGB initialisé avec succès !");
    Ok(())
}

Configuration Initiale (JavaScript)

import { RgbClient, Network } from '@rgb-protocol/rgb-sdk';

async function initRgb() {
    const config = {
        network: Network.Testnet,
        dataDir: './rgb-data',
        electrumServer: 'electrum.example.com:50002'
    };
    
    const client = new RgbClient(config);
    await client.initialize();
    
    console.log('Client RGB initialisé !');
    return client;
}

Configuration Initiale (Python)

import asyncio
from rgb_python import RgbClient, Network

async def init_rgb():
    config = {
        'network': Network.TESTNET,
        'data_dir': './rgb-data',
        'electrum_server': 'electrum.example.com:50002'
    }
    
    client = RgbClient(config)
    await client.initialize()
    
    print("Client RGB initialisé !")
    return client

# Utilisation
client = asyncio.run(init_rgb())

Gestion des Portefeuilles 💼

Création d'un Portefeuille (Rust)

use rgb_sdk::wallet::*;
use bip32::ExtendedPrivKey;

// Génération d'un nouveau portefeuille
let mnemonic = generate_mnemonic()?;
let seed = mnemonic_to_seed(&mnemonic, None)?;
let master_key = ExtendedPrivKey::new_master(Network::Testnet, &seed)?;

// Création du portefeuille RGB
let wallet = RgbWallet::new(master_key, Network::Testnet)?;

println!("Adresse Bitcoin : {}", wallet.next_bitcoin_address()?);
println!("Mémonique : {}", mnemonic);

Opérations sur Portefeuille (JavaScript)

import { RgbWallet, generateMnemonic } from '@rgb-protocol/rgb-sdk';

class WalletManager {
    async createWallet() {
        const mnemonic = generateMnemonic();
        this.wallet = new RgbWallet({ mnemonic, network: 'testnet' });
        await this.wallet.initialize();
        
        return {
            mnemonic,
            bitcoinAddress: await this.wallet.getNextBitcoinAddress(),
            rgbAddress: await this.wallet.getRgbAddress()
        };
    }
    
    async getBalance(assetId = null) {
        if (assetId) {
            return await this.wallet.getAssetBalance(assetId);
        }
        return await this.wallet.getBitcoinBalance();
    }
    
    async listAssets() {
        return await this.wallet.listAssets();
    }
}

Création d'Actifs 🎨

Token Fongible (Rust)

use rgb_sdk::contract::fungible::*;

async fn create_token(
    client: &RgbClient,
    name: &str,
    ticker: &str,
    supply: u64,
    genesis_utxo: OutPoint
) -> Result<AssetId, RgbError> {
    let contract_data = FungibleContract {
        name: name.to_string(),
        ticker: ticker.to_string(),
        precision: 8,
        supply,
        inflatable: false,
        burnable: false,
        metadata: None,
    };
    
    let asset_id = client.issue_fungible(
        contract_data,
        genesis_utxo,
        None // pas de fee custom
    ).await?;
    
    println!("Token créé avec l'ID : {}", asset_id);
    Ok(asset_id)
}

NFT Collection (JavaScript)

class NftCreator {
    constructor(rgbClient) {
        this.client = rgbClient;
    }
    
    async createCollection({
        name,
        description,
        maxItems,
        baseUri,
        genesisUtxo
    }) {
        const contractData = {
            schema: 'RGB21',
            name,
            description,
            maxItems,
            metadata: {
                baseUri,
                createdAt: new Date().toISOString()
            }
        };
        
        const assetId = await this.client.issueNonFungible(
            contractData,
            genesisUtxo
        );
        
        console.log(`Collection créée : ${assetId}`);
        return assetId;
    }
    
    async mintNft(assetId, tokenData, recipientUtxo) {
        const nftData = {
            name: tokenData.name,
            description: tokenData.description,
            image: tokenData.image,
            attributes: tokenData.attributes
        };
        
        return await this.client.mintNft(assetId, nftData, recipientUtxo);
    }
}

Transactions et Transferts 🔄

Transfert Simple (Rust)

use rgb_sdk::transfer::*;

async fn transfer_tokens(
    client: &RgbClient,
    asset_id: AssetId,
    amount: u64,
    recipient_address: &str
) -> Result<Txid, RgbError> {
    // Création de la facture destinataire
    let invoice = client.create_invoice(
        asset_id,
        amount,
        recipient_address
    ).await?;
    
    // Exécution du transfert
    let txid = client.transfer(
        invoice,
        None // frais automatiques
    ).await?;
    
    println!("Transfert effectué : {}", txid);
    Ok(txid)
}

Batch Transfer (JavaScript)

class TransferManager {
    constructor(rgbClient) {
        this.client = rgbClient;
    }
    
    async batchTransfer(transfers) {
        const batch = [];
        
        for (const transfer of transfers) {
            const invoice = await this.client.createInvoice({
                assetId: transfer.assetId,
                amount: transfer.amount,
                recipientAddress: transfer.recipient
            });
            
            batch.push(invoice);
        }
        
        // Exécution en lot pour économiser les frais
        const txid = await this.client.batchTransfer(batch);
        
        console.log(`Batch transfer complété : ${txid}`);
        return txid;
    }
    
    async getTransferHistory(assetId) {
        return await this.client.getAssetHistory(assetId);
    }
}

Intégration Lightning Network ⚡

Canal RGB-Lightning (Rust)

use rgb_sdk::lightning::*;

async fn setup_rgb_channel(
    client: &RgbClient,
    peer_pubkey: PublicKey,
    channel_capacity: u64,
    rgb_assets: Vec<AssetId>
) -> Result<ChannelId, RgbError> {
    let channel_config = RgbChannelConfig {
        capacity: channel_capacity,
        supported_assets: rgb_assets,
        fee_rate: FeeRate::default(),
    };
    
    let channel_id = client.open_rgb_channel(
        peer_pubkey,
        channel_config
    ).await?;
    
    println!("Canal RGB ouvert : {}", channel_id);
    Ok(channel_id)
}

async fn lightning_payment(
    client: &RgbClient,
    invoice: &str,
    asset_id: AssetId,
    amount: u64
) -> Result<PaymentHash, RgbError> {
    let payment = client.pay_rgb_invoice(
        invoice,
        asset_id,
        amount
    ).await?;
    
    Ok(payment.hash)
}

Paiements Instantanés (JavaScript)

class LightningRgbPayments {
    constructor(rgbClient, lnClient) {
        this.rgb = rgbClient;
        this.ln = lnClient;
    }
    
    async createRgbInvoice(assetId, amount, description) {
        const invoice = await this.rgb.createLightningInvoice({
            assetId,
            amount,
            description,
            expiry: 3600 // 1 heure
        });
        
        return invoice;
    }
    
    async payRgbInvoice(invoice, assetId) {
        // Vérification du solde
        const balance = await this.rgb.getAssetBalance(assetId);
        const invoiceData = await this.rgb.decodeInvoice(invoice);
        
        if (balance < invoiceData.amount) {
            throw new Error('Solde insuffisant');
        }
        
        // Paiement via Lightning
        const payment = await this.ln.payInvoice(invoice, {
            assetId,
            maxFee: invoiceData.amount * 0.01 // 1% max fee
        });
        
        return payment;
    }
}

Sécurité et Validation 🛡️

Validation de Contrats (Rust)

use rgb_sdk::validation::*;

async fn validate_asset(
    client: &RgbClient,
    asset_id: AssetId
) -> Result<ValidationReport, RgbError> {
    let report = client.validate_asset_full(asset_id).await?;
    
    match report.status {
        ValidationStatus::Valid => {
            println!("Actif valide : {}", asset_id);
        },
        ValidationStatus::Invalid(errors) => {
            println!("Actif invalide : {:?}", errors);
            return Err(RgbError::InvalidAsset(errors));
        },
        ValidationStatus::Unknown => {
            println!("Statut de validation inconnu");
        }
    }
    
    Ok(report)
}

// Vérification des transitions
async fn validate_transition(
    client: &RgbClient,
    transition_id: &str
) -> Result<bool, RgbError> {
    let is_valid = client.validate_transition(transition_id).await?;
    
    if !is_valid {
        return Err(RgbError::InvalidTransition);
    }
    
    Ok(true)
}

Gestion des Erreurs (JavaScript)

class RgbErrorHandler {
    static handle(error) {
        switch (error.type) {
            case 'INSUFFICIENT_FUNDS':
                return {
                    message: 'Solde insuffisant',
                    action: 'fund_wallet',
                    details: error.details
                };
                
            case 'INVALID_ASSET':
                return {
                    message: 'Actif invalide ou non reconnu',
                    action: 'verify_asset',
                    details: error.details
                };
                
            case 'NETWORK_ERROR':
                return {
                    message: 'Erreur réseau',
                    action: 'retry',
                    retryable: true
                };
                
            default:
                return {
                    message: 'Erreur inconnue',
                    action: 'contact_support',
                    details: error
                };
        }
    }
    
    static async retry(operation, maxRetries = 3) {
        for (let i = 0; i < maxRetries; i++) {
            try {
                return await operation();
            } catch (error) {
                const handled = this.handle(error);
                
                if (!handled.retryable || i === maxRetries - 1) {
                    throw error;
                }
                
                // Attente exponentielle
                await new Promise(resolve => 
                    setTimeout(resolve, Math.pow(2, i) * 1000)
                );
            }
        }
    }
}

Tests et Débogage 🔍

Tests Unitaires (Rust)

#[cfg(test)]
mod tests {
    use super::*;
    use rgb_sdk::test_utils::*;
    
    #[tokio::test]
    async fn test_token_creation() {
        let client = create_test_client().await;
        let genesis_utxo = create_test_utxo(&client).await;
        
        let asset_id = create_token(
            &client,
            "Test Token",
            "TEST",
            1000000,
            genesis_utxo
        ).await.unwrap();
        
        // Vérification
        let asset_info = client.get_asset_info(asset_id).await.unwrap();
        assert_eq!(asset_info.name, "Test Token");
        assert_eq!(asset_info.ticker, "TEST");
    }
    
    #[tokio::test]
    async fn test_transfer() {
        let client = create_test_client().await;
        let asset_id = create_test_asset(&client).await;
        
        let recipient = "rgb:test:recipient123";
        let amount = 1000;
        
        let txid = transfer_tokens(
            &client,
            asset_id,
            amount,
            recipient
        ).await.unwrap();
        
        assert!(txid.to_string().len() == 64);
    }
}

Tests d'Intégration (JavaScript)

import { describe, it, expect, beforeEach } from 'vitest';
import { RgbTestClient } from '@rgb-protocol/rgb-sdk/testing';

describe('RGB Integration Tests', () => {
    let client;
    let wallet;
    
    beforeEach(async () => {
        client = new RgbTestClient();
        await client.initialize();
        
        wallet = await client.createTestWallet();
        await wallet.fund(1000000); // 0.01 BTC
    });
    
    it('should create and transfer tokens', async () => {
        // Création du token
        const assetId = await client.issueToken({
            name: 'Test Token',
            ticker: 'TEST',
            supply: 1000000
        });
        
        expect(assetId).toBeDefined();
        
        // Transfert
        const recipient = await client.createTestWallet();
        const txid = await wallet.transfer({
            assetId,
            amount: 1000,
            recipient: recipient.address
        });
        
        expect(txid).toBeDefined();
        
        // Vérification des soldes
        const senderBalance = await wallet.getBalance(assetId);
        const recipientBalance = await recipient.getBalance(assetId);
        
        expect(senderBalance).toBe(999000);
        expect(recipientBalance).toBe(1000);
    });
});

Monitoring et Analytics 📊

Métriques de Performance (Rust)

use rgb_sdk::metrics::*;

struct RgbMetrics {
    client: RgbClient,
    metrics_collector: MetricsCollector,
}

impl RgbMetrics {
    async fn collect_metrics(&self) -> RgbStats {
        let stats = RgbStats {
            total_assets: self.client.count_assets().await?,
            total_transactions: self.client.count_transactions().await?,
            wallet_balance: self.client.get_total_balance().await?,
            network_fees_paid: self.client.get_fees_paid().await?,
            validation_success_rate: self.calculate_validation_rate().await?,
        };
        
        self.metrics_collector.record(stats.clone()).await?;
        stats
    }
    
    async fn get_asset_analytics(&self, asset_id: AssetId) -> AssetAnalytics {
        AssetAnalytics {
            holder_count: self.client.count_asset_holders(asset_id).await?,
            transaction_volume: self.client.get_asset_volume(asset_id).await?,
            price_history: self.client.get_price_history(asset_id).await?,
            velocity: self.calculate_velocity(asset_id).await?,
        }
    }
}

Alertes et Notifications (JavaScript)

class RgbMonitoring {
    constructor(client, alertManager) {
        this.client = client;
        this.alerts = alertManager;
        this.thresholds = {
            lowBalance: 0.001, // BTC
            highFees: 1000, // sats
            validationFailures: 5 // par heure
        };
    }
    
    async startMonitoring() {
        setInterval(async () => {
            await this.checkBalances();
            await this.checkFees();
            await this.checkValidations();
        }, 60000); // Toutes les minutes
    }
    
    async checkBalances() {
        const balance = await this.client.getBitcoinBalance();
        
        if (balance < this.thresholds.lowBalance) {
            await this.alerts.send({
                type: 'LOW_BALANCE',
                message: `Solde Bitcoin faible : ${balance} BTC`,
                severity: 'warning',
                action: 'Fund wallet with Bitcoin'
            });
        }
    }
    
    async checkFees() {
        const recentTxs = await this.client.getRecentTransactions(10);
        const avgFee = recentTxs.reduce((sum, tx) => sum + tx.fee, 0) / recentTxs.length;
        
        if (avgFee > this.thresholds.highFees) {
            await this.alerts.send({
                type: 'HIGH_FEES',
                message: `Frais élevés détectés : ${avgFee} sats`,
                severity: 'info',
                suggestion: 'Consider waiting for lower network fees'
            });
        }
    }
}

Ressources et Documentation 📚

Documentation Officielle

Exemples de Code

Communauté Développeur

Conseil d'Expert : 💡 Commencez par les exemples simples sur testnet, puis progressez vers des implémentations plus complexes. La validation côté client de RGB nécessite une approche de développement différente des smart contracts traditionnels.

🚀

Automatisez votre Success Lightning Network

Suite complète DazNode : Hardware + Logiciel + Support Expert

89% réduction force-close = 150-600€/an économisés
+3.2% ROI optimisé = 320€/an sur 10k€ capital
Setup 15min vs 12h configuration manuelle
Support 24/7 + communauté 500+ experts
Garantie résultats : ROI optimisé ou remboursé