XRP LedgerのSubscription機能
はじめに
この記事は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"
}
失敗条件(新規作成)
-
Destination
とAccount
が同じ場合 -
Amount
が不正なフォーマットであったり、0以下の場合 -
Frequency
がシステム最小値(TBD: 例: 1時間、1日)より小さい場合 -
Subscription
オブジェクトがすでに存在している場合 -
Account
がIOUトークンを指定している場合に、正しいトラストラインを保持していない場合 -
StartTime
が現在時刻より前の場合 -
Expiration
が現在時刻より前の場合 -
Expiration
がStartTime
より前の場合 -
Expiration
がNextPaymentTime
より前の場合
Stateの変更(新規作成)
- 初期化された全てのフィールドを含む
Subscription
オブジェクトの作成 -
StateTime
が含まれる場合、NextPaymentTime
にStartTime
を設定 -
StateTime
が含まれない場合、NextPaymentTime
に現在時刻を設定
失敗条件(更新)
- レジャーエントリの
Account
がトランザクションのAccount
と異なる場合 -
Amount
が不正なフォーマットであったり、0以下の場合 -
Subscription
オブジェクトが存在しない場合 -
Account
がIOUトークンの場合に、正しいトラストラインを保持していない場合 -
Expiration
が現在時刻より前の場合 -
Expiration
がStartTime
より前の場合 -
Expiration
がNextPaymentTime
より前の場合
Stateの変更(更新)
-
Amount
とExpiration
の更新
SubscriptionCancel
新しいトランザクションタイプ: SubscriptionCancelトランザクションは、既存のサブスクリプションをキャンセルするために使用されます。このトランザクションは、サブスクリプションを作成したアカウントまたは宛先アカウントによって署名されます。
フィールド
フィールド名 | 型 | 必須 | 説明 |
---|---|---|---|
sfTransactionType |
AccountID |
✅ | トランザクションのタイプ: SubscriptionCancel
|
sfAccount |
AccountID |
✅ | キャンセルしようとしているサブスクリプションを作成したまたは宛先として設定されているアカウント |
sfSubscriptionID |
Hash256 |
✅ | キャンセルするサブスクリプションを識別するID |
SubscriptionCancel
トランザクションの例
{
"TransactionType": "SubscriptionCancel",
"Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
"SubscriptionID": "E8A6F9B99B041DF5C932DF8DA29B2A84B42D4D4F0F4A08931D76D62F42E1F1B9"
}
失敗条件
-
SubscriptionID
に対応するSubscription
オブジェクトが存在しない場合 -
Account
がSubscription
オブジェクトの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
のフォーマットと異なる場合 -
Amount
がSubscription
オブジェクトのAmount
より大きい場合 -
Amount
が送信元アカウントの残高を超える場合 - 宛先アカウントのトラストラインが正しくない場合
- 宛先アカウントが新規トラストラインを作成するための十分な残高を持っていない場合
- 現在時刻が
NextPaymentTime
より前の場合
Stateの変更
- 送信元アカウントの残高がトランザクションの
Amount
分減少 - レジャーオブジェクトの
NextPaymentTime
をNextPaymentTime
+Frequency
に更新 - トランザクションで指定された
Amount
を受取人アカウントが受け取る - 宛先アカウントのトラストラインが作成される(必要である場合)
- 現在時刻 >
Expiration
の場合、Subscription
オブジェクトを削除
Amount
=0でのSubscriptionClaim
トランザクション
本提案では、Amount
=0(IOU含む)の場合を失敗条件に含んでいません。この場合SubscriptionClaim
トランザクションは、Subscription
オブジェクトのNextPaymentTime
を更新するだけで、送金は行われません。
トランザクション手数料と準備金
SubscriptionSet
、SubscriptionCancel
、SubscriptionClaim
など、サブスクリプションに関連するすべてのトランザクションは、通常の支払いと同様に標準のトランザクション手数料が発生すると想定されます。
Subscription
オブジェクトレジャーへの追加により、他のレジャーオブジェクトに適用されるものと同額分、アカウントの準備金の増加が必要となります。これにより、アカウントが十分な準備金を維持せずに過剰な数のサブスクリプションを作成できないようにします。
このトランザクションは、Subscription
オブジェクトのNextPaymentTime
を更新するために使用されます。
理解すべき重要なポイント
-
トランザクションによる請求:
NextPaymentTime
は成功時に更新され、期間内に請求できるプル型支払いは1回のみとなります。 -
時間管理:
Subscription
レジャーエントリのNextPaymentTime
フィールドにより、Frequency
で指定された頻度を超える請求はできないようになっています。 - セキュリティ: サブスクリプションの作成にはユーザーの明示的な承認が必要なため、事前に承認された金額までしか引き出すことができません。
想定される一般的なシナリオ
ユーザオンボーディング
- ユーザがサービスにサインアップする
- サービスは金額と頻度の詳細を含むサブスクリプションリクエストを生成し、ユーザに提示する
- ユーザはサブスクリプションを確認し、署名してXRPLに作成する
引き落としサービス
- サービスは、開始日が"現在"または指定された開始日が経過した場合、すぐに支払いを引き落とします。
- 定期支払いは、サブスクリプションの詳細に従って引き落とされます。
支払い失敗
- 支払いが資金不足により失敗した場合、サービスはユーザに通知し、7日後に再試行します。
- 成功した再試行後、支払いプロセスは正常に続行されます。
手数料の上昇
- サービスは利用者が負担するサービス利用手数料を増やし、ユーザに通知します。
- ユーザは、SubscriptionSetトランザクションを使用してサブスクリプション金額を更新するよう促されます。
キャンセル
- ユーザはいつでもサブスクリプションをキャンセルし、サービスを終了することができます。
- 理想的には、ユーザはキャンセルする前にサービスに通知しますが、これは必須ではありません。
- サービスはいつでもサブスクリプションをキャンセルすることができます。
後方互換性
この提案は、既存のトランザクションタイプを変更するものではなく、XRPLの現在の操作に影響を与えません。サブスクリプションシステムに参加しないユーザーは、変更を経験することはありません。さらに、サブスクリプション設定は新しいレジャーオブジェクトとして追加されます。
まとめ
この提案は、XRPLに必要な機能を導入し、ユーザーが定義されたパラメータ内で事前承認されたトランザクションを可能にし、システムが繰り返し支払いに伴う摩擦を減らし、XRPL上でより幅広いサービスをサポートできるようにします。
Discussion