コンテンツにスキップ

未保有の通貨(トークン)を送金する | JavaScriptでのXRPL開発 三段編

次は、クロスカレンシー送金の補足事項として、未保有の通貨(トークン)の送金について解説します。

引き続き、発行者AのA.USDを取り扱う形で進行します。

前提

ダニエルはA.USDを保有していませんが、アリスにA.USDの支払いを行う必要があります。

アリスに送付するA.USDの額は5 XRPほどで良さそうです。

異なる通貨間のクロスカレンシー送金では、必ず流動性が必要ですので、以下のプロセスが必要です。

  1. ボブから、A.USDXRPと交換したいというオファーを出し、流動性を提供します。
  2. ダニエルはA.USDを保有していませんが、アリスにA.USDを支払うために、自身の5 XRPを上限に支払いを行います。(流動性があることを前提にしています。なければ送金は失敗します。)
  3. この章では、アリスに100 A.USD送付されれば成功です。

1. ボブからオファーを作成(流動性の提供)

クロスカレンシー送金が発生する条件として、流動性が存在している必要があります。

ボブから、自身のA.USDXRPと交換したいというオファーを出し、流動性を提供します。

  1. この章で作成済みのcreateOffers.jsを以下に修正します。(不要な部分はコメントアウトしてください。)

    import { Client, xrpToDrops } from 'xrpl';
    import { wallets } from './wallets.js';
    import { createOffer } from './utils/createOffer.js';
    const client = new Client('wss://s.altnet.rippletest.net:51233'); // テストネットを使用
    async function main() {
    try {
    await client.connect();
    const { issuerA, issuerB, alice, bob, charlie, daniel } = wallets;
    // Bob
    await createOffer(
    client,
    bob,
    { currency: 'USD', issuer: issuerA.address, value: '100' }, // TokenGets: 100 A.USD を提供する
    xrpToDrops(5); // TakerPays: ボブは5 XRP を受け取りたい
    );
    } catch (error) {
    console.error(`Error in offer creation: ${error}`);
    } finally {
    await client.disconnect();
    }
    }
    main();
  2. スクリプトを実行します。

    Terminal window
    node createOffers.js

    これで、ボブから自身のA.USDを売り、XRPを買うオファーの作成が完了しました。

2. ダニエルからアリスへA.USDを送付する

ダニエルからアリスにA.USDを送付します。

ダニエルはXRPで支払いたいのですが、必要以上にXRPを支払う結果になると困るため、上限を決めて送金したいと考えています。

そういった場合は、sendMaxで量を指定します。XRPLでは、sendMaxフィールドが存在しており、上限額を指定することが可能になっています。(最小も可)

これまでの章でも使用してきましたが、改めてsendMaxについて解説します。

経路としては至ってシンプルで、ここではダニエル → ボブ → アリスというイメージになります。もちろん、流動性が高いトークンの場合は自動的に最適な経路が選択されます。

  1. この章で作成済みのcrossCurrencyPayment.jsを以下に修正します。(不要な部分はコメントアウトしてください。)

    import xrpl from 'xrpl';
    import { wallets } from './wallets.js';
    import { sendPayment } from './utils/payment.js';
    const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233');
    const main = async () => {
    await client.connect();
    const { issuerA, issuerB, alice, bob, charlie, daniel } = wallets;
    await sendPayment(
    client,
    daniel,
    { currency: 'USD', issuer: issuerA.address, value: '100' }, // アリスが受け取りたい通貨:A.USD
    alice.address,
    {
    sendMax: xrpToDrops(5), // 5 XRP までを支払い上限とする
    }
    );
    await client.disconnect();
    };
    main().catch(console.error);
  2. スクリプトを実行します。

    Terminal window
    node crossCurrencyPayment.js

    以下のようなログが表示されれば、成功です。

    ぜひ、テストネット用のエクスプローラで確認してみてください。

    Terminal window
    Payment sent from rf6R7pFgytT9JKjMVjKqeTv6MeDTrbNw3 to r3KQdHtUHUouGkLBFLZRxRYiugbW8cNwyJ: {
    id: 14,
    result: {
    Account: 'rf6R7pFgytT9JKjMVjKqeTv6MeDTrbNw3', // ダニエル
    Amount: {
    currency: 'USD',
    issuer: 'rfkJ7Uz6NrNV1FdbmKB5wepoim51KFpYQp', // 発行者A
    value: '100'
    },
    DeliverMax: {
    currency: 'USD',
    issuer: 'rfkJ7Uz6NrNV1FdbmKB5wepoim51KFpYQp',
    value: '100'
    },
    Destination: 'r3KQdHtUHUouGkLBFLZRxRYiugbW8cNwyJ', // アリス
    Fee: '12',
    Flags: 0,
    LastLedgerSequence: 1371126,
    SendMax: '5000000', // 5 XRP
    Sequence: 1046459,
    SigningPubKey: 'EDEC83B1B5D761F21A9625E88C70EE68CE5D5496B513DC6295CEDA7905065DD51A',
    TransactionType: 'Payment',
    TxnSignature: '939CD057964FCEEA621E358B65D780B50EBC50C6D80D83F5E93B463B9365F553261E27B7420E18CFBD9524A7E57C8EF20694C39B6B677F1EDBAD0ECA88F8260F',
    ctid: 'C014EBE500000001',
    date: 771245761,
    hash: '49C8ABCA168351936BE825B27F97836E68D4C49818F9664BD08447B6E4044A2A',
    inLedger: 1371109,
    ledger_index: 1371109,
    meta: {
    AffectedNodes: [Array],
    TransactionIndex: 0,
    TransactionResult: 'tesSUCCESS', // 成功
    delivered_amount: [Object]
    },
    validated: true
    },
    type: 'response'
    }

    これで、アリスへA.USDの送金が完了しました。

    改めて解説すると、5 XRPに収まる程度のA.USDをアリスに送金するために、ダニエルは自身の5 XRPを上限として送金しました。 ボブは保有していた100 A.USD5 XRPを交換するための注文を出していたので、結果としてはボブが5 XRPを受け取り、ボブが保有していたA.USDがアリスに届いたという流れとなります。

まとめ

このガイドで証明したように、XRPLでは未保有の通貨でも流動性さえあれば相手に届けることができます。

このような機能が、ネイティブ機能として提供されていることがXRPLの強みであり、XRPLが元来、支払いのためブロックチェーンといわれる理由です。 最近ではAMMなどパワフルな機能が組み込まれたりと進化を続けていますが、このような基本的なことを理解してからでないと習得の難易度は高いと思いますので、ぜひ引き続き習得に取り組んでください。

このシンプルな送金の仕組み自体も、なかなかドキュメントベースだとイメージしづらいかと思いますので、 ぜひ今後の開発やプロジェクトにおいて、この知識が役立つことを願っています。