Merge pull request #3188 from XRPLF/migrate-code-samples-from-sdks

Add code snippets from xrpl.js and xrpl-py
This commit is contained in:
Maria Shodunke
2025-07-23 12:10:38 +01:00
committed by GitHub
17 changed files with 284 additions and 102 deletions

View File

@@ -1,6 +1,6 @@
/*
* Create, claim and verify a Payment Channel.
* Reference: https://xrpl.org/paychannel.html
* Reference: https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/paychannel
*/
import {
AccountObjectsRequest,
@@ -12,13 +12,11 @@ import {
const client = new Client('wss://s.altnet.rippletest.net:51233')
void claimPayChannel()
// The snippet walks us through creating and claiming a Payment Channel.
async function claimPayChannel(): Promise<void> {
await client.connect()
// creating wallets as prerequisite
// Creating wallets as prerequisite
const { wallet: wallet1 } = await client.fundWallet()
const { wallet: wallet2 } = await client.fundWallet()
@@ -26,13 +24,13 @@ async function claimPayChannel(): Promise<void> {
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`)
// create a Payment Channel and submit and wait for tx to be validated
// Create a Payment Channel and submit and wait for tx to be validated
const paymentChannelCreate: PaymentChannelCreate = {
TransactionType: 'PaymentChannelCreate',
Account: wallet1.classicAddress,
Amount: '100',
Amount: '100', // 10 XRP
Destination: wallet2.classicAddress,
SettleDelay: 86400,
SettleDelay: 86400, // 1 day in seconds
PublicKey: wallet1.publicKey,
}
@@ -44,7 +42,7 @@ async function claimPayChannel(): Promise<void> {
console.log("PaymentChannelCreate transaction response:")
console.log(paymentChannelResponse)
// check that the object was actually created
// Check that the object was actually created
const accountObjectsRequest: AccountObjectsRequest = {
command: 'account_objects',
account: wallet1.classicAddress,
@@ -52,25 +50,23 @@ async function claimPayChannel(): Promise<void> {
const accountObjects = (await client.request(accountObjectsRequest)).result
.account_objects
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 = {
Account: wallet2.classicAddress,
TransactionType: 'PaymentChannelClaim',
Channel: hashes.hashPaymentChannel(
wallet1.classicAddress,
wallet2.classicAddress,
paymentChannelResponse.result.Sequence ?? 0,
paymentChannelResponse.result.tx_json.Sequence ?? 0,
),
Amount: '100',
}
console.log("Submitting a PaymentChannelClaim transaction...")
const channelClaimResponse = await client.submit(paymentChannelClaim, {
wallet: wallet1,
wallet: wallet2,
})
console.log("PaymentChannelClaim transaction response:")
console.log(channelClaimResponse)
@@ -81,3 +77,5 @@ async function claimPayChannel(): Promise<void> {
await client.disconnect()
}
void claimPayChannel()

View File

@@ -0,0 +1,85 @@
"""
Create, claim and verify a Payment Channel.
Reference: https://xrpl.org/docs/references/protocol/ledger-data/ledger-entry-types/paychannel
"""
from xrpl.clients import JsonRpcClient
from xrpl.models import (
AccountObjects,
PaymentChannelCreate,
PaymentChannelClaim,
)
from xrpl.wallet import generate_faucet_wallet
from xrpl.transaction import submit, submit_and_wait
from xrpl.account import get_balance
"""The snippet walks us through creating and claiming a Payment Channel."""
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
# Creating wallets as prerequisite
print("Setting up wallets...")
wallet1 = generate_faucet_wallet(client)
wallet2 = generate_faucet_wallet(client)
print("Balances of wallets before 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")
# Create a Payment Channel and submit and wait for tx to be validated
payment_channel_create = PaymentChannelCreate(
account=wallet1.address,
amount="100", # 10 XRP
destination=wallet2.address,
settle_delay=86400, # 1 day in seconds
public_key=wallet1.public_key,
)
print("\nSubmitting a PaymentChannelCreate transaction...")
payment_channel_response = submit_and_wait(
payment_channel_create,
client,
wallet1
)
print("PaymentChannelCreate transaction response:")
print(payment_channel_response.result)
# Check that the object was actually created
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 PayChannel object to get the correct channel ID
channel_id = None
if 'meta' in payment_channel_response.result and 'AffectedNodes' in payment_channel_response.result['meta']:
for node in payment_channel_response.result["meta"]["AffectedNodes"]:
if 'CreatedNode' in node and node["CreatedNode"]["LedgerEntryType"] == 'PayChannel':
channel_id = node['CreatedNode']['LedgerIndex']
break
if not channel_id:
raise Exception("Payment Channel ID not found in the response.")
print(f"Payment Channel ID: {channel_id}")
# Destination claims the Payment Channel and we see the balances to verify.
payment_channel_claim = PaymentChannelClaim(
account=wallet2.address,
channel=channel_id,
amount="100",
)
print("\nSubmitting a PaymentChannelClaim transaction...")
channel_claim_response = submit_and_wait(
payment_channel_claim,
client,
wallet2,
)
print("PaymentChannelClaim transaction response:")
print(channel_claim_response.result)
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")

View File

@@ -14,15 +14,6 @@ const seed = "sEd7jfWyNG6J71dEojB3W9YdHp2KCjy";
async function main() {
try {
// Construct condition and fulfillment ------------------------------------
const preimageData = crypto.randomBytes(32);
const myFulfillment = new cc.PreimageSha256();
myFulfillment.setPreimage(preimageData);
const conditionHex = myFulfillment.getConditionBinary().toString('hex').toUpperCase();
console.log('Condition:', conditionHex);
console.log('Fulfillment:', myFulfillment.serializeBinary().toString('hex').toUpperCase());
// Connect ----------------------------------------------------------------
const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233');
await client.connect();
@@ -37,16 +28,26 @@ async function main() {
finishAfter = new Date(finishAfter * 1000);
console.log("This escrow will finish after: ", finishAfter);
// Construct condition and fulfillment ------------------------------------
const preimageData = crypto.randomBytes(32);
const myFulfillment = new cc.PreimageSha256();
myFulfillment.setPreimage(preimageData);
const conditionHex = myFulfillment.getConditionBinary().toString('hex').toUpperCase();
console.log('Condition:', conditionHex);
console.log('Fulfillment:', myFulfillment.serializeBinary().toString('hex').toUpperCase());
// Prepare EscrowCreate transaction ------------------------------------
const escrowCreateTransaction = {
"TransactionType": "EscrowCreate",
"Account": wallet.address,
"Destination": wallet.address,
"Amount": "6000000", //drops XRP
"DestinationTag": 2023,
"Condition": conditionHex,
"Condition": conditionHex, // Omit this for time-held escrows
"Fee": "12",
"FinishAfter": xrpl.isoTimeToRippleTime(finishAfter.toISOString()),
};
};
xrpl.validate(escrowCreateTransaction);
@@ -54,7 +55,7 @@ async function main() {
console.log('Signing and submitting the transaction:',
JSON.stringify(escrowCreateTransaction, null, "\t"), "\n"
);
const response = await client.submitAndWait(escrowCreateTransaction, { wallet });
const response = await client.submitAndWait(escrowCreateTransaction, { wallet });
console.log(`Sequence number: ${response.result.tx_json.Sequence}`);
console.log(`Finished submitting! ${JSON.stringify(response.result, null, "\t")}`);

View File

@@ -28,15 +28,18 @@ const main = async () => {
throw new Error("Please specify the sequence number, condition and fulfillment of the escrow you created");
};
// Prepare EscrowFinish transaction ---------------------------------
const escrowFinishTransaction = {
"Account": wallet.address,
"TransactionType": "EscrowFinish",
"Owner": wallet.address,
// This should equal the sequence number of the escrow transaction
"OfferSequence": offerSequence,
// Crypto condition that must be met before escrow can be completed, passed on escrow creation
// Crypto condition that must be met before escrow can be completed, passed on escrow creation.
// Omit this for time-held escrows.
"Condition": condition,
// Fulfillment of the condition, passed on escrow creation
// Fulfillment of the condition, passed on escrow creation.
// Omit this for time-held escrows.
"Fulfillment": fulfillment,
};

View File

@@ -14,7 +14,11 @@ escrow_sequence = 30215126
sender_wallet = generate_faucet_wallet(client=client)
# Build escrow cancel transaction
cancel_txn = EscrowCancel(account=sender_wallet.address, owner=sender_wallet.address, offer_sequence=escrow_sequence)
cancel_txn = EscrowCancel(
account=sender_wallet.address,
owner=sender_wallet.address,
offer_sequence=escrow_sequence
)
# Autofill, sign, then submit transaction and wait for result
stxn_response = submit_and_wait(cancel_txn, client, sender_wallet)

View File

@@ -34,7 +34,8 @@ create_txn = EscrowCreate(
destination=receiver_addr,
finish_after=claim_date,
cancel_after=expiry_date,
condition=condition)
condition=condition # Omit this for time-held escrows
)
# Autofill, sign, then submit transaction and wait for result
stxn_response = submit_and_wait(create_txn, client, sender_wallet)

View File

@@ -25,7 +25,13 @@ fulfillment = "A0228020AED2C5FE4D147D310D3CFEBD9BFA81AD0F63CE1ADD92E00379DDDAF8E
sender_wallet = generate_faucet_wallet(client=client)
# Build escrow finish transaction
finish_txn = EscrowFinish(account=sender_wallet.address, owner=escrow_creator, offer_sequence=escrow_sequence, condition=condition, fulfillment=fulfillment)
finish_txn = EscrowFinish(
account=sender_wallet.address,
owner=escrow_creator,
offer_sequence=escrow_sequence, # The sequence number of the escrow transaction
condition=condition, # Omit this for time-held escrows
fulfillment=fulfillment # Omit this for time-held escrows
)
# Autofill, sign, then submit transaction and wait for result
stxn_response = submit_and_wait(finish_txn, client, sender_wallet)

View File

@@ -22,6 +22,7 @@ async function multisigning(): Promise<void> {
const { wallet: wallet1 } = await client.fundWallet()
const { wallet: wallet2 } = await client.fundWallet()
const { wallet: walletMaster } = await client.fundWallet()
const signerListSet: SignerListSet = {
TransactionType: 'SignerListSet',
Account: walletMaster.classicAddress,
@@ -56,9 +57,14 @@ async function multisigning(): Promise<void> {
const accountSetTx = await client.autofill(accountSet, 2)
console.log('AccountSet transaction is ready to be multisigned:')
console.log(accountSetTx)
const { tx_blob: tx_blob1 } = wallet1.sign(accountSetTx, true)
const { tx_blob: tx_blob2 } = wallet2.sign(accountSetTx, true)
const multisignedTx = multisign([tx_blob1, tx_blob2])
console.log("Successfully multisigned the transaction")
console.log(multisignedTx)
const submitResponse = await client.submit(multisignedTx)
if (submitResponse.result.engine_result === 'tesSUCCESS') {
@@ -79,4 +85,4 @@ async function multisigning(): Promise<void> {
await client.disconnect()
}
void multisigning()
void multisigning()

View File

@@ -2,7 +2,7 @@
* Extract best paths from RipplePathFind to trade with and send a payment using paths.
* Reference: https://xrpl.org/paths.html
*/
import { Client, Payment, RipplePathFindResponse } from 'xrpl'
import { Client, Payment, RipplePathFindResponse, RipplePathFindRequest } from 'xrpl'
const client = new Client('wss://s.altnet.rippletest.net:51233')
@@ -17,7 +17,7 @@ async function createTxWithPaths(): Promise<void> {
issuer: 'rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc',
}
const request = {
const request: RipplePathFindRequest = {
command: 'ripple_path_find',
source_account: wallet.classicAddress,
source_currencies: [