🧐

XRP LedgerのSubscription機能

2024/09/25に公開

はじめに

この記事はXLS-78として提案されているSubscription機能を紹介するものです。

原文

この提案はまだ確定しているものではないため、今後変更される可能性があります。

概要

本提案はXRP Ledger(XRPL)にサブスクリプション(継続課金)の仕組みを導入し、口座引落しに似た機能を実現します。これによりユーザは支払いごとに取引に署名する必要がなくなり、アカウントの所有者は不正使用を防ぐために引き落とし毎に利用可能な最大額を定義します。

背景と根拠

現在、XRPLedger上での支払いには、送信者がトランザクションを生成し、それぞれに署名することが必要です。Xaman APIのようなオフチェーンソリューションの導入により、プル型支払いという概念が生まれました。この方法では、宛先アドレスによってトランザクションが生成され、送信者によって署名されます。しかし、この方法でも、ユーザーは個々のトランザクションを個別に承認する必要があり、定期支払いを必要とするサービス、例えばサブスクリプションには実用的ではありません。

この提案は、この制限に対処するために、事前承認済みの定期的な支払いを行うことを可能にするサブスクリプション機能を導入し、ユーザー体験を向上させ、XRPLedger上でより幅広いサービスを可能にします。

提案されているサブスクリプションモデルは、ユーザーの利便性とセキュリティのバランスを取るように設計されています。定義されたパラメータ内で事前承認済みの支払いを行うことを可能にすることで、このシステムは、支払い金額と頻度を管理しながら、ユーザーとの頻繁なやり取りの必要性を減らします。このアプローチにより、企業は請求プロセスを自動化でき、サービス提供を改善しながら、ユーザーが定期的な支払いを監視し管理できるようにします。サブスクリプション機能は、XRP Ledgerの汎用性を高め、自動化された定期的な支払いに依存するサービスにより適応させます。

この提案は、ネイティブトークンであるXRPと発行されたトークンの両方をサポートします。

修正内容

この機能を導入することで、アカウント所有者は、金額、支払い頻度、支払い先などの事前定義されたパラメータに従って自動決済を承認できるようになり、その都度手動で取引に署名する必要がなくなります。

この機能では、以下の内容が追加されます。

  • 新しいレジャーエントリ: Subscription
  • 新しいトランザクション: SubscriptionSet, SubscriptionCancel, SubscriptionClaim

新しいレジャーエントリ: Subscription

Subscriptionレジャーエントリは、宛先アドレス、支払い毎の最大許容額、支払い頻度、サブスクリプションの開始時刻などのサブスクリプション詳細を保存する新しいレジャー上のオブジェクトです。

フィールド

フィールド名 必須 説明
sfAccount AccountID サブスクリプションの支払い元アカウント
sfDestination AccountID サブスクリプション支払いの受け取りアカウント
sfDestinationTag Number 支払い先アカウントの区別のために利用可能
sfAmount Currency サブスクリプションの支払い毎の(最大)金額
sfFrequency UInt64 サブスクリプションの支払い頻度を秒数で指定 (例: 毎月の場合2592000)
sfNextPaymentTime UInt32 サブスクリプションの次回支払い時刻をリップルエポックで指定, このフィールドは支払いが成功するたびに自動的に更新されます
sfExpiration UInt32 サブスクリプションの終了時刻をリップルエポックで指定, 固定期間支払いのために任意フィールドとなっています。

Subscriptionオブジェクトの例

{
  "LedgerEntryType": "Subscription",
  "Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
  "Destination": "rLdCa1mLK5R5Am25ArfXFmqgNwjZgnfy91",
  "DestinationTag": 10, // Bob is customer number 10
  "Amount": "100000000", // 100 XRP
  "Frequency": 2592000, // 30 days in seconds
  "NextPaymentTime": 711232800, // (example epoch time for next payment)
  "Expiration": 721600800 // (example epoch time for final payment)
}

SubscriptionIDと呼ばれるSubscriptionのオブジェクトIDは、以下の値のSHA512-Halfを順番に連結したものです。

  • Subscriptionスペースキー(0x00??)
  • sfAccountアカウントID
  • sfDestinationアカウントID
  • トランザクションシーケンス

新しいトランザクションタイプ: SubscriptionSet

SubscriptionSetトランザクションは、新規サブスクリプションを作成するために使用されます。アカウントの所有者は、宛先、数量、頻度、およびオプションとして開始時刻を指定します。

フィールド

