🚸

XRPLのペイメントチャネルについて知っておくべきこと3選

2024/06/23に公開
2

今回は私がペイメントチャネル(Payment Channel)を触る中で気がついたことについてまとめてみました。

ペイメントチャネルとは

ペイメントチャネルは、送金者と受領者がオフチェーンで取引を行うための手段です。

概念としてはチェーンを問わず存在するものとなりますが、XRPLでは、ネイティブ機能としてメインネットで使用できる「高度な支払い機能」のひとつで、アプリケーション開発においては、様々なアイデアを実現できる強力な機能だと思います。

また、XRPL界隈では、略して「ペイチャン」と呼ばれています。

SettleDelay フィールド

SettleDelayフィールドは資金が残っていた場合に猶予時間を設定できるフィールドで、PaymentChannelCreateトランザクションで使用します。

以下はPaymentChannelCreateトランザクションで、ペイメントチャネルを新規作成する際のフィールド指定の例です。

const tx = {
    TransactionType: 'PaymentChannelCreate', // トランザクションタイプ: PaymentChannelCreate
    Account: bobWallet.address, // 送金者のアカウントアドレス
    Amount: xrpToDrops('10'), // チャネルにデポジットするXRPの量(ここでは10 XRP)
    Destination: aliceWallet.address, // 受領者のアカウントアドレス
    SettleDelay: 86400, // 未請求のXRPがある場合に、ソースアドレスがチャネルを閉じる前の猶予時間。待機秒数(ここでは1日)
    PublicKey: bob.publicKey,
};

そして、以下はPaymentChannelClaimトランザクションでチャネルをクローズするサンプルコードです。

以下のようなコードでチャネルをクローズしたタイミングから、SettleDelayフィールドで指定した期限まで、継続的にチャネルが存在することになります。

const closePaymentChannel = async (channelId) => {
    try {
        // PaymentChannelClaim トランザクションを作成
        const tx = {
            TransactionType: 'PaymentChannelClaim',
            Account: bobWallet.address, // 送金人のアカウントアドレス
            Channel: channelId, // チャネルID
            Flags: PaymentChannelClaimFlags.tfClose, // クローズフラグ: 131072
        };

        console.log('Submitting a PaymentChannelClaim transaction to close the channel...');
        
        // トランザクションの送信
        const closeChannelResponse = await client.submitAndWait(tx, {
            wallet: bobWallet,
        });

        console.log(
            'PaymentChannelClaim (close) transaction response:',
            closeChannelResponse
        );
    } catch (error) {
        console.error('Error closing Payment Channel:', error);
    }
};

実際のプロダクト開発にて、意図しない挙動を起こさないように覚えておくとよいでしょう。

CancelAfter フィールド

CancelAfterフィールドはチャネルの期限を決定するオプションフィールドで、SettleDelayフィールドと同様に、PaymentChannelCreateトランザクションで使用します。

以下はPaymentChannelCreateトランザクションで、ペイメントチャネルを新規作成する際のCancelAfterフィールド指定の例です。

const tx = {
    TransactionType: 'PaymentChannelCreate', // トランザクションタイプ:
    ...
    CancelAfter: unixTimeToRippleTime(Math.floor(Date.now() / 1000) + 86400 * 30), // チャネルがキャンセルされるまでの秒数(ここでは1ヶ月)
};

CancelAfterフィールドは作成時にのみ指定可能で、変更することができません。確実にチャネルを閉じる必要性がある取引において必要となります。また、CancelAfterフィールドはRippleエポックで指定する必要があります。

こちらも地味ですが、開発において重要な知識となるので必ず覚えておくと良いでしょう。

受領人からチャネルを閉じる場合の挙動について

先ほど紹介した、SettleDelayフィールドで指定した期限までクローズしたあともチャネルが存在すると言いましたが、受領人からチャネルクローズを行う場合は挙動が異なります。

実は、受領人がチャネルのFlagsを変更すると、SettleDelayCancelAfterフィールドの指定が無視され、チャネルが強制的に終了します。

以下は先ほどと、ほぼ同様ですが、受領人がチャネルをクローズするためのサンプルコードです。受領人自身のアカウントアドレスを指定し、自身でトランザクションを送信します。

const closePaymentChannel = async (channelId) => {
    try {
        // PaymentChannelClaim トランザクションを作成
        const tx = {
            TransactionType: 'PaymentChannelClaim',
            Account: aliceWallet.address, // 受領人のアカウントアドレスを指定
            Channel: channelId, // チャネルID
            Flags: PaymentChannelClaimFlags.tfClose, // クローズフラグ: 131072
        };

        console.log('Submitting a PaymentChannelClaim transaction to close the channel...');
        
        // トランザクションの送信
        const closeChannelResponse = await client.submitAndWait(tx, {
            wallet: aliceWallet, // 受領人で署名する
        });

        console.log(
            'PaymentChannelClaim (close) transaction response:',
            closeChannelResponse
        );
    } catch (error) {
        console.error('Error closing Payment Channel:', error);
    }
};

まとめ

ペイメントチャネル(PaymentChannel)はXRPLの高度な支払い機能の中でも比較的、実装難易度が高い部類に入るかと思います。なかなかドキュメントベースだとイメージしづらいかと思いますので、今後の開発やプロジェクトにおいて、この知識を役立てていただけたら嬉しいです。

XRPLの各機能には触れてみないと気がつけない仕様が存在しているので、必ず一通り機能を試してから実装することを推奨します。

また、私が執筆しているXRPL Dojoにて、ペイメントチャネルのガイドをXRPL Dojoに作成しましたので、興味を持たれた方はぜひ一読いただけますと幸いです!!

Discussion

Nabe3Nabe3

コメントとコアの該当箇所の共有ありがとうございます!
たしか、こちらで知りました。
https://js.xrpl.org/enums/PaymentChannelClaimFlags.html
これを機に、実際にコアのコードを覗きにいく癖もつけていきたいと思います。

また、Rippleエポックについてもご指摘ありがとうございました。