ガイド

ガイド · 全6部中 第2部

最初の存在証明を発行する

Label 309 のうち、ゲートウェイが必要になるのは発行側です。検証はトラストレスでアカウントも要りませんが、発行はチェーンにトランザクションを書き込むため手数料が発生します。そこで、トランザクションを構築し、手数料を支払い、独自の残高モデルから費用を引き落とす Label 309 ゲートウェイ経由で送信します。SDK と CLI はゲートウェイ非依存の設計なので、API キーを持っているゲートウェイならどれにでも向けられます。

発行はどれも同じ2ステップの形です。価格をロックし、それから送信する、という流れです。ゲートウェイはリアルタイムの為替スナップショットからレコードの価格を算出し、15分間有効な quote_id を返します。発行の呼び出しは、チェーン上への書き込みとアトミックにこの quote_id を消費します。高レベルのヘルパーがコンテンツのハッシュ化と正規 CBOR レコードの構築を代行します。

CLI から

cardanowall バイナリをインストールし、submit でファイルを指定します。コンテンツをハッシュ化してダイジェストをチェーン上に記録し、結果を出力します。

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

--base-url--api-key は環境変数 CARDANOWALL_BASE_URL および CARDANOWALL_API_KEY、あるいは保存済みのゲートウェイプロファイルからも読み込まれるため、CI ではコマンドから省略できます。すでにダイジェストを持っている場合は、--file の代わりに --hash でそのまま記録できます。デフォルトの sha2-256 から切り替えるには --alg blake2b-256 を、機械可読な要約には --json を付けてください。

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

レコードに自分のアイデンティティ鍵で署名するには、32バイトのマスターシードを --seed-file または --seed-stdin 経由で渡してください(--seed を argv に直接書くとシェル履歴に残るため避けてください)。省略すると署名なしで発行されます。

TypeScript SDK から

ゲートウェイに対してクライアントを生成し、1回のヘルパー呼び出しで見積もりと発行をまとめて行います。publishContent はバイト列をハッシュ化し、レコードを構築して送信します。

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 は最初 submitting から始まります。ゲートウェイがトランザクションを構築するまで tx_hashnull です。idempotencyKey を渡すと再試行が安全になります。同一の送信を繰り返しても元のレコードが返され(dedup_hit: true)、二重に引き落とされることはありません。事前計算済みのダイジェストには publishPrehashed を、受信者宛の封緘済みエンベロープには publishSealed を使ってください。

Python SDK から

cardanowall-sdk は TypeScript のヘルパーとメソッド単位で対応しています。クライアントは非同期コンテキストマネージャーで、レスポンスは素の辞書として返ります。

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

Rust SDK から

cardanowall クレートも、同じゲートウェイ非依存のクライアントを提供します。呼び出しはブロッキングなので非同期ランタイムは不要で、ヘルパーは型付きの結果を返します。

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

事前計算済みのダイジェストには publish_prehashed を、受信者宛の封緘済みエンベロープには publish_sealed を使ってください。

手数料はゲートウェイ、存在証明は自分のもの

発行に使ったゲートウェイが Cardano の手数料を支払い、独自の残高モデルから費用を引き落とします。とはいえ、チェーン上に記録されるのはラベル 309 の下に置かれた素の Label 309 メタデータです。アカウントもゲートウェイへの信頼も不要で、だれでも公開されたチェーンだけから検証できます。代わりに受信者宛にレコードを送るには封緘済み PoE を作るを、チェーン上の正確な構造についてはレコードを参照してください。