Compare commits

...

1 Commits

Author SHA1 Message Date
Maria Shodunke
36083f247a Add payment channel code snippet/tutorial 2025-07-02 11:07:14 +01:00
6 changed files with 248 additions and 12 deletions

View File

@@ -12,13 +12,11 @@ import {
const client = new Client('wss://s.altnet.rippletest.net:51233') const client = new Client('wss://s.altnet.rippletest.net:51233')
void claimPayChannel()
// The snippet walks us through creating and claiming a Payment Channel. // The snippet walks us through creating and claiming a Payment Channel.
async function claimPayChannel(): Promise<void> { async function claimPayChannel(): Promise<void> {
await client.connect() await client.connect()
// creating wallets as prerequisite // Creating wallets as prerequisite
const { wallet: wallet1 } = await client.fundWallet() const { wallet: wallet1 } = await client.fundWallet()
const { wallet: wallet2 } = await client.fundWallet() const { wallet: wallet2 } = await client.fundWallet()
@@ -26,16 +24,17 @@ async function claimPayChannel(): Promise<void> {
console.log(`Balance of ${wallet1.address} is ${await client.getXrpBalance(wallet1.address)} XRP`) console.log(`Balance of ${wallet1.address} is ${await client.getXrpBalance(wallet1.address)} XRP`)
console.log(`Balance of ${wallet2.address} is ${await client.getXrpBalance(wallet2.address)} XRP`) console.log(`Balance of ${wallet2.address} is ${await client.getXrpBalance(wallet2.address)} XRP`)
// create a Payment Channel and submit and wait for tx to be validated // Create a Payment Channel transaction
const paymentChannelCreate: PaymentChannelCreate = { const paymentChannelCreate: PaymentChannelCreate = {
TransactionType: 'PaymentChannelCreate', TransactionType: 'PaymentChannelCreate',
Account: wallet1.classicAddress, Account: wallet1.classicAddress,
Amount: '100', Amount: '3000000', // 3 XRP in drops
Destination: wallet2.classicAddress, Destination: wallet2.classicAddress,
SettleDelay: 86400, SettleDelay: 86400, // 1 day in seconds
PublicKey: wallet1.publicKey, PublicKey: wallet1.publicKey,
} }
// Submit and wait for the transaction to be validated
console.log("Submitting a PaymentChannelCreate transaction...") console.log("Submitting a PaymentChannelCreate transaction...")
const paymentChannelResponse = await client.submitAndWait( const paymentChannelResponse = await client.submitAndWait(
paymentChannelCreate, paymentChannelCreate,
@@ -44,7 +43,7 @@ async function claimPayChannel(): Promise<void> {
console.log("PaymentChannelCreate transaction response:") console.log("PaymentChannelCreate transaction response:")
console.log(paymentChannelResponse) console.log(paymentChannelResponse)
// check that the object was actually created // Check that the object was actually created
const accountObjectsRequest: AccountObjectsRequest = { const accountObjectsRequest: AccountObjectsRequest = {
command: 'account_objects', command: 'account_objects',
account: wallet1.classicAddress, account: wallet1.classicAddress,
@@ -55,14 +54,14 @@ async function claimPayChannel(): Promise<void> {
console.log("Account Objects:", accountObjects) console.log("Account Objects:", accountObjects)
// destination claims the Payment Channel and we see the balances to verify. // Destination claims the Payment Channel and we see the balances to verify.
const paymentChannelClaim: PaymentChannelClaim = { const paymentChannelClaim: PaymentChannelClaim = {
Account: wallet2.classicAddress, Account: wallet2.classicAddress,
TransactionType: 'PaymentChannelClaim', TransactionType: 'PaymentChannelClaim',
Channel: hashes.hashPaymentChannel( Channel: hashes.hashPaymentChannel(
wallet1.classicAddress, wallet1.classicAddress,
wallet2.classicAddress, wallet2.classicAddress,
paymentChannelResponse.result.Sequence ?? 0, paymentChannelResponse.result.tx_json.Sequence ?? 0,
), ),
Amount: '100', Amount: '100',
} }
@@ -70,7 +69,7 @@ async function claimPayChannel(): Promise<void> {
console.log("Submitting a PaymentChannelClaim transaction...") console.log("Submitting a PaymentChannelClaim transaction...")
const channelClaimResponse = await client.submit(paymentChannelClaim, { const channelClaimResponse = await client.submit(paymentChannelClaim, {
wallet: wallet1, wallet: wallet2,
}) })
console.log("PaymentChannelClaim transaction response:") console.log("PaymentChannelClaim transaction response:")
console.log(channelClaimResponse) console.log(channelClaimResponse)
@@ -81,3 +80,5 @@ async function claimPayChannel(): Promise<void> {
await client.disconnect() await client.disconnect()
} }
void claimPayChannel()

View File

@@ -0,0 +1,97 @@
"""
Create, claim and verify a Payment Channel.
Reference: https://xrpl.org/paychannel.html
"""
from xrpl.clients import JsonRpcClient
from xrpl.models import (
AccountObjects,
PaymentChannelCreate,
PaymentChannelClaim,
)
from xrpl.wallet import generate_faucet_wallet
from xrpl.transaction import submit_and_wait, submit
from xrpl.account import get_balance
def claim_pay_channel():
"""The snippet walks us through creating and claiming a Payment Channel."""
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
try:
# Creating wallets as prerequisite
print("Creating and funding wallets...")
wallet1 = generate_faucet_wallet(client, debug=True)
wallet2 = generate_faucet_wallet(client, debug=True)
print("Balances of wallets before Payment Channel is claimed:")
balance1 = get_balance(wallet1.address, client)
balance2 = get_balance(wallet2.address, client)
print(f"Balance of {wallet1.address} is {balance1} XRP")
print(f"Balance of {wallet2.address} is {balance2} XRP")
# Create a Payment Channel transaction
payment_channel_create = PaymentChannelCreate(
account=wallet1.address,
amount="3000000", # 3 XRP in drops
destination=wallet2.address,
settle_delay=86400,
public_key=wallet1.public_key,
)
# Submit and wait for the transaction to be validated
print("Submitting a PaymentChannelCreate transaction...")
payment_channel_response = submit_and_wait(
payment_channel_create,
client,
wallet1
)
print("PaymentChannelCreate transaction response:")
print(payment_channel_response)
# Check that the object was actually created and get the channel ID
account_objects_request = AccountObjects(
account=wallet1.address,
)
account_objects_response = client.request(account_objects_request)
account_objects = account_objects_response.result["account_objects"]
# Find the payment channel from account objects and get its ID
channel_id = None
for obj in account_objects:
if obj.get("LedgerEntryType") == "PayChannel":
channel_id = obj["index"]
break
if not channel_id:
raise Exception("Could not find PayChannel in account objects")
print(f"Payment Channel ID: {channel_id}")
# Destination claims the Payment Channel
payment_channel_claim = PaymentChannelClaim(
account=wallet2.address,
channel=channel_id,
amount="100",
sequence=payment_channel_response.result["tx_json"]["Sequence"],
fee="12", # Fee in drops (0.000012 XRP)
)
print("Submitting a PaymentChannelClaim transaction...")
channel_claim_response = submit(
payment_channel_claim,
wallet2,
)
print("PaymentChannelClaim transaction response:")
print(channel_claim_response)
print("Balances of wallets after Payment Channel is claimed:")
print(f"Balance of {wallet1.address} is {get_balance(wallet1.address, client)} XRP")
print(f"Balance of {wallet2.address} is {get_balance(wallet2.address, client)} XRP")
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
claim_pay_channel()

View File

@@ -0,0 +1 @@
xrpl-py>=2.0.0

View File

@@ -0,0 +1,136 @@
---
seo:
description: Learn how to create and claim a payment channel using the XRP Ledger SDKs.
cta_text: Create and Claim a Payment Channel with the XRPL SDKs
labels:
- Payment Channels
---
# Create and Claim a Payment Channel with the SDK Libraries
This tutorial explains how to create, verify, and claim a payment channel using `xrpl.js` for JavaScript, and `xrpl-py` for Python.
{% admonition type="success" name="Tip" %}Check out the [Code Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/claim-payment-channel) for a complete version of the code used in this tutorial.{% /admonition %}
## Prerequisites
<!-- Source for this specific tutorial's interactive bits: -->
<!-- <script type="application/javascript" src="/js/interactive-tutorial.js"></script> -->
<!-- <script type="application/javascript" src="/js/tutorials/send-xrp.js"></script> -->
To interact with the XRP Ledger, you need to set up a dev environment with the necessary tools. This tutorial provides examples using the following options:
- **JavaScript** with the [`xrpl.js` library](https://github.com/XRPLF/xrpl.js/). See [Get Started Using JavaScript](../../../javascript/build-apps/get-started.md) for setup steps.
- **Python** with the [`xrpl-py` library](https://xrpl-py.readthedocs.io/). See [Get Started using Python](../../../python/build-apps/get-started.md) for setup steps.
## 1. Connect to a Testnet Server
First, you must connect to an XRP Ledger server. The following code initializes the XRP Ledger client and connects to a public Testnet server:
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/claim-payment-channel/js/claimPayChannel.ts" from="import" before="// Creating wallets" language="js" /%}
{% /tab %}
{% tab label="Python" %}
{% code-snippet file="/_code-samples/claim-payment-channel/py/claim_pay_channel.py" from="xrpl.clients" before="try:" language="py" /%}
{% /tab %}
{% /tabs %}
<!-- For this tutorial, click the following button to connect:
{% partial file="/docs/_snippets/interactive-tutorials/connect-step.md" /%} -->
## 2. Create Testnet Wallets
Create two Testnet wallets and log their initial XRP balances:
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/claim-payment-channel/js/claimPayChannel.ts" from="// Creating wallets" before="// Create a Payment Channel" language="js" /%}
{% /tab %}
{% /tabs %}
For this example, `wallet1` represents the _payer_, and `wallet2` is the _payee_.
The payer can be an individual person or institution using the XRP Ledger who is a customer of the payee. The payee is a person or business who receives XRP or fungible tokens as payment for goods or services.
## 3. Create and Submit the Payment Channel Transaction
Next, prepare the [`PaymentChannelCreate`](../../../../references/protocol/transactions/types/paymentchannelcreate) transaction.
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/claim-payment-channel/js/claimPayChannel.ts" from="// Create a Payment Channel" before="// Submit and wait for the transaction" language="js" /%}
{% /tab %}
{% /tabs %}
The key fields in this transaction are:
| Field | Description |
| :---------------------- | :---------- |
| `TransactionType` | The type of transaction to be submitted (i.e., `PaymentChannelCreate`). |
| `Account` | The _payer_ (source) address of the transaction, which in this example is `wallet1`. |
| `Amount` | The amount of XRP, in drops, to deduct from the sender's balance and set aside in the payment channel. For this example, we are setting this to 3 XRP. |
| `SettleDelay` | The amount of time the source address must wait before closing the channel if it has unclaimed XRP. This is set to 1 day (in seconds). |
| `PublicKey` | The public key of the key pair used to sign claims against the payment channel. |
| `Destination` | The _payee_ (destination) address to receive claims against this channel, which in this example is `wallet2`. |
Submit and wait for the transaction to be validated on the ledger:
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/claim-payment-channel/js/claimPayChannel.ts" from="// Submit and wait for the transaction" before="// Check that the object " language="js" /%}
{% /tab %}
{% /tabs %}
## 4. Verify the Payment Channel is Created
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/claim-payment-channel/js/claimPayChannel.ts" from="// Check that the object" before="// Destination claims" language="js" /%}
{% /tab %}
{% /tabs %}
## 5. Claim the Payment Channel
Create a `PaymentChannelClaim` transaction:
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/claim-payment-channel/js/claimPayChannel.ts" from="// Destination claims" before="" language="js" /%}
{% /tab %}
{% /tabs %}
Submit and wait for the transaction to be validated:
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/claim-payment-channel/js/claimPayChannel.ts" from="console.log(\"Submitting" before="console.log('Balances" language="js" /%}
{% /tab %}
{% /tabs %}
## 6. Check Balances after Payment Channel is Claimed
Finally, we check the balance of both `wallet1` and `wallet2`, after the claiming the payment channel. Then, we close the client connection.
{% tabs %}
{% tab label="JavaScript" %}
{% code-snippet file="/_code-samples/claim-payment-channel/js/claimPayChannel.ts" from="console.log('Balances" language="js" /%}
{% /tab %}
{% /tabs %}

View File

@@ -84,7 +84,7 @@ Content-Type: application/json
"fee_mult_max": 1000 "fee_mult_max": 1000
}] }]
} }
```json ```
Response: Response:

View File

@@ -299,6 +299,7 @@
expanded: false expanded: false
items: items:
- page: docs/tutorials/how-tos/use-specialized-payment-types/use-payment-channels/open-a-payment-channel-to-enable-an-inter-exchange-network.md - page: docs/tutorials/how-tos/use-specialized-payment-types/use-payment-channels/open-a-payment-channel-to-enable-an-inter-exchange-network.md
- page: docs/tutorials/how-tos/use-specialized-payment-types/use-payment-channels/create-and-claim-payment-channel.md
- page: docs/tutorials/how-tos/use-specialized-payment-types/use-checks/index.md - page: docs/tutorials/how-tos/use-specialized-payment-types/use-checks/index.md
expanded: false expanded: false
items: items: