Guias

Guias · Parte 2 de 6

Publique sua primeira PoE

Publicar é a metade do Label 309 que de fato precisa de um gateway. Verificar dispensa confiança e dispensa conta; publicar coloca uma transação na cadeia, e isso tem um custo — por isso você envia através de um gateway Label 309 que constrói a transação, paga a taxa e debita seu próprio modelo de saldo. O SDK e a CLI não dependem de um gateway específico: aponte-os para qualquer gateway para o qual você tenha uma chave de API.

Toda publicação segue o mesmo formato em duas etapas — travar um preço e depois enviar. O gateway precifica o registro a partir de um snapshot de câmbio em tempo real e devolve um quote_id válido por 15 minutos; a chamada de publicação o consome de forma atômica junto com a gravação na cadeia. Os helpers de alto nível calculam o hash do seu conteúdo e constroem para você o registro em CBOR canônico.

Com a CLI

Instale o binário cardanowall e aponte o submit para um arquivo. Ele calcula o hash do conteúdo, ancora o digest e imprime o resultado:

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

--base-url e --api-key também são lidos a partir das variáveis CARDANOWALL_BASE_URL e CARDANOWALL_API_KEY, ou de um perfil de gateway salvo, de modo que podem ser omitidos no comando em CI. Se você já tem o digest em mãos, ancore-o diretamente com --hash em vez de --file; acrescente --alg blake2b-256 para trocar o padrão sha2-256, e --json para obter um resumo legível por máquina:

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

Para assinar o registro com sua chave de identidade, passe os 32 bytes do seed mestre via --seed-file ou --seed-stdin (nunca um --seed direto na linha de comando — ele acaba no histórico do shell). Omita esse passo para publicar sem assinatura.

Com o SDK TypeScript

Crie um cliente apontado para o seu gateway e, em seguida, cote e publique em uma única chamada de helper. O publishContent calcula o hash dos bytes, constrói o registro e o envia:

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

O result.status começa em submitting; tx_hash é null até que o gateway construa a transação. Passe uma idempotencyKey para tornar seguras as tentativas de reenvio — uma submissão idêntica repetida retorna o registro original (dedup_hit: true) sem debitar duas vezes. Para um digest pré-computado, use publishPrehashed; para um envelope selado com destinatário, use publishSealed.

Com o SDK Python

O cardanowall-sdk espelha os helpers do TypeScript, método a método. O cliente é um gerenciador de contexto assíncrono; as respostas voltam como dicionários simples:

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())

Com o SDK Rust

O crate cardanowall expõe o mesmo cliente, independente do gateway. As chamadas são bloqueantes, portanto nenhum runtime assíncrono é necessário; os helpers retornam resultados tipados:

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(())
}

Para um digest pré-computado, use publish_prehashed; para um envelope selado com destinatário, use publish_sealed.

A taxa é do gateway, a prova é sua

O gateway pelo qual você publica paga a taxa do Cardano e debita seu modelo de saldo — mas o registro que ele ancora nada mais é do que metadados Label 309 comuns sob o rótulo 309. Qualquer pessoa pode verificá-lo apenas a partir da cadeia pública, sem conta e sem precisar confiar no gateway. Para endereçar um registro a um destinatário, consulte construir uma PoE selada; para conhecer o formato exato na cadeia, leia o registro.