フィールド名 必須 説明
sfTransactionType AccountID トランザクションのタイプ: SubscriptionSet
sfAccount AccountID サブスクリプションを作成するアカウント
sfDestination AccountID サブスクリプション支払いの受け取りアカウント
sfDestinationTag Number 支払い先アカウントの区別のためのタグ
sfAmount Amount サブスクリプションの支払い毎の(最大)金額
sfFrequency UInt64 サブスクリプションの支払い頻度を秒数で指定 (例: 毎月の場合2592000)
sfStartTime UInt32 サブスクリプションの次回支払い時刻をリップルエポックで指定, 設定されていない場合は即時に期間が開始します
sfExpiration UInt32 サブスクリプションの終了時刻をリップルエポックで指定
sfSubscriptionID Hash256 サブスクリプション情報の更新に使用

SubscriptionSetトランザクションの例(新規作成)

{
  "TransactionType": "SubscriptionSet",
  "Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
  "Destination": "rLdCa1mLK5R5Am25ArfXFmqgNwjZgnfy91",
  "DestinationTag": 10, // Bob is customer number 10
  "Amount": "100000000", // 100 XRP
  "Frequency": 2592000, // 30 days in seconds
  "StartTime": 711232800, // (example epoch time for start time)
  "Expiration": 721600800 // (example epoch time for final payment)
}

SubscriptionSetトランザクションの例(更新)

{
  "TransactionType": "SubscriptionSet",
  "Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
  "Amount": "100000000", // 100 XRP
  "Expiration": 724192800, // (example epoch time for final payment increased by one frequency period)
  "SubscriptionID": "E8A6F9B99B041DF5C932DF8DA29B2A84B42D4D4F0F4A08931D76D62F42E1F1B9"
}

失敗条件(新規作成)

  • DestinationAccountが同じ場合
  • Amountが不正なフォーマットであったり、0以下の場合
  • Frequencyがシステム最小値(TBD: 例: 1時間、1日)より小さい場合
  • Subscriptionオブジェクトがすでに存在している場合
  • AccountがIOUトークンを指定している場合に、正しいトラストラインを保持していない場合
  • StartTimeが現在時刻より前の場合
  • Expirationが現在時刻より前の場合
  • ExpirationStartTimeより前の場合
  • ExpirationNextPaymentTimeより前の場合

Stateの変更(新規作成)

  • 初期化された全てのフィールドを含むSubscriptionオブジェクトの作成
  • StateTimeが含まれる場合、NextPaymentTimeStartTimeを設定
  • StateTimeが含まれない場合、NextPaymentTimeに現在時刻を設定

失敗条件(更新)

  • レジャーエントリのAccountがトランザクションのAccountと異なる場合
  • Amountが不正なフォーマットであったり、0以下の場合
  • Subscriptionオブジェクトが存在しない場合
  • AccountがIOUトークンの場合に、正しいトラストラインを保持していない場合
  • Expirationが現在時刻より前の場合
  • ExpirationStartTimeより前の場合
  • ExpirationNextPaymentTimeより前の場合

Stateの変更(更新)

  • AmountExpirationの更新

新しいトランザクションタイプ: SubscriptionCancel

SubscriptionCancelトランザクションは、既存のサブスクリプションをキャンセルするために使用されます。このトランザクションは、サブスクリプションを作成したアカウントまたは宛先アカウントによって署名されます。

フィールド

フィールド名 必須 説明
sfTransactionType AccountID トランザクションのタイプ: SubscriptionCancel
sfAccount AccountID キャンセルしようとしているサブスクリプションを作成したまたは宛先として設定されているアカウント
sfSubscriptionID Hash256 キャンセルするサブスクリプションを識別するID

SubscriptionCancelトランザクションの例

{
  "TransactionType": "SubscriptionCancel",
  "Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
  "SubscriptionID": "E8A6F9B99B041DF5C932DF8DA29B2A84B42D4D4F0F4A08931D76D62F42E1F1B9"
}

失敗条件

  • SubscriptionIDに対応するSubscriptionオブジェクトが存在しない場合
  • AccountSubscriptionオブジェクトのAccountまたはDestinationのいずれでもない場合

Stateの変更

  • SubscriptionIDに紐づくSubscriptionオブジェクトの削除

新しいトランザクションタイプ: SubscriptionClaim

SubscriptionClaimトランザクションは、あらかじめ設定されたルールに従って、受取人(受益者)が加入者のアカウントから資金を引き出すために使用されます。

フィールド

フィールド名 必須 説明
sfTransactionType AccountID トランザクションのタイプ: SubscriptionClaim
sfAccount AccountID サブスクリプション支払いを受け取るアカウント
sfSubscriptionID Hash256 請求するサブスクリプションを識別するID
sfAmount Amount 送金元アカウントから引き落とす受け取る金額、利用可能金額を超えることはできない

XRPを利用したSubscriptionClaimトランザクションの例

{
  "TransactionType": "SubscriptionClaim",
  "Account": "rLdCa1mLK5R5Am25ArfXFmqgNwjZgnfy91",
  "SubscriptionID": "E8A6F9B99B041DF5C932DF8DA29B2A84B42D4D4F0F4A08931D76D62F42E1F1B9",
  "Amount": "100000000" // 100 XRP
}

