mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-12-05 08:48:11 +00:00
Merge pull request #1711 from pdp2121/migrate-snippets
migrate code snippets from xrpl-js and xrpl-py
This commit is contained in:
5
content/_code-samples/claim-payment-channel/README.md
Normal file
5
content/_code-samples/claim-payment-channel/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Create and Claim a Payment Channel
|
||||
|
||||
Create, claim and verify a Payment Channel.
|
||||
|
||||
For more context, see [PayChannel](https://xrpl.org/paychannel.html).
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Create, claim and verify a Payment Channel.
|
||||
* Reference: https://xrpl.org/paychannel.html
|
||||
*/
|
||||
import {
|
||||
AccountObjectsRequest,
|
||||
Client,
|
||||
PaymentChannelCreate,
|
||||
PaymentChannelClaim,
|
||||
hashes,
|
||||
} from 'xrpl'
|
||||
|
||||
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
|
||||
const { wallet: wallet1 } = await client.fundWallet()
|
||||
const { wallet: wallet2 } = await client.fundWallet()
|
||||
|
||||
console.log('Balances of wallets before Payment Channel is claimed:')
|
||||
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
|
||||
const paymentChannelCreate: PaymentChannelCreate = {
|
||||
TransactionType: 'PaymentChannelCreate',
|
||||
Account: wallet1.classicAddress,
|
||||
Amount: '100',
|
||||
Destination: wallet2.classicAddress,
|
||||
SettleDelay: 86400,
|
||||
PublicKey: wallet1.publicKey,
|
||||
}
|
||||
|
||||
console.log("Submitting a PaymentChannelCreate transaction...")
|
||||
const paymentChannelResponse = await client.submitAndWait(
|
||||
paymentChannelCreate,
|
||||
{ wallet: wallet1 },
|
||||
)
|
||||
console.log("PaymentChannelCreate transaction response:")
|
||||
console.log(paymentChannelResponse)
|
||||
|
||||
// check that the object was actually created
|
||||
const accountObjectsRequest: AccountObjectsRequest = {
|
||||
command: 'account_objects',
|
||||
account: wallet1.classicAddress,
|
||||
}
|
||||
|
||||
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.
|
||||
const paymentChannelClaim: PaymentChannelClaim = {
|
||||
Account: wallet2.classicAddress,
|
||||
TransactionType: 'PaymentChannelClaim',
|
||||
Channel: hashes.hashPaymentChannel(
|
||||
wallet1.classicAddress,
|
||||
wallet2.classicAddress,
|
||||
paymentChannelResponse.result.Sequence ?? 0,
|
||||
),
|
||||
Amount: '100',
|
||||
}
|
||||
|
||||
console.log("Submitting a PaymentChannelClaim transaction...")
|
||||
|
||||
const channelClaimResponse = await client.submit(paymentChannelClaim, {
|
||||
wallet: wallet1,
|
||||
})
|
||||
console.log("PaymentChannelClaim transaction response:")
|
||||
console.log(channelClaimResponse)
|
||||
|
||||
console.log('Balances of wallets after Payment Channel is claimed:')
|
||||
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`)
|
||||
|
||||
await client.disconnect()
|
||||
}
|
||||
5
content/_code-samples/get-tx/README.md
Normal file
5
content/_code-samples/get-tx/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Get a Transaction on the Ledger
|
||||
|
||||
Retrieve and display a transaction on the ledger.
|
||||
|
||||
For more context, see [tx Method](https://xrpl.org/tx.html).
|
||||
44
content/_code-samples/get-tx/js/getTransaction.ts
Normal file
44
content/_code-samples/get-tx/js/getTransaction.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Retrieve and display a transaction on the ledger.
|
||||
* Reference: https://xrpl.org/tx.html
|
||||
*/
|
||||
import { Client, LedgerResponse, TxResponse } from 'xrpl'
|
||||
|
||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
|
||||
|
||||
async function getTransaction(): Promise<void> {
|
||||
await client.connect()
|
||||
const ledger: LedgerResponse = await client.request({
|
||||
command: 'ledger',
|
||||
transactions: true,
|
||||
ledger_index: 'validated',
|
||||
})
|
||||
console.log("Latest validated ledger:", ledger)
|
||||
|
||||
const transactions = ledger.result.ledger.transactions
|
||||
if (transactions) {
|
||||
const tx: TxResponse = await client.request({
|
||||
command: 'tx',
|
||||
transaction: transactions[0],
|
||||
})
|
||||
console.log("First transaction in the ledger:")
|
||||
console.log(tx)
|
||||
|
||||
// The meta field would be a string(hex) when the `binary` parameter is `true` for the `tx` request.
|
||||
if (tx.result.meta == null) {
|
||||
throw new Error('meta not included in the response')
|
||||
}
|
||||
/*
|
||||
* delivered_amount is the amount actually received by the destination account.
|
||||
* Use this field to determine how much was delivered, regardless of whether the transaction is a partial payment.
|
||||
* https://xrpl.org/transaction-metadata.html#delivered_amount
|
||||
*/
|
||||
if (typeof tx.result.meta !== 'string') {
|
||||
console.log('delivered_amount:', tx.result.meta.delivered_amount)
|
||||
}
|
||||
}
|
||||
|
||||
await client.disconnect()
|
||||
}
|
||||
|
||||
void getTransaction()
|
||||
30
content/_code-samples/get-tx/py/get_transaction.py
Normal file
30
content/_code-samples/get-tx/py/get_transaction.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""Example of how we can see a transaction that was validated on the ledger"""
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models.requests import Ledger, Tx
|
||||
|
||||
# References
|
||||
# - https://xrpl.org/look-up-transaction-results.html
|
||||
# - https://xrpl.org/parallel-networks.html#parallel-networks
|
||||
# - https://xrpl.org/tx.html
|
||||
|
||||
# Create a client to connect to the main network
|
||||
client = JsonRpcClient("https://xrplcluster.com/")
|
||||
|
||||
# Create a Ledger request and have the client call it
|
||||
ledger_request = Ledger(ledger_index="validated", transactions=True)
|
||||
ledger_response = client.request(ledger_request)
|
||||
print(ledger_response)
|
||||
|
||||
# Extract out transactions from the ledger response
|
||||
transactions = ledger_response.result["ledger"]["transactions"]
|
||||
|
||||
# If there are transactions, we can display the first one
|
||||
# If there are none (visualized at https://testnet.xrpl.org/), try re running the script
|
||||
if transactions:
|
||||
# Create a Transaction request and have the client call it
|
||||
tx_request = Tx(transaction=transactions[0])
|
||||
tx_response = client.request(tx_request)
|
||||
print("First transaction in the ledger:")
|
||||
print(tx_response)
|
||||
else:
|
||||
print("No transactions were found on the ledger!")
|
||||
5
content/_code-samples/multisigning/README.md
Normal file
5
content/_code-samples/multisigning/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Multisign a transaction.
|
||||
|
||||
Create and submit a SignerListSet and multisign a transaction.
|
||||
|
||||
For more context, see [Multi-signing](https://xrpl.org/multi-signing.html).
|
||||
82
content/_code-samples/multisigning/js/multisigning.ts
Normal file
82
content/_code-samples/multisigning/js/multisigning.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Create and submit a SignerListSet and multisign a transaction.
|
||||
* Reference: https://xrpl.org/multi-signing.html
|
||||
*/
|
||||
import {
|
||||
multisign,
|
||||
Client,
|
||||
AccountSet,
|
||||
convertStringToHex,
|
||||
SignerListSet,
|
||||
} from 'xrpl'
|
||||
|
||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
|
||||
|
||||
async function multisigning(): Promise<void> {
|
||||
await client.connect()
|
||||
/*
|
||||
* This wallet creation is for demonstration purposes.
|
||||
* In practice, users generally will not have all keys in one spot,
|
||||
* hence, users need to implement a way to get signatures.
|
||||
*/
|
||||
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,
|
||||
SignerEntries: [
|
||||
{
|
||||
SignerEntry: {
|
||||
Account: wallet1.classicAddress,
|
||||
SignerWeight: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
SignerEntry: {
|
||||
Account: wallet2.classicAddress,
|
||||
SignerWeight: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
SignerQuorum: 2,
|
||||
}
|
||||
|
||||
const signerListResponse = await client.submit(signerListSet, {
|
||||
wallet: walletMaster,
|
||||
})
|
||||
console.log('SignerListSet constructed successfully:')
|
||||
console.log(signerListResponse)
|
||||
|
||||
const accountSet: AccountSet = {
|
||||
TransactionType: 'AccountSet',
|
||||
Account: walletMaster.classicAddress,
|
||||
Domain: convertStringToHex('example.com'),
|
||||
}
|
||||
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])
|
||||
const submitResponse = await client.submit(multisignedTx)
|
||||
|
||||
if (submitResponse.result.engine_result === 'tesSUCCESS') {
|
||||
console.log('The multisigned transaction was accepted by the ledger:')
|
||||
console.log(submitResponse)
|
||||
if (submitResponse.result.tx_json.Signers) {
|
||||
console.log(
|
||||
`The transaction had ${submitResponse.result.tx_json.Signers.length} signatures`,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
"The multisigned transaction was rejected by rippled. Here's the response from rippled:",
|
||||
)
|
||||
console.log(submitResponse)
|
||||
}
|
||||
|
||||
await client.disconnect()
|
||||
}
|
||||
|
||||
void multisigning()
|
||||
79
content/_code-samples/multisigning/py/multisigning.py
Normal file
79
content/_code-samples/multisigning/py/multisigning.py
Normal file
@@ -0,0 +1,79 @@
|
||||
"""
|
||||
Example of how we can multisign a transaction.
|
||||
This will only work with version 2.0.0-beta.0 or later.
|
||||
Reference: https://xrpl.org/multi-signing.html
|
||||
"""
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models.requests import SubmitMultisigned
|
||||
from xrpl.models.transactions import AccountSet, SignerEntry, SignerListSet
|
||||
from xrpl.transaction import (
|
||||
autofill,
|
||||
autofill_and_sign,
|
||||
multisign,
|
||||
send_reliable_submission,
|
||||
sign,
|
||||
)
|
||||
from xrpl.utils import str_to_hex
|
||||
from xrpl.wallet import generate_faucet_wallet
|
||||
|
||||
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
|
||||
|
||||
# Create a wallets to use for multisigning
|
||||
# Prints debug info as it creates the wallet
|
||||
master_wallet = generate_faucet_wallet(client, debug=True)
|
||||
signer_wallet_1 = generate_faucet_wallet(client, debug=True)
|
||||
signer_wallet_2 = generate_faucet_wallet(client, debug=True)
|
||||
|
||||
signer_entries = [
|
||||
SignerEntry(account=signer_wallet_1.classic_address, signer_weight=1),
|
||||
SignerEntry(account=signer_wallet_2.classic_address, signer_weight=1),
|
||||
]
|
||||
signer_list_set_tx = SignerListSet(
|
||||
account=master_wallet.classic_address,
|
||||
signer_quorum=2,
|
||||
signer_entries=signer_entries,
|
||||
)
|
||||
signed_signer_list_set_tx = autofill_and_sign(signer_list_set_tx, master_wallet, client)
|
||||
|
||||
print("Constructed SignerListSet and submitting it to the ledger...")
|
||||
signed_list_set_tx_response = send_reliable_submission(
|
||||
signed_signer_list_set_tx, client
|
||||
)
|
||||
print("SignerListSet submitted, here's the response:")
|
||||
print(signed_list_set_tx_response)
|
||||
|
||||
# Now that we've set up multisigning, let's try using it to submit an AccountSet
|
||||
# transaction.
|
||||
account_set_tx = AccountSet(
|
||||
account=master_wallet.classic_address, domain=str_to_hex("example.com")
|
||||
)
|
||||
autofilled_account_set_tx = autofill(account_set_tx, client, len(signer_entries))
|
||||
print("AccountSet transaction is ready to be multisigned")
|
||||
print(autofilled_account_set_tx)
|
||||
|
||||
# Since we created both signer keys, we can sign locally, but if you are building an app
|
||||
# That allows multisigning, you would need to request signatures from the key holders.
|
||||
tx_1 = sign(autofilled_account_set_tx, signer_wallet_1, multisign=True)
|
||||
tx_2 = sign(autofilled_account_set_tx, signer_wallet_2, multisign=True)
|
||||
|
||||
multisigned_tx = multisign(autofilled_account_set_tx, [tx_1, tx_2])
|
||||
|
||||
print("Successfully multisigned the transaction")
|
||||
print(multisigned_tx)
|
||||
|
||||
multisigned_tx_response = client.request(SubmitMultisigned(tx_json=multisigned_tx))
|
||||
|
||||
if multisigned_tx_response.result["engine_result"] == "tesSUCCESS":
|
||||
print("The multisigned transaction was accepted by the ledger:")
|
||||
print(multisigned_tx_response)
|
||||
if multisigned_tx_response.result["tx_json"]["Signers"]:
|
||||
print(
|
||||
"The transaction had "
|
||||
f"{len(multisigned_tx_response.result['tx_json']['Signers'])} signatures"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
"The multisigned transaction was rejected by rippled."
|
||||
"Here's the response from rippled:"
|
||||
)
|
||||
print(multisigned_tx_response)
|
||||
12
content/_code-samples/partial-payment/README.md
Normal file
12
content/_code-samples/partial-payment/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Send Partial Payments
|
||||
|
||||
Send partial payments with money amount less than the amount specified on 2 conditions:
|
||||
|
||||
- Sender has less money than the aamount specified in the payment Tx.
|
||||
- Sender has the tfPartialPayment flag activated.
|
||||
|
||||
Other ways to specify flags are by using Hex code and decimal code.
|
||||
eg. For partial payment(tfPartialPayment)
|
||||
decimal ->131072, hex -> 0x00020000
|
||||
|
||||
For more context, see [Partial Payments](https://xrpl.org/partial-payments.html)
|
||||
97
content/_code-samples/partial-payment/js/partialPayment.ts
Normal file
97
content/_code-samples/partial-payment/js/partialPayment.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { Client, Payment, PaymentFlags, TrustSet } from 'xrpl'
|
||||
|
||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
|
||||
|
||||
// This snippet walks us through partial payment.
|
||||
// Reference: https://xrpl.org/partial-payments.html
|
||||
async function partialPayment(): Promise<void> {
|
||||
await client.connect()
|
||||
|
||||
// creating wallets as prerequisite
|
||||
const { wallet: wallet1 } = await client.fundWallet()
|
||||
const { wallet: wallet2 } = await client.fundWallet()
|
||||
|
||||
// create a trustline to issue an IOU `FOO` and set limit on it.
|
||||
const trust_set_tx: TrustSet = {
|
||||
TransactionType: 'TrustSet',
|
||||
Account: wallet2.classicAddress,
|
||||
LimitAmount: {
|
||||
currency: 'FOO',
|
||||
issuer: wallet1.classicAddress,
|
||||
// Value for the new IOU - 10000000000 - is arbitarily chosen.
|
||||
value: '10000000000',
|
||||
},
|
||||
}
|
||||
console.log("Submitting a TrustSet transaction...")
|
||||
|
||||
const trust_set_res = await client.submitAndWait(trust_set_tx, {
|
||||
wallet: wallet2,
|
||||
})
|
||||
|
||||
console.log("TrustSet transaction response:")
|
||||
console.log(trust_set_res)
|
||||
|
||||
console.log('Balances after trustline is created')
|
||||
console.log(`Balance of ${wallet1.classicAddress} is ${await client.getBalances(wallet1.classicAddress)}`)
|
||||
console.log(`Balance of ${wallet2.classicAddress} is ${await client.getBalances(wallet2.classicAddress)}`)
|
||||
|
||||
// Initially, the issuer(wallet1) sends an amount to the other account(wallet2)
|
||||
const issue_quantity = '3840'
|
||||
const payment: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: wallet1.classicAddress,
|
||||
Amount: {
|
||||
currency: 'FOO',
|
||||
value: issue_quantity,
|
||||
issuer: wallet1.classicAddress,
|
||||
},
|
||||
Destination: wallet2.classicAddress,
|
||||
}
|
||||
|
||||
// submit payment
|
||||
const initialPayment = await client.submitAndWait(payment, {
|
||||
wallet: wallet1,
|
||||
})
|
||||
console.log("Initial payment response:", initialPayment)
|
||||
|
||||
console.log('Balances after issuer(wallet1) sends IOU("FOO") to wallet2')
|
||||
console.log(`Balance of ${wallet1.classicAddress} is ${await client.getBalances(wallet1.classicAddress)}`)
|
||||
console.log(`Balance of ${wallet2.classicAddress} is ${await client.getBalances(wallet2.classicAddress)}`)
|
||||
|
||||
/*
|
||||
* Send money less than the amount specified on 2 conditions:
|
||||
* 1. Sender has less money than the aamount specified in the payment Tx.
|
||||
* 2. Sender has the tfPartialPayment flag activated.
|
||||
*
|
||||
* Other ways to specify flags are by using Hex code and decimal code.
|
||||
* eg. For partial payment(tfPartialPayment)
|
||||
* decimal ->131072, hex -> 0x00020000
|
||||
*/
|
||||
const partialPaymentTx: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: wallet2.classicAddress,
|
||||
Amount: {
|
||||
currency: 'FOO',
|
||||
value: '4000',
|
||||
issuer: wallet1.classicAddress,
|
||||
},
|
||||
Destination: wallet1.classicAddress,
|
||||
Flags: PaymentFlags.tfPartialPayment,
|
||||
}
|
||||
|
||||
// submit payment
|
||||
console.log("Submitting a Partial Payment transaction...")
|
||||
const submitResponse = await client.submitAndWait(partialPaymentTx, {
|
||||
wallet: wallet2,
|
||||
})
|
||||
console.log("Partial Payment response: ", submitResponse)
|
||||
|
||||
console.log(
|
||||
"Balances after Partial Payment, when wallet2 tried to send 4000 FOO's",
|
||||
)
|
||||
console.log(`Balance of ${wallet1.classicAddress} is ${await client.getBalances(wallet1.classicAddress)}`)
|
||||
console.log(`Balance of ${wallet2.classicAddress} is ${await client.getBalances(wallet2.classicAddress)}`)
|
||||
|
||||
await client.disconnect()
|
||||
}
|
||||
void partialPayment()
|
||||
102
content/_code-samples/partial-payment/py/partial-payment.py
Normal file
102
content/_code-samples/partial-payment/py/partial-payment.py
Normal file
@@ -0,0 +1,102 @@
|
||||
"""Example of how to handle partial payments"""
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models.amounts import IssuedCurrencyAmount
|
||||
from xrpl.models.requests import AccountLines
|
||||
from xrpl.models.transactions import Payment, PaymentFlag, TrustSet
|
||||
from xrpl.transaction import autofill_and_sign, send_reliable_submission
|
||||
from xrpl.wallet import generate_faucet_wallet
|
||||
|
||||
# References
|
||||
# - https://xrpl.org/partial-payments.html#partial-payments
|
||||
# - https://xrpl.org/payment.html#payment-flags
|
||||
# - https://xrpl.org/trustset.html#trustset
|
||||
# - https://xrpl.org/account_lines.html#account_lines
|
||||
|
||||
# Create a client to connect to the test network
|
||||
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
|
||||
|
||||
# Creating two wallets to send money between
|
||||
wallet1 = generate_faucet_wallet(client, debug=True)
|
||||
wallet2 = generate_faucet_wallet(client, debug=True)
|
||||
|
||||
# Create a TrustSet to issue an IOU `FOO` and set limit on it
|
||||
trust_set_tx = TrustSet(
|
||||
account=wallet2.classic_address,
|
||||
limit_amount=IssuedCurrencyAmount(
|
||||
currency="FOO",
|
||||
value="10000000000",
|
||||
issuer=wallet1.classic_address,
|
||||
),
|
||||
)
|
||||
|
||||
# Sign and autofill, then send transaction to the ledger
|
||||
signed_trust_set_tx = autofill_and_sign(trust_set_tx, wallet2, client)
|
||||
send_reliable_submission(signed_trust_set_tx, client)
|
||||
|
||||
# Both balances should be zero since nothing has been sent yet
|
||||
print("Balances after trustline is claimed:")
|
||||
print("Balance of ${wallet1.classic_address} is:")
|
||||
print((client.request(AccountLines(account=wallet1.classic_address))).result["lines"])
|
||||
print("Balance of ${wallet2.classic_address} is:")
|
||||
print((client.request(AccountLines(account=wallet2.classic_address))).result["lines"])
|
||||
|
||||
# Create a Payment to send 3840 FOO from wallet1 (issuer) to destination (wallet2)
|
||||
issue_quantity = "3840"
|
||||
payment_tx = Payment(
|
||||
account=wallet1.classic_address,
|
||||
amount=IssuedCurrencyAmount(
|
||||
currency="FOO",
|
||||
value=issue_quantity,
|
||||
issuer=wallet1.classic_address,
|
||||
),
|
||||
destination=wallet2.classic_address,
|
||||
)
|
||||
|
||||
# Sign and autofill, then send transaction to the ledger
|
||||
signed_payment_tx = autofill_and_sign(payment_tx, wallet1, client)
|
||||
payment_response = send_reliable_submission(signed_payment_tx, client)
|
||||
print("Initial Payment response: ", payment_response)
|
||||
|
||||
# Issuer (wallet1) should have -3840 FOO and destination (wallet2) should have 3840 FOO
|
||||
print("Balances after wallet1 sends 3840 FOO to wallet2:")
|
||||
print("Balance of ${wallet1.classic_address} is:")
|
||||
print((client.request(AccountLines(account=wallet1.classic_address))).result["lines"])
|
||||
print("Balance of ${wallet2.classic_address} is:")
|
||||
print((client.request(AccountLines(account=wallet2.classic_address))).result["lines"])
|
||||
|
||||
# Send money less than the amount specified on 2 conditions:
|
||||
# 1. Sender has less money than the amount specified in the payment Tx.
|
||||
# 2. Sender has the tfPartialPayment flag activated.
|
||||
|
||||
# Other ways to specify flags are by using Hex code and decimal code.
|
||||
# eg. For partial payment(tfPartialPayment)
|
||||
# decimal ->131072, hex -> 0x00020000
|
||||
|
||||
# Create Payment to send 4000 (of 3840) FOO from wallet2 to wallet1
|
||||
partial_payment_tx = Payment(
|
||||
account=wallet2.classic_address,
|
||||
amount=IssuedCurrencyAmount(
|
||||
currency="FOO",
|
||||
value="4000",
|
||||
issuer=wallet1.classic_address,
|
||||
),
|
||||
destination=wallet1.classic_address,
|
||||
flags=[PaymentFlag.TF_PARTIAL_PAYMENT],
|
||||
send_max=IssuedCurrencyAmount(
|
||||
currency="FOO",
|
||||
value="1000000",
|
||||
issuer=wallet1.classic_address,
|
||||
),
|
||||
)
|
||||
|
||||
# Sign and autofill, then send transaction to the ledger
|
||||
signed_partial_payment_tx = autofill_and_sign(partial_payment_tx, wallet2, client)
|
||||
partial_payment_response = send_reliable_submission(signed_partial_payment_tx, client)
|
||||
print("Partial Payment response: ", partial_payment_response)
|
||||
|
||||
# Tried sending 4000 of 3840 FOO -> wallet1 and wallet2 should have 0 FOO
|
||||
print("Balances after Partial Payment, when wallet2 tried to send 4000 FOOs")
|
||||
print("Balance of ${wallet1.classic_address} is:")
|
||||
print((client.request(AccountLines(account=wallet1.classic_address))).result["lines"])
|
||||
print("Balance of ${wallet2.classic_address} is:")
|
||||
print((client.request(AccountLines(account=wallet2.classic_address))).result["lines"])
|
||||
5
content/_code-samples/paths/README.md
Normal file
5
content/_code-samples/paths/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Use Paths
|
||||
|
||||
Extract paths from RipplePathFind and send a payment using paths.
|
||||
|
||||
For more context, see [Paths](https://xrpl.org/paths.html).
|
||||
53
content/_code-samples/paths/js/paths.ts
Normal file
53
content/_code-samples/paths/js/paths.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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'
|
||||
|
||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
|
||||
|
||||
async function createTxWithPaths(): Promise<void> {
|
||||
await client.connect()
|
||||
|
||||
const { wallet } = await client.fundWallet()
|
||||
const destination_account = 'rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj'
|
||||
const destination_amount = {
|
||||
value: '0.001',
|
||||
currency: 'USD',
|
||||
issuer: 'rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc',
|
||||
}
|
||||
|
||||
const request = {
|
||||
command: 'ripple_path_find',
|
||||
source_account: wallet.classicAddress,
|
||||
source_currencies: [
|
||||
{
|
||||
currency: 'XRP',
|
||||
},
|
||||
],
|
||||
destination_account,
|
||||
destination_amount,
|
||||
}
|
||||
|
||||
const resp: RipplePathFindResponse = await client.request(request)
|
||||
console.log("Ripple Path Find response: ", resp)
|
||||
|
||||
const paths = resp.result.alternatives[0].paths_computed
|
||||
console.log("Computed paths: ", paths)
|
||||
|
||||
const tx: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: wallet.classicAddress,
|
||||
Amount: destination_amount,
|
||||
Destination: destination_account,
|
||||
Paths: paths,
|
||||
}
|
||||
|
||||
await client.autofill(tx)
|
||||
const signed = wallet.sign(tx)
|
||||
console.log('signed:', signed)
|
||||
|
||||
await client.disconnect()
|
||||
}
|
||||
|
||||
void createTxWithPaths()
|
||||
50
content/_code-samples/paths/py/paths.py
Normal file
50
content/_code-samples/paths/py/paths.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""Example of how to find the best path to trade with"""
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models.amounts import IssuedCurrencyAmount
|
||||
from xrpl.models.currencies.xrp import XRP
|
||||
from xrpl.models.requests import RipplePathFind
|
||||
from xrpl.models.transactions import Payment
|
||||
from xrpl.transaction import autofill_and_sign
|
||||
from xrpl.wallet import generate_faucet_wallet
|
||||
|
||||
# References
|
||||
# - https://xrpl.org/paths.html#paths
|
||||
# - https://xrpl.org/ripple_path_find.html#ripple_path_find
|
||||
|
||||
# Create a client to connect to the test network
|
||||
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
|
||||
|
||||
# Creating wallet to send money from
|
||||
wallet = generate_faucet_wallet(client, debug=True)
|
||||
|
||||
# Create account and amount variables for later transaction
|
||||
destination_account = "rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj"
|
||||
destination_amount = IssuedCurrencyAmount(
|
||||
value="0.001",
|
||||
currency="USD",
|
||||
issuer="rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc",
|
||||
)
|
||||
|
||||
# Create a RipplePathFind request and have the client call it
|
||||
path_request = RipplePathFind(
|
||||
source_account=wallet.classic_address,
|
||||
source_currencies=[XRP()],
|
||||
destination_account=destination_account,
|
||||
destination_amount=destination_amount,
|
||||
)
|
||||
path_response = client.request(path_request)
|
||||
print(path_response)
|
||||
|
||||
# Extract out paths from the RipplePathFind response
|
||||
paths = path_response.result["alternatives"][0]["paths_computed"]
|
||||
print(paths)
|
||||
|
||||
# # Create a Payment to send money from wallet to destination_account using path
|
||||
payment_tx = Payment(
|
||||
account=wallet.classic_address,
|
||||
amount=destination_amount,
|
||||
destination=destination_account,
|
||||
paths=paths,
|
||||
)
|
||||
|
||||
print("signed: ", autofill_and_sign(payment_tx, wallet, client))
|
||||
9
content/_code-samples/reliable-tx-submission/README.md
Normal file
9
content/_code-samples/reliable-tx-submission/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Implement Reliable Transaction Submission
|
||||
|
||||
Send a transaction and see its validation response. For the implementation in this example, we have made the following decisions:
|
||||
|
||||
- We allow the autofill function as a part of submitAndWait to fill up the account sequence, LastLedgerSequence and Fee. Payments are defined upfront, and idempotency is not needed. If the script is run a second time, duplicate payments will result.
|
||||
- We will rely on the submitAndWait function to get us the transaction submission result after the wait time.
|
||||
- Transactions will not be automatically retried. Transactions are limited to XRP-to-XRP payments and cannot "succeed" in an unexpected way.
|
||||
|
||||
For more context, see [Reliable Transaction Submission](https://xrpl.org/reliable-transaction-submission.html)
|
||||
@@ -0,0 +1,81 @@
|
||||
import { Client, Payment } from 'xrpl';
|
||||
|
||||
/**
|
||||
* When implementing Reliable Transaction Submission, there are many potential solutions, each with different trade-offs.
|
||||
* The main decision points are:
|
||||
* 1) Transaction preparation:
|
||||
* - The autofill function as a part of the submitAndWait should be able to correctly populate
|
||||
* values for the fields Sequence, LastLedgerSequence and Fee.
|
||||
* 2) Transaction status retrieval. Options include:
|
||||
* - Poll for transaction status:
|
||||
* - On a regular interval (e.g. Every 3-5 seconds), or
|
||||
* - When a new validated ledger is detected
|
||||
* + (To accommodate an edge case in transaction retrieval,
|
||||
* check the sending account's Sequence number to confirm that it has the expected value;
|
||||
* alternatively, wait until a few additional ledgers have been validated before deciding that a
|
||||
* transaction has definitively not been included in a validated ledger)
|
||||
* - Listen for transaction status: scan all validated transactions to see if our transactions are among them
|
||||
* 3) What do we do when a transaction fails? It is possible to implement retry logic, but caution is advised.
|
||||
* Note that there are a few ways for a transaction to fail:
|
||||
* A) `tec`: The transaction was included in a ledger but only claimed the transaction fee
|
||||
* B) `tesSUCCESS` but unexpected result: The transaction was successful but did not have the expected result.
|
||||
* This generally does not occur for XRP-to-XRP payments
|
||||
* C) The transaction was not, and never will be, included in a validated ledger [3C].
|
||||
*
|
||||
* References:
|
||||
* - https://xrpl.org/reliable-transaction-submission.html
|
||||
* - https://xrpl.org/send-xrp.html
|
||||
* - https://xrpl.org/look-up-transaction-results.html
|
||||
* - https://xrpl.org/monitor-incoming-payments-with-websocket.html.
|
||||
*
|
||||
* For the implementation in this example, we have made the following decisions:
|
||||
* 1) We allow the autofill function as a part of submitAndWait to fill up the account sequence,
|
||||
* LastLedgerSequence and Fee. Payments are defined upfront, and idempotency is not needed.
|
||||
* If the script is run a second time, duplicate payments will result.
|
||||
* 2) We will rely on the xrpl.js submitAndWait function to get us the transaction submission result after the wait time.
|
||||
* 3) Transactions will not be automatically retried. Transactions are limited to XRP-to-XRP payments
|
||||
* and cannot "succeed" in an unexpected way.
|
||||
*/
|
||||
|
||||
const client = new Client("wss://s.altnet.rippletest.net:51233");
|
||||
|
||||
void sendReliableTx();
|
||||
|
||||
async function sendReliableTx(): Promise<void> {
|
||||
await client.connect();
|
||||
|
||||
// creating wallets as prerequisite
|
||||
const { wallet: wallet1 } = await client.fundWallet();
|
||||
const { wallet: wallet2 } = await client.fundWallet();
|
||||
|
||||
console.log("Balances of wallets before Payment tx");
|
||||
|
||||
console.log(`Balance of ${wallet1.classicAddress} is ${await client.getXrpBalance(wallet1.classicAddress)}XRP`);
|
||||
console.log(`Balance of ${wallet2.classicAddress} is ${await client.getXrpBalance(wallet2.classicAddress)}XRP`);
|
||||
|
||||
// create a Payment tx and submit and wait for tx to be validated
|
||||
const payment: Payment = {
|
||||
TransactionType: "Payment",
|
||||
Account: wallet1.classicAddress,
|
||||
Amount: "1000",
|
||||
Destination: wallet2.classicAddress,
|
||||
};
|
||||
|
||||
console.log("Submitting a Payment transaction...")
|
||||
const paymentResponse = await client.submitAndWait(payment, {
|
||||
wallet: wallet1,
|
||||
});
|
||||
console.log("\nTransaction was submitted.\n");
|
||||
const txResponse = await client.request({
|
||||
command: "tx",
|
||||
transaction: paymentResponse.result.hash,
|
||||
});
|
||||
// With the following reponse we are able to see that the tx was indeed validated.
|
||||
console.log("Validated:", txResponse.result.validated);
|
||||
|
||||
console.log("Balances of wallets after Payment tx:");
|
||||
console.log(`Balance of ${wallet1.classicAddress} is ${await client.getXrpBalance(wallet1.classicAddress)}XRP`);
|
||||
console.log(`Balance of ${wallet2.classicAddress} is ${await client.getXrpBalance(wallet2.classicAddress)}XRP`);
|
||||
|
||||
await client.disconnect();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
"""Example of how to send a transaction and see its validation response"""
|
||||
from xrpl.account import get_balance
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models.requests import Tx
|
||||
from xrpl.models.transactions import Payment
|
||||
from xrpl.transaction import autofill_and_sign, send_reliable_submission
|
||||
from xrpl.wallet import generate_faucet_wallet
|
||||
|
||||
# References:
|
||||
# - https://xrpl.org/reliable-transaction-submission.html
|
||||
# - https://xrpl.org/send-xrp.html
|
||||
# - https://xrpl.org/look-up-transaction-results.html
|
||||
|
||||
# Create a client to connect to the test network
|
||||
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
|
||||
|
||||
# Creating two wallets to send money between
|
||||
wallet1 = generate_faucet_wallet(client, debug=True)
|
||||
wallet2 = generate_faucet_wallet(client, debug=True)
|
||||
|
||||
# Both balances should be zero since nothing has been sent yet
|
||||
print("Balances of wallets before Payment tx")
|
||||
print(get_balance(wallet1.classic_address, client))
|
||||
print(get_balance(wallet2.classic_address, client))
|
||||
|
||||
# Create a Payment transaction
|
||||
payment_tx = Payment(
|
||||
account=wallet1.classic_address,
|
||||
amount="1000",
|
||||
destination=wallet2.classic_address,
|
||||
)
|
||||
|
||||
# Sign and autofill the transaction (prepares it to be ready to submit)
|
||||
signed_payment_tx = autofill_and_sign(payment_tx, wallet1, client)
|
||||
|
||||
# Submits transaction and waits for response (validated or rejected)
|
||||
payment_response = send_reliable_submission(signed_payment_tx, client)
|
||||
print("Transaction was submitted")
|
||||
|
||||
# Create a Transaction request to see transaction
|
||||
tx_response = client.request(Tx(transaction=payment_response.result["hash"]))
|
||||
|
||||
# Check validated field on the transaction
|
||||
print("Validated:", tx_response.result["validated"])
|
||||
|
||||
# Check balances after 1000 was sent from wallet1 to wallet2
|
||||
print("Balances of wallets after Payment tx:")
|
||||
print(get_balance(wallet1.classic_address, client))
|
||||
print(get_balance(wallet2.classic_address, client))
|
||||
5
content/_code-samples/set-regular-key/README.md
Normal file
5
content/_code-samples/set-regular-key/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Use `SetRegularKey`
|
||||
|
||||
Use `SetRegularKey` to assign a key pair to a wallet and make a payment signed using the regular key wallet.
|
||||
|
||||
For more context, see [SetRegularKey](https://xrpl.org/setregularkey.html).
|
||||
56
content/_code-samples/set-regular-key/js/setRegularKey.ts
Normal file
56
content/_code-samples/set-regular-key/js/setRegularKey.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Use `SetRegularKey` to assign a key pair to a wallet and make a payment signed using the regular key wallet.
|
||||
* Reference: https://xrpl.org/setregularkey.html
|
||||
*/
|
||||
import { Client, Payment, SetRegularKey } from 'xrpl'
|
||||
|
||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
|
||||
|
||||
async function setRegularKey(): Promise<void> {
|
||||
await client.connect()
|
||||
const { wallet: wallet1 } = await client.fundWallet()
|
||||
const { wallet: wallet2 } = await client.fundWallet()
|
||||
const { wallet: regularKeyWallet } = await client.fundWallet()
|
||||
|
||||
console.log('Balances before payment')
|
||||
console.log(`Balance of ${wallet1.classicAddress} is ${await client.getXrpBalance(wallet1.classicAddress)}XRP`)
|
||||
console.log(`Balance of ${wallet2.classicAddress} is ${await client.getXrpBalance(wallet2.classicAddress)}XRP`)
|
||||
|
||||
// assigns key-pair(regularKeyWallet) to wallet1 using `SetRegularKey`.
|
||||
const tx: SetRegularKey = {
|
||||
TransactionType: 'SetRegularKey',
|
||||
Account: wallet1.classicAddress,
|
||||
RegularKey: regularKeyWallet.classicAddress,
|
||||
}
|
||||
|
||||
console.log('Submitting a SetRegularKey transaction...')
|
||||
const response = await client.submitAndWait(tx, {
|
||||
wallet: wallet1,
|
||||
})
|
||||
|
||||
console.log('Response for successful SetRegularKey tx')
|
||||
console.log(response)
|
||||
|
||||
/*
|
||||
* when wallet1 sends payment to wallet2 and
|
||||
* signs using the regular key wallet, the transaction goes through.
|
||||
*/
|
||||
const payment: Payment = {
|
||||
TransactionType: 'Payment',
|
||||
Account: wallet1.classicAddress,
|
||||
Destination: wallet2.classicAddress,
|
||||
Amount: '1000',
|
||||
}
|
||||
|
||||
const submitTx = await client.submit(payment, {
|
||||
wallet: regularKeyWallet,
|
||||
})
|
||||
console.log('Response for tx signed using Regular Key:')
|
||||
console.log(submitTx)
|
||||
console.log('Balances after payment:')
|
||||
console.log(`Balance of ${wallet1.classicAddress} is ${await client.getXrpBalance(wallet1.classicAddress)}XRP`)
|
||||
console.log(`Balance of ${wallet2.classicAddress} is ${await client.getXrpBalance(wallet2.classicAddress)}XRP`)
|
||||
|
||||
await client.disconnect()
|
||||
}
|
||||
void setRegularKey()
|
||||
54
content/_code-samples/set-regular-key/py/setRegularKey.py
Normal file
54
content/_code-samples/set-regular-key/py/setRegularKey.py
Normal file
@@ -0,0 +1,54 @@
|
||||
"""Example of how we can setting a regular key"""
|
||||
from xrpl.account import get_balance
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models.transactions import Payment, SetRegularKey
|
||||
from xrpl.transaction import autofill_and_sign, send_reliable_submission
|
||||
from xrpl.wallet import generate_faucet_wallet
|
||||
|
||||
# References
|
||||
# - https://xrpl.org/assign-a-regular-key-pair.html#assign-a-regular-key-pair
|
||||
# - https://xrpl.org/setregularkey.html#setregularkey
|
||||
# - https://xrpl.org/change-or-remove-a-regular-key-pair.html
|
||||
|
||||
# Create a client to connect to the test network
|
||||
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
|
||||
|
||||
# Creating two wallets to send money between
|
||||
wallet1 = generate_faucet_wallet(client, debug=True)
|
||||
wallet2 = generate_faucet_wallet(client, debug=True)
|
||||
regular_key_wallet = generate_faucet_wallet(client, debug=True)
|
||||
|
||||
# Both balances should be zero since nothing has been sent yet
|
||||
print("Balances before payment:")
|
||||
print(get_balance(wallet1.classic_address, client))
|
||||
print(get_balance(wallet2.classic_address, client))
|
||||
|
||||
# Assign key pair (regular_key_wallet) to wallet1 using SetRegularKey transaction
|
||||
tx = SetRegularKey(
|
||||
account=wallet1.classic_address, regular_key=regular_key_wallet.classic_address
|
||||
)
|
||||
|
||||
signed_tx = autofill_and_sign(tx, wallet1, client)
|
||||
set_regular_key_response = send_reliable_submission(signed_tx, client)
|
||||
|
||||
print("Response for successful SetRegularKey tx:")
|
||||
print(set_regular_key_response)
|
||||
|
||||
# Since regular_key_wallet is linked to wallet1,
|
||||
# walet1 can send payment to wallet2 and have regular_key_wallet sign it
|
||||
payment = Payment(
|
||||
account=wallet1.classic_address,
|
||||
destination=wallet2.classic_address,
|
||||
amount="1000",
|
||||
)
|
||||
|
||||
signed_payment = autofill_and_sign(payment, regular_key_wallet, client)
|
||||
payment_response = send_reliable_submission(signed_payment, client)
|
||||
|
||||
print("Response for tx signed using Regular Key:")
|
||||
print(payment_response)
|
||||
|
||||
# Balance after sending 1000 from wallet1 to wallet2
|
||||
print("Balances after payment:")
|
||||
print(get_balance(wallet1.classic_address, client))
|
||||
print(get_balance(wallet2.classic_address, client))
|
||||
Reference in New Issue
Block a user