💰

XRPLでトークンを発行する:Trust Line&Issuanceハンズオン

に公開

はじめに

XRP Ledgerの最大の特徴の一つが、スマートコントラクトなしで、トークン(独自通貨)を発行できる ということです。

ブロックチェーンの本来のビジョン — 「誰もが独自の通貨を発行できる世界」。それがXRPLでは現実です。

この記事で学べること

  • Trust Line とは何か、なぜ必要なのか
  • トークンの発行フロー(Issuer ↔ Holder)
  • XRP Ledgerのトークン仕様(精度、小数点、凍結)
  • 実装コード付きハンズオン
  • 注意点:Counterparty Risk(信用リスク)の理解

Trust Lineってなに?

ブロックチェーン初心者向け説明

Trust Line = 「誰かが発行したトークンを受け取ることを許可する回線」

イメージ:銀行口座の「限度額設定」みたいなもの。

あなた  ← Trust Line ← 友人(Issuer)
        ↑ Max 1000 USD ↑

友人が「USD」という通貨を発行している場合、あなたが「最大1000 USDまで受け取ります」という信用枠を作る。これが Trust Line です。

XRPLではなぜTrust Lineが必要か?

XRPと異なり、トークンは「純粋な信用」 だからです。

  • XRP = ネイティブ資産(ブロックチェーンに組み込まれている)
  • トークン = 発行者のIOU(負債証書)

例:

  • 銀行が「1 USD = 1銀行ドル」と発行
  • あなたはそれを信用して受け取る
  • 銀行が破産したら? → 帳消し

XRPLはこの「信用関係」を明示的に記録します。それが Trust Line です。


トークン発行フロー

Step 1: Issuer(発行者)がトークンを「作る」

実は、XRPLでトークンを作成する 専用トランザクションは不要 です。発行者がトークンを送金しようとする時点で、トークンが自動的に「存在」するようになります。

const issuer = "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH";
const token = {
  currency: "USD",      // 3文字コード(カスタム)
  issuer: issuer
};

Step 2: Holder(受取人)がTrust Lineを設定

受取人は、発行者のトークンを受け取る前に、Trust Lineを開く 必要があります。

const trustSetTx = {
  Account: holder,
  TransactionType: "TrustSet",
  LimitAmount: {
    currency: "USD",
    issuer: issuer,
    value: "1000"        // 最大1000 USDまで受け取る
  },
  Fee: "12"
};

Step 3: Issuer が Holder にトークンを送金

Trust Lineが設定されたら、発行者は自由に送金できます。

const paymentTx = {
  Account: issuer,
  Destination: holder,
  Amount: {
    currency: "USD",
    issuer: issuer,
    value: "100"         // 100 USD を送金
  },
  Fee: "12"
};

実装コード:トークン発行・送金

環境構築

npm install xrpl

完全なハンズオンコード

const xrpl = require("xrpl");

async function demonstrateTokenFlow() {
  // Testnet に接続
  const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233");
  await client.connect();

  // Step 1: テストアカウント生成
  const issuer = await generateTestAccount(client);
  const holder = await generateTestAccount(client);

  console.log(`Issuer: ${issuer.address}`);
  console.log(`Holder: ${holder.address}`);

  // Step 2: Holder が Trust Line を設定
  await setupTrustLine(client, holder, issuer.address);

  // Step 3: Issuer がトークンを送金
  await sendToken(client, issuer, holder.address);

  // Step 4: 残高確認
  await checkBalance(client, holder.address);

  await client.disconnect();
}

async function generateTestAccount(client) {
  const wallet = xrpl.Wallet.generate();
  
  // Testnet から XRP をもらう
  const fundResult = await client.fundAccount({
    address: wallet.address
  });
  
  console.log(`Funded ${wallet.address}`);
  return wallet;
}

async function setupTrustLine(client, holder, issuerAddress) {
  const trustSetTx = {
    Account: holder.address,
    TransactionType: "TrustSet",
    LimitAmount: {
      currency: "USD",
      issuer: issuerAddress,
      value: "10000"      // 最大10000 USD まで
    }
  };

  const submittedTx = await client.submitAndWait(trustSetTx, {
    wallet: holder
  });

  console.log(`Trust Line established: ${submittedTx.result.hash}`);
}