IOUトークンを利用したSubscriptionClaimトランザクションの例

{
  "TransactionType": "SubscriptionClaim",
  "Account": "rLdCa1mLK5R5Am25ArfXFmqgNwjZgnfy91",
  "SubscriptionID": "E8A6F9B99B041DF5C932DF8DA29B2A84B42D4D4F0F4A08931D76D62F42E1F1B9",
  "Amount": "100000000" // 100 XRP
}

失敗条件

  • SubscriptionIDに対応するSubscriptionオブジェクトが存在しない場合
  • Amountがマイナスの値の場合
  • AmountがIOUかつ不正な通貨コードの場合
  • AmountのフォーマットがSubscriptionオブジェクトのAmountのフォーマットと異なる場合
  • AmountSubscriptionオブジェクトのAmountより大きい場合
  • Amountが送信元アカウントの残高を超える場合
  • 宛先アカウントのトラストラインが正しくない場合
  • 宛先アカウントが新規トラストラインを作成するための十分な残高を持っていない場合
  • 現在時刻がNextPaymentTimeより前の場合

Stateの変更

  • 送信元アカウントの残高がトランザクションのAmount分減少
  • レジャーオブジェクトのNextPaymentTimeNextPaymentTime+Frequencyに更新
  • トランザクションで指定されたAmountを受取人アカウントが受け取る
  • 宛先アカウントのトラストラインが作成される(必要である場合)
  • 現在時刻 > Expirationの場合、Subscriptionオブジェクトを削除

Amount=0でのSubscriptionClaimトランザクション

本提案では、Amount=0(IOU含む)の場合を失敗条件に含んでいません。この場合SubscriptionClaimトランザクションは、SubscriptionオブジェクトのNextPaymentTimeを更新するだけで、送金は行われません。

トランザクション手数料と準備金

SubscriptionSetSubscriptionCancelSubscriptionClaimなど、サブスクリプションに関連するすべてのトランザクションは、通常の支払いと同様に標準のトランザクション手数料が発生すると想定されます。
Subscriptionオブジェクトレジャーへの追加により、他のレジャーオブジェクトに適用されるものと同額分、アカウントの準備金の増加が必要となります。これにより、アカウントが十分な準備金を維持せずに過剰な数のサブスクリプションを作成できないようにします。

このトランザクションは、SubscriptionオブジェクトのNextPaymentTimeを更新するために使用されます。

理解すべき重要なポイント

  • トランザクションによる請求: NextPaymentTimeは成功時に更新され、期間内に請求できるプル型支払いは1回のみとなります。
  • 時間管理: SubscriptionレジャーエントリのNextPaymentTimeフィールドにより、Frequencyで指定された頻度を超える請求はできないようになっています。
  • セキュリティ: サブスクリプションの作成にはユーザーの明示的な承認が必要なため、事前に承認された金額までしか引き出すことができません。

想定される一般的なシナリオ

ユーザオンボーディング

  • ユーザがサービスにサインアップする
  • サービスは金額と頻度の詳細を含むサブスクリプションリクエストを生成し、ユーザに提示する
  • ユーザはサブスクリプションを確認し、署名してXRPLに作成する

引き落としサービス

  • サービスは、開始日が"現在"または指定された開始日が経過した場合、すぐに支払いを引き落とします。
  • 定期支払いは、サブスクリプションの詳細に従って引き落とされます。

支払い失敗

  • 支払いが資金不足により失敗した場合、サービスはユーザに通知し、7日後に再試行します。
  • 成功した再試行後、支払いプロセスは正常に続行されます。

手数料の上昇

  • サービスは利用者が負担するサービス利用手数料を増やし、ユーザに通知します。
  • ユーザは、SubscriptionSetトランザクションを使用してサブスクリプション金額を更新するよう促されます。

キャンセル

  • ユーザはいつでもサブスクリプションをキャンセルし、サービスを終了することができます。
  • 理想的には、ユーザはキャンセルする前にサービスに通知しますが、これは必須ではありません。
  • サービスはいつでもサブスクリプションをキャンセルすることができます。

後方互換性

この提案は、既存のトランザクションタイプを変更するものではなく、XRPLの現在の操作に影響を与えません。サブスクリプションシステムに参加しないユーザーは、変更を経験することはありません。さらに、サブスクリプション設定は新しいレジャーオブジェクトとして追加されます。

まとめ

この提案は、XRPLに必要な機能を導入し、ユーザーが定義されたパラメータ内で事前承認されたトランザクションを可能にし、システムが繰り返し支払いに伴う摩擦を減らし、XRPL上でより幅広いサービスをサポートできるようにします。

Discussion