Guides

Guides · Partie 2 sur 6

Publiez votre première PoE

La publication est la moitié de Label 309 qui, elle, nécessite une passerelle. La vérification ne requiert aucune confiance et aucun compte ; la publication, elle, inscrit une transaction sur la chaîne, et cela a un coût — vous soumettez donc par l’intermédiaire d’une passerelle Label 309 qui construit la transaction, paie les frais et les débite de son propre modèle de solde. Le SDK et la CLI sont indépendants de la passerelle : dirigez-les vers la passerelle pour laquelle vous détenez une clé d’API.

Toute publication suit la même structure en deux étapes — fixer un prix, puis soumettre. La passerelle calcule le prix de l’enregistrement à partir d’un instantané FX en temps réel et renvoie un quote_id valable 15 minutes ; l’appel de publication le consomme de façon atomique en même temps que l’insertion sur la chaîne. Les fonctions utilitaires de haut niveau calculent l’empreinte de votre contenu et construisent pour vous l’enregistrement en CBOR canonique.

Avec la CLI

Installez le binaire cardanowall, puis dirigez submit vers un fichier. Il en calcule l’empreinte, ancre le condensé et affiche le résultat :

cardanowall submit \
  --file ./contract.pdf \
  --base-url https://your-gateway.example \
  --api-key "$CW_API_KEY"

--base-url et --api-key se lisent aussi depuis CARDANOWALL_BASE_URL et CARDANOWALL_API_KEY, ou depuis un profil de passerelle enregistré, de sorte qu’ils disparaissent de la commande en CI. Si vous détenez déjà le condensé, ancrez-le directement avec --hash au lieu de --file ; ajoutez --alg blake2b-256 pour remplacer la valeur par défaut sha2-256, et --json pour un résumé lisible par une machine :

cardanowall submit --hash 3b9f…c1a2 --json

Pour signer l’enregistrement avec votre clé d’identité, transmettez le seed maître de 32 octets via --seed-file ou --seed-stdin (jamais un --seed brut sur argv — il atterrit dans l’historique du shell). Omettez-le pour publier sans signature.

Avec le SDK TypeScript

Construisez un client pointant vers votre passerelle, puis obtenez un prix et publiez en un seul appel utilitaire. publishContent calcule l’empreinte des octets, construit l’enregistrement et le soumet :

import { Label309Client } from '@cardanowall/sdk-ts';

const client = new Label309Client({
  baseUrl: 'https://your-gateway.example',
  apiKey: process.env.CW_API_KEY,
});

const quote = await client.poe.quote({
  recordBytes: 256,
  recipientCount: 0,
  fileBytesTotal: 0,
});

const result = await client.poe.publishContent({
  content: fileBytes, // Uint8Array or a UTF-8 string
  quoteId: quote.quote_id,
  // idempotencyKey: crypto.randomUUID(), // safe to retry the same submit
  // signer is optional — omit to publish unsigned (profile=core)
});

console.log(result.id, result.tx_hash, result.status);
console.log(result.balance_after_usd_micros); // decimal string of USD micro-cents

result.status commence à submitting ; tx_hash reste null tant que la passerelle n’a pas construit la transaction. Transmettez un idempotencyKey pour sécuriser les nouvelles tentatives — une soumission identique répétée renvoie l’enregistrement d’origine (dedup_hit: true) sans débiter deux fois. Pour un condensé précalculé, utilisez publishPrehashed ; pour une enveloppe scellée adressée à un destinataire, utilisez publishSealed.

Avec le SDK Python

cardanowall-sdk reproduit les fonctions utilitaires TypeScript méthode pour méthode. Le client est un gestionnaire de contexte asynchrone ; les réponses reviennent sous forme de simples dictionnaires :

import asyncio
from cardanowall.client import Label309Client


async def main() -> None:
    async with Label309Client(
        base_url="https://your-gateway.example",
        api_key="<opaque-bearer>",
    ) as client:
        quote = await client.poe.quote(
            record_bytes=256, recipient_count=0, file_bytes_total=0
        )
        out = await client.poe.publish_content(
            content="hello world",  # str (UTF-8) or bytes
            quote_id=quote["quote_id"],
        )
        print(out["id"], out["tx_hash"], out["status"])


asyncio.run(main())

Avec le SDK Rust

Le crate cardanowall expose le même client indépendant de la passerelle. Les appels sont bloquants, aucun environnement d’exécution asynchrone n’est donc nécessaire ; les fonctions utilitaires renvoient des résultats typés :

use cardanowall::client::{
    Label309Client, Label309ClientConfig, PublishContentInput, QuoteInput,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Label309Client::new(Label309ClientConfig {
        base_url: Some("https://your-gateway.example".into()),
        api_key: std::env::var("CW_API_KEY").ok(),
    })?;

    let quote = client.poe().quote(&QuoteInput {
        record_bytes: 256,
        recipient_count: 0,
        file_bytes_total: 0,
    })?;

    let result = client.poe().publish_content(&PublishContentInput {
        content: file_bytes, // Vec<u8>
        quote_id: quote.quote_id,
        hash_alg: None, // defaults to sha2-256
        signer: None,   // omit to publish unsigned (profile = core)
        idempotency_key: None,
    })?;

    println!("{} {:?} {:?}", result.id, result.tx_hash, result.status);
    Ok(())
}

Pour un condensé précalculé, utilisez publish_prehashed ; pour une enveloppe scellée adressée à un destinataire, utilisez publish_sealed.

Les frais sont à la passerelle, la preuve est à vous

La passerelle par laquelle vous publiez paie les frais Cardano et les débite de son modèle de solde — mais l’enregistrement qu’elle ancre n’est que de simples métadonnées Label 309 sous le label 309. N’importe qui peut le vérifier à partir de la seule chaîne publique, sans compte et sans accorder la moindre confiance à la passerelle. Pour adresser plutôt un enregistrement à un destinataire, voyez construire une PoE scellée ; pour la forme exacte sur la chaîne, lisez l’enregistrement.