async function sendToken(client, issuer, holderAddress) {
  const paymentTx = {
    Account: issuer.address,
    Destination: holderAddress,
    Amount: {
      currency: "USD",
      issuer: issuer.address,
      value: "500"        // 500 USD を送金
    }
  };

  const submittedTx = await client.submitAndWait(paymentTx, {
    wallet: issuer
  });

  console.log(`Token sent: ${submittedTx.result.hash}`);
}

async function checkBalance(client, address) {
  const accountInfo = await client.request({
    command: "account_lines",
    account: address,
    ledger_index: "validated"
  });

  console.log(`\n${address} Balances:`);
  for (const line of accountInfo.result.lines) {
    console.log(`- ${line.currency} (${line.account}): ${line.balance}`);
  }
}

// 実行
demonstrateTokenFlow().catch(console.error);

実行結果

Issuer: rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH
Holder: rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1
Funded rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH
Funded rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1
Trust Line established: ABC123...
Token sent: DEF456...

rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1 Balances:
- USD (rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH): 500

トークンの仕様:細かいルール

通貨コード(Currency Code)

3文字コード(例: USD, EUR, JPY)、または160ビット16進数(カスタム)を使用。

{
  currency: "USD",           // 標準コード
  issuer: "rN7n..."
}

// OR

{
  currency: "015841551A748AD2C1F76FF6ECB0BACF1000000000000000000000000",
  issuer: "rN7n..."
}

精度(Precision)

トークンは最大16桁の精度をサポート。小数点は動的 です。

{
  value: "123.456789",       // 小数点で指定
  currency: "USD"
}

凍結(Freezing)

発行者は、特定のホルダーのトークン保有を凍結できます(Counterparty Risk への対抗手段)。

const freezeTx = {
  Account: issuer.address,
  TransactionType: "TrustSet",
  LimitAmount: {
    currency: "USD",
    issuer: issuer.address,
    value: "0"             // 凍結(制限)
  },
  QualityIn: 0,
  QualityOut: 0
};

実装時の注意点

1. Reserve(リザーブ)を考慮する

Trust Line を作成すると、アカウントのリザーブが増えます(最新ネットワークでは約2 XRP/行)。

// Trust Line が増えるたびに Reserve が増加
Reserve = BaseReserve + (OwnerCount * IncrementReserve)

2. Counterparty Risk(信用リスク)

トークンはただのIOUなので、発行者が破産したら価値がゼロ になります。

100 USD 保有 ← Issuer が破産 → 0 USD

XRPLでトークンを選ぶときは、発行者を信用できるか を必ず確認してください。

3. Decimal精度

計算のズレを避けるため、文字列で値を扱う

// ❌ 悪い例
value: 100.50

// ✅ 良い例
value: "100.50"

よくある質問

Q: なぜXRPではなくトークンを発行するのか?

A:

  • 多通貨対応(各国の法定通貨をオンチェーン化)
  • プライベート通貨の発行(企業が独自トークン)
  • ステーブルコイン(法定通貨に連動)

Q: Trust Line を削除できるか?

A: はい。value: "0" で制限すれば、本質的にそのトークンを受け取れなくなります。

{
  LimitAmount: {
    value: "0"   // Trust Line を削除
  }
}

Q: トークンの発行上限はあるか?

A: XRPLプロトコル的には上限なし。ただし、発行者の信用力に依存 します。


まとめ

  • Trust Line = トークン受取の信用枠
  • Token Issuance = 発行者がトークンを送金するだけで、自動的に「存在」
  • Counterparty Risk(発行者への信用)が重要
  • デジタル金融の本質:信用をプログラムする

XRPLでトークンを発行することで、金融システムの本質を理解できます。


参考リンク


次は? Escrow の次は、DEX(分散型交換所)でトークン取引を試すか、ペイメントチャネルで高速送金を体験してみてください。

GitHubで編集を提案

Discussion