mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-04 20:05:50 +00:00
Compare commits
1 Commits
fdcbc6c747
...
payment-ch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36083f247a |
@@ -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()
|
||||||
|
|||||||
97
_code-samples/claim-payment-channel/py/claim_pay_channel.py
Normal file
97
_code-samples/claim-payment-channel/py/claim_pay_channel.py
Normal 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()
|
||||||
1
_code-samples/claim-payment-channel/py/requirements.txt
Normal file
1
_code-samples/claim-payment-channel/py/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
xrpl-py>=2.0.0
|
||||||
@@ -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 %}
|
||||||
@@ -84,7 +84,7 @@ Content-Type: application/json
|
|||||||
"fee_mult_max": 1000
|
"fee_mult_max": 1000
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
```json
|
```
|
||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user