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(分散型交換所)でトークン取引を試すか、ペイメントチャネルで高速送金を体験してみてください。
Discussion