mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2026-02-16 03:42:26 +00:00
Compare commits
6 Commits
master
...
add-bitget
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9af8e7849e | ||
|
|
c62d5090d0 | ||
|
|
19ec38e7d8 | ||
|
|
f119214cea | ||
|
|
69d4113536 | ||
|
|
f5988554db |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,7 +8,7 @@ yarn-error.log
|
||||
*.iml
|
||||
.venv/
|
||||
_code-samples/*/js/package-lock.json
|
||||
_code-samples/*/*/*[Ss]etup.json
|
||||
_code-samples/*/js/*[Ss]etup.json
|
||||
|
||||
# PHP
|
||||
composer.lock
|
||||
|
||||
@@ -177,84 +177,84 @@ node createLoan.js
|
||||
The script should output the LoanSet transaction, the updated LoanSet transaction with the loan broker signature, the final LoanSet transaction with the borrower signature added, and then the loan information:
|
||||
|
||||
```sh
|
||||
Loan broker address: rn6CD8i3Yc3UGagSosZfegG7hpXxwgVAgz
|
||||
Borrower address: rN2PMxegkEMZHin78o7wSs1JeYjxAvAfvt
|
||||
LoanBrokerID: 3CDEA7CEB9F2ECDD76CD41A864F4E3B5DB9C91AEDBD0906EE466FDD21CCF49B5
|
||||
Loan broker address: rKL3u76wNGdF2Th4EvCuHV5885T6h2iFTY
|
||||
Borrower address: r46Ef5jjnaY7CDP7g22sQgSJJPQEBSmbWA
|
||||
LoanBrokerID: F133118D55342F7F78188BDC9259E8593853010878C9F6CEA0E2F56D829C6B15
|
||||
|
||||
=== Preparing LoanSet transaction ===
|
||||
|
||||
{
|
||||
"TransactionType": "LoanSet",
|
||||
"Account": "rn6CD8i3Yc3UGagSosZfegG7hpXxwgVAgz",
|
||||
"Counterparty": "rN2PMxegkEMZHin78o7wSs1JeYjxAvAfvt",
|
||||
"LoanBrokerID": "3CDEA7CEB9F2ECDD76CD41A864F4E3B5DB9C91AEDBD0906EE466FDD21CCF49B5",
|
||||
"PrincipalRequested": "1000",
|
||||
"Account": "rKL3u76wNGdF2Th4EvCuHV5885T6h2iFTY",
|
||||
"Counterparty": "r46Ef5jjnaY7CDP7g22sQgSJJPQEBSmbWA",
|
||||
"LoanBrokerID": "F133118D55342F7F78188BDC9259E8593853010878C9F6CEA0E2F56D829C6B15",
|
||||
"PrincipalRequested": 1000,
|
||||
"InterestRate": 500,
|
||||
"PaymentTotal": 12,
|
||||
"PaymentInterval": 2592000,
|
||||
"GracePeriod": 604800,
|
||||
"LoanOriginationFee": "100",
|
||||
"LoanServiceFee": "10",
|
||||
"LoanOriginationFee": 100,
|
||||
"LoanServiceFee": 10,
|
||||
"Flags": 0,
|
||||
"Sequence": 3670743,
|
||||
"LastLedgerSequence": 3673248,
|
||||
"Sequence": 3212122,
|
||||
"LastLedgerSequence": 3212233,
|
||||
"Fee": "2"
|
||||
}
|
||||
|
||||
=== Adding loan broker signature ===
|
||||
|
||||
TxnSignature: F8B2F2AB960191991FC48120A48A089B479018A6469466E43E6F974E1345B32688D59D381E6BC18B6CA383235B708FE4FB44527C51E5B29BCDCC4A08C340A00A
|
||||
SigningPubKey: EDDABC72936FF734FA56D6C60C064D48C5DA9911C8B7C26C4AEAC06534B5D7C530
|
||||
TxnSignature: 44348B918E780608534A9499B9990470E6A3C8E5C7DAC33BF2A5EFA0C292D17B3267D3A177A363CC832D6C6DA36E41CB64909C39CA5D55CF36D232DA49022400
|
||||
SigningPubKey: ED37EF81218C3C97389A11F07C8339C2880CEAF1A8C6EB539C616D69EF5EBC688C
|
||||
|
||||
Signed loanSetTx for borrower to sign over:
|
||||
{
|
||||
"TransactionType": "LoanSet",
|
||||
"Flags": 0,
|
||||
"Sequence": 3670743,
|
||||
"LastLedgerSequence": 3673248,
|
||||
"PaymentInterval": 2592000,
|
||||
"GracePeriod": 604800,
|
||||
"PaymentTotal": 12,
|
||||
"InterestRate": 500,
|
||||
"LoanBrokerID": "3CDEA7CEB9F2ECDD76CD41A864F4E3B5DB9C91AEDBD0906EE466FDD21CCF49B5",
|
||||
"Account": "rKL3u76wNGdF2Th4EvCuHV5885T6h2iFTY",
|
||||
"Counterparty": "r46Ef5jjnaY7CDP7g22sQgSJJPQEBSmbWA",
|
||||
"Fee": "2",
|
||||
"SigningPubKey": "EDDABC72936FF734FA56D6C60C064D48C5DA9911C8B7C26C4AEAC06534B5D7C530",
|
||||
"TxnSignature": "F8B2F2AB960191991FC48120A48A089B479018A6469466E43E6F974E1345B32688D59D381E6BC18B6CA383235B708FE4FB44527C51E5B29BCDCC4A08C340A00A",
|
||||
"Account": "rn6CD8i3Yc3UGagSosZfegG7hpXxwgVAgz",
|
||||
"Counterparty": "rN2PMxegkEMZHin78o7wSs1JeYjxAvAfvt",
|
||||
"Flags": 0,
|
||||
"GracePeriod": 604800,
|
||||
"InterestRate": 500,
|
||||
"LastLedgerSequence": 3212233,
|
||||
"LoanBrokerID": "F133118D55342F7F78188BDC9259E8593853010878C9F6CEA0E2F56D829C6B15",
|
||||
"LoanOriginationFee": "100",
|
||||
"LoanServiceFee": "10",
|
||||
"PrincipalRequested": "1000"
|
||||
"PaymentInterval": 2592000,
|
||||
"PaymentTotal": 12,
|
||||
"PrincipalRequested": "1000",
|
||||
"Sequence": 3212122,
|
||||
"SigningPubKey": "ED37EF81218C3C97389A11F07C8339C2880CEAF1A8C6EB539C616D69EF5EBC688C",
|
||||
"TransactionType": "LoanSet",
|
||||
"TxnSignature": "44348B918E780608534A9499B9990470E6A3C8E5C7DAC33BF2A5EFA0C292D17B3267D3A177A363CC832D6C6DA36E41CB64909C39CA5D55CF36D232DA49022400"
|
||||
}
|
||||
|
||||
=== Adding borrower signature ===
|
||||
|
||||
Borrower TxnSignature: 52E16B88F5640F637A05E59AB2BE0DBFE4FBE7F1D7580C2A39D4981F6066A7C42047A401B953CDAB4993954A85D73DE35F69317EE8279D23ECB4958AA10C0800
|
||||
Borrower SigningPubKey: EDE624A07899AEF826DF2A3E2A325F69BC1F169D23F08091E9042644D6B06D3D62
|
||||
Borrower TxnSignature: 2D17F5BAED2540CD875B009A99B02649E24A5DCDFDC5BAFCB2DC41F998FE4AFBDD6BDF8BDF1C3C857ED8DD638F10BEA10295812155D9759E3ADED9D6208F150F
|
||||
Borrower SigningPubKey: ED4C7C0127EFEAFD04B2CDFA1CA3A8EF5933227C610031DF2130010B73CBBBDCDA
|
||||
|
||||
Fully signed LoanSet transaction:
|
||||
{
|
||||
"TransactionType": "LoanSet",
|
||||
"Flags": 0,
|
||||
"Sequence": 3670743,
|
||||
"LastLedgerSequence": 3673248,
|
||||
"PaymentInterval": 2592000,
|
||||
"GracePeriod": 604800,
|
||||
"PaymentTotal": 12,
|
||||
"InterestRate": 500,
|
||||
"LoanBrokerID": "3CDEA7CEB9F2ECDD76CD41A864F4E3B5DB9C91AEDBD0906EE466FDD21CCF49B5",
|
||||
"Account": "rKL3u76wNGdF2Th4EvCuHV5885T6h2iFTY",
|
||||
"Counterparty": "r46Ef5jjnaY7CDP7g22sQgSJJPQEBSmbWA",
|
||||
"CounterpartySignature": {
|
||||
"SigningPubKey": "ED4C7C0127EFEAFD04B2CDFA1CA3A8EF5933227C610031DF2130010B73CBBBDCDA",
|
||||
"TxnSignature": "2D17F5BAED2540CD875B009A99B02649E24A5DCDFDC5BAFCB2DC41F998FE4AFBDD6BDF8BDF1C3C857ED8DD638F10BEA10295812155D9759E3ADED9D6208F150F"
|
||||
},
|
||||
"Fee": "2",
|
||||
"SigningPubKey": "EDDABC72936FF734FA56D6C60C064D48C5DA9911C8B7C26C4AEAC06534B5D7C530",
|
||||
"TxnSignature": "F8B2F2AB960191991FC48120A48A089B479018A6469466E43E6F974E1345B32688D59D381E6BC18B6CA383235B708FE4FB44527C51E5B29BCDCC4A08C340A00A",
|
||||
"Account": "rn6CD8i3Yc3UGagSosZfegG7hpXxwgVAgz",
|
||||
"Counterparty": "rN2PMxegkEMZHin78o7wSs1JeYjxAvAfvt",
|
||||
"Flags": 0,
|
||||
"GracePeriod": 604800,
|
||||
"InterestRate": 500,
|
||||
"LastLedgerSequence": 3212233,
|
||||
"LoanBrokerID": "F133118D55342F7F78188BDC9259E8593853010878C9F6CEA0E2F56D829C6B15",
|
||||
"LoanOriginationFee": "100",
|
||||
"LoanServiceFee": "10",
|
||||
"PaymentInterval": 2592000,
|
||||
"PaymentTotal": 12,
|
||||
"PrincipalRequested": "1000",
|
||||
"CounterpartySignature": {
|
||||
"SigningPubKey": "EDE624A07899AEF826DF2A3E2A325F69BC1F169D23F08091E9042644D6B06D3D62",
|
||||
"TxnSignature": "52E16B88F5640F637A05E59AB2BE0DBFE4FBE7F1D7580C2A39D4981F6066A7C42047A401B953CDAB4993954A85D73DE35F69317EE8279D23ECB4958AA10C0800"
|
||||
}
|
||||
"Sequence": 3212122,
|
||||
"SigningPubKey": "ED37EF81218C3C97389A11F07C8339C2880CEAF1A8C6EB539C616D69EF5EBC688C",
|
||||
"TransactionType": "LoanSet",
|
||||
"TxnSignature": "44348B918E780608534A9499B9990470E6A3C8E5C7DAC33BF2A5EFA0C292D17B3267D3A177A363CC832D6C6DA36E41CB64909C39CA5D55CF36D232DA49022400"
|
||||
}
|
||||
|
||||
=== Submitting signed LoanSet transaction ===
|
||||
@@ -264,19 +264,19 @@ Loan created successfully!
|
||||
=== Loan Information ===
|
||||
|
||||
{
|
||||
"Borrower": "rN2PMxegkEMZHin78o7wSs1JeYjxAvAfvt",
|
||||
"Borrower": "r46Ef5jjnaY7CDP7g22sQgSJJPQEBSmbWA",
|
||||
"GracePeriod": 604800,
|
||||
"InterestRate": 500,
|
||||
"LoanBrokerID": "3CDEA7CEB9F2ECDD76CD41A864F4E3B5DB9C91AEDBD0906EE466FDD21CCF49B5",
|
||||
"LoanBrokerID": "F133118D55342F7F78188BDC9259E8593853010878C9F6CEA0E2F56D829C6B15",
|
||||
"LoanOriginationFee": "100",
|
||||
"LoanSequence": 6,
|
||||
"LoanSequence": 3,
|
||||
"LoanServiceFee": "10",
|
||||
"NextPaymentDueDate": 826862960,
|
||||
"NextPaymentDueDate": 825408182,
|
||||
"PaymentInterval": 2592000,
|
||||
"PaymentRemaining": 12,
|
||||
"PeriodicPayment": "83.55610375293148956",
|
||||
"PrincipalOutstanding": "1000",
|
||||
"StartDate": 824270960,
|
||||
"StartDate": 822816182,
|
||||
"TotalValueOutstanding": "1003"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -41,42 +41,77 @@ const loanSetTx = await client.autofill({
|
||||
Account: loanBroker.address,
|
||||
Counterparty: borrower.address,
|
||||
LoanBrokerID: loanBrokerID,
|
||||
PrincipalRequested: '1000',
|
||||
PrincipalRequested: 1000,
|
||||
InterestRate: 500,
|
||||
PaymentTotal: 12,
|
||||
PaymentInterval: 2592000,
|
||||
GracePeriod: 604800,
|
||||
LoanOriginationFee: '100',
|
||||
LoanServiceFee: '10'
|
||||
LoanOriginationFee: 100,
|
||||
LoanServiceFee: 10
|
||||
})
|
||||
|
||||
console.log(JSON.stringify(loanSetTx, null, 2))
|
||||
|
||||
// Loan broker signs first
|
||||
console.log(`\n=== Adding loan broker signature ===\n`)
|
||||
const loanBrokerSigned = loanBroker.sign(loanSetTx)
|
||||
const loanBrokerSignedTx = xrpl.decode(loanBrokerSigned.tx_blob)
|
||||
const loanBrokerSignature = await client.request({
|
||||
command: 'sign',
|
||||
tx_json: loanSetTx,
|
||||
secret: loanBroker.seed
|
||||
})
|
||||
|
||||
console.log(`TxnSignature: ${loanBrokerSignedTx.TxnSignature}`)
|
||||
console.log(`SigningPubKey: ${loanBrokerSignedTx.SigningPubKey}\n`)
|
||||
console.log(`Signed loanSetTx for borrower to sign over:\n${JSON.stringify(loanBrokerSignedTx, null, 2)}`)
|
||||
const loanBrokerSignatureResult = loanBrokerSignature.result.tx_json
|
||||
|
||||
console.log(`TxnSignature: ${loanBrokerSignatureResult.TxnSignature}`)
|
||||
console.log(`SigningPubKey: ${loanBrokerSignatureResult.SigningPubKey}\n`)
|
||||
console.log(`Signed loanSetTx for borrower to sign over:\n${JSON.stringify(loanBrokerSignatureResult, null, 2)}`)
|
||||
|
||||
// Borrower signs second
|
||||
console.log(`\n=== Adding borrower signature ===\n`)
|
||||
const fullySigned = xrpl.signLoanSetByCounterparty(borrower, loanBrokerSignedTx)
|
||||
|
||||
console.log(`Borrower TxnSignature: ${fullySigned.tx.CounterpartySignature.TxnSignature}`)
|
||||
console.log(`Borrower SigningPubKey: ${fullySigned.tx.CounterpartySignature.SigningPubKey}`)
|
||||
const borrowerSignature = await client.request({
|
||||
command: 'sign',
|
||||
tx_json: loanBrokerSignatureResult,
|
||||
secret: borrower.seed,
|
||||
signature_target: 'CounterpartySignature'
|
||||
})
|
||||
|
||||
const borrowerSignatureResult = borrowerSignature.result.tx_json
|
||||
|
||||
console.log(`Borrower TxnSignature: ${borrowerSignatureResult.CounterpartySignature.TxnSignature}`)
|
||||
console.log(`Borrower SigningPubKey: ${borrowerSignatureResult.CounterpartySignature.SigningPubKey}`)
|
||||
|
||||
// Validate the transaction structure before submitting.
|
||||
xrpl.validate(fullySigned.tx)
|
||||
console.log(`\nFully signed LoanSet transaction:\n${JSON.stringify(fullySigned.tx, null, 2)}`)
|
||||
xrpl.validate(borrowerSignatureResult)
|
||||
console.log(`\nFully signed LoanSet transaction:\n${JSON.stringify(borrowerSignatureResult, null, 2)}`)
|
||||
|
||||
// Submit and wait for validation ----------------------
|
||||
console.log(`\n=== Submitting signed LoanSet transaction ===\n`)
|
||||
|
||||
const submitResponse = await client.submitAndWait(fullySigned.tx)
|
||||
// Submit the transaction
|
||||
const submitResult = await client.submit(borrowerSignatureResult)
|
||||
const txHash = submitResult.result.tx_json.hash
|
||||
|
||||
// Helper function to check tx hash is validated
|
||||
async function validateTx (hash, maxRetries = 20) {
|
||||
for (let i = 0; i < maxRetries; i++) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
try {
|
||||
const tx = await client.request({ command: 'tx', transaction: hash })
|
||||
if (tx.result.validated) {
|
||||
return tx
|
||||
}
|
||||
} catch (error) {
|
||||
// Transaction not validated yet, check again
|
||||
}
|
||||
}
|
||||
console.error(`Error: Transaction ${hash} not validated after ${maxRetries} attempts.`)
|
||||
await client.disconnect()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Validate the transaction
|
||||
const submitResponse = await validateTx(txHash)
|
||||
if (submitResponse.result.meta.TransactionResult !== 'tesSUCCESS') {
|
||||
const resultCode = submitResponse.result.meta.TransactionResult
|
||||
console.error('Error: Unable to create loan:', resultCode)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Setup script for lending protocol tutorials
|
||||
|
||||
import xrpl from 'xrpl'
|
||||
import fs from 'fs'
|
||||
|
||||
// Setup script for lending protocol tutorials
|
||||
|
||||
process.stdout.write('Setting up tutorial: 0/6\r')
|
||||
|
||||
const client = new xrpl.Client('wss://s.devnet.rippletest.net:51233')
|
||||
@@ -262,35 +262,73 @@ process.stdout.write('Setting up tutorial: 5/6\r')
|
||||
// Suppress unnecessary console warning from autofilling LoanSet.
|
||||
console.warn = () => {}
|
||||
|
||||
// Helper function to create, sign, and submit a LoanSet transaction
|
||||
async function createLoan (ticketSequence) {
|
||||
// Helper function to create and sign a LoanSet transaction
|
||||
async function createSignedLoanSetTx (ticketSequence) {
|
||||
const loanSetTx = await client.autofill({
|
||||
TransactionType: 'LoanSet',
|
||||
Account: loanBroker.address,
|
||||
Counterparty: borrower.address,
|
||||
LoanBrokerID: loanBrokerID,
|
||||
PrincipalRequested: '1000',
|
||||
PrincipalRequested: 1000,
|
||||
InterestRate: 500,
|
||||
PaymentTotal: 1,
|
||||
PaymentInterval: 2592000,
|
||||
LoanOriginationFee: '100',
|
||||
LoanServiceFee: '10',
|
||||
LoanOriginationFee: 100,
|
||||
LoanServiceFee: 10,
|
||||
Sequence: 0,
|
||||
TicketSequence: ticketSequence
|
||||
})
|
||||
|
||||
const loanBrokerSigned = loanBroker.sign(loanSetTx)
|
||||
const loanBrokerSignedTx = xrpl.decode(loanBrokerSigned.tx_blob)
|
||||
const loanBrokerSignature = await client.request({
|
||||
command: 'sign',
|
||||
tx_json: loanSetTx,
|
||||
secret: loanBroker.seed
|
||||
})
|
||||
|
||||
const fullySigned = xrpl.signLoanSetByCounterparty(borrower, loanBrokerSignedTx)
|
||||
const submitResponse = await client.submitAndWait(fullySigned.tx)
|
||||
const borrowerSignature = await client.request({
|
||||
command: 'sign',
|
||||
tx_json: loanBrokerSignature.result.tx_json,
|
||||
secret: borrower.seed,
|
||||
signature_target: 'CounterpartySignature'
|
||||
})
|
||||
|
||||
return submitResponse
|
||||
return borrowerSignature.result.tx_json
|
||||
}
|
||||
|
||||
// Create and submit both loans
|
||||
const [signedLoan1, signedLoan2] = await Promise.all([
|
||||
createSignedLoanSetTx(tickets[0]),
|
||||
createSignedLoanSetTx(tickets[1])
|
||||
])
|
||||
|
||||
const [submitLoan1, submitLoan2] = await Promise.all([
|
||||
client.submit(signedLoan1),
|
||||
client.submit(signedLoan2)
|
||||
])
|
||||
const hash1 = submitLoan1.result.tx_json.hash
|
||||
const hash2 = submitLoan2.result.tx_json.hash
|
||||
|
||||
// Helper function to check tx hash is validated
|
||||
async function validateTx (hash, maxRetries = 20) {
|
||||
for (let i = 0; i < maxRetries; i++) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
try {
|
||||
const tx = await client.request({ command: 'tx', transaction: hash })
|
||||
if (tx.result.validated) {
|
||||
return tx
|
||||
}
|
||||
} catch (error) {
|
||||
// Transaction not validated yet, check again
|
||||
}
|
||||
}
|
||||
console.error(`Error: Transaction ${hash} not validated after ${maxRetries} attempts.`)
|
||||
await client.disconnect()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const [submitResponse1, submitResponse2] = await Promise.all([
|
||||
createLoan(tickets[0]),
|
||||
createLoan(tickets[1])
|
||||
validateTx(hash1),
|
||||
validateTx(hash2)
|
||||
])
|
||||
|
||||
const loanID1 = submitResponse1.result.meta.AffectedNodes.find(node =>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "lending-protocol-examples",
|
||||
"description": "Example code for creating and managing loans.",
|
||||
"dependencies": {
|
||||
"xrpl": "^4.6.0"
|
||||
"xrpl": "^4.5.0"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
||||
@@ -1,403 +0,0 @@
|
||||
# Lending Protocol Examples (Python)
|
||||
|
||||
This directory contains Python examples demonstrating how to create a loan broker, claw back first-loss capital, deposit and withdraw first-loss capital, create a loan, manage a loan, and repay a loan.
|
||||
|
||||
## Setup
|
||||
|
||||
Install dependencies before running any examples:
|
||||
|
||||
```sh
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Create a Loan Broker
|
||||
|
||||
```sh
|
||||
python3 create_loan_broker.py
|
||||
```
|
||||
|
||||
The script should output the LoanBrokerSet transaction, loan broker ID, and loan broker pseudo-account:
|
||||
|
||||
```sh
|
||||
Loan broker/vault owner address: rBeEX3qQzP3UL5WMwZAzdPPpzckH73YvBn
|
||||
Vault ID: 2B71E8E1323BFC8F2AC27F8C217870B63921EFA0C02DF7BA8B099C7DC6A1D00F
|
||||
|
||||
=== Preparing LoanBrokerSet transaction ===
|
||||
|
||||
{
|
||||
"Account": "rBeEX3qQzP3UL5WMwZAzdPPpzckH73YvBn",
|
||||
"TransactionType": "LoanBrokerSet",
|
||||
"SigningPubKey": "",
|
||||
"VaultID": "2B71E8E1323BFC8F2AC27F8C217870B63921EFA0C02DF7BA8B099C7DC6A1D00F",
|
||||
"ManagementFeeRate": 1000
|
||||
}
|
||||
|
||||
=== Submitting LoanBrokerSet transaction ===
|
||||
|
||||
Loan broker created successfully!
|
||||
|
||||
=== Loan Broker Information ===
|
||||
|
||||
LoanBroker ID: 86911896026EA9DEAEFC1A7959BC05D8B1A1EC25B9960E8C54424B7DC41F8DA8
|
||||
LoanBroker Psuedo-Account Address: rPhpC2XGz7v5g2rPom7JSWJcic1cnkoBh9
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Claw Back First-loss Capital
|
||||
|
||||
```sh
|
||||
python3 cover_clawback.py
|
||||
```
|
||||
|
||||
The script should output the cover available, the LoanBrokerCoverDeposit transaction, cover available after the deposit, the LoanBrokerCoverClawback transaction, and the final cover available after the clawback:
|
||||
|
||||
```sh
|
||||
Loan broker address: rBeEX3qQzP3UL5WMwZAzdPPpzckH73YvBn
|
||||
MPT issuer address: rNzJg2EVwo56eAoBxz5WnTfmgoLbfaAT8d
|
||||
LoanBrokerID: 041E256F124841FF81DF105C62A72676BFD746975F86786166B689F304BE96E0
|
||||
MPT ID: 0037A8ED99701AFEC4BCC3A39299252CA41838059572E7F2
|
||||
|
||||
=== Cover Available ===
|
||||
|
||||
1000 TSTUSD
|
||||
|
||||
=== Preparing LoanBrokerCoverDeposit transaction ===
|
||||
|
||||
{
|
||||
"Account": "rBeEX3qQzP3UL5WMwZAzdPPpzckH73YvBn",
|
||||
"TransactionType": "LoanBrokerCoverDeposit",
|
||||
"SigningPubKey": "",
|
||||
"LoanBrokerID": "041E256F124841FF81DF105C62A72676BFD746975F86786166B689F304BE96E0",
|
||||
"Amount": {
|
||||
"mpt_issuance_id": "0037A8ED99701AFEC4BCC3A39299252CA41838059572E7F2",
|
||||
"value": "1000"
|
||||
}
|
||||
}
|
||||
|
||||
=== Submitting LoanBrokerCoverDeposit transaction ===
|
||||
|
||||
Cover deposit successful!
|
||||
|
||||
=== Cover Available After Deposit ===
|
||||
|
||||
2000 TSTUSD
|
||||
|
||||
=== Verifying Asset Issuer ===
|
||||
|
||||
MPT issuer account verified: rNzJg2EVwo56eAoBxz5WnTfmgoLbfaAT8d. Proceeding to clawback.
|
||||
|
||||
=== Preparing LoanBrokerCoverClawback transaction ===
|
||||
|
||||
{
|
||||
"Account": "rNzJg2EVwo56eAoBxz5WnTfmgoLbfaAT8d",
|
||||
"TransactionType": "LoanBrokerCoverClawback",
|
||||
"SigningPubKey": "",
|
||||
"LoanBrokerID": "041E256F124841FF81DF105C62A72676BFD746975F86786166B689F304BE96E0",
|
||||
"Amount": {
|
||||
"mpt_issuance_id": "0037A8ED99701AFEC4BCC3A39299252CA41838059572E7F2",
|
||||
"value": "2000"
|
||||
}
|
||||
}
|
||||
|
||||
=== Submitting LoanBrokerCoverClawback transaction ===
|
||||
|
||||
Successfully clawed back 2000 TSTUSD!
|
||||
|
||||
=== Final Cover Available After Clawback ===
|
||||
|
||||
0 TSTUSD
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deposit and Withdraw First-loss Capital
|
||||
|
||||
```sh
|
||||
python3 cover_deposit_and_withdraw.py
|
||||
```
|
||||
|
||||
The script should output the LoanBrokerCoverDeposit, cover balance after the deposit, the LoanBrokerCoverWithdraw transaction, and the cover balance after the withdrawal:
|
||||
|
||||
```sh
|
||||
Loan broker address: rBeEX3qQzP3UL5WMwZAzdPPpzckH73YvBn
|
||||
LoanBrokerID: 041E256F124841FF81DF105C62A72676BFD746975F86786166B689F304BE96E0
|
||||
MPT ID: 0037A8ED99701AFEC4BCC3A39299252CA41838059572E7F2
|
||||
|
||||
=== Preparing LoanBrokerCoverDeposit transaction ===
|
||||
|
||||
{
|
||||
"Account": "rBeEX3qQzP3UL5WMwZAzdPPpzckH73YvBn",
|
||||
"TransactionType": "LoanBrokerCoverDeposit",
|
||||
"SigningPubKey": "",
|
||||
"LoanBrokerID": "041E256F124841FF81DF105C62A72676BFD746975F86786166B689F304BE96E0",
|
||||
"Amount": {
|
||||
"mpt_issuance_id": "0037A8ED99701AFEC4BCC3A39299252CA41838059572E7F2",
|
||||
"value": "2000"
|
||||
}
|
||||
}
|
||||
|
||||
=== Submitting LoanBrokerCoverDeposit transaction ===
|
||||
|
||||
Cover deposit successful!
|
||||
|
||||
=== Cover Balance ===
|
||||
|
||||
LoanBroker Pseudo-Account: rUrs1bkhQyh1nxE7u99H92U2Tg8Pogw1bZ
|
||||
Cover balance after deposit: 2000 TSTUSD
|
||||
|
||||
=== Preparing LoanBrokerCoverWithdraw transaction ===
|
||||
|
||||
{
|
||||
"Account": "rBeEX3qQzP3UL5WMwZAzdPPpzckH73YvBn",
|
||||
"TransactionType": "LoanBrokerCoverWithdraw",
|
||||
"SigningPubKey": "",
|
||||
"LoanBrokerID": "041E256F124841FF81DF105C62A72676BFD746975F86786166B689F304BE96E0",
|
||||
"Amount": {
|
||||
"mpt_issuance_id": "0037A8ED99701AFEC4BCC3A39299252CA41838059572E7F2",
|
||||
"value": "1000"
|
||||
}
|
||||
}
|
||||
|
||||
=== Submitting LoanBrokerCoverWithdraw transaction ===
|
||||
|
||||
Cover withdraw successful!
|
||||
|
||||
=== Updated Cover Balance ===
|
||||
|
||||
LoanBroker Pseudo-Account: rUrs1bkhQyh1nxE7u99H92U2Tg8Pogw1bZ
|
||||
Cover balance after withdraw: 1000 TSTUSD
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Create a Loan
|
||||
|
||||
```sh
|
||||
python3 create_loan.py
|
||||
```
|
||||
|
||||
The script should output the LoanSet transaction, the updated LoanSet transaction with the loan broker signature, the final LoanSet transaction with the borrower signature added, and then the loan information:
|
||||
|
||||
```sh
|
||||
Loan broker address: ra3aoaincCNBQ7uxvHDgFbtCbVw1VNQkZy
|
||||
Borrower address: raXnMyDFQWVhvVuyb2oK3oCLGZhemkLqKL
|
||||
LoanBrokerID: 61A1D6B0F019C5D5BD039AC3DBE2E31813471567854D07D278564E4E2463ABD2
|
||||
|
||||
=== Preparing LoanSet transaction ===
|
||||
|
||||
{
|
||||
"Account": "ra3aoaincCNBQ7uxvHDgFbtCbVw1VNQkZy",
|
||||
"TransactionType": "LoanSet",
|
||||
"Fee": "2",
|
||||
"Sequence": 3652181,
|
||||
"LastLedgerSequence": 3674792,
|
||||
"SigningPubKey": "",
|
||||
"LoanBrokerID": "61A1D6B0F019C5D5BD039AC3DBE2E31813471567854D07D278564E4E2463ABD2",
|
||||
"Counterparty": "raXnMyDFQWVhvVuyb2oK3oCLGZhemkLqKL",
|
||||
"LoanOriginationFee": "100",
|
||||
"LoanServiceFee": "10",
|
||||
"InterestRate": 500,
|
||||
"PrincipalRequested": "1000",
|
||||
"PaymentTotal": 12,
|
||||
"PaymentInterval": 2592000,
|
||||
"GracePeriod": 604800
|
||||
}
|
||||
|
||||
=== Adding loan broker signature ===
|
||||
|
||||
TxnSignature: 9756E70F33B359FAEA789D732E752401DE41CAB1A3711517B576DBFF4D89B6A01C234A379391C48B3D88CB031BD679A7EDE4F4BB67AA7297EEE25EA29FF6BD0D
|
||||
SigningPubKey: ED0DC8C222C4BB86CE07165CD0486C598B8146C3150EE40AF48921983DED98FA47
|
||||
|
||||
Signed loan_set_tx for borrower to sign over:
|
||||
{
|
||||
"Account": "ra3aoaincCNBQ7uxvHDgFbtCbVw1VNQkZy",
|
||||
"TransactionType": "LoanSet",
|
||||
"Fee": "2",
|
||||
"Sequence": 3652181,
|
||||
"LastLedgerSequence": 3674792,
|
||||
"SigningPubKey": "ED0DC8C222C4BB86CE07165CD0486C598B8146C3150EE40AF48921983DED98FA47",
|
||||
"TxnSignature": "9756E70F33B359FAEA789D732E752401DE41CAB1A3711517B576DBFF4D89B6A01C234A379391C48B3D88CB031BD679A7EDE4F4BB67AA7297EEE25EA29FF6BD0D",
|
||||
"LoanBrokerID": "61A1D6B0F019C5D5BD039AC3DBE2E31813471567854D07D278564E4E2463ABD2",
|
||||
"Counterparty": "raXnMyDFQWVhvVuyb2oK3oCLGZhemkLqKL",
|
||||
"LoanOriginationFee": "100",
|
||||
"LoanServiceFee": "10",
|
||||
"InterestRate": 500,
|
||||
"PrincipalRequested": "1000",
|
||||
"PaymentTotal": 12,
|
||||
"PaymentInterval": 2592000,
|
||||
"GracePeriod": 604800
|
||||
}
|
||||
|
||||
=== Adding borrower signature ===
|
||||
|
||||
Borrower TxnSignature: A0A515BFB131EDC7A8B74F7A66F9DA1DEE25B099373F581BDA340C95F918CEA91E3F4D2019A8DBAFEC53012038839FEA48436D61970B0834F6DDEA64B1776207
|
||||
Borrower SigningPubKey: ED36B94636EC0F98BB5F6EC58039E23A8C8F1521D2EC1B32C0422A86718C9B95DC
|
||||
|
||||
Fully signed LoanSet transaction:
|
||||
{
|
||||
"Account": "ra3aoaincCNBQ7uxvHDgFbtCbVw1VNQkZy",
|
||||
"TransactionType": "LoanSet",
|
||||
"Fee": "2",
|
||||
"Sequence": 3652181,
|
||||
"LastLedgerSequence": 3674792,
|
||||
"SigningPubKey": "ED0DC8C222C4BB86CE07165CD0486C598B8146C3150EE40AF48921983DED98FA47",
|
||||
"TxnSignature": "9756E70F33B359FAEA789D732E752401DE41CAB1A3711517B576DBFF4D89B6A01C234A379391C48B3D88CB031BD679A7EDE4F4BB67AA7297EEE25EA29FF6BD0D",
|
||||
"LoanBrokerID": "61A1D6B0F019C5D5BD039AC3DBE2E31813471567854D07D278564E4E2463ABD2",
|
||||
"Counterparty": "raXnMyDFQWVhvVuyb2oK3oCLGZhemkLqKL",
|
||||
"CounterpartySignature": {
|
||||
"SigningPubKey": "ED36B94636EC0F98BB5F6EC58039E23A8C8F1521D2EC1B32C0422A86718C9B95DC",
|
||||
"TxnSignature": "A0A515BFB131EDC7A8B74F7A66F9DA1DEE25B099373F581BDA340C95F918CEA91E3F4D2019A8DBAFEC53012038839FEA48436D61970B0834F6DDEA64B1776207"
|
||||
},
|
||||
"LoanOriginationFee": "100",
|
||||
"LoanServiceFee": "10",
|
||||
"InterestRate": 500,
|
||||
"PrincipalRequested": "1000",
|
||||
"PaymentTotal": 12,
|
||||
"PaymentInterval": 2592000,
|
||||
"GracePeriod": 604800
|
||||
}
|
||||
|
||||
=== Submitting signed LoanSet transaction ===
|
||||
|
||||
Loan created successfully!
|
||||
|
||||
=== Loan Information ===
|
||||
|
||||
{
|
||||
"Borrower": "raXnMyDFQWVhvVuyb2oK3oCLGZhemkLqKL",
|
||||
"GracePeriod": 604800,
|
||||
"InterestRate": 500,
|
||||
"LoanBrokerID": "61A1D6B0F019C5D5BD039AC3DBE2E31813471567854D07D278564E4E2463ABD2",
|
||||
"LoanOriginationFee": "100",
|
||||
"LoanSequence": 4,
|
||||
"LoanServiceFee": "10",
|
||||
"NextPaymentDueDate": 826867870,
|
||||
"PaymentInterval": 2592000,
|
||||
"PaymentRemaining": 12,
|
||||
"PeriodicPayment": "83.55610375293148956",
|
||||
"PrincipalOutstanding": "1000",
|
||||
"StartDate": 824275870,
|
||||
"TotalValueOutstanding": "1003"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Manage a Loan
|
||||
|
||||
```sh
|
||||
python3 loan_manage.py
|
||||
```
|
||||
|
||||
The script should output the initial status of the loan, the LoanManage transaction, and the updated loan status and grace period after impairment. The script will countdown the grace period before outputting another LoanManage transaction, and then the final flags on the loan.
|
||||
|
||||
```sh
|
||||
Loan broker address: r9x3etrs2GZSF73vQ8endi9CWpKr5N2Rjn
|
||||
LoanID: E86DB385401D361A33DD74C8E1B44D7F996E9BA02724BCD44127F60BE057A322
|
||||
|
||||
=== Loan Status ===
|
||||
|
||||
Total Amount Owed: 1001 TSTUSD.
|
||||
Payment Due Date: 2026-03-14 02:01:51
|
||||
|
||||
=== Preparing LoanManage transaction to impair loan ===
|
||||
|
||||
{
|
||||
"Account": "r9x3etrs2GZSF73vQ8endi9CWpKr5N2Rjn",
|
||||
"TransactionType": "LoanManage",
|
||||
"Flags": 131072,
|
||||
"SigningPubKey": "",
|
||||
"LoanID": "E86DB385401D361A33DD74C8E1B44D7F996E9BA02724BCD44127F60BE057A322"
|
||||
}
|
||||
|
||||
=== Submitting LoanManage impairment transaction ===
|
||||
|
||||
Loan impaired successfully!
|
||||
New Payment Due Date: 2026-02-12 01:01:50
|
||||
Grace Period: 60 seconds
|
||||
|
||||
=== Countdown until loan can be defaulted ===
|
||||
|
||||
Grace period expired. Loan can now be defaulted.
|
||||
|
||||
=== Preparing LoanManage transaction to default loan ===
|
||||
|
||||
{
|
||||
"Account": "r9x3etrs2GZSF73vQ8endi9CWpKr5N2Rjn",
|
||||
"TransactionType": "LoanManage",
|
||||
"Flags": 65536,
|
||||
"SigningPubKey": "",
|
||||
"LoanID": "E86DB385401D361A33DD74C8E1B44D7F996E9BA02724BCD44127F60BE057A322"
|
||||
}
|
||||
|
||||
=== Submitting LoanManage default transaction ===
|
||||
|
||||
Loan defaulted successfully!
|
||||
|
||||
=== Checking final loan status ===
|
||||
|
||||
Final loan flags: ['TF_LOAN_DEFAULT', 'TF_LOAN_IMPAIR']
|
||||
```
|
||||
|
||||
## Pay a Loan
|
||||
|
||||
```sh
|
||||
python3 loan_pay.py
|
||||
```
|
||||
|
||||
The script should output the amount required to totally pay off a loan, the LoanPay transaction, the amount due after the payment, the LoanDelete transaction, and then the status of the loan ledger entry:
|
||||
|
||||
```sh
|
||||
Borrower address: raXnMyDFQWVhvVuyb2oK3oCLGZhemkLqKL
|
||||
LoanID: A9CC92540995E49B39E79883A22FF10A374BF2CB32763E89AA986B613E16D5FD
|
||||
MPT ID: 0037BA4C909352D28BF9580F1D536AF4F7E07649B5B6E116
|
||||
|
||||
=== Loan Status ===
|
||||
|
||||
Amount Owed: 1001 TSTUSD
|
||||
Loan Service Fee: 10 TSTUSD
|
||||
Total Payment Due (including fees): 1011 TSTUSD
|
||||
|
||||
=== Preparing LoanPay transaction ===
|
||||
|
||||
{
|
||||
"Account": "raXnMyDFQWVhvVuyb2oK3oCLGZhemkLqKL",
|
||||
"TransactionType": "LoanPay",
|
||||
"SigningPubKey": "",
|
||||
"LoanID": "A9CC92540995E49B39E79883A22FF10A374BF2CB32763E89AA986B613E16D5FD",
|
||||
"Amount": {
|
||||
"mpt_issuance_id": "0037BA4C909352D28BF9580F1D536AF4F7E07649B5B6E116",
|
||||
"value": "1011"
|
||||
}
|
||||
}
|
||||
|
||||
=== Submitting LoanPay transaction ===
|
||||
|
||||
Loan paid successfully!
|
||||
|
||||
=== Loan Status After Payment ===
|
||||
|
||||
Outstanding Loan Balance: Loan fully paid off!
|
||||
|
||||
=== Preparing LoanDelete transaction ===
|
||||
|
||||
{
|
||||
"Account": "raXnMyDFQWVhvVuyb2oK3oCLGZhemkLqKL",
|
||||
"TransactionType": "LoanDelete",
|
||||
"SigningPubKey": "",
|
||||
"LoanID": "A9CC92540995E49B39E79883A22FF10A374BF2CB32763E89AA986B613E16D5FD"
|
||||
}
|
||||
|
||||
=== Submitting LoanDelete transaction ===
|
||||
|
||||
Loan deleted successfully!
|
||||
|
||||
=== Verifying Loan Deletion ===
|
||||
|
||||
Loan has been successfully removed from the XRP Ledger!
|
||||
```
|
||||
@@ -1,124 +0,0 @@
|
||||
# IMPORTANT: This example deposits and claws back first-loss capital from a
|
||||
# preconfigured LoanBroker entry. The first-loss capital is an MPT
|
||||
# with clawback enabled.
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models import LedgerEntry, LoanBrokerCoverClawback, LoanBrokerCoverDeposit, MPTAmount
|
||||
from xrpl.transaction import submit_and_wait
|
||||
from xrpl.wallet import Wallet
|
||||
|
||||
# Set up client ----------------------
|
||||
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
||||
|
||||
# This step checks for the necessary setup data to run the lending protocol tutorials.
|
||||
# If missing, lending_setup.py will generate the data.
|
||||
if not os.path.exists("lending_setup.json"):
|
||||
print("\n=== Lending tutorial data doesn't exist. Running setup script... ===\n")
|
||||
subprocess.run([sys.executable, "lending_setup.py"], check=True)
|
||||
|
||||
# Load preconfigured accounts, loan_broker_id, and mpt_id.
|
||||
with open("lending_setup.json") as f:
|
||||
setup_data = json.load(f)
|
||||
|
||||
# You can replace these values with your own.
|
||||
loan_broker = Wallet.from_seed(setup_data["loan_broker"]["seed"])
|
||||
mpt_issuer = Wallet.from_seed(setup_data["depositor"]["seed"])
|
||||
loan_broker_id = setup_data["loan_broker_id"]
|
||||
mpt_id = setup_data["mpt_id"]
|
||||
|
||||
print(f"\nLoan broker address: {loan_broker.address}")
|
||||
print(f"MPT issuer address: {mpt_issuer.address}")
|
||||
print(f"LoanBrokerID: {loan_broker_id}")
|
||||
print(f"MPT ID: {mpt_id}")
|
||||
|
||||
# Check cover available ----------------------
|
||||
print("\n=== Cover Available ===\n")
|
||||
cover_info = client.request(LedgerEntry(
|
||||
index=loan_broker_id,
|
||||
ledger_index="validated",
|
||||
))
|
||||
|
||||
current_cover_available = cover_info.result["node"].get("CoverAvailable", "0")
|
||||
print(f"{current_cover_available} TSTUSD")
|
||||
|
||||
# Prepare LoanBrokerCoverDeposit transaction ----------------------
|
||||
print("\n=== Preparing LoanBrokerCoverDeposit transaction ===\n")
|
||||
cover_deposit_tx = LoanBrokerCoverDeposit(
|
||||
account=loan_broker.address,
|
||||
loan_broker_id=loan_broker_id,
|
||||
amount=MPTAmount(mpt_issuance_id=mpt_id, value="1000"),
|
||||
)
|
||||
|
||||
print(json.dumps(cover_deposit_tx.to_xrpl(), indent=2))
|
||||
|
||||
# Sign, submit, and wait for deposit validation ----------------------
|
||||
print("\n=== Submitting LoanBrokerCoverDeposit transaction ===\n")
|
||||
deposit_response = submit_and_wait(cover_deposit_tx, client, loan_broker)
|
||||
|
||||
if deposit_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = deposit_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to deposit cover: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Cover deposit successful!")
|
||||
|
||||
# Extract updated cover available after deposit ----------------------
|
||||
print("\n=== Cover Available After Deposit ===\n")
|
||||
loan_broker_node = next(
|
||||
node for node in deposit_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("ModifiedNode", {}).get("LedgerEntryType") == "LoanBroker"
|
||||
)
|
||||
|
||||
current_cover_available = loan_broker_node["ModifiedNode"]["FinalFields"]["CoverAvailable"]
|
||||
print(f"{current_cover_available} TSTUSD")
|
||||
|
||||
# Verify issuer of cover asset matches ----------------------
|
||||
# Only the issuer of the asset can submit clawback transactions.
|
||||
# The asset must also have clawback enabled.
|
||||
print("\n=== Verifying Asset Issuer ===\n")
|
||||
asset_issuer_info = client.request(LedgerEntry(
|
||||
mpt_issuance=mpt_id,
|
||||
ledger_index="validated",
|
||||
))
|
||||
|
||||
if asset_issuer_info.result["node"]["Issuer"] != mpt_issuer.address:
|
||||
issuer = asset_issuer_info.result["node"]["Issuer"]
|
||||
print(f"Error: {issuer} does not match account ({mpt_issuer.address}) attempting clawback!")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"MPT issuer account verified: {mpt_issuer.address}. Proceeding to clawback.")
|
||||
|
||||
# Prepare LoanBrokerCoverClawback transaction ----------------------
|
||||
print("\n=== Preparing LoanBrokerCoverClawback transaction ===\n")
|
||||
cover_clawback_tx = LoanBrokerCoverClawback(
|
||||
account=mpt_issuer.address,
|
||||
loan_broker_id=loan_broker_id,
|
||||
amount=MPTAmount(mpt_issuance_id=mpt_id, value=current_cover_available),
|
||||
)
|
||||
|
||||
print(json.dumps(cover_clawback_tx.to_xrpl(), indent=2))
|
||||
|
||||
# Sign, submit, and wait for clawback validation ----------------------
|
||||
print("\n=== Submitting LoanBrokerCoverClawback transaction ===\n")
|
||||
clawback_response = submit_and_wait(cover_clawback_tx, client, mpt_issuer)
|
||||
|
||||
if clawback_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = clawback_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to clawback cover: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Successfully clawed back {current_cover_available} TSTUSD!")
|
||||
|
||||
# Extract final cover available ----------------------
|
||||
print("\n=== Final Cover Available After Clawback ===\n")
|
||||
loan_broker_node = next(
|
||||
node for node in clawback_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("ModifiedNode", {}).get("LedgerEntryType") == "LoanBroker"
|
||||
)
|
||||
|
||||
print(f"{loan_broker_node['ModifiedNode']['FinalFields'].get('CoverAvailable', '0')} TSTUSD")
|
||||
@@ -1,95 +0,0 @@
|
||||
# IMPORTANT: This example deposits and withdraws first-loss capital from a
|
||||
# preconfigured LoanBroker entry.
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models import LoanBrokerCoverDeposit, LoanBrokerCoverWithdraw, MPTAmount
|
||||
from xrpl.transaction import submit_and_wait
|
||||
from xrpl.wallet import Wallet
|
||||
|
||||
# Set up client ----------------------
|
||||
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
||||
|
||||
# This step checks for the necessary setup data to run the lending protocol tutorials.
|
||||
# If missing, lending_setup.py will generate the data.
|
||||
if not os.path.exists("lending_setup.json"):
|
||||
print("\n=== Lending tutorial data doesn't exist. Running setup script... ===\n")
|
||||
subprocess.run([sys.executable, "lending_setup.py"], check=True)
|
||||
|
||||
# Load preconfigured accounts and loan_broker_id.
|
||||
with open("lending_setup.json") as f:
|
||||
setup_data = json.load(f)
|
||||
|
||||
# You can replace these values with your own.
|
||||
loan_broker = Wallet.from_seed(setup_data["loan_broker"]["seed"])
|
||||
loan_broker_id = setup_data["loan_broker_id"]
|
||||
mpt_id = setup_data["mpt_id"]
|
||||
|
||||
print(f"\nLoan broker address: {loan_broker.address}")
|
||||
print(f"LoanBrokerID: {loan_broker_id}")
|
||||
print(f"MPT ID: {mpt_id}")
|
||||
|
||||
# Prepare LoanBrokerCoverDeposit transaction ----------------------
|
||||
print("\n=== Preparing LoanBrokerCoverDeposit transaction ===\n")
|
||||
cover_deposit_tx = LoanBrokerCoverDeposit(
|
||||
account=loan_broker.address,
|
||||
loan_broker_id=loan_broker_id,
|
||||
amount=MPTAmount(mpt_issuance_id=mpt_id, value="2000"),
|
||||
)
|
||||
|
||||
print(json.dumps(cover_deposit_tx.to_xrpl(), indent=2))
|
||||
|
||||
# Sign, submit, and wait for deposit validation ----------------------
|
||||
print("\n=== Submitting LoanBrokerCoverDeposit transaction ===\n")
|
||||
deposit_response = submit_and_wait(cover_deposit_tx, client, loan_broker)
|
||||
|
||||
if deposit_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = deposit_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to deposit cover: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Cover deposit successful!")
|
||||
|
||||
# Extract cover balance from the transaction result
|
||||
print("\n=== Cover Balance ===\n")
|
||||
loan_broker_node = next(
|
||||
node for node in deposit_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("ModifiedNode", {}).get("LedgerEntryType") == "LoanBroker"
|
||||
)
|
||||
# First-loss capital is stored in the LoanBroker's pseudo-account.
|
||||
print(f"LoanBroker Pseudo-Account: {loan_broker_node['ModifiedNode']['FinalFields']['Account']}")
|
||||
print(f"Cover balance after deposit: {loan_broker_node['ModifiedNode']['FinalFields']['CoverAvailable']} TSTUSD")
|
||||
|
||||
# Prepare LoanBrokerCoverWithdraw transaction ----------------------
|
||||
print("\n=== Preparing LoanBrokerCoverWithdraw transaction ===\n")
|
||||
cover_withdraw_tx = LoanBrokerCoverWithdraw(
|
||||
account=loan_broker.address,
|
||||
loan_broker_id=loan_broker_id,
|
||||
amount=MPTAmount(mpt_issuance_id=mpt_id, value="1000"),
|
||||
)
|
||||
|
||||
print(json.dumps(cover_withdraw_tx.to_xrpl(), indent=2))
|
||||
|
||||
# Sign, submit, and wait for withdraw validation ----------------------
|
||||
print("\n=== Submitting LoanBrokerCoverWithdraw transaction ===\n")
|
||||
withdraw_response = submit_and_wait(cover_withdraw_tx, client, loan_broker)
|
||||
|
||||
if withdraw_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = withdraw_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to withdraw cover: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Cover withdraw successful!")
|
||||
|
||||
# Extract updated cover balance from the transaction result
|
||||
print("\n=== Updated Cover Balance ===\n")
|
||||
loan_broker_node = next(
|
||||
node for node in withdraw_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("ModifiedNode", {}).get("LedgerEntryType") == "LoanBroker"
|
||||
)
|
||||
print(f"LoanBroker Pseudo-Account: {loan_broker_node['ModifiedNode']['FinalFields']['Account']}")
|
||||
print(f"Cover balance after withdraw: {loan_broker_node['ModifiedNode']['FinalFields']['CoverAvailable']} TSTUSD")
|
||||
@@ -1,89 +0,0 @@
|
||||
# IMPORTANT: This example creates a loan using a preconfigured
|
||||
# loan broker, borrower, and private vault.
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models import LoanSet
|
||||
from xrpl.transaction import autofill, sign, sign_loan_set_by_counterparty, submit_and_wait
|
||||
from xrpl.wallet import Wallet
|
||||
|
||||
# Set up client ----------------------
|
||||
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
||||
|
||||
# This step checks for the necessary setup data to run the lending protocol tutorials.
|
||||
# If missing, lending_setup.py will generate the data.
|
||||
if not os.path.exists("lending_setup.json"):
|
||||
print("\n=== Lending tutorial data doesn't exist. Running setup script... ===\n")
|
||||
subprocess.run([sys.executable, "lending_setup.py"], check=True)
|
||||
|
||||
# Load preconfigured accounts and loan_broker_id.
|
||||
with open("lending_setup.json") as f:
|
||||
setup_data = json.load(f)
|
||||
|
||||
# You can replace these values with your own.
|
||||
loan_broker = Wallet.from_seed(setup_data["loan_broker"]["seed"])
|
||||
borrower = Wallet.from_seed(setup_data["borrower"]["seed"])
|
||||
loan_broker_id = setup_data["loan_broker_id"]
|
||||
|
||||
print(f"\nLoan broker address: {loan_broker.address}")
|
||||
print(f"Borrower address: {borrower.address}")
|
||||
print(f"LoanBrokerID: {loan_broker_id}")
|
||||
|
||||
# Prepare LoanSet transaction ----------------------
|
||||
# Account and Counterparty accounts can be swapped, but determines signing order.
|
||||
# Account signs first, Counterparty signs second.
|
||||
print("\n=== Preparing LoanSet transaction ===\n")
|
||||
|
||||
loan_set_tx = autofill(LoanSet(
|
||||
account=loan_broker.address,
|
||||
counterparty=borrower.address,
|
||||
loan_broker_id=loan_broker_id,
|
||||
principal_requested="1000",
|
||||
interest_rate=500,
|
||||
payment_total=12,
|
||||
payment_interval=2592000,
|
||||
grace_period=604800,
|
||||
loan_origination_fee="100",
|
||||
loan_service_fee="10",
|
||||
), client)
|
||||
|
||||
print(json.dumps(loan_set_tx.to_xrpl(), indent=2))
|
||||
|
||||
# Loan broker signs first.
|
||||
print("\n=== Adding loan broker signature ===\n")
|
||||
loan_broker_signed = sign(loan_set_tx, loan_broker)
|
||||
|
||||
print(f"TxnSignature: {loan_broker_signed.txn_signature}")
|
||||
print(f"SigningPubKey: {loan_broker_signed.signing_pub_key}\n")
|
||||
print(f"Signed loan_set_tx for borrower to sign over:\n{json.dumps(loan_broker_signed.to_xrpl(), indent=2)}")
|
||||
|
||||
# Borrower signs second.
|
||||
print("\n=== Adding borrower signature ===\n")
|
||||
fully_signed = sign_loan_set_by_counterparty(borrower, loan_broker_signed)
|
||||
|
||||
print(f"Borrower TxnSignature: {fully_signed.tx.counterparty_signature.txn_signature}")
|
||||
print(f"Borrower SigningPubKey: {fully_signed.tx.counterparty_signature.signing_pub_key}")
|
||||
print(f"\nFully signed LoanSet transaction:\n{json.dumps(fully_signed.tx.to_xrpl(), indent=2)}")
|
||||
|
||||
# Submit and wait for validation ----------------------
|
||||
print("\n=== Submitting signed LoanSet transaction ===\n")
|
||||
submit_response = submit_and_wait(fully_signed.tx, client)
|
||||
|
||||
if submit_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = submit_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to create loan: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Loan created successfully!")
|
||||
|
||||
# Extract loan information from the transaction result.
|
||||
print("\n=== Loan Information ===\n")
|
||||
loan_node = next(
|
||||
node for node in submit_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("CreatedNode", {}).get("LedgerEntryType") == "Loan"
|
||||
)
|
||||
print(json.dumps(loan_node["CreatedNode"]["NewFields"], indent=2))
|
||||
@@ -1,64 +0,0 @@
|
||||
# IMPORTANT: This example creates a loan broker using an existing account
|
||||
# that has already created a PRIVATE vault.
|
||||
# If you want to create a loan broker for a PUBLIC vault, you can replace the vault_id
|
||||
# and loan_broker values with your own.
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models import LoanBrokerSet
|
||||
from xrpl.transaction import submit_and_wait
|
||||
from xrpl.wallet import Wallet
|
||||
|
||||
# Set up client ----------------------
|
||||
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
||||
|
||||
# This step checks for the necessary setup data to run the lending protocol tutorials.
|
||||
# If missing, lending_setup.py will generate the data.
|
||||
if not os.path.exists("lending_setup.json"):
|
||||
print("\n=== Lending tutorial data doesn't exist. Running setup script... ===\n")
|
||||
subprocess.run([sys.executable, "lending_setup.py"], check=True)
|
||||
|
||||
# Load preconfigured accounts and vault_id.
|
||||
with open("lending_setup.json") as f:
|
||||
setup_data = json.load(f)
|
||||
|
||||
# You can replace these values with your own.
|
||||
loan_broker = Wallet.from_seed(setup_data["loan_broker"]["seed"])
|
||||
vault_id = setup_data["vault_id"]
|
||||
|
||||
print(f"\nLoan broker/vault owner address: {loan_broker.address}")
|
||||
print(f"Vault ID: {vault_id}")
|
||||
|
||||
# Prepare LoanBrokerSet transaction ----------------------
|
||||
print("\n=== Preparing LoanBrokerSet transaction ===\n")
|
||||
loan_broker_set_tx = LoanBrokerSet(
|
||||
account=loan_broker.address,
|
||||
vault_id=vault_id,
|
||||
management_fee_rate=1000,
|
||||
)
|
||||
|
||||
print(json.dumps(loan_broker_set_tx.to_xrpl(), indent=2))
|
||||
|
||||
# Submit, sign, and wait for validation ----------------------
|
||||
print("\n=== Submitting LoanBrokerSet transaction ===\n")
|
||||
submit_response = submit_and_wait(loan_broker_set_tx, client, loan_broker)
|
||||
|
||||
if submit_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = submit_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to create loan broker: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Loan broker created successfully!")
|
||||
|
||||
# Extract loan broker information from the transaction result
|
||||
print("\n=== Loan Broker Information ===\n")
|
||||
loan_broker_node = next(
|
||||
node for node in submit_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("CreatedNode", {}).get("LedgerEntryType") == "LoanBroker"
|
||||
)
|
||||
print(f"LoanBroker ID: {loan_broker_node['CreatedNode']['LedgerIndex']}")
|
||||
print(f"LoanBroker Psuedo-Account Address: {loan_broker_node['CreatedNode']['NewFields']['Account']}")
|
||||
@@ -1,366 +0,0 @@
|
||||
# Setup script for lending protocol tutorials
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from xrpl.asyncio.clients import AsyncWebsocketClient
|
||||
from xrpl.asyncio.wallet import generate_faucet_wallet
|
||||
from xrpl.asyncio.transaction import submit_and_wait, autofill, sign
|
||||
from xrpl.transaction import sign_loan_set_by_counterparty
|
||||
from xrpl.models import (
|
||||
AccountObjects,
|
||||
Batch,
|
||||
BatchFlag,
|
||||
CredentialAccept,
|
||||
CredentialCreate,
|
||||
LoanBrokerSet,
|
||||
LoanSet,
|
||||
MPTAmount,
|
||||
MPTCurrency,
|
||||
MPTokenAuthorize,
|
||||
MPTokenIssuanceCreate,
|
||||
MPTokenIssuanceCreateFlag,
|
||||
Payment,
|
||||
PermissionedDomainSet,
|
||||
TicketCreate,
|
||||
VaultCreate,
|
||||
VaultDeposit,
|
||||
)
|
||||
from xrpl.models.transactions.vault_create import VaultCreateFlag
|
||||
from xrpl.models.transactions.deposit_preauth import Credential
|
||||
from xrpl.utils import encode_mptoken_metadata, str_to_hex
|
||||
|
||||
|
||||
async def main():
|
||||
async with AsyncWebsocketClient("wss://s.devnet.rippletest.net:51233") as client:
|
||||
|
||||
print("Setting up tutorial: 0/6", end="\r")
|
||||
|
||||
# Create and fund wallets
|
||||
loan_broker, borrower, depositor, credential_issuer = await asyncio.gather(
|
||||
generate_faucet_wallet(client),
|
||||
generate_faucet_wallet(client),
|
||||
generate_faucet_wallet(client),
|
||||
generate_faucet_wallet(client),
|
||||
)
|
||||
|
||||
print("Setting up tutorial: 1/6", end="\r")
|
||||
|
||||
# Issue MPT with depositor
|
||||
# Create tickets for later use with loan_broker
|
||||
# Set up credentials and domain with credential_issuer
|
||||
credential_type = str_to_hex("KYC-Verified")
|
||||
|
||||
mpt_data = {
|
||||
"ticker": "TSTUSD",
|
||||
"name": "Test USD MPT",
|
||||
"desc": "A sample non-yield-bearing stablecoin backed by U.S. Treasuries.",
|
||||
"icon": "https://example.org/tstusd-icon.png",
|
||||
"asset_class": "rwa",
|
||||
"asset_subclass": "stablecoin",
|
||||
"issuer_name": "Example Treasury Reserve Co.",
|
||||
"uris": [
|
||||
{
|
||||
"uri": "https://exampletreasury.com/tstusd",
|
||||
"category": "website",
|
||||
"title": "Product Page",
|
||||
},
|
||||
{
|
||||
"uri": "https://exampletreasury.com/tstusd/reserve",
|
||||
"category": "docs",
|
||||
"title": "Reserve Attestation",
|
||||
},
|
||||
],
|
||||
"additional_info": {
|
||||
"reserve_type": "U.S. Treasury Bills",
|
||||
"custody_provider": "Example Custodian Bank",
|
||||
"audit_frequency": "Monthly",
|
||||
"last_audit_date": "2026-01-15",
|
||||
"pegged_currency": "USD",
|
||||
},
|
||||
}
|
||||
|
||||
ticket_create_response, mpt_issuance_response, _ = await asyncio.gather(
|
||||
submit_and_wait(
|
||||
TicketCreate(
|
||||
account=loan_broker.address,
|
||||
ticket_count=2,
|
||||
),
|
||||
client,
|
||||
loan_broker,
|
||||
),
|
||||
submit_and_wait(
|
||||
MPTokenIssuanceCreate(
|
||||
account=depositor.address,
|
||||
maximum_amount="100000000",
|
||||
transfer_fee=0,
|
||||
flags=(
|
||||
MPTokenIssuanceCreateFlag.TF_MPT_CAN_TRANSFER
|
||||
| MPTokenIssuanceCreateFlag.TF_MPT_CAN_CLAWBACK
|
||||
| MPTokenIssuanceCreateFlag.TF_MPT_CAN_TRADE
|
||||
),
|
||||
mptoken_metadata=encode_mptoken_metadata(mpt_data),
|
||||
),
|
||||
client,
|
||||
depositor,
|
||||
),
|
||||
submit_and_wait(
|
||||
Batch(
|
||||
account=credential_issuer.address,
|
||||
flags=BatchFlag.TF_ALL_OR_NOTHING,
|
||||
raw_transactions=[
|
||||
CredentialCreate(
|
||||
account=credential_issuer.address,
|
||||
subject=loan_broker.address,
|
||||
credential_type=credential_type,
|
||||
),
|
||||
CredentialCreate(
|
||||
account=credential_issuer.address,
|
||||
subject=borrower.address,
|
||||
credential_type=credential_type,
|
||||
),
|
||||
CredentialCreate(
|
||||
account=credential_issuer.address,
|
||||
subject=depositor.address,
|
||||
credential_type=credential_type,
|
||||
),
|
||||
PermissionedDomainSet(
|
||||
account=credential_issuer.address,
|
||||
accepted_credentials=[
|
||||
Credential(
|
||||
issuer=credential_issuer.address,
|
||||
credential_type=credential_type,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
client,
|
||||
credential_issuer,
|
||||
),
|
||||
)
|
||||
|
||||
# Extract ticket sequence numbers
|
||||
tickets = [
|
||||
node["CreatedNode"]["NewFields"]["TicketSequence"]
|
||||
for node in ticket_create_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("CreatedNode", {}).get("LedgerEntryType") == "Ticket"
|
||||
]
|
||||
|
||||
# Extract MPT issuance ID
|
||||
mpt_id = mpt_issuance_response.result["meta"]["mpt_issuance_id"]
|
||||
|
||||
# Get domain ID
|
||||
credential_issuer_objects = await client.request(AccountObjects(
|
||||
account=credential_issuer.address,
|
||||
ledger_index="validated",
|
||||
))
|
||||
domain_id = next(
|
||||
node["index"]
|
||||
for node in credential_issuer_objects.result["account_objects"]
|
||||
if node["LedgerEntryType"] == "PermissionedDomain"
|
||||
)
|
||||
|
||||
print("Setting up tutorial: 2/6", end="\r")
|
||||
|
||||
# Accept credentials and authorize MPT for each account
|
||||
await asyncio.gather(
|
||||
submit_and_wait(
|
||||
Batch(
|
||||
account=loan_broker.address,
|
||||
flags=BatchFlag.TF_ALL_OR_NOTHING,
|
||||
raw_transactions=[
|
||||
CredentialAccept(
|
||||
account=loan_broker.address,
|
||||
issuer=credential_issuer.address,
|
||||
credential_type=credential_type,
|
||||
),
|
||||
MPTokenAuthorize(
|
||||
account=loan_broker.address,
|
||||
mptoken_issuance_id=mpt_id,
|
||||
),
|
||||
],
|
||||
),
|
||||
client,
|
||||
loan_broker,
|
||||
),
|
||||
submit_and_wait(
|
||||
Batch(
|
||||
account=borrower.address,
|
||||
flags=BatchFlag.TF_ALL_OR_NOTHING,
|
||||
raw_transactions=[
|
||||
CredentialAccept(
|
||||
account=borrower.address,
|
||||
issuer=credential_issuer.address,
|
||||
credential_type=credential_type,
|
||||
),
|
||||
MPTokenAuthorize(
|
||||
account=borrower.address,
|
||||
mptoken_issuance_id=mpt_id,
|
||||
),
|
||||
],
|
||||
),
|
||||
client,
|
||||
borrower,
|
||||
),
|
||||
submit_and_wait(
|
||||
CredentialAccept(
|
||||
account=depositor.address,
|
||||
issuer=credential_issuer.address,
|
||||
credential_type=credential_type,
|
||||
),
|
||||
client,
|
||||
depositor,
|
||||
),
|
||||
)
|
||||
|
||||
print("Setting up tutorial: 3/6", end="\r")
|
||||
|
||||
# Create private vault and distribute MPT to accounts
|
||||
vault_create_response, _ = await asyncio.gather(
|
||||
submit_and_wait(
|
||||
VaultCreate(
|
||||
account=loan_broker.address,
|
||||
asset=MPTCurrency(mpt_issuance_id=mpt_id),
|
||||
flags=VaultCreateFlag.TF_VAULT_PRIVATE,
|
||||
domain_id=domain_id,
|
||||
),
|
||||
client,
|
||||
loan_broker,
|
||||
),
|
||||
submit_and_wait(
|
||||
Batch(
|
||||
account=depositor.address,
|
||||
flags=BatchFlag.TF_ALL_OR_NOTHING,
|
||||
raw_transactions=[
|
||||
Payment(
|
||||
account=depositor.address,
|
||||
destination=loan_broker.address,
|
||||
amount=MPTAmount(mpt_issuance_id=mpt_id, value="5000"),
|
||||
),
|
||||
Payment(
|
||||
account=depositor.address,
|
||||
destination=borrower.address,
|
||||
amount=MPTAmount(mpt_issuance_id=mpt_id, value="2500"),
|
||||
),
|
||||
],
|
||||
),
|
||||
client,
|
||||
depositor,
|
||||
),
|
||||
)
|
||||
|
||||
vault_id = next(
|
||||
node["CreatedNode"]["LedgerIndex"]
|
||||
for node in vault_create_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("CreatedNode", {}).get("LedgerEntryType") == "Vault"
|
||||
)
|
||||
|
||||
print("Setting up tutorial: 4/6", end="\r")
|
||||
|
||||
# Create LoanBroker and deposit MPT into vault
|
||||
loan_broker_set_response, _ = await asyncio.gather(
|
||||
submit_and_wait(
|
||||
LoanBrokerSet(
|
||||
account=loan_broker.address,
|
||||
vault_id=vault_id,
|
||||
),
|
||||
client,
|
||||
loan_broker,
|
||||
),
|
||||
submit_and_wait(
|
||||
VaultDeposit(
|
||||
account=depositor.address,
|
||||
vault_id=vault_id,
|
||||
amount=MPTAmount(mpt_issuance_id=mpt_id, value="50000000"),
|
||||
),
|
||||
client,
|
||||
depositor,
|
||||
),
|
||||
)
|
||||
|
||||
loan_broker_id = next(
|
||||
node["CreatedNode"]["LedgerIndex"]
|
||||
for node in loan_broker_set_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("CreatedNode", {}).get("LedgerEntryType") == "LoanBroker"
|
||||
)
|
||||
|
||||
print("Setting up tutorial: 5/6", end="\r")
|
||||
|
||||
# Create 2 identical loans with complete repayment due in 30 days
|
||||
|
||||
# Helper function to create, sign, and submit a LoanSet transaction
|
||||
async def create_loan(ticket_sequence):
|
||||
loan_set_tx = await autofill(LoanSet(
|
||||
account=loan_broker.address,
|
||||
counterparty=borrower.address,
|
||||
loan_broker_id=loan_broker_id,
|
||||
principal_requested="1000",
|
||||
interest_rate=500,
|
||||
payment_total=1,
|
||||
payment_interval=2592000,
|
||||
loan_origination_fee="100",
|
||||
loan_service_fee="10",
|
||||
sequence=0,
|
||||
ticket_sequence=ticket_sequence,
|
||||
), client)
|
||||
|
||||
loan_broker_signed = sign(loan_set_tx, loan_broker)
|
||||
fully_signed = sign_loan_set_by_counterparty(borrower, loan_broker_signed)
|
||||
submit_response = await submit_and_wait(fully_signed.tx, client)
|
||||
|
||||
return submit_response
|
||||
|
||||
submit_response_1, submit_response_2 = await asyncio.gather(
|
||||
create_loan(tickets[0]),
|
||||
create_loan(tickets[1]),
|
||||
)
|
||||
|
||||
loan_id_1 = next(
|
||||
node["CreatedNode"]["LedgerIndex"]
|
||||
for node in submit_response_1.result["meta"]["AffectedNodes"]
|
||||
if node.get("CreatedNode", {}).get("LedgerEntryType") == "Loan"
|
||||
)
|
||||
|
||||
loan_id_2 = next(
|
||||
node["CreatedNode"]["LedgerIndex"]
|
||||
for node in submit_response_2.result["meta"]["AffectedNodes"]
|
||||
if node.get("CreatedNode", {}).get("LedgerEntryType") == "Loan"
|
||||
)
|
||||
|
||||
print("Setting up tutorial: 6/6", end="\r")
|
||||
|
||||
# Write setup data to JSON file
|
||||
setup_data = {
|
||||
"description": "This file is auto-generated by lending_setup.py. It stores XRPL account info for use in lending protocol tutorials.",
|
||||
"loan_broker": {
|
||||
"address": loan_broker.address,
|
||||
"seed": loan_broker.seed,
|
||||
},
|
||||
"borrower": {
|
||||
"address": borrower.address,
|
||||
"seed": borrower.seed,
|
||||
},
|
||||
"depositor": {
|
||||
"address": depositor.address,
|
||||
"seed": depositor.seed,
|
||||
},
|
||||
"credential_issuer": {
|
||||
"address": credential_issuer.address,
|
||||
"seed": credential_issuer.seed,
|
||||
},
|
||||
"domain_id": domain_id,
|
||||
"mpt_id": mpt_id,
|
||||
"vault_id": vault_id,
|
||||
"loan_broker_id": loan_broker_id,
|
||||
"loan_id_1": loan_id_1,
|
||||
"loan_id_2": loan_id_2,
|
||||
}
|
||||
|
||||
with open("lending_setup.json", "w") as f:
|
||||
json.dump(setup_data, f, indent=2)
|
||||
|
||||
print("Setting up tutorial: Complete!")
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -1,130 +0,0 @@
|
||||
# IMPORTANT: This example impairs an existing loan, which has a 60 second grace period.
|
||||
# After the 60 seconds pass, this example defaults the loan.
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models import LedgerEntry, LoanManage
|
||||
from xrpl.models.transactions.loan_manage import LoanManageFlag
|
||||
from xrpl.transaction import submit_and_wait
|
||||
from xrpl.utils import posix_to_ripple_time, ripple_time_to_posix
|
||||
from xrpl.wallet import Wallet
|
||||
|
||||
# Set up client ----------------------
|
||||
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
||||
|
||||
# This step checks for the necessary setup data to run the lending protocol tutorials.
|
||||
# If missing, lending_setup.py will generate the data.
|
||||
if not os.path.exists("lending_setup.json"):
|
||||
print("\n=== Lending tutorial data doesn't exist. Running setup script... ===\n")
|
||||
subprocess.run([sys.executable, "lending_setup.py"], check=True)
|
||||
|
||||
# Load preconfigured accounts and loan_id.
|
||||
with open("lending_setup.json") as f:
|
||||
setup_data = json.load(f)
|
||||
|
||||
# You can replace these values with your own.
|
||||
loan_broker = Wallet.from_seed(setup_data["loan_broker"]["seed"])
|
||||
loan_id = setup_data["loan_id_1"]
|
||||
|
||||
print(f"\nLoan broker address: {loan_broker.address}")
|
||||
print(f"LoanID: {loan_id}")
|
||||
|
||||
# Check loan status before impairment ----------------------
|
||||
print("\n=== Loan Status ===\n")
|
||||
loan_status = client.request(LedgerEntry(
|
||||
index=loan_id,
|
||||
ledger_index="validated",
|
||||
))
|
||||
|
||||
print(f"Total Amount Owed: {loan_status.result['node']['TotalValueOutstanding']} TSTUSD.")
|
||||
# Convert Ripple Epoch timestamp to local date and time
|
||||
next_payment_due_date = loan_status.result["node"]["NextPaymentDueDate"]
|
||||
payment_due = datetime.fromtimestamp(ripple_time_to_posix(next_payment_due_date))
|
||||
print(f"Payment Due Date: {payment_due}")
|
||||
|
||||
# Prepare LoanManage transaction to impair the loan ----------------------
|
||||
print("\n=== Preparing LoanManage transaction to impair loan ===\n")
|
||||
loan_manage_impair = LoanManage(
|
||||
account=loan_broker.address,
|
||||
loan_id=loan_id,
|
||||
flags=LoanManageFlag.TF_LOAN_IMPAIR,
|
||||
)
|
||||
|
||||
print(json.dumps(loan_manage_impair.to_xrpl(), indent=2))
|
||||
|
||||
# Sign, submit, and wait for impairment validation ----------------------
|
||||
print("\n=== Submitting LoanManage impairment transaction ===\n")
|
||||
impair_response = submit_and_wait(loan_manage_impair, client, loan_broker)
|
||||
|
||||
if impair_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = impair_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to impair loan: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Loan impaired successfully!")
|
||||
|
||||
# Extract loan impairment info from transaction results ----------------------
|
||||
loan_node = next(
|
||||
node for node in impair_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("ModifiedNode", {}).get("LedgerEntryType") == "Loan"
|
||||
)
|
||||
|
||||
# Check grace period and next payment due date
|
||||
grace_period = loan_node["ModifiedNode"]["FinalFields"]["GracePeriod"]
|
||||
next_payment_due_date = loan_node["ModifiedNode"]["FinalFields"]["NextPaymentDueDate"]
|
||||
default_time = next_payment_due_date + grace_period
|
||||
payment_due = datetime.fromtimestamp(ripple_time_to_posix(next_payment_due_date))
|
||||
|
||||
print(f"New Payment Due Date: {payment_due}")
|
||||
print(f"Grace Period: {grace_period} seconds")
|
||||
|
||||
# Convert current time to Ripple Epoch timestamp
|
||||
current_time = posix_to_ripple_time(int(time.time()))
|
||||
seconds_until_default = default_time - current_time
|
||||
|
||||
# Countdown until loan can be defaulted ----------------------
|
||||
print("\n=== Countdown until loan can be defaulted ===\n")
|
||||
|
||||
while seconds_until_default >= 0:
|
||||
print(f"{seconds_until_default} seconds...", end="\r")
|
||||
time.sleep(1)
|
||||
seconds_until_default -= 1
|
||||
|
||||
print("\rGrace period expired. Loan can now be defaulted.")
|
||||
|
||||
# Prepare LoanManage transaction to default the loan ----------------------
|
||||
print("\n=== Preparing LoanManage transaction to default loan ===\n")
|
||||
loan_manage_default = LoanManage(
|
||||
account=loan_broker.address,
|
||||
loan_id=loan_id,
|
||||
flags=LoanManageFlag.TF_LOAN_DEFAULT,
|
||||
)
|
||||
|
||||
print(json.dumps(loan_manage_default.to_xrpl(), indent=2))
|
||||
|
||||
# Sign, submit, and wait for default validation ----------------------
|
||||
print("\n=== Submitting LoanManage default transaction ===\n")
|
||||
default_response = submit_and_wait(loan_manage_default, client, loan_broker)
|
||||
|
||||
if default_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = default_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to default loan: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Loan defaulted successfully!")
|
||||
|
||||
# Verify loan default status from transaction results ----------------------
|
||||
print("\n=== Checking final loan status ===\n")
|
||||
loan_node = next(
|
||||
node for node in default_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("ModifiedNode", {}).get("LedgerEntryType") == "Loan"
|
||||
)
|
||||
loan_flags = loan_node["ModifiedNode"]["FinalFields"]["Flags"]
|
||||
active_flags = [f.name for f in LoanManageFlag if loan_flags & f.value]
|
||||
print(f"Final loan flags: {active_flags}")
|
||||
@@ -1,117 +0,0 @@
|
||||
# IMPORTANT: This example pays off an existing loan and then deletes it.
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models import LedgerEntry, LoanDelete, LoanPay, MPTAmount
|
||||
from xrpl.transaction import submit_and_wait
|
||||
from xrpl.wallet import Wallet
|
||||
|
||||
# Set up client ----------------------
|
||||
client = JsonRpcClient("https://s.devnet.rippletest.net:51234")
|
||||
|
||||
# This step checks for the necessary setup data to run the lending protocol tutorials.
|
||||
# If missing, lending_setup.py will generate the data.
|
||||
if not os.path.exists("lending_setup.json"):
|
||||
print("\n=== Lending tutorial data doesn't exist. Running setup script... ===\n")
|
||||
subprocess.run([sys.executable, "lending_setup.py"], check=True)
|
||||
|
||||
# Load preconfigured accounts, loan_id, and mpt_id.
|
||||
with open("lending_setup.json") as f:
|
||||
setup_data = json.load(f)
|
||||
|
||||
# You can replace these values with your own.
|
||||
borrower = Wallet.from_seed(setup_data["borrower"]["seed"])
|
||||
loan_id = setup_data["loan_id_2"]
|
||||
mpt_id = setup_data["mpt_id"]
|
||||
|
||||
print(f"\nBorrower address: {borrower.address}")
|
||||
print(f"LoanID: {loan_id}")
|
||||
print(f"MPT ID: {mpt_id}")
|
||||
|
||||
# Check initial loan status ----------------------
|
||||
print("\n=== Loan Status ===\n")
|
||||
loan_status = client.request(LedgerEntry(
|
||||
index=loan_id,
|
||||
ledger_index="validated",
|
||||
))
|
||||
|
||||
total_value_outstanding = loan_status.result["node"]["TotalValueOutstanding"]
|
||||
loan_service_fee = loan_status.result["node"]["LoanServiceFee"]
|
||||
total_payment = str(int(total_value_outstanding) + int(loan_service_fee))
|
||||
|
||||
print(f"Amount Owed: {total_value_outstanding} TSTUSD")
|
||||
print(f"Loan Service Fee: {loan_service_fee} TSTUSD")
|
||||
print(f"Total Payment Due (including fees): {total_payment} TSTUSD")
|
||||
|
||||
# Prepare LoanPay transaction ----------------------
|
||||
print("\n=== Preparing LoanPay transaction ===\n")
|
||||
loan_pay_tx = LoanPay(
|
||||
account=borrower.address,
|
||||
loan_id=loan_id,
|
||||
amount=MPTAmount(mpt_issuance_id=mpt_id, value=total_payment),
|
||||
)
|
||||
|
||||
print(json.dumps(loan_pay_tx.to_xrpl(), indent=2))
|
||||
|
||||
# Sign, submit, and wait for payment validation ----------------------
|
||||
print("\n=== Submitting LoanPay transaction ===\n")
|
||||
pay_response = submit_and_wait(loan_pay_tx, client, borrower)
|
||||
|
||||
if pay_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = pay_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to pay loan: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Loan paid successfully!")
|
||||
|
||||
# Extract updated loan info from transaction results ----------------------
|
||||
print("\n=== Loan Status After Payment ===\n")
|
||||
loan_node = next(
|
||||
node for node in pay_response.result["meta"]["AffectedNodes"]
|
||||
if node.get("ModifiedNode", {}).get("LedgerEntryType") == "Loan"
|
||||
)
|
||||
|
||||
final_balance = loan_node["ModifiedNode"]["FinalFields"].get("TotalValueOutstanding")
|
||||
if final_balance:
|
||||
print(f"Outstanding Loan Balance: {final_balance} TSTUSD")
|
||||
else:
|
||||
print("Outstanding Loan Balance: Loan fully paid off!")
|
||||
|
||||
# Prepare LoanDelete transaction ----------------------
|
||||
# Either the loan broker or borrower can submit this transaction.
|
||||
print("\n=== Preparing LoanDelete transaction ===\n")
|
||||
loan_delete_tx = LoanDelete(
|
||||
account=borrower.address,
|
||||
loan_id=loan_id,
|
||||
)
|
||||
|
||||
print(json.dumps(loan_delete_tx.to_xrpl(), indent=2))
|
||||
|
||||
# Sign, submit, and wait for deletion validation ----------------------
|
||||
print("\n=== Submitting LoanDelete transaction ===\n")
|
||||
delete_response = submit_and_wait(loan_delete_tx, client, borrower)
|
||||
|
||||
if delete_response.result["meta"]["TransactionResult"] != "tesSUCCESS":
|
||||
result_code = delete_response.result["meta"]["TransactionResult"]
|
||||
print(f"Error: Unable to delete loan: {result_code}")
|
||||
sys.exit(1)
|
||||
|
||||
print("Loan deleted successfully!")
|
||||
|
||||
# Verify loan deletion ----------------------
|
||||
print("\n=== Verifying Loan Deletion ===\n")
|
||||
verify_response = client.request(LedgerEntry(
|
||||
index=loan_id,
|
||||
ledger_index="validated",
|
||||
))
|
||||
|
||||
if verify_response.is_successful():
|
||||
print("Warning: Loan still exists in the ledger.")
|
||||
elif verify_response.result.get("error") == "entryNotFound":
|
||||
print("Loan has been successfully removed from the XRP Ledger!")
|
||||
else:
|
||||
print(f"Error checking loan status: {verify_response.result.get('error')}")
|
||||
@@ -1 +0,0 @@
|
||||
xrpl-py>=4.5.0
|
||||
@@ -26,7 +26,7 @@ const logos = {
|
||||
],
|
||||
developer_tooling: ["cryptum", "evernode", "threezy", "tokenize"],
|
||||
interoperability: ["multichain"],
|
||||
wallet: ["crossmark", "edge", "gem-wallet", "xumm", "joey-wallet", "bifrost-wallet"],
|
||||
wallet: ["crossmark", "edge", "gem-wallet", "xumm", "joey-wallet", "bifrost-wallet", "bitget-wallet"],
|
||||
nfts: [
|
||||
"aesthetes",
|
||||
"audiotarky",
|
||||
@@ -422,6 +422,15 @@ const cardsData = [
|
||||
category_name: "Wallet",
|
||||
link: "https://bifrostwallet.com/",
|
||||
},
|
||||
{
|
||||
id: "bitget-wallet",
|
||||
title: "Bitget Wallet",
|
||||
description:
|
||||
"Bitget Wallet is a non-custodial wallet designed to make crypto simple and secure for everyone.",
|
||||
category_id: "wallet",
|
||||
category_name: "Wallet",
|
||||
link: "https://web3.bitget.com/",
|
||||
},
|
||||
];
|
||||
|
||||
const featured_categories = {
|
||||
@@ -468,7 +477,7 @@ const uses = [
|
||||
{
|
||||
id: "wallet",
|
||||
title: "Wallet",
|
||||
number: 6,
|
||||
number: 7,
|
||||
description:
|
||||
"Build digital wallets to store passwords and interact with various blockchains to send and receive digital assets, including XRP."
|
||||
},
|
||||
|
||||
@@ -19,18 +19,14 @@ const links = [
|
||||
|
||||
const softwallets = [
|
||||
{ href: "https://bifrostwallet.com/", id: "wallet-bifrost", alt: "Bifrost Wallet" },
|
||||
{ href: "https://xaman.app/", id: "wallet-xumm", alt: "Xaman" },
|
||||
{ href: "https://trustwallet.com/", id: "wallet-trust", alt: "Trust Wallet" },
|
||||
{
|
||||
href: "https://gatehub.net/",
|
||||
id: "wallet-gatehub",
|
||||
alt: "Gatehub",
|
||||
imgclasses: "invertible-img",
|
||||
},
|
||||
{ href: "https://gemwallet.app/", id: "wallet-gem", alt: "Gem Wallet" },
|
||||
{ href: "https://web3.bitget.com/", id: "wallet-bitget", alt: "Bitget Wallet" },
|
||||
{ href: "https://coin.space/", id: "wallet-coin", alt: "Coin Space" },
|
||||
{ href: "https://crossmark.io/", id: "wallet-crossmark", alt: "Crossmark Wallet" },
|
||||
{ href: "https://gatehub.net/", id: "wallet-gatehub", alt: "Gatehub", imgclasses: "invertible-img" },
|
||||
{ href: "https://gemwallet.app/", id: "wallet-gem", alt: "Gem Wallet" },
|
||||
{ href: "https://joeywallet.xyz/", id: "wallet-joey", alt: "Joey Wallet" },
|
||||
{ href: "https://trustwallet.com/", id: "wallet-trust", alt: "Trust Wallet" },
|
||||
{ href: "https://xaman.app/", id: "wallet-xumm", alt: "Xaman" }
|
||||
];
|
||||
|
||||
const hardwallets = [
|
||||
@@ -61,16 +57,8 @@ const exchanges = [
|
||||
{ href: "https://www.liquid.com/", id: "exch-liquid", alt: "Liquid" },
|
||||
{ href: "https://www.lmax.com/", id: "exch-lmax", alt: "LMAX" },
|
||||
{ href: "https://www.bitfinex.com/", id: "exch-bitfinex", alt: "Bitfinex" },
|
||||
{
|
||||
href: "https://www.etoro.com/crypto/exchange/",
|
||||
id: "exch-etoro",
|
||||
alt: "eToro",
|
||||
},
|
||||
{
|
||||
href: "https://currency.com",
|
||||
id: "exch-currency-com",
|
||||
alt: "Currency.com",
|
||||
},
|
||||
{ href: "https://www.etoro.com/crypto/exchange/", id: "exch-etoro", alt: "eToro"},
|
||||
{ href: "https://currency.com", id: "exch-currency-com", alt: "Currency.com"},
|
||||
{ href: "https://bittrex.com/", id: "exch-bittrex", alt: "Bittrex" },
|
||||
];
|
||||
|
||||
|
||||
@@ -370,7 +370,6 @@
|
||||
[get_counts command]: /docs/references/http-websocket-apis/admin-api-methods/status-and-debugging-methods/get_counts.md
|
||||
[get_counts method]: /docs/references/http-websocket-apis/admin-api-methods/status-and-debugging-methods/get_counts.md
|
||||
[Get Started Using JavaScript]: /docs/tutorials/javascript/build-apps/get-started.md
|
||||
[Get Started Using Python]: /docs/tutorials/python/build-apps/get-started.md
|
||||
[hexadecimal]: https://en.wikipedia.org/wiki/Hexadecimal
|
||||
[identifying hash]: /docs/concepts/transactions/index.md#identifying-transactions
|
||||
[json command]: /docs/references/http-websocket-apis/public-api-methods/utility-methods/json.md
|
||||
@@ -487,4 +486,3 @@
|
||||
[wallet_propose command]: /docs/references/http-websocket-apis/admin-api-methods/key-generation-methods/wallet_propose.md
|
||||
[wallet_propose method]: /docs/references/http-websocket-apis/admin-api-methods/key-generation-methods/wallet_propose.md
|
||||
[xrpl.js library]: https://github.com/XRPLF/xrpl.js
|
||||
[xrpl-py library]: https://github.com/XRPLF/xrpl-py
|
||||
|
||||
@@ -68,10 +68,10 @@ In addition to the [common ledger entry fields][], {% code-page-name /%} entries
|
||||
| `LoanBrokerNode` | Number | UInt64 | Yes | Identifies the page where this item is referenced in the `LoanBroker` owner directory. |
|
||||
| `LoanBrokerID` | String | Hash256 | Yes | The ID of the _Loan Broker_ associated with this loan. |
|
||||
| `Borrower` | String | AccountID | Yes | The account address of the _Borrower_. |
|
||||
| `LoanOriginationFee` | String | Number | Yes | The amount paid to the _Loan Broker_, taken from the principal loan at creation. |
|
||||
| `LoanServiceFee` | String | Number | Yes | The amount paid to the _Loan Broker_ with each loan payment. |
|
||||
| `LatePaymentFee` | String | Number | Yes | The amount paid to the _Loan Broker_ for each late payment. |
|
||||
| `ClosePaymentFee` | String | Number | Yes | The amount paid to the _Loan Broker_ when a full early payment is made. |
|
||||
| `LoanOriginationFee` | Number | Number | Yes | The amount paid to the _Loan Broker_, taken from the principal loan at creation. |
|
||||
| `LoanServiceFee` | Number | Number | Yes | The amount paid to the _Loan Broker_ with each loan payment. |
|
||||
| `LatePaymentFee` | Number | Number | Yes | The amount paid to the _Loan Broker_ for each late payment. |
|
||||
| `ClosePaymentFee` | Number | Number | Yes | The amount paid to the _Loan Broker_ when a full early payment is made. |
|
||||
| `OverpaymentFee` | Number | UInt32 | Yes | The fee charged on overpayments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
| `InterestRate` | Number | UInt32 | Yes | The annualized interest rate of the loan, in 1/10th basis points. |
|
||||
| `LateInterestRate` | Number | UInt32 | Yes | The premium added to the interest rate for late payments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
@@ -83,10 +83,10 @@ In addition to the [common ledger entry fields][], {% code-page-name /%} entries
|
||||
| `PreviousPaymentDueDate` | Number | UInt32 | Yes | The timestamp of when the previous payment was made, in [seconds since the Ripple Epoch][]. |
|
||||
| `NextPaymentDueDate` | Number | UInt32 | Yes | The timestamp of when the next payment is due, in [seconds since the Ripple Epoch][]. |
|
||||
| `PaymentRemaining` | Number | UInt32 | Yes | The number of payments remaining on the loan. |
|
||||
| `PrincipalOutstanding` | String | Number | Yes | The principal amount still owed on the loan. |
|
||||
| `TotalValueOutstanding` | String | Number | Yes | The total amount owed on the loan, including remaining principal and fees. |
|
||||
| `ManagementFeeOutstanding` | String | Number | Yes | The remaining management fee owed to the loan broker. |
|
||||
| `PeriodicPayment` | String | Number | Yes | The amount due for each payment interval. |
|
||||
| `PrincipalOutstanding` | Number | Number | Yes | The principal amount still owed on the loan. |
|
||||
| `TotalValueOutstanding` | Number | Number | Yes | The total amount owed on the loan, including remaining principal and fees. |
|
||||
| `ManagementFeeOutstanding` | Number | Number | Yes | The remaining management fee owed to the loan broker. |
|
||||
| `PeriodicPayment` | Number | Number | Yes | The amount due for each payment interval. |
|
||||
| `LoanScale` | Number | Int32 | No | The scale factor that ensures all computed amounts are rounded to the same number of decimal places. It is based on the total loan value at creation time. |
|
||||
|
||||
{% admonition type="info" name="Note" %}
|
||||
@@ -115,6 +115,7 @@ When the loan broker discovers that the borrower can't make an upcoming payment,
|
||||
The ID of a `Loan` ledger entry is the [SHA-512Half][] of the following values, concatenated in order:
|
||||
|
||||
- The `Loan` space key `0x004C`.
|
||||
- The [AccountID][] of the Borrower account.
|
||||
- The `LoanBrokerID` of the associated `LoanBroker` ledger entry.
|
||||
- The `LoanSequence` number of the `LoanBroker` ledger entry.
|
||||
|
||||
|
||||
@@ -65,9 +65,9 @@ In addition to the [common ledger entry fields][], {% code-page-name /%} entries
|
||||
| `Data` | String | Blob | No | Arbitrary metadata about the vault. Limited to 256 bytes. |
|
||||
| `ManagementFeeRate` | Number | UInt16 | No | The fee charged by the lending protocol, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
| `OwnerCount` | Number | UInt32 | Yes | The number of active loans issued by the LoanBroker. |
|
||||
| `DebtTotal` | String | Number | Yes | The total asset amount the protocol owes the vault, including interest. |
|
||||
| `DebtMaximum` | String | Number | Yes | The maximum amount the protocol can owe the vault. The default value of `0` means there is no limit to the debt. |
|
||||
| `CoverAvailable` | String | Number | Yes | The total amount of first-loss capital deposited into the lending protocol. |
|
||||
| `DebtTotal` | Number | Number | Yes | The total asset amount the protocol owes the vault, including interest. |
|
||||
| `DebtMaximum` | Number | Number | Yes | The maximum amount the protocol can owe the vault. The default value of `0` means there is no limit to the debt. |
|
||||
| `CoverAvailable` | Number | Number | Yes | The total amount of first-loss capital deposited into the lending protocol. |
|
||||
| `CoverRateMinimum` | Number | UInt32 | Yes | The 1/10th basis point of the `DebtTotal` that the first-loss capital must cover. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
| `CoverRateLiquidation`| Number | UInt12 | Yes | The 1/10th basis point of minimum required first-loss capital that is moved to an asset vault to cover a loan default. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
|
||||
|
||||
@@ -38,10 +38,10 @@ The `LoanBrokerCoverClawback` transaction claws back first-loss capital from a `
|
||||
|
||||
In addition to the [common fields][], {% code-page-name /%} transactions use the following fields:
|
||||
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:-------------- |:--------------------|:--------------|:----------|:------------|
|
||||
| `LoanBrokerID` | String | Hash256 | No | The ID of the `LoanBroker` ledger entry to clawback first-loss capital. Must be provided if `Amount` is an MPT, or `Amount` is an IOU and the specified `issuer` matches the `Account` submitting the transaction. |
|
||||
| `Amount` | [Currency Amount][] | Amount | No | The amount of first-loss capital to claw back. If the value is `0` or empty, claw back all assets down to the minimum cover (`DebtTotal * CoverRateMinimum`). |
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:-------------- |:----------|:--------------|:----------|:------------|
|
||||
| `LoanBrokerID` | String | Hash256 | No | The ID of the `LoanBroker` ledger entry to clawback first-loss capital. Must be provided if `Amount` is an MPT, or `Amount` is an IOU and the specified `issuer` matches the `Account` submitting the transaction. |
|
||||
| `Amount` | Object | Amount | No | The amount of first-loss capital to claw back. If the value is `0` or empty, claw back all assets down to the minimum cover (`DebtTotal * CoverRateMinimum`). |
|
||||
|
||||
|
||||
## Error Cases
|
||||
|
||||
@@ -40,10 +40,10 @@ Only the owner of the associated `LoanBroker` entry can initiate this transactio
|
||||
|
||||
In addition to the [common fields][], {% code-page-name /%} transactions use the following fields:
|
||||
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:-------------- |:--------------------|:--------------|:----------|:------------|
|
||||
| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry to deposit the first-loss capital. |
|
||||
| `Amount` | [Currency Amount][] | Amount | Yes | The amount of first-loss capital to deposit. |
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:-------------- |:----------|:--------------|:----------|:------------|
|
||||
| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry to deposit the first-loss capital. |
|
||||
| `Amount` | Object | Amount | Yes | The amount of first-loss capital to deposit. |
|
||||
|
||||
|
||||
## Error Cases
|
||||
|
||||
@@ -40,11 +40,11 @@ Only the owner of the associated `LoanBroker` entry can initiate this transactio
|
||||
|
||||
In addition to the [common fields][], {% code-page-name /%} transactions use the following fields:
|
||||
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:-------------- |:--------------------|:--------------|:----------|:------------|
|
||||
| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry to withdraw from. |
|
||||
| `Amount` | [Currency Amount][] | Amount | Yes | The amount of first-loss capital to withdraw. |
|
||||
| `Destination` | String | AccountID | No | An account to receive the assets. |
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:-------------- |:----------|:-------------|:----------|:------------|
|
||||
| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry to withdraw from. |
|
||||
| `Amount` | Object | Amount | Yes | The amount of first-loss capital to withdraw. |
|
||||
| `Destination` | String | AccountID | No | An account to receive the assets. |
|
||||
|
||||
|
||||
## Error Cases
|
||||
|
||||
@@ -45,7 +45,7 @@ In addition to the [common fields][], {% code-page-name /%} transactions use the
|
||||
| `LoanBrokerID` | String | Hash256 | No | The loan broker ID that the transaction is modifying. |
|
||||
| `Data` | String | Blob | No | Arbitrary metadata in hex format--limited to 256 bytes. |
|
||||
| `ManagementFeeRate` | Number | UInt16 | No | The 1/10th basis point fee charged by the lending protocol owner. Valid values range from `0` to `10000` (inclusive), representing 0% to 10%. |
|
||||
| `DebtMaximum` | String | Number | No | The maximum amount the protocol can owe the vault. The default value of `0` means there is no limit to the debt. Must be a positive value. |
|
||||
| `DebtMaximum` | Number | Number | No | The maximum amount the protocol can owe the vault. The default value of `0` means there is no limit to the debt. Must be a positive value. |
|
||||
| `CoverRateMinimum` | Number | UInt32 | No | The 1/10th basis point `DebtTotal` that the first-loss capital must cover. Valid values range from `0` to `100000` (inclusive), representing 0% to 100%. |
|
||||
| `CoverRateLiquidation` | Number | UInt32 | No | The 1/10th basis point of minimum required first-loss capital that is moved to an asset vault to cover a loan default. Valid values range from `0` to `100000` (inclusive), representing 0% to 100%. |
|
||||
|
||||
|
||||
@@ -38,11 +38,12 @@ In addition to the [common fields][], {% code-page-name /%} transactions use the
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:-------------- |:----------|:-------------|:----------|:------------|
|
||||
| `LoanID` | String | Hash256 | Yes | The ID of the `Loan` ledger entry to manage. |
|
||||
| `Flags` | String | UInt32 | No | The flag to modify the loan. |
|
||||
|
||||
|
||||
## {% $frontmatter.seo.title %} Flags
|
||||
|
||||
Transactions of the {% code-page-name /%} type support additional values in the [flags field], as follows:
|
||||
Transactions of the {% code-page-name /%} type support additional values in the [`flags` field], as follows:
|
||||
|
||||
| Field Name | Hex Value | Decimal Value | Description |
|
||||
|:----------------|:-------------|:--------------|:------------|
|
||||
|
||||
@@ -43,21 +43,20 @@ To see how loan payment transactions are calculated, see [transaction pseudo-cod
|
||||
|
||||
In addition to the [common fields][], {% code-page-name /%} transactions use the following fields:
|
||||
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:--------------- |:--------------------|:--------------|:----------|:------------|
|
||||
| `LoanID` | String | Hash256 | Yes | The ID of the `Loan` ledger entry to repay. |
|
||||
| `Amount` | [Currency Amount][] | Amount | Yes | The amount to pay toward the loan. |
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:--------------- |:----------|:-------------|:----------|:------------|
|
||||
| `LoanID` | String | Hash256 | Yes | The ID of the `Loan` ledger entry to repay. |
|
||||
| `Amount` | Number | Amount | Yes | The amount to pay toward the loan. |
|
||||
|
||||
|
||||
## {% $frontmatter.seo.title %} Flags
|
||||
|
||||
Transactions of the {% code-page-name /%} type support additional values in the [flags field], as follows:
|
||||
|
||||
| Flag Name | Hex Value | Decimal Value | Description |
|
||||
|:--------------------|:-------------|:--------------|:------------|
|
||||
| `tfLoanOverpayment` | `0x00010000` | 65536 | Indicates that the remaining payment amount should be treated as an overpayment. |
|
||||
| `tfLoanFullPayment` | `0x00020000` | 131072 | Indicates that the borrower is making a full early repayment. |
|
||||
| `tfLoanLatePayment` | `0x00040000` | 262144 | Indicates that the borrower is making a late loan payment. |
|
||||
| Flag Name | Hex Value | Decimal Value | Description |
|
||||
|:----------|:----------|:--------------|:------------|
|
||||
| `tfLoanOverpayment` | `0x00010000` | 65536 | Indicates that the remaining payment amount should be treated as an overpayment. |
|
||||
| `tfLoanFullPayment` | `0x00020000` | 131072 | Indicates that the borrower is making a full early repayment. |
|
||||
|
||||
|
||||
## Error Cases
|
||||
|
||||
@@ -58,18 +58,19 @@ In addition to the [common fields][], {% code-page-name /%} transactions use the
|
||||
| Field Name | JSON Type | Internal Type | Required? | Description |
|
||||
|:--------------------------|:----------|:--------------|:----------|:------------|
|
||||
| `LoanBrokerID` | String | Hash256 | Yes | The ID of the `LoanBroker` ledger entry. |
|
||||
| `Flags` | String | UInt32 | No | Flags for the loan. |
|
||||
| `Data` | String | Blob | No | Arbitrary metadata in hex format (max 256 bytes). |
|
||||
| `Counterparty` | String | AccountID | No | The address of the counterparty of the loan. |
|
||||
| `LoanOriginationFee` | String | Number | No | The amount paid to the `LoanBroker` owner when the loan is created. |
|
||||
| `LoanServiceFee` | String | Number | No | The amount paid to the `LoanBroker` owner with each loan payment. |
|
||||
| `LatePaymentFee` | String | Number | No | The amount paid to the `LoanBroker` owner for late payments. |
|
||||
| `ClosePaymentFee` | String | Number | No | The amount paid to the `LoanBroker` owner for early full repayment. |
|
||||
| `LoanOriginationFee` | Number | Number | No | The amount paid to the `LoanBroker` owner when the loan is created. |
|
||||
| `LoanServiceFee` | Number | Number | No | The amount paid to the `LoanBroker` owner with each loan payment. |
|
||||
| `LatePaymentFee` | Number | Number | No | The amount paid to the `LoanBroker` owner for late payments. |
|
||||
| `ClosePaymentFee` | Number | Number | No | The amount paid to the `LoanBroker` owner for early full repayment. |
|
||||
| `OverpaymentFee` | Number | UInt32 | No | A fee charged on overpayments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
| `InterestRate` | Number | UInt32 | No | The annualized interest rate of the loan, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
| `LateInterestRate` | Number | UInt32 | No | A premium added to the interest rate for late payments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
| `CloseInterestRate` | Number | UInt32 | No | A fee charged for repaying the loan early, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
| `OverpaymentInterestRate` | Number | UInt32 | No | The interest rate charged on overpayments, in units of 1/10th basis points. Valid values are 0 to 100000 (inclusive), representing 0% to 100%. |
|
||||
| `PrincipalRequested` | String | Number | Yes | The principal loan amount requested by the borrower. |
|
||||
| `PrincipalRequested` | Number | Number | Yes | The principal loan amount requested by the borrower. |
|
||||
| `PaymentTotal` | Number | UInt32 | No | The total number of payments to be made against the loan. |
|
||||
| `PaymentInterval` | Number | UInt32 | No | The number of seconds between loan payments. |
|
||||
| `GracePeriod` | Number | UInt32 | No | The number of seconds after the loan's payment due date when it can be defaulted. |
|
||||
@@ -112,7 +113,7 @@ Besides errors that can occur for all transactions, {% code-page-name /%} transa
|
||||
| Error Code | Description |
|
||||
|:--------------------------|:-----------------------------------|
|
||||
| `temBAD_SIGNER` | - The transaction is missing a `CounterpartySignature` field.<br>- This transaction is part of a `Batch` transaction, but didn't specify a `Counterparty`. |
|
||||
| `temINVALID` | One or more of the numeric fields are outside their valid ranges. For example, the `GracePeriod` can't be longer than the `PaymentInterval` or less than `60` seconds. |
|
||||
| `temINVALID` | One or more of the numeric fields are outside their valid ranges. For example, the `GracePeriod` can't be longer than the `PaymentInterval`. |
|
||||
| `tecNO_ENTRY` | The `LoanBroker` doesn't exist. |
|
||||
| `tecNO_PERMISSION` | Neither the transaction sender's `Account` or the `Counterparty` field owns the associated `LoanBroker` ledger entry. |
|
||||
| `tecINSUFFICIENT_FUNDS` | - The `Vault` associated with the `LoanBroker` doesn't have enough assets to fund the loan.<br>- The `LoanBroker` ledger entry doesn't have enough first-loss capital to meet the minimum coverage requirement for the new total debt. |
|
||||
|
||||
@@ -30,7 +30,6 @@ To complete this tutorial, you should:
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||
- **JavaScript** with the [xrpl.js library][]. See [Get Started Using JavaScript][] for setup steps.
|
||||
- **Python** with the [xrpl-py library][]. See [Get Started Using Python][] for setup steps.
|
||||
|
||||
## Source Code
|
||||
|
||||
@@ -42,41 +41,25 @@ You can find the complete source code for this tutorial's examples in the {% rep
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
From the code sample folder, use `npm` to install dependencies.
|
||||
From the code sample folder, use npm to install dependencies.
|
||||
|
||||
```bash
|
||||
npm install xrpl
|
||||
```
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
From the code sample folder, set up a virtual environment and use `pip` to install dependencies.
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Set up client and accounts
|
||||
|
||||
To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:
|
||||
- `xrpl`: Used for XRPL client connection and transaction handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" before="// This step checks" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `json`: Used for loading and formatting JSON data.
|
||||
- `os`, `subprocess`, and `sys`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" before="# This step checks" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Next, load the loan broker account, MPT issuer account, loan broker ID, and MPT ID.
|
||||
@@ -84,16 +67,11 @@ Next, load the loan broker account, MPT issuer account, loan broker ID, and MPT
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// This step checks" before="// Check cover available" /%}
|
||||
|
||||
This example uses preconfigured accounts, MPTs, and loan broker data from the `lendingSetup.js` script, but you can replace `loanBroker`, `mptIssuer`, `loanBrokerID`, and `mptID` with your own values.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# This step checks" before="# Check cover available" /%}
|
||||
|
||||
This example uses preconfigured accounts, MPTs, and loan broker data from the `lending_setup.py` script, but you can replace `loan_broker`, `mpt_issuer`, `loan_broker_id`, and `mpt_id` with your own values.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
This example uses preconfigured accounts, MPTs, and loan broker data from the `lendingSetup.js` script, but you can replace `loanBroker`, `mptIssuer`, `loanBrokerID`, and `mptID` with your own values.
|
||||
|
||||
### 3. Check initial cover available
|
||||
|
||||
Check the initial cover (first-loss capital) available using the [ledger_entry method][].
|
||||
@@ -102,9 +80,6 @@ Check the initial cover (first-loss capital) available using the [ledger_entry m
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// Check cover available" before="// Prepare LoanBrokerCoverDeposit" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# Check cover available" before="# Prepare LoanBrokerCoverDeposit" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
If the `CoverAvailable` field is missing, it means no first-loss capital has been deposited.
|
||||
@@ -116,17 +91,10 @@ Create the [LoanBrokerCoverDeposit transaction][] object.
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// Prepare LoanBrokerCoverDeposit" before="// Sign, submit, and wait for deposit validation" /%}
|
||||
|
||||
The `Amount` field specifies the MPT and amount to deposit as first-loss capital.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# Prepare LoanBrokerCoverDeposit" before="# Sign, submit, and wait for deposit validation" /%}
|
||||
|
||||
The `amount` field specifies the MPT and amount to deposit as first-loss capital.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
If the transaction succeeds, the amount is deposited and held in the pseudo-account associated with the `LoanBroker` entry.
|
||||
The `Amount` field specifies the MPT and amount to deposit as first-loss capital. If the transaction succeeds, the amount is deposited and held in the pseudo-account associated with the `LoanBroker` entry.
|
||||
|
||||
### 5. Submit LoanBrokerCoverDeposit transaction
|
||||
|
||||
@@ -136,9 +104,6 @@ Sign and submit the `LoanBrokerCoverDeposit` transaction to the XRP Ledger.
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// Sign, submit, and wait for deposit validation" before="// Extract updated cover available" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# Sign, submit, and wait for deposit validation" before="# Extract updated cover available" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
@@ -151,9 +116,6 @@ Retrieve the cover available from the transaction result by checking the `LoanBr
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// Extract updated cover available" before="// Verify issuer of cover asset" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# Extract updated cover available" before="# Verify issuer of cover asset" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 7. Verify the asset issuer
|
||||
@@ -164,14 +126,11 @@ Before executing a clawback, verify that the account submitting the transaction
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// Verify issuer of cover asset" before="// Prepare LoanBrokerCoverClawback" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# Verify issuer of cover asset" before="# Prepare LoanBrokerCoverClawback" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Clawback functionality is disabled by default. In the case of MPTs, the `tfMPTCanClawback` flag must be enabled when the [MPTokenIssuanceCreate transaction][] is submitted. This tutorial uses an MPT that is already configured for clawback.
|
||||
|
||||
### 8. Prepare LoanBrokerCoverClawback transaction
|
||||
### 7. Prepare LoanBrokerCoverClawback transaction
|
||||
|
||||
Create the [LoanBrokerCoverClawback transaction][] object.
|
||||
|
||||
@@ -179,14 +138,11 @@ Create the [LoanBrokerCoverClawback transaction][] object.
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// Prepare LoanBrokerCoverClawback" before="// Sign, submit, and wait for clawback validation" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# Prepare LoanBrokerCoverClawback" before="# Sign, submit, and wait for clawback validation" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
In this example we claw back the entire amount, but you can specify any amount so long as it doesn't exceed the available cover or reduce the cover below the minimum required by the `LoanBroker`.
|
||||
|
||||
### 9. Submit LoanBrokerCoverClawback transaction
|
||||
### 8. Submit LoanBrokerCoverClawback transaction
|
||||
|
||||
Sign and submit the `LoanBrokerCoverClawback` transaction to the XRP Ledger.
|
||||
|
||||
@@ -194,14 +150,11 @@ Sign and submit the `LoanBrokerCoverClawback` transaction to the XRP Ledger.
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// Sign, submit, and wait for clawback validation" before="// Extract final cover available" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# Sign, submit, and wait for clawback validation" before="# Extract final cover available" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
|
||||
### 10. Check final cover available
|
||||
### 9. Check final cover available
|
||||
|
||||
Retrieve the final cover available from the transaction result.
|
||||
|
||||
@@ -209,9 +162,6 @@ Retrieve the final cover available from the transaction result.
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverClawback.js" language="js" from="// Extract final cover available" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_clawback.py" language="py" from="# Extract final cover available" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
## See Also
|
||||
|
||||
@@ -29,7 +29,6 @@ To complete this tutorial, you should:
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||
- **JavaScript** with the [xrpl.js library][]. See [Get Started Using JavaScript][] for setup steps.
|
||||
- **Python** with the [xrpl-py library][]. See [Get Started Using Python][] for setup steps.
|
||||
|
||||
## Source Code
|
||||
|
||||
@@ -41,41 +40,25 @@ You can find the complete source code for this tutorial's examples in the {% rep
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
From the code sample folder, use `npm` to install dependencies.
|
||||
From the code sample folder, use npm to install dependencies:
|
||||
|
||||
```bash
|
||||
npm install xrpl
|
||||
```
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
From the code sample folder, set up a virtual environment and use `pip` to install dependencies.
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Set up client and accounts
|
||||
|
||||
To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:
|
||||
- `xrpl`: Used for XRPL client connection and transaction handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoanBroker.js" language="js" before="// This step checks" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `json`: Used for loading and formatting JSON data.
|
||||
- `os`, `subprocess`, and `sys`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan_broker.py" language="py" before="# This step checks" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Next, load the vault owner account and vault ID. The vault owner will also be the loan broker.
|
||||
@@ -83,30 +66,22 @@ Next, load the vault owner account and vault ID. The vault owner will also be th
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoanBroker.js" language="js" from="// This step checks" before="// Prepare LoanBrokerSet" /%}
|
||||
|
||||
This example uses preconfigured accounts and vault data from the `lendingSetup.js` script, but you can replace `loanBroker` and `vaultID` with your own values.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan_broker.py" language="py" from="# This step checks" before="# Prepare LoanBrokerSet" /%}
|
||||
|
||||
This example uses preconfigured accounts and vault data from the `lending_setup.py` script, but you can replace `loan_broker` and `vault_id` with your own values.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
This example uses preconfigured accounts and vault data from the `lendingSetup.js` script, but you can replace `loanBroker` and `vaultID` with your own values.
|
||||
|
||||
### 3. Prepare LoanBrokerSet transaction
|
||||
|
||||
Create the [LoanBrokerSet transaction][] object.
|
||||
Create the [LoanBrokerSet transaction][] object:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoanBroker.js" language="js" from="// Prepare LoanBrokerSet" before="// Submit, sign" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan_broker.py" language="py" from="# Prepare LoanBrokerSet" before="# Submit, sign" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The management fee rate is set in 1/10th basis points. A value of `1000` equals 1% (100 basis points).
|
||||
The `ManagementFeeRate` is set in 1/10th basis points. A value of `1000` equals 1% (100 basis points).
|
||||
|
||||
### 4. Submit LoanBrokerSet transaction
|
||||
|
||||
@@ -116,9 +91,6 @@ Sign and submit the `LoanBrokerSet` transaction to the XRP Ledger.
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoanBroker.js" language="js" from="// Submit, sign" before="// Extract loan broker" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan_broker.py" language="py" from="# Submit, sign" before="# Extract loan broker" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
@@ -131,9 +103,6 @@ Retrieve the loan broker's information from the transaction result by checking f
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoanBroker.js" language="js" from="// Extract loan broker" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan_broker.py" language="py" from="# Extract loan broker" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The loan broker pseudo-account is a special account that holds first-loss capital.
|
||||
|
||||
@@ -32,7 +32,6 @@ To complete this tutorial, you should:
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||
- **JavaScript** with the [xrpl.js library][]. See [Get Started Using JavaScript][] for setup steps.
|
||||
- **Python** with the [xrpl-py library][]. See [Get Started Using Python][] for setup steps.
|
||||
|
||||
## Source Code
|
||||
|
||||
@@ -44,41 +43,25 @@ You can find the complete source code for this tutorial's examples in the {% rep
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
From the code sample folder, use `npm` to install dependencies.
|
||||
From the code sample folder, use npm to install dependencies:
|
||||
|
||||
```bash
|
||||
npm install xrpl
|
||||
```
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
From the code sample folder, set up a virtual environment and use `pip` to install dependencies.
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Set up client and accounts
|
||||
|
||||
To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:
|
||||
- `xrpl`: Used for XRPL client connection and transaction handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoan.js" language="js" before="// This step checks" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `json`: Used for loading and formatting JSON data.
|
||||
- `os`, `subprocess`, and `sys`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan.py" language="py" before="# This step checks" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Next, load the loan broker account, borrower account, and loan broker ID.
|
||||
@@ -86,23 +69,20 @@ Next, load the loan broker account, borrower account, and loan broker ID.
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoan.js" language="js" from="// This step checks" before="// Prepare LoanSet" /%}
|
||||
|
||||
This example uses preconfigured accounts and loan broker data from the `lendingSetup.js` script, but you can replace `loanBroker`, `borrower`, and `loanBrokerID` with your own values.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan.py" language="py" from="# This step checks" before="# Prepare LoanSet" /%}
|
||||
|
||||
This example uses preconfigured accounts and loan broker data from the `lending_setup.py` script, but you can replace `loan_broker`, `borrower`, and `loan_broker_id` with your own values.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
This example uses preconfigured accounts and loan broker data from the `lendingSetup.js` script, but you can replace `loanBroker`, `borrower`, and `loanBrokerID` with your own values.
|
||||
|
||||
### 3. Prepare LoanSet transaction
|
||||
|
||||
Create the [LoanSet transaction][] object with the loan terms.
|
||||
Create the [LoanSet transaction][] object with the loan terms:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoan.js" language="js" from="// Prepare LoanSet" before="// Loan broker signs first" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The `Account` field is the loan broker, and the `Counterparty` field is the borrower. These fields can be swapped, but determine the signing order: the `Account` signs first, and the `Counterparty` signs second.
|
||||
|
||||
@@ -114,60 +94,39 @@ The loan terms include:
|
||||
- `GracePeriod`: The number of seconds after a missed payment before the loan can be defaulted (604800 = 7 days).
|
||||
- `LoanOriginationFee`: A one-time fee charged when the loan is created, paid in the borrowed asset.
|
||||
- `LoanServiceFee`: A fee charged with every loan payment, paid in the borrowed asset.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan.py" language="py" from="# Prepare LoanSet" before="# Loan broker signs first" /%}
|
||||
|
||||
The `account` field is the loan broker, and the `counterparty` field is the borrower. These fields can be swapped, but determine the signing order: the `account` signs first, and the `counterparty` signs second.
|
||||
|
||||
The loan terms include:
|
||||
- `principal_requested`: The amount of an asset requested by the borrower. You don't have to specify the type of asset in this field.
|
||||
- `interest_rate`: The annualized interest rate in 1/10th basis points (500 = 0.5%).
|
||||
- `payment_total`: The number of payments to be made.
|
||||
- `payment_interval`: The number of seconds between payments (2592000 = 30 days).
|
||||
- `grace_period`: The number of seconds after a missed payment before the loan can be defaulted (604800 = 7 days).
|
||||
- `loan_origination_fee`: A one-time fee charged when the loan is created, paid in the borrowed asset.
|
||||
- `loan_service_fee`: A fee charged with every loan payment, paid in the borrowed asset.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 4. Add loan broker signature
|
||||
|
||||
The loan broker (the `Account`) signs the transaction first, adding their `TxnSignature` and `SigningPubKey` to the `LoanSet` transaction object.
|
||||
The loan broker (the `Account`) signs the transaction first, using the [sign method][]:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoan.js" language="js" from="// Loan broker signs first" before="// Borrower signs second" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan.py" language="py" from="# Loan broker signs first" before="# Borrower signs second" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The loan broker adds their `TxnSignature` and `SigningPubKey` to the `LoanSet` transaction object.
|
||||
|
||||
### 5. Add borrower signature
|
||||
|
||||
The borrower (the `Counterparty`) signs the transaction second. Their `TxnSignature` and `SigningPubKey` are stored in a `CounterpartySignature` field, which is added to the `LoanSet` transaction object.
|
||||
The borrower (the `Counterparty`) signs the transaction second, using the [sign method][]:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoan.js" language="js" from="// Borrower signs second" before="// Submit and wait" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan.py" language="py" from="# Borrower signs second" before="# Submit and wait" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The borrower must specify `signature_target: 'CounterpartySignature'`. This adds the borrower's signatures to a `CounterpartySignature` object, which includes the borrower's `TxnSignature` and `SigningPubKey`.
|
||||
|
||||
### 6. Submit LoanSet transaction
|
||||
|
||||
Submit the fully signed `LoanSet` transaction to the XRP Ledger.
|
||||
Sign and submit the fully signed `LoanSet` transaction to the XRP Ledger.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoan.js" language="js" from="// Submit and wait" before="// Extract loan information" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan.py" language="py" from="# Submit and wait" before="# Extract loan information" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
@@ -180,9 +139,6 @@ Retrieve the loan's information from the transaction result by checking for the
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/createLoan.js" language="js" from="// Extract loan information" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/create_loan.py" language="py" from="# Extract loan information" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
## See Also
|
||||
|
||||
@@ -31,7 +31,6 @@ To complete this tutorial, you should:
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||
- **JavaScript** with the [xrpl.js library][]. See [Get Started Using JavaScript][] for setup steps.
|
||||
- **Python** with the [xrpl-py library][]. See [Get Started Using Python][] for setup steps.
|
||||
|
||||
## Source Code
|
||||
|
||||
@@ -43,41 +42,25 @@ You can find the complete source code for this tutorial's examples in the {% rep
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
From the code sample folder, use `npm` to install dependencies.
|
||||
From the code sample folder, use npm to install dependencies:
|
||||
|
||||
```bash
|
||||
npm install xrpl
|
||||
```
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
From the code sample folder, set up a virtual environment and use `pip` to install dependencies.
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Set up client and accounts
|
||||
|
||||
To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:
|
||||
- `xrpl`: Used for XRPL client connection and transaction handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverDepositAndWithdraw.js" language="js" before="// This step checks" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `json`: Used for loading and formatting JSON data.
|
||||
- `os`, `subprocess`, and `sys`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_deposit_and_withdraw.py" language="py" before="# This step checks" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Next, load the loan broker account, loan broker ID, and MPT issuance ID.
|
||||
@@ -85,34 +68,22 @@ Next, load the loan broker account, loan broker ID, and MPT issuance ID.
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverDepositAndWithdraw.js" language="js" from="// This step checks" before="// Prepare LoanBrokerCoverDeposit" /%}
|
||||
|
||||
This example uses preconfigured accounts and loan broker data from the `lendingSetup.js` script, but you can replace `loanBroker`, `loanBrokerID`, and `mptID` with your own values.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_deposit_and_withdraw.py" language="py" from="# This step checks" before="# Prepare LoanBrokerCoverDeposit" /%}
|
||||
|
||||
This example uses preconfigured accounts and loan broker data from the `lending_setup.py` script, but you can replace `loan_broker`, `loan_broker_id`, and `mpt_id` with your own values.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
This example uses preconfigured accounts and loan broker data from the `lendingSetup.js` script, but you can replace `loanBroker`, `loanBrokerID`, and `mptID` with your own values.
|
||||
|
||||
### 3. Prepare LoanBrokerCoverDeposit transaction
|
||||
|
||||
Create the [LoanBrokerCoverDeposit transaction][] object.
|
||||
Create the [LoanBrokerCoverDeposit transaction][] object:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverDepositAndWithdraw.js" language="js" from="// Prepare LoanBrokerCoverDeposit" before="// Sign, submit, and wait for deposit" /%}
|
||||
|
||||
The `Amount` field specifies the MPT and amount to deposit as first-loss capital.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_deposit_and_withdraw.py" language="py" from="# Prepare LoanBrokerCoverDeposit" before="# Sign, submit, and wait for deposit" /%}
|
||||
|
||||
The `amount` field specifies the MPT and amount to deposit as first-loss capital.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
If the transaction succeeds, the amount is deposited and held in the pseudo-account associated with the `LoanBroker` entry.
|
||||
The `Amount` field specifies the MPT and amount to deposit as first-loss capital. If the transaction succeeds, the amount is deposited and held in the pseudo-account associated with the `LoanBroker` entry.
|
||||
|
||||
### 4. Submit LoanBrokerCoverDeposit transaction
|
||||
|
||||
@@ -122,9 +93,6 @@ Sign and submit the `LoanBrokerCoverDeposit` transaction to the XRP Ledger.
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverDepositAndWithdraw.js" language="js" from="// Sign, submit, and wait for deposit" before="// Extract cover balance" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_deposit_and_withdraw.py" language="py" from="# Sign, submit, and wait for deposit" before="# Extract cover balance" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
@@ -137,24 +105,18 @@ Retrieve the cover balance from the transaction result by checking the `LoanBrok
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverDepositAndWithdraw.js" language="js" from="// Extract cover balance" before="// Prepare LoanBrokerCoverWithdraw" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_deposit_and_withdraw.py" language="py" from="# Extract cover balance" before="# Prepare LoanBrokerCoverWithdraw" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The `LoanBroker` pseudo-account address is the `Account` field, and `CoverAvailable` shows the cover balance.
|
||||
|
||||
### 6. Prepare LoanBrokerCoverWithdraw transaction
|
||||
|
||||
Create the [LoanBrokerCoverWithdraw transaction][] object.
|
||||
Create the [LoanBrokerCoverWithdraw transaction][] object:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverDepositAndWithdraw.js" language="js" from="// Prepare LoanBrokerCoverWithdraw" before="// Sign, submit, and wait for withdraw" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_deposit_and_withdraw.py" language="py" from="# Prepare LoanBrokerCoverWithdraw" before="# Sign, submit, and wait for withdraw" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 7. Submit LoanBrokerCoverWithdraw transaction
|
||||
@@ -165,9 +127,6 @@ Sign and submit the `LoanBrokerCoverWithdraw` transaction to the XRP Ledger.
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverDepositAndWithdraw.js" language="js" from="// Sign, submit, and wait for withdraw" before="// Extract updated cover balance" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_deposit_and_withdraw.py" language="py" from="# Sign, submit, and wait for withdraw" before="# Extract updated cover balance" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
@@ -180,9 +139,6 @@ Retrieve the updated cover balance from the transaction result.
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/coverDepositAndWithdraw.js" language="js" from="// Extract updated cover balance" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/cover_deposit_and_withdraw.py" language="py" from="# Extract updated cover balance" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The `CoverAvailable` field now shows the reduced balance after the withdrawal.
|
||||
|
||||
@@ -32,7 +32,6 @@ To complete this tutorial, you should:
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||
- **JavaScript** with the [xrpl.js library][]. See [Get Started Using JavaScript][] for setup steps.
|
||||
- **Python** with the [xrpl-py library][]. See [Get Started Using Python][] for setup steps.
|
||||
|
||||
## Source Code
|
||||
|
||||
@@ -44,42 +43,25 @@ You can find the complete source code for this tutorial's examples in the {% rep
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
From the code sample folder, use `npm` to install dependencies.
|
||||
From the code sample folder, use npm to install dependencies:
|
||||
|
||||
```bash
|
||||
npm install xrpl
|
||||
```
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
From the code sample folder, set up a virtual environment and use `pip` to install dependencies.
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Set up client and accounts
|
||||
|
||||
To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:
|
||||
- `xrpl`: Used for XRPL client connection and transaction handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" before="// This step checks" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `json`: Used for loading and formatting JSON data.
|
||||
- `os`, `subprocess`, and `sys`: Used to run tutorial set up scripts.
|
||||
- `time` and `datetime`: Used for grace period countdown and date formatting.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" before="# This step checks" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Next, load the loan broker account and loan ID.
|
||||
@@ -87,70 +69,53 @@ Next, load the loan broker account and loan ID.
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// This step checks" before="// Check loan status" /%}
|
||||
|
||||
This example uses preconfigured accounts and loan data from the `lendingSetup.js` script, but you can replace `loanBroker` and `loanID` with your own values.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# This step checks" before="# Check loan status" /%}
|
||||
|
||||
This example uses preconfigured accounts and loan data from the `lending_setup.py` script, but you can replace `loan_broker` and `loan_id` with your own values.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
This example uses preconfigured accounts and loan data from the `lendingSetup.js` script, but you can replace `loanBroker` and `loanID` with your own values.
|
||||
|
||||
### 3. Check loan status
|
||||
|
||||
Check the current status of the loan using the [ledger_entry method][].
|
||||
Check the current status of the loan using the [ledger_entry method][]:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// Check loan status" before="// Prepare LoanManage transaction to impair" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# Check loan status" before="# Prepare LoanManage transaction to impair" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
This shows the total amount owed and the next payment due date. The [Ripple Epoch][] timestamp is converted to a readable date format.
|
||||
This shows the total amount owed and the next payment due date. The [Ripple Epoch][] timestamp is converted to a JavaScript Date object for readability.
|
||||
|
||||
### 4. Prepare LoanManage transaction to impair the loan
|
||||
|
||||
Create the [LoanManage transaction][] with the `tfLoanImpair` flag.
|
||||
Create the [LoanManage transaction][] with the `tfLoanImpair` flag:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// Prepare LoanManage transaction to impair" before="// Sign, submit, and wait for impairment" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# Prepare LoanManage transaction to impair" before="# Sign, submit, and wait for impairment" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 5. Submit LoanManage impairment transaction
|
||||
|
||||
Sign and submit the `LoanManage` transaction to impair the loan.
|
||||
Sign and submit the `LoanManage` transaction to impair the loan:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// Sign, submit, and wait for impairment" before="// Extract loan impairment info" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# Sign, submit, and wait for impairment" before="# Extract loan impairment info" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
|
||||
### 6. Get loan impairment information
|
||||
|
||||
Retrieve the loan's grace period and updated payment due date from the transaction result by checking for the `Loan` entry in the transaction metadata.
|
||||
Retrieve the loan's grace period and updated payment due date from the transaction result by checking for the `Loan` entry in the transaction metadata:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// Extract loan impairment info" before="// Countdown until loan can be defaulted" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# Extract loan impairment info" before="# Countdown until loan can be defaulted" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The loan can only be defaulted after the grace period expires. The example calculates when the grace period ends and displays a countdown.
|
||||
@@ -163,53 +128,41 @@ This countdown displays the remaining seconds in real-time. Once the grace perio
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// Countdown until loan can be defaulted" before="// Prepare LoanManage transaction to default" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# Countdown until loan can be defaulted" before="# Prepare LoanManage transaction to default" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 8. Prepare LoanManage transaction to default the loan
|
||||
|
||||
After the grace period expires, create a `LoanManage` transaction with the `tfLoanDefault` flag.
|
||||
After the grace period expires, create a `LoanManage` transaction with the `tfLoanDefault` flag:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// Prepare LoanManage transaction to default" before="// Sign, submit, and wait for default" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# Prepare LoanManage transaction to default" before="# Sign, submit, and wait for default" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 9. Submit LoanManage default transaction
|
||||
|
||||
Sign and submit the `LoanManage` transaction to default the loan.
|
||||
Sign and submit the `LoanManage` transaction to default the loan:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// Sign, submit, and wait for default" before="// Verify loan default status" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# Sign, submit, and wait for default" before="# Verify loan default status" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
|
||||
### 10. Verify loan default status
|
||||
|
||||
Confirm the loan has been defaulted by checking the loan flags.
|
||||
Confirm the loan has been defaulted by checking the loan flags:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanManage.js" language="js" from="// Verify loan default status" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_manage.py" language="py" from="# Verify loan default status" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The loan flags are parsed to confirm the `tfLoanDefault` flag is now set.
|
||||
The `parseTransactionFlags` function converts the numeric flags to a readable format, showing that the `tfLoanDefault` flag is now set.
|
||||
|
||||
## See Also
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ To complete this tutorial, you should:
|
||||
- Have a basic understanding of the XRP Ledger.
|
||||
- Have an XRP Ledger client library set up in your development environment. This page provides examples for the following:
|
||||
- **JavaScript** with the [xrpl.js library][]. See [Get Started Using JavaScript][] for setup steps.
|
||||
- **Python** with the [xrpl-py library][]. See [Get Started Using Python][] for setup steps.
|
||||
|
||||
## Source Code
|
||||
|
||||
@@ -44,41 +43,25 @@ You can find the complete source code for this tutorial's examples in the {% rep
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
From the code sample folder, use `npm` to install dependencies.
|
||||
From the code sample folder, use npm to install dependencies:
|
||||
|
||||
```bash
|
||||
npm install xrpl
|
||||
```
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
From the code sample folder, set up a virtual environment and use `pip` to install dependencies.
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 2. Set up client and accounts
|
||||
|
||||
To get started, import the necessary libraries and instantiate a client to connect to the XRPL. This example imports:
|
||||
- `xrpl`: Used for XRPL client connection and transaction handling.
|
||||
- `fs` and `child_process`: Used to run tutorial setup scripts.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `fs` and `child_process`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" before="// This step checks" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
- `xrpl`: Used for XRPL client connection, transaction submission, and wallet handling.
|
||||
- `json`: Used for loading and formatting JSON data.
|
||||
- `os`, `subprocess`, and `sys`: Used to run tutorial set up scripts.
|
||||
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" before="# This step checks" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Next, load the borrower account, loan ID, and MPT issuance ID.
|
||||
@@ -86,27 +69,19 @@ Next, load the borrower account, loan ID, and MPT issuance ID.
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" from="// This step checks" before="// Check initial loan status" /%}
|
||||
|
||||
This example uses preconfigured accounts and loan data from the `lendingSetup.js` script, but you can replace `borrower`, `loanID`, and `mptID` with your own values.
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" from="# This step checks" before="# Check initial loan status" /%}
|
||||
|
||||
This example uses preconfigured accounts and loan data from the `lending_setup.py` script, but you can replace `borrower`, `loan_id`, and `mpt_id` with your own values.
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
This example uses preconfigured accounts and loan data from the `lendingSetup.js` script, but you can replace `borrower`, `loanID`, and `mptID` with your own values.
|
||||
|
||||
### 3. Check loan status
|
||||
|
||||
Check the current status of the loan using the [ledger_entry method][].
|
||||
Check the current status of the loan using the [ledger_entry method][]:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" from="// Check initial loan status" before="// Prepare LoanPay transaction" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" from="# Check initial loan status" before="# Prepare LoanPay transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
The `TotalValueOutstanding` field contains the remaining principal plus accrued interest; the `LoanServiceFee` is an additional fee charged per payment. Add these together to calculate the total payment.
|
||||
@@ -117,88 +92,70 @@ Other fees can be charged on a loan, such as late or early payment fees. These a
|
||||
|
||||
### 4. Prepare LoanPay transaction
|
||||
|
||||
Create the [LoanPay transaction][] with the total payment amount.
|
||||
Create the [LoanPay transaction][] with the total payment amount:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" from="// Prepare LoanPay transaction" before="// Sign, submit, and wait for payment validation" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" from="# Prepare LoanPay transaction" before="# Sign, submit, and wait for payment validation" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
### 5. Submit LoanPay transaction
|
||||
|
||||
Sign and submit the `LoanPay` transaction to the XRP Ledger.
|
||||
Sign and submit the `LoanPay` transaction to the XRP Ledger:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" from="// Sign, submit, and wait for payment validation" before="// Extract updated loan info" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" from="# Sign, submit, and wait for payment validation" before="# Extract updated loan info" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
|
||||
### 6. Check loan balance
|
||||
|
||||
Retrieve the loan balance from the transaction result by checking for the `Loan` entry in the transaction metadata.
|
||||
Retrieve the loan balance from the transaction result by checking for the `Loan` entry in the transaction metadata:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" from="// Extract updated loan info" before="// Prepare LoanDelete transaction" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" from="# Extract updated loan info" before="# Prepare LoanDelete transaction" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
If `TotalValueOutstanding` is absent from the loan metadata, the loan has been fully paid off and is ready for deletion.
|
||||
|
||||
### 7. Prepare LoanDelete transaction
|
||||
|
||||
Create a [LoanDelete transaction][] to remove the paid loan from the XRP Ledger.
|
||||
Create a [LoanDelete transaction][] to remove the paid loan from the XRP Ledger:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" from="// Prepare LoanDelete transaction" before="// Sign, submit, and wait for deletion validation" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" from="# Prepare LoanDelete transaction" before="# Sign, submit, and wait for deletion validation" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Either the loan broker or the borrower can submit a `LoanDelete` transaction. In this example, the borrower deletes their own paid off loan.
|
||||
|
||||
### 8. Submit LoanDelete transaction
|
||||
|
||||
Sign and submit the `LoanDelete` transaction.
|
||||
Sign and submit the `LoanDelete` transaction:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" from="// Sign, submit, and wait for deletion validation" before="// Verify loan deletion" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" from="# Sign, submit, and wait for deletion validation" before="# Verify loan deletion" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
Verify that the transaction succeeded by checking for a `tesSUCCESS` result code.
|
||||
|
||||
### 9. Verify loan deletion
|
||||
|
||||
Confirm that the loan has been removed from the XRP Ledger.
|
||||
Confirm that the loan has been removed from the XRP Ledger:
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="JavaScript" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/js/loanPay.js" language="js" from="// Verify loan deletion" /%}
|
||||
{% /tab %}
|
||||
{% tab label="Python" %}
|
||||
{% code-snippet file="/_code-samples/lending-protocol/py/loan_pay.py" language="py" from="# Verify loan deletion" /%}
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
If the `ledger_entry` method returns an `entryNotFound` error, the loan has been successfully deleted.
|
||||
|
||||
@@ -44,8 +44,8 @@ The XRPL lending protocol addresses these challenges through:
|
||||
|
||||
### Regulatory Compliance
|
||||
|
||||
- Accounts on the XRPL can be vetted by a trusted credential issuer. Credentials can be issued and revoked based on relevant criteria, such as credit score.
|
||||
- Permissioned Domains act as a gateway, limiting who can access the credit facilities based on accepted credentials you define.
|
||||
- Accounts on the XRPL can be vetted by a trusted credential issuer. Credentials can be issued and revoked, based around relevant criteria, such as credit score.
|
||||
- Permissioned Domains act as a gateway, limiting who can access the credit facilities, based on accepted credentials you define.
|
||||
- All credential and loan info is transparent on the XRPL, which makes compliance reporting and monitoring simpler and tamper-proof.
|
||||
|
||||
|
||||
@@ -56,46 +56,18 @@ The XRPL lending protocol addresses these challenges through:
|
||||
- Built-in first-loss capital features automatically protect against asset losses from defaults.
|
||||
|
||||
|
||||
## User Journeys
|
||||
## Implementation Steps
|
||||
|
||||
There are three users that enable institutional credit facilities on the XRP Ledger: Loan Brokers, Lenders, and Borrowers. The tabs below outline which features and transactions each user typically uses in the lending process.
|
||||
|
||||
{% tabs %}
|
||||
{% tab label="Loan Broker" %}
|
||||
As a **Loan Broker**, I need to:
|
||||
- Create a [LoanBroker entry][] to define the configuration of a Lending Protocol.
|
||||
- Maintain the required [first-loss capital](../../concepts/tokens/lending-protocol.md#first-loss-capital) to protect deposits in my Single Asset Vault.
|
||||
|
||||
| Step | Description | Technical Implementation |
|
||||
|:-------------------------------|:------------|:-------------------------|
|
||||
| Vault Setup | The Loan Broker creates a Single Asset Vault to aggregate one type of asset to lend out. They define a [permissioned domain][] to ensure only accounts that meet KYB (Know Your Business) compliance requirements can deposit into the vault. | - [Create Permissioned Domains](../../tutorials/javascript/compliance/create-permissioned-domains.md)<br>- [Create a Single Asset Vault](../../tutorials/how-tos/set-up-lending/use-single-asset-vaults/create-a-single-asset-vault.md) |
|
||||
| Lending Protocol Setup | The Loan Broker sets up the Lending Protocol instance, linking it to the Single Asset Vault they created, and defining parameters such as payment fees. | [Create a Loan Broker](../../tutorials/how-tos/set-up-lending/use-the-lending-protocol/create-a-loan-broker.md) |
|
||||
| First-loss Capital Maintenance | The Loan Broker deposits first-loss capital into the Lending Protocol to meet the minimum cover required. When there is excess cover, they withdraw first-loss capital. | [Deposit and Withdraw First-Loss Capital](../../tutorials/how-tos/set-up-lending/use-the-lending-protocol/deposit-and-withdraw-cover.md) |
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Lender" %}
|
||||
As a **Lender**, I need to:
|
||||
- Authorize my account to deposit assets into a Single Asset Vault, so that I can deploy idle liquidity to generate yield.
|
||||
- Redeem vault shares to realize my earnings and return assets to my account.
|
||||
|
||||
| Step | Description | Technical Implementation |
|
||||
|:----------------|:------------|:-------------------------|
|
||||
| Onboarding | The Lender triggers a verification workflow with the Loan Broker managing the Lending Protocol. The Loan Broker can issue their own credentials or utilize a credential issuer. Upon successful KYB, a credential is issued and the Lender accepts the credential. | [Build a Credential Issuing Service](../../tutorials/javascript/build-apps/credential-issuing-service.md) |
|
||||
| Deposit Asset | The Lender deposits assets into a Single Asset Vault to lend out. Vault shares are minted and sent back to the Lender, representing their stake in the vault. | [Deposit into a Vault](../../tutorials/how-tos/set-up-lending/use-single-asset-vaults/deposit-into-a-vault.md) |
|
||||
| Withdraw Asset | Vault shares are yield-bearing assets; the vault collects interest and fees on loans, which increases the underlying value of each vault share. The Lender collects their deposit (plus yield) by redeeming vault shares. | [Withdraw from a Vault](../../tutorials/how-tos/set-up-lending/use-single-asset-vaults/withdraw-from-a-vault.md) |
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="Borrower" %}
|
||||
As a **Borrower**, I need to:
|
||||
- Authorize my account to request loans from a Loan Broker.
|
||||
- Repay my loan.
|
||||
|
||||
| Step | Description | Technical Implementation |
|
||||
|:-----------------|:------------|:-------------------------|
|
||||
| Onboarding | The Borrower triggers a verification workflow with the Loan Broker managing the Lending Protocol. The Loan Broker can issue their own credentials or utilize a credential issuer. Upon successful KYB, a credential is issued and the Borrower accepts the credential. | [Build a Credential Issuing Service](../../tutorials/javascript/build-apps/credential-issuing-service.md) |
|
||||
| Loan Application | The Borrower applies for a loan with the Loan Broker. Both parties agree on the terms and co-sign the loan. | [Create a Loan](../../tutorials/how-tos/set-up-lending/use-the-lending-protocol/create-a-loan.md) |
|
||||
| Repayment | The Borrower makes payments on principal, interest, and fees according to the loan agreement. | [Pay Off a Loan](../../tutorials/how-tos/set-up-lending/use-the-lending-protocol/pay-off-a-loan.md) |
|
||||
{% /tab %}
|
||||
{% /tabs %}
|
||||
|
||||
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||
1. Set Up Credential System
|
||||
- Select or become a credential issuer.
|
||||
- Define required credentials for borrowers.
|
||||
- Set up Permissioned Domains to protect your lending protocol and stay compliant with regulations.
|
||||
2. Set Up Asset Vaults
|
||||
- Set up vaults for different lending assets.
|
||||
- Define public/private access parameters.
|
||||
- Establish vault management policies.
|
||||
3. Deploy Lending Protocol
|
||||
- Create a LoanBroker and configure lending parameters.
|
||||
- Create and manage loans, including fees, impairment and default settings.
|
||||
- Set up monitoring and reporting systems.
|
||||
- Withdraw and repay loans.
|
||||
|
||||
File diff suppressed because one or more lines are too long
23
static/img/uses/bitget-wallet.svg
Normal file
23
static/img/uses/bitget-wallet.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<svg width="1623" height="256" viewBox="0 0 1623 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1542_6419)">
|
||||
<rect width="256" height="256" rx="60" fill="white"/>
|
||||
<path d="M106.241 37.6137C95.9065 37.6084 85.5894 37.6031 75.2185 37.619C68.9476 37.619 66.5955 45.4918 71.2593 50.1551L141.857 120.753C144.06 122.768 145.434 124.959 145.485 127.846C145.434 130.733 144.06 132.923 141.857 134.939L71.2593 205.537C66.5955 210.2 68.9476 218.073 75.2185 218.073C85.5894 218.089 95.9065 218.083 106.241 218.078C111.416 218.075 116.594 218.073 121.787 218.073C128.579 218.073 132.62 214.444 136.249 210.815L199.919 147.145C205 142.063 209.547 135.316 209.485 127.846C209.547 120.375 205 113.628 199.919 108.547L136.249 44.8768C132.62 41.2479 128.579 37.619 121.787 37.619C116.594 37.619 111.416 37.6163 106.241 37.6137Z" fill="#001F29"/>
|
||||
<path d="M1601.73 208.139C1579.27 208.139 1568.77 196.418 1568.77 175.662V119.011H1559.98C1556.31 119.011 1554.12 116.814 1554.12 113.151V101.674C1554.12 98.0115 1556.31 95.8138 1559.98 95.8138H1568.77V67.2442C1568.77 63.5815 1570.96 61.3838 1574.63 61.3838H1593.43C1597.09 61.3838 1599.29 63.5815 1599.29 67.2442V95.8138H1617.36C1621.02 95.8138 1623.22 98.0115 1623.22 101.674V113.151C1623.22 116.814 1621.02 119.011 1617.36 119.011H1599.29V170.779C1599.29 183.965 1607.35 184.453 1614.43 184.453H1616.14C1619.8 184.453 1622 186.651 1622 190.313V202.278C1622 205.941 1619.8 208.139 1616.14 208.139H1601.73Z" fill="white"/>
|
||||
<path d="M1493.17 210.58C1458.75 210.58 1436.04 185.429 1436.04 151.976C1436.04 118.523 1458.01 93.6157 1491.95 93.6157C1525.4 93.6157 1545.91 118.523 1545.91 151.976V154.418C1545.91 158.08 1543.72 160.278 1540.05 160.278H1465.34C1468.27 175.418 1479.26 184.452 1493.17 184.452C1504.41 184.452 1511.49 180.546 1516.13 176.394C1518.81 173.953 1521.25 173.464 1524.18 175.662L1535.66 184.208C1538.83 186.65 1539.57 189.092 1537.37 191.778C1527.36 203.499 1511.73 210.58 1493.17 210.58ZM1465.83 140.988H1517.35C1514.66 127.802 1506.36 117.79 1491.95 117.79C1478.04 117.79 1468.76 126.825 1465.83 140.988Z" fill="white"/>
|
||||
<path d="M1393.23 208.139C1389.56 208.139 1387.37 205.941 1387.37 202.279V55.2794C1387.37 51.6166 1389.56 49.4189 1393.23 49.4189H1412.27C1415.93 49.4189 1418.13 51.6166 1418.13 55.2794L1417.89 202.279C1417.89 205.941 1415.69 208.139 1412.03 208.139H1393.23Z" fill="white"/>
|
||||
<path d="M1340.4 208.139C1336.74 208.139 1334.54 205.941 1334.54 202.279V55.2794C1334.54 51.6166 1336.74 49.4189 1340.4 49.4189H1359.45C1363.11 49.4189 1365.31 51.6166 1365.31 55.2794L1365.07 202.279C1365.07 205.941 1362.87 208.139 1359.21 208.139H1340.4Z" fill="white"/>
|
||||
<path d="M1249.73 210.093C1218.96 210.093 1196.5 185.43 1196.5 151.977C1196.5 118.035 1218.96 94.105 1249.73 94.105C1263.89 94.105 1274.39 99.2329 1281.96 107.779V101.675C1281.96 98.0119 1284.16 95.8143 1287.82 95.8143H1306.62C1310.28 95.8143 1312.48 98.0119 1312.48 101.675V202.279C1312.48 205.942 1310.28 208.139 1306.62 208.139H1287.82C1284.16 208.139 1281.96 205.942 1281.96 202.279V196.418C1274.39 204.965 1263.89 210.093 1249.73 210.093ZM1254.12 181.279C1270.97 181.279 1281.96 168.826 1281.96 151.977C1281.96 135.128 1270.97 122.675 1254.12 122.675C1237.28 122.675 1226.04 135.128 1226.04 151.977C1226.04 168.826 1237.28 181.279 1254.12 181.279Z" fill="white"/>
|
||||
<path d="M1037.19 208.139C1033.77 208.139 1031.33 206.43 1030.35 203.255L981.274 56.0119C980.053 52.105 982.006 49.4189 986.157 49.4189H1007.4C1010.82 49.4189 1013.26 51.1282 1014.24 54.3026L1046.22 150.511L1077.97 54.3026C1078.94 51.1282 1081.14 49.4189 1084.56 49.4189H1097.5C1100.92 49.4189 1103.36 51.1282 1104.34 54.3026L1135.35 146.605L1166.11 54.3026C1167.09 51.1282 1169.53 49.4189 1172.95 49.4189H1194.19C1198.34 49.4189 1200.29 52.105 1199.07 56.0119L1150 203.255C1149.02 206.43 1146.58 208.139 1143.16 208.139H1126.31C1122.89 208.139 1120.45 206.43 1119.47 203.255L1090.17 114.616L1060.87 203.255C1059.9 206.43 1057.45 208.139 1054.04 208.139H1037.19Z" fill="white"/>
|
||||
<path d="M904.354 208.139C881.89 208.139 871.39 196.418 871.39 175.662V119.011H862.6C858.938 119.011 856.74 116.814 856.74 113.151V101.674C856.74 98.0115 858.938 95.8138 862.6 95.8138H871.39V67.2442C871.39 63.5815 873.588 61.3838 877.251 61.3838H896.052C899.714 61.3838 901.912 63.5815 901.912 67.2442V95.8138H919.98C923.643 95.8138 925.841 98.0115 925.841 101.674V113.151C925.841 116.814 923.643 119.011 919.98 119.011H901.912V170.779C901.912 183.965 909.969 184.453 917.05 184.453H918.76C922.422 184.453 924.62 186.651 924.62 190.313V202.278C924.62 205.941 922.422 208.139 918.76 208.139H904.354Z" fill="white"/>
|
||||
<path d="M795.801 210.58C761.373 210.58 738.665 185.429 738.665 151.976C738.665 118.523 760.64 93.6157 794.58 93.6157C828.032 93.6157 848.542 118.523 848.542 151.976V154.418C848.542 158.08 846.344 160.278 842.682 160.278H767.966C770.896 175.418 781.883 184.452 795.801 184.452C807.033 184.452 814.114 180.546 818.753 176.394C821.439 173.953 823.881 173.464 826.811 175.662L838.287 184.208C841.461 186.65 842.193 189.092 839.996 191.778C829.985 203.499 814.358 210.58 795.801 210.58ZM768.454 140.988H819.974C817.288 127.802 808.986 117.79 794.58 117.79C780.662 117.79 771.384 126.825 768.454 140.988Z" fill="white"/>
|
||||
<path d="M660.68 256C642.855 256 627.717 249.895 617.217 240.127C614.287 237.441 614.776 234.511 617.706 231.825L628.693 222.546C631.379 220.104 634.065 220.349 636.995 222.546C644.809 228.895 653.355 230.36 660.68 230.36C671.179 230.36 690.224 224.5 690.224 200.325V196.174C682.655 204.721 671.912 210.093 657.75 210.093C626.984 210.093 604.765 185.43 604.765 151.977C604.765 118.523 626.984 94.105 657.75 94.105C671.912 94.105 682.655 99.2329 690.224 108.024V101.675C690.224 98.0119 692.422 95.8143 696.084 95.8143H714.886C718.548 95.8143 720.746 98.0119 720.746 101.675V200.325C720.746 232.558 699.503 256 660.68 256ZM662.145 181.279C678.993 181.279 690.224 168.826 690.224 151.977C690.224 135.128 678.993 122.675 662.145 122.675C645.297 122.675 634.309 135.128 634.309 151.977C634.309 168.826 645.297 181.279 662.145 181.279Z" fill="white"/>
|
||||
<path d="M574.449 208.139C551.986 208.139 541.486 196.418 541.486 175.662V119.011H532.696C529.033 119.011 526.836 116.814 526.836 113.151V101.674C526.836 98.0115 529.033 95.8138 532.696 95.8138H541.486V67.2442C541.486 63.5815 543.684 61.3838 547.346 61.3838H566.147C569.81 61.3838 572.008 63.5815 572.008 67.2442V95.8138H590.076C593.739 95.8138 595.936 98.0115 595.936 101.674V113.151C595.936 116.814 593.739 119.011 590.076 119.011H572.008V170.779C572.008 183.965 580.065 184.453 587.146 184.453H588.855C592.518 184.453 594.715 186.651 594.715 190.313V202.278C594.715 205.941 592.518 208.139 588.855 208.139H574.449Z" fill="white"/>
|
||||
<path d="M495.323 79.2091C487.022 79.2091 478.476 72.8603 478.476 62.1162C478.476 51.6162 487.022 46 495.323 46C503.381 46 512.171 51.6162 512.171 62.1162C512.171 72.8603 503.381 79.2091 495.323 79.2091ZM485.801 208.139C482.138 208.139 479.941 205.941 479.941 202.278V101.674C479.941 98.0114 482.138 95.8137 485.801 95.8137H504.846C508.509 95.8137 510.706 98.0114 510.706 101.674L510.462 202.278C510.462 205.941 508.264 208.139 504.602 208.139H485.801Z" fill="white"/>
|
||||
<path d="M341.86 208.139C338.198 208.139 336 205.941 336 202.279V55.2794C336 51.6166 338.198 49.4189 341.86 49.4189H409.984C434.401 49.4189 456.132 65.291 456.132 94.1048C456.132 109.244 450.272 119.5 441.238 125.849C453.446 132.686 461.992 144.651 461.992 162.232C461.992 191.046 438.796 208.139 414.379 208.139H341.86ZM367.498 113.64H404.856C416.332 113.64 423.657 106.802 423.657 95.8141C423.657 84.8258 416.332 78.2328 404.856 78.2328H367.498V113.64ZM367.498 179.325H409.251C421.948 179.325 429.517 170.535 429.517 159.546C429.517 148.558 421.46 139.767 409.251 139.767H367.498V179.325Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1542_6419">
|
||||
<rect width="1623" height="256" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
BIN
static/img/uses/lightmode/bitget-wallet.png
Normal file
BIN
static/img/uses/lightmode/bitget-wallet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
23
static/img/uses/lightmode/bitget-wallet.svg
Normal file
23
static/img/uses/lightmode/bitget-wallet.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<svg width="1623" height="256" viewBox="0 0 1623 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1542_2219)">
|
||||
<rect width="256" height="256" rx="60" fill="#001F29"/>
|
||||
<path d="M106.241 37.6137C95.9065 37.6084 85.5894 37.6031 75.2185 37.619C68.9476 37.619 66.5955 45.4918 71.2593 50.1551L141.857 120.753C144.06 122.768 145.434 124.959 145.485 127.846C145.434 130.733 144.06 132.923 141.857 134.939L71.2593 205.537C66.5955 210.2 68.9476 218.073 75.2185 218.073C85.5894 218.089 95.9065 218.083 106.241 218.078C111.416 218.075 116.594 218.073 121.787 218.073C128.579 218.073 132.62 214.444 136.249 210.815L199.919 147.145C205 142.063 209.547 135.316 209.485 127.846C209.547 120.375 205 113.628 199.919 108.547L136.249 44.8768C132.62 41.2479 128.579 37.619 121.787 37.619C116.594 37.619 111.416 37.6163 106.241 37.6137Z" fill="#00F0FF"/>
|
||||
<path d="M1601.73 208.139C1579.27 208.139 1568.77 196.418 1568.77 175.662V119.011H1559.98C1556.31 119.011 1554.12 116.814 1554.12 113.151V101.674C1554.12 98.0115 1556.31 95.8138 1559.98 95.8138H1568.77V67.2442C1568.77 63.5815 1570.96 61.3838 1574.63 61.3838H1593.43C1597.09 61.3838 1599.29 63.5815 1599.29 67.2442V95.8138H1617.36C1621.02 95.8138 1623.22 98.0115 1623.22 101.674V113.151C1623.22 116.814 1621.02 119.011 1617.36 119.011H1599.29V170.779C1599.29 183.965 1607.35 184.453 1614.43 184.453H1616.14C1619.8 184.453 1622 186.651 1622 190.313V202.278C1622 205.941 1619.8 208.139 1616.14 208.139H1601.73Z" fill="#001F29"/>
|
||||
<path d="M1493.17 210.58C1458.75 210.58 1436.04 185.429 1436.04 151.976C1436.04 118.523 1458.01 93.6157 1491.95 93.6157C1525.4 93.6157 1545.91 118.523 1545.91 151.976V154.418C1545.91 158.08 1543.72 160.278 1540.05 160.278H1465.34C1468.27 175.418 1479.26 184.452 1493.17 184.452C1504.41 184.452 1511.49 180.546 1516.13 176.394C1518.81 173.953 1521.25 173.464 1524.18 175.662L1535.66 184.208C1538.83 186.65 1539.57 189.092 1537.37 191.778C1527.36 203.499 1511.73 210.58 1493.17 210.58ZM1465.83 140.988H1517.35C1514.66 127.802 1506.36 117.79 1491.95 117.79C1478.04 117.79 1468.76 126.825 1465.83 140.988Z" fill="#001F29"/>
|
||||
<path d="M1393.23 208.139C1389.56 208.139 1387.37 205.941 1387.37 202.279V55.2794C1387.37 51.6166 1389.56 49.4189 1393.23 49.4189H1412.27C1415.93 49.4189 1418.13 51.6166 1418.13 55.2794L1417.89 202.279C1417.89 205.941 1415.69 208.139 1412.03 208.139H1393.23Z" fill="#001F29"/>
|
||||
<path d="M1340.4 208.139C1336.74 208.139 1334.54 205.941 1334.54 202.279V55.2794C1334.54 51.6166 1336.74 49.4189 1340.4 49.4189H1359.45C1363.11 49.4189 1365.31 51.6166 1365.31 55.2794L1365.07 202.279C1365.07 205.941 1362.87 208.139 1359.21 208.139H1340.4Z" fill="#001F29"/>
|
||||
<path d="M1249.73 210.093C1218.96 210.093 1196.5 185.43 1196.5 151.977C1196.5 118.035 1218.96 94.105 1249.73 94.105C1263.89 94.105 1274.39 99.2329 1281.96 107.779V101.675C1281.96 98.0119 1284.16 95.8143 1287.82 95.8143H1306.62C1310.28 95.8143 1312.48 98.0119 1312.48 101.675V202.279C1312.48 205.942 1310.28 208.139 1306.62 208.139H1287.82C1284.16 208.139 1281.96 205.942 1281.96 202.279V196.418C1274.39 204.965 1263.89 210.093 1249.73 210.093ZM1254.12 181.279C1270.97 181.279 1281.96 168.826 1281.96 151.977C1281.96 135.128 1270.97 122.675 1254.12 122.675C1237.28 122.675 1226.04 135.128 1226.04 151.977C1226.04 168.826 1237.28 181.279 1254.12 181.279Z" fill="#001F29"/>
|
||||
<path d="M1037.19 208.139C1033.77 208.139 1031.33 206.43 1030.35 203.255L981.274 56.0119C980.053 52.105 982.006 49.4189 986.157 49.4189H1007.4C1010.82 49.4189 1013.26 51.1282 1014.24 54.3026L1046.22 150.511L1077.97 54.3026C1078.94 51.1282 1081.14 49.4189 1084.56 49.4189H1097.5C1100.92 49.4189 1103.36 51.1282 1104.34 54.3026L1135.35 146.605L1166.11 54.3026C1167.09 51.1282 1169.53 49.4189 1172.95 49.4189H1194.19C1198.34 49.4189 1200.29 52.105 1199.07 56.0119L1150 203.255C1149.02 206.43 1146.58 208.139 1143.16 208.139H1126.31C1122.89 208.139 1120.45 206.43 1119.47 203.255L1090.17 114.616L1060.87 203.255C1059.9 206.43 1057.45 208.139 1054.04 208.139H1037.19Z" fill="#001F29"/>
|
||||
<path d="M904.354 208.139C881.89 208.139 871.39 196.418 871.39 175.662V119.011H862.6C858.938 119.011 856.74 116.814 856.74 113.151V101.674C856.74 98.0115 858.938 95.8138 862.6 95.8138H871.39V67.2442C871.39 63.5815 873.588 61.3838 877.251 61.3838H896.052C899.714 61.3838 901.912 63.5815 901.912 67.2442V95.8138H919.98C923.643 95.8138 925.841 98.0115 925.841 101.674V113.151C925.841 116.814 923.643 119.011 919.98 119.011H901.912V170.779C901.912 183.965 909.969 184.453 917.05 184.453H918.76C922.422 184.453 924.62 186.651 924.62 190.313V202.278C924.62 205.941 922.422 208.139 918.76 208.139H904.354Z" fill="#001F29"/>
|
||||
<path d="M795.801 210.58C761.373 210.58 738.665 185.429 738.665 151.976C738.665 118.523 760.64 93.6157 794.58 93.6157C828.032 93.6157 848.542 118.523 848.542 151.976V154.418C848.542 158.08 846.344 160.278 842.682 160.278H767.966C770.896 175.418 781.883 184.452 795.801 184.452C807.033 184.452 814.114 180.546 818.753 176.394C821.439 173.953 823.881 173.464 826.811 175.662L838.287 184.208C841.461 186.65 842.193 189.092 839.996 191.778C829.985 203.499 814.358 210.58 795.801 210.58ZM768.454 140.988H819.974C817.288 127.802 808.986 117.79 794.58 117.79C780.662 117.79 771.384 126.825 768.454 140.988Z" fill="#001F29"/>
|
||||
<path d="M660.68 256C642.855 256 627.717 249.895 617.217 240.127C614.287 237.441 614.776 234.511 617.706 231.825L628.693 222.546C631.379 220.104 634.065 220.349 636.995 222.546C644.809 228.895 653.355 230.36 660.68 230.36C671.179 230.36 690.224 224.5 690.224 200.325V196.174C682.655 204.721 671.912 210.093 657.75 210.093C626.984 210.093 604.765 185.43 604.765 151.977C604.765 118.523 626.984 94.105 657.75 94.105C671.912 94.105 682.655 99.2329 690.224 108.024V101.675C690.224 98.0119 692.422 95.8143 696.084 95.8143H714.886C718.548 95.8143 720.746 98.0119 720.746 101.675V200.325C720.746 232.558 699.503 256 660.68 256ZM662.145 181.279C678.993 181.279 690.224 168.826 690.224 151.977C690.224 135.128 678.993 122.675 662.145 122.675C645.297 122.675 634.309 135.128 634.309 151.977C634.309 168.826 645.297 181.279 662.145 181.279Z" fill="#001F29"/>
|
||||
<path d="M574.449 208.139C551.986 208.139 541.486 196.418 541.486 175.662V119.011H532.696C529.033 119.011 526.836 116.814 526.836 113.151V101.674C526.836 98.0115 529.033 95.8138 532.696 95.8138H541.486V67.2442C541.486 63.5815 543.684 61.3838 547.346 61.3838H566.147C569.81 61.3838 572.008 63.5815 572.008 67.2442V95.8138H590.076C593.739 95.8138 595.936 98.0115 595.936 101.674V113.151C595.936 116.814 593.739 119.011 590.076 119.011H572.008V170.779C572.008 183.965 580.065 184.453 587.146 184.453H588.855C592.518 184.453 594.715 186.651 594.715 190.313V202.278C594.715 205.941 592.518 208.139 588.855 208.139H574.449Z" fill="#001F29"/>
|
||||
<path d="M495.323 79.2091C487.022 79.2091 478.476 72.8603 478.476 62.1162C478.476 51.6162 487.022 46 495.323 46C503.381 46 512.171 51.6162 512.171 62.1162C512.171 72.8603 503.381 79.2091 495.323 79.2091ZM485.801 208.139C482.138 208.139 479.941 205.941 479.941 202.278V101.674C479.941 98.0114 482.138 95.8137 485.801 95.8137H504.846C508.509 95.8137 510.706 98.0114 510.706 101.674L510.462 202.278C510.462 205.941 508.264 208.139 504.602 208.139H485.801Z" fill="#001F29"/>
|
||||
<path d="M341.86 208.139C338.198 208.139 336 205.941 336 202.279V55.2794C336 51.6166 338.198 49.4189 341.86 49.4189H409.984C434.401 49.4189 456.132 65.291 456.132 94.1048C456.132 109.244 450.272 119.5 441.238 125.849C453.446 132.686 461.992 144.651 461.992 162.232C461.992 191.046 438.796 208.139 414.379 208.139H341.86ZM367.498 113.64H404.856C416.332 113.64 423.657 106.802 423.657 95.8141C423.657 84.8258 416.332 78.2328 404.856 78.2328H367.498V113.64ZM367.498 179.325H409.251C421.948 179.325 429.517 170.535 429.517 159.546C429.517 148.558 421.46 139.767 409.251 139.767H367.498V179.325Z" fill="#001F29"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1542_2219">
|
||||
<rect width="1623" height="256" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
BIN
static/img/uses/modallogos/bitget-wallet.png
Normal file
BIN
static/img/uses/modallogos/bitget-wallet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
23
static/img/wallets/bitget.svg
Normal file
23
static/img/wallets/bitget.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<svg width="1623" height="256" viewBox="0 0 1623 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1542_6419)">
|
||||
<rect width="256" height="256" rx="60" fill="white"/>
|
||||
<path d="M106.241 37.6137C95.9065 37.6084 85.5894 37.6031 75.2185 37.619C68.9476 37.619 66.5955 45.4918 71.2593 50.1551L141.857 120.753C144.06 122.768 145.434 124.959 145.485 127.846C145.434 130.733 144.06 132.923 141.857 134.939L71.2593 205.537C66.5955 210.2 68.9476 218.073 75.2185 218.073C85.5894 218.089 95.9065 218.083 106.241 218.078C111.416 218.075 116.594 218.073 121.787 218.073C128.579 218.073 132.62 214.444 136.249 210.815L199.919 147.145C205 142.063 209.547 135.316 209.485 127.846C209.547 120.375 205 113.628 199.919 108.547L136.249 44.8768C132.62 41.2479 128.579 37.619 121.787 37.619C116.594 37.619 111.416 37.6163 106.241 37.6137Z" fill="#001F29"/>
|
||||
<path d="M1601.73 208.139C1579.27 208.139 1568.77 196.418 1568.77 175.662V119.011H1559.98C1556.31 119.011 1554.12 116.814 1554.12 113.151V101.674C1554.12 98.0115 1556.31 95.8138 1559.98 95.8138H1568.77V67.2442C1568.77 63.5815 1570.96 61.3838 1574.63 61.3838H1593.43C1597.09 61.3838 1599.29 63.5815 1599.29 67.2442V95.8138H1617.36C1621.02 95.8138 1623.22 98.0115 1623.22 101.674V113.151C1623.22 116.814 1621.02 119.011 1617.36 119.011H1599.29V170.779C1599.29 183.965 1607.35 184.453 1614.43 184.453H1616.14C1619.8 184.453 1622 186.651 1622 190.313V202.278C1622 205.941 1619.8 208.139 1616.14 208.139H1601.73Z" fill="white"/>
|
||||
<path d="M1493.17 210.58C1458.75 210.58 1436.04 185.429 1436.04 151.976C1436.04 118.523 1458.01 93.6157 1491.95 93.6157C1525.4 93.6157 1545.91 118.523 1545.91 151.976V154.418C1545.91 158.08 1543.72 160.278 1540.05 160.278H1465.34C1468.27 175.418 1479.26 184.452 1493.17 184.452C1504.41 184.452 1511.49 180.546 1516.13 176.394C1518.81 173.953 1521.25 173.464 1524.18 175.662L1535.66 184.208C1538.83 186.65 1539.57 189.092 1537.37 191.778C1527.36 203.499 1511.73 210.58 1493.17 210.58ZM1465.83 140.988H1517.35C1514.66 127.802 1506.36 117.79 1491.95 117.79C1478.04 117.79 1468.76 126.825 1465.83 140.988Z" fill="white"/>
|
||||
<path d="M1393.23 208.139C1389.56 208.139 1387.37 205.941 1387.37 202.279V55.2794C1387.37 51.6166 1389.56 49.4189 1393.23 49.4189H1412.27C1415.93 49.4189 1418.13 51.6166 1418.13 55.2794L1417.89 202.279C1417.89 205.941 1415.69 208.139 1412.03 208.139H1393.23Z" fill="white"/>
|
||||
<path d="M1340.4 208.139C1336.74 208.139 1334.54 205.941 1334.54 202.279V55.2794C1334.54 51.6166 1336.74 49.4189 1340.4 49.4189H1359.45C1363.11 49.4189 1365.31 51.6166 1365.31 55.2794L1365.07 202.279C1365.07 205.941 1362.87 208.139 1359.21 208.139H1340.4Z" fill="white"/>
|
||||
<path d="M1249.73 210.093C1218.96 210.093 1196.5 185.43 1196.5 151.977C1196.5 118.035 1218.96 94.105 1249.73 94.105C1263.89 94.105 1274.39 99.2329 1281.96 107.779V101.675C1281.96 98.0119 1284.16 95.8143 1287.82 95.8143H1306.62C1310.28 95.8143 1312.48 98.0119 1312.48 101.675V202.279C1312.48 205.942 1310.28 208.139 1306.62 208.139H1287.82C1284.16 208.139 1281.96 205.942 1281.96 202.279V196.418C1274.39 204.965 1263.89 210.093 1249.73 210.093ZM1254.12 181.279C1270.97 181.279 1281.96 168.826 1281.96 151.977C1281.96 135.128 1270.97 122.675 1254.12 122.675C1237.28 122.675 1226.04 135.128 1226.04 151.977C1226.04 168.826 1237.28 181.279 1254.12 181.279Z" fill="white"/>
|
||||
<path d="M1037.19 208.139C1033.77 208.139 1031.33 206.43 1030.35 203.255L981.274 56.0119C980.053 52.105 982.006 49.4189 986.157 49.4189H1007.4C1010.82 49.4189 1013.26 51.1282 1014.24 54.3026L1046.22 150.511L1077.97 54.3026C1078.94 51.1282 1081.14 49.4189 1084.56 49.4189H1097.5C1100.92 49.4189 1103.36 51.1282 1104.34 54.3026L1135.35 146.605L1166.11 54.3026C1167.09 51.1282 1169.53 49.4189 1172.95 49.4189H1194.19C1198.34 49.4189 1200.29 52.105 1199.07 56.0119L1150 203.255C1149.02 206.43 1146.58 208.139 1143.16 208.139H1126.31C1122.89 208.139 1120.45 206.43 1119.47 203.255L1090.17 114.616L1060.87 203.255C1059.9 206.43 1057.45 208.139 1054.04 208.139H1037.19Z" fill="white"/>
|
||||
<path d="M904.354 208.139C881.89 208.139 871.39 196.418 871.39 175.662V119.011H862.6C858.938 119.011 856.74 116.814 856.74 113.151V101.674C856.74 98.0115 858.938 95.8138 862.6 95.8138H871.39V67.2442C871.39 63.5815 873.588 61.3838 877.251 61.3838H896.052C899.714 61.3838 901.912 63.5815 901.912 67.2442V95.8138H919.98C923.643 95.8138 925.841 98.0115 925.841 101.674V113.151C925.841 116.814 923.643 119.011 919.98 119.011H901.912V170.779C901.912 183.965 909.969 184.453 917.05 184.453H918.76C922.422 184.453 924.62 186.651 924.62 190.313V202.278C924.62 205.941 922.422 208.139 918.76 208.139H904.354Z" fill="white"/>
|
||||
<path d="M795.801 210.58C761.373 210.58 738.665 185.429 738.665 151.976C738.665 118.523 760.64 93.6157 794.58 93.6157C828.032 93.6157 848.542 118.523 848.542 151.976V154.418C848.542 158.08 846.344 160.278 842.682 160.278H767.966C770.896 175.418 781.883 184.452 795.801 184.452C807.033 184.452 814.114 180.546 818.753 176.394C821.439 173.953 823.881 173.464 826.811 175.662L838.287 184.208C841.461 186.65 842.193 189.092 839.996 191.778C829.985 203.499 814.358 210.58 795.801 210.58ZM768.454 140.988H819.974C817.288 127.802 808.986 117.79 794.58 117.79C780.662 117.79 771.384 126.825 768.454 140.988Z" fill="white"/>
|
||||
<path d="M660.68 256C642.855 256 627.717 249.895 617.217 240.127C614.287 237.441 614.776 234.511 617.706 231.825L628.693 222.546C631.379 220.104 634.065 220.349 636.995 222.546C644.809 228.895 653.355 230.36 660.68 230.36C671.179 230.36 690.224 224.5 690.224 200.325V196.174C682.655 204.721 671.912 210.093 657.75 210.093C626.984 210.093 604.765 185.43 604.765 151.977C604.765 118.523 626.984 94.105 657.75 94.105C671.912 94.105 682.655 99.2329 690.224 108.024V101.675C690.224 98.0119 692.422 95.8143 696.084 95.8143H714.886C718.548 95.8143 720.746 98.0119 720.746 101.675V200.325C720.746 232.558 699.503 256 660.68 256ZM662.145 181.279C678.993 181.279 690.224 168.826 690.224 151.977C690.224 135.128 678.993 122.675 662.145 122.675C645.297 122.675 634.309 135.128 634.309 151.977C634.309 168.826 645.297 181.279 662.145 181.279Z" fill="white"/>
|
||||
<path d="M574.449 208.139C551.986 208.139 541.486 196.418 541.486 175.662V119.011H532.696C529.033 119.011 526.836 116.814 526.836 113.151V101.674C526.836 98.0115 529.033 95.8138 532.696 95.8138H541.486V67.2442C541.486 63.5815 543.684 61.3838 547.346 61.3838H566.147C569.81 61.3838 572.008 63.5815 572.008 67.2442V95.8138H590.076C593.739 95.8138 595.936 98.0115 595.936 101.674V113.151C595.936 116.814 593.739 119.011 590.076 119.011H572.008V170.779C572.008 183.965 580.065 184.453 587.146 184.453H588.855C592.518 184.453 594.715 186.651 594.715 190.313V202.278C594.715 205.941 592.518 208.139 588.855 208.139H574.449Z" fill="white"/>
|
||||
<path d="M495.323 79.2091C487.022 79.2091 478.476 72.8603 478.476 62.1162C478.476 51.6162 487.022 46 495.323 46C503.381 46 512.171 51.6162 512.171 62.1162C512.171 72.8603 503.381 79.2091 495.323 79.2091ZM485.801 208.139C482.138 208.139 479.941 205.941 479.941 202.278V101.674C479.941 98.0114 482.138 95.8137 485.801 95.8137H504.846C508.509 95.8137 510.706 98.0114 510.706 101.674L510.462 202.278C510.462 205.941 508.264 208.139 504.602 208.139H485.801Z" fill="white"/>
|
||||
<path d="M341.86 208.139C338.198 208.139 336 205.941 336 202.279V55.2794C336 51.6166 338.198 49.4189 341.86 49.4189H409.984C434.401 49.4189 456.132 65.291 456.132 94.1048C456.132 109.244 450.272 119.5 441.238 125.849C453.446 132.686 461.992 144.651 461.992 162.232C461.992 191.046 438.796 208.139 414.379 208.139H341.86ZM367.498 113.64H404.856C416.332 113.64 423.657 106.802 423.657 95.8141C423.657 84.8258 416.332 78.2328 404.856 78.2328H367.498V113.64ZM367.498 179.325H409.251C421.948 179.325 429.517 170.535 429.517 159.546C429.517 148.558 421.46 139.767 409.251 139.767H367.498V179.325Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1542_6419">
|
||||
<rect width="1623" height="256" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
23
static/img/wallets/lightmode/bitget.svg
Normal file
23
static/img/wallets/lightmode/bitget.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<svg width="1623" height="256" viewBox="0 0 1623 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1542_2219)">
|
||||
<rect width="256" height="256" rx="60" fill="#001F29"/>
|
||||
<path d="M106.241 37.6137C95.9065 37.6084 85.5894 37.6031 75.2185 37.619C68.9476 37.619 66.5955 45.4918 71.2593 50.1551L141.857 120.753C144.06 122.768 145.434 124.959 145.485 127.846C145.434 130.733 144.06 132.923 141.857 134.939L71.2593 205.537C66.5955 210.2 68.9476 218.073 75.2185 218.073C85.5894 218.089 95.9065 218.083 106.241 218.078C111.416 218.075 116.594 218.073 121.787 218.073C128.579 218.073 132.62 214.444 136.249 210.815L199.919 147.145C205 142.063 209.547 135.316 209.485 127.846C209.547 120.375 205 113.628 199.919 108.547L136.249 44.8768C132.62 41.2479 128.579 37.619 121.787 37.619C116.594 37.619 111.416 37.6163 106.241 37.6137Z" fill="#00F0FF"/>
|
||||
<path d="M1601.73 208.139C1579.27 208.139 1568.77 196.418 1568.77 175.662V119.011H1559.98C1556.31 119.011 1554.12 116.814 1554.12 113.151V101.674C1554.12 98.0115 1556.31 95.8138 1559.98 95.8138H1568.77V67.2442C1568.77 63.5815 1570.96 61.3838 1574.63 61.3838H1593.43C1597.09 61.3838 1599.29 63.5815 1599.29 67.2442V95.8138H1617.36C1621.02 95.8138 1623.22 98.0115 1623.22 101.674V113.151C1623.22 116.814 1621.02 119.011 1617.36 119.011H1599.29V170.779C1599.29 183.965 1607.35 184.453 1614.43 184.453H1616.14C1619.8 184.453 1622 186.651 1622 190.313V202.278C1622 205.941 1619.8 208.139 1616.14 208.139H1601.73Z" fill="#001F29"/>
|
||||
<path d="M1493.17 210.58C1458.75 210.58 1436.04 185.429 1436.04 151.976C1436.04 118.523 1458.01 93.6157 1491.95 93.6157C1525.4 93.6157 1545.91 118.523 1545.91 151.976V154.418C1545.91 158.08 1543.72 160.278 1540.05 160.278H1465.34C1468.27 175.418 1479.26 184.452 1493.17 184.452C1504.41 184.452 1511.49 180.546 1516.13 176.394C1518.81 173.953 1521.25 173.464 1524.18 175.662L1535.66 184.208C1538.83 186.65 1539.57 189.092 1537.37 191.778C1527.36 203.499 1511.73 210.58 1493.17 210.58ZM1465.83 140.988H1517.35C1514.66 127.802 1506.36 117.79 1491.95 117.79C1478.04 117.79 1468.76 126.825 1465.83 140.988Z" fill="#001F29"/>
|
||||
<path d="M1393.23 208.139C1389.56 208.139 1387.37 205.941 1387.37 202.279V55.2794C1387.37 51.6166 1389.56 49.4189 1393.23 49.4189H1412.27C1415.93 49.4189 1418.13 51.6166 1418.13 55.2794L1417.89 202.279C1417.89 205.941 1415.69 208.139 1412.03 208.139H1393.23Z" fill="#001F29"/>
|
||||
<path d="M1340.4 208.139C1336.74 208.139 1334.54 205.941 1334.54 202.279V55.2794C1334.54 51.6166 1336.74 49.4189 1340.4 49.4189H1359.45C1363.11 49.4189 1365.31 51.6166 1365.31 55.2794L1365.07 202.279C1365.07 205.941 1362.87 208.139 1359.21 208.139H1340.4Z" fill="#001F29"/>
|
||||
<path d="M1249.73 210.093C1218.96 210.093 1196.5 185.43 1196.5 151.977C1196.5 118.035 1218.96 94.105 1249.73 94.105C1263.89 94.105 1274.39 99.2329 1281.96 107.779V101.675C1281.96 98.0119 1284.16 95.8143 1287.82 95.8143H1306.62C1310.28 95.8143 1312.48 98.0119 1312.48 101.675V202.279C1312.48 205.942 1310.28 208.139 1306.62 208.139H1287.82C1284.16 208.139 1281.96 205.942 1281.96 202.279V196.418C1274.39 204.965 1263.89 210.093 1249.73 210.093ZM1254.12 181.279C1270.97 181.279 1281.96 168.826 1281.96 151.977C1281.96 135.128 1270.97 122.675 1254.12 122.675C1237.28 122.675 1226.04 135.128 1226.04 151.977C1226.04 168.826 1237.28 181.279 1254.12 181.279Z" fill="#001F29"/>
|
||||
<path d="M1037.19 208.139C1033.77 208.139 1031.33 206.43 1030.35 203.255L981.274 56.0119C980.053 52.105 982.006 49.4189 986.157 49.4189H1007.4C1010.82 49.4189 1013.26 51.1282 1014.24 54.3026L1046.22 150.511L1077.97 54.3026C1078.94 51.1282 1081.14 49.4189 1084.56 49.4189H1097.5C1100.92 49.4189 1103.36 51.1282 1104.34 54.3026L1135.35 146.605L1166.11 54.3026C1167.09 51.1282 1169.53 49.4189 1172.95 49.4189H1194.19C1198.34 49.4189 1200.29 52.105 1199.07 56.0119L1150 203.255C1149.02 206.43 1146.58 208.139 1143.16 208.139H1126.31C1122.89 208.139 1120.45 206.43 1119.47 203.255L1090.17 114.616L1060.87 203.255C1059.9 206.43 1057.45 208.139 1054.04 208.139H1037.19Z" fill="#001F29"/>
|
||||
<path d="M904.354 208.139C881.89 208.139 871.39 196.418 871.39 175.662V119.011H862.6C858.938 119.011 856.74 116.814 856.74 113.151V101.674C856.74 98.0115 858.938 95.8138 862.6 95.8138H871.39V67.2442C871.39 63.5815 873.588 61.3838 877.251 61.3838H896.052C899.714 61.3838 901.912 63.5815 901.912 67.2442V95.8138H919.98C923.643 95.8138 925.841 98.0115 925.841 101.674V113.151C925.841 116.814 923.643 119.011 919.98 119.011H901.912V170.779C901.912 183.965 909.969 184.453 917.05 184.453H918.76C922.422 184.453 924.62 186.651 924.62 190.313V202.278C924.62 205.941 922.422 208.139 918.76 208.139H904.354Z" fill="#001F29"/>
|
||||
<path d="M795.801 210.58C761.373 210.58 738.665 185.429 738.665 151.976C738.665 118.523 760.64 93.6157 794.58 93.6157C828.032 93.6157 848.542 118.523 848.542 151.976V154.418C848.542 158.08 846.344 160.278 842.682 160.278H767.966C770.896 175.418 781.883 184.452 795.801 184.452C807.033 184.452 814.114 180.546 818.753 176.394C821.439 173.953 823.881 173.464 826.811 175.662L838.287 184.208C841.461 186.65 842.193 189.092 839.996 191.778C829.985 203.499 814.358 210.58 795.801 210.58ZM768.454 140.988H819.974C817.288 127.802 808.986 117.79 794.58 117.79C780.662 117.79 771.384 126.825 768.454 140.988Z" fill="#001F29"/>
|
||||
<path d="M660.68 256C642.855 256 627.717 249.895 617.217 240.127C614.287 237.441 614.776 234.511 617.706 231.825L628.693 222.546C631.379 220.104 634.065 220.349 636.995 222.546C644.809 228.895 653.355 230.36 660.68 230.36C671.179 230.36 690.224 224.5 690.224 200.325V196.174C682.655 204.721 671.912 210.093 657.75 210.093C626.984 210.093 604.765 185.43 604.765 151.977C604.765 118.523 626.984 94.105 657.75 94.105C671.912 94.105 682.655 99.2329 690.224 108.024V101.675C690.224 98.0119 692.422 95.8143 696.084 95.8143H714.886C718.548 95.8143 720.746 98.0119 720.746 101.675V200.325C720.746 232.558 699.503 256 660.68 256ZM662.145 181.279C678.993 181.279 690.224 168.826 690.224 151.977C690.224 135.128 678.993 122.675 662.145 122.675C645.297 122.675 634.309 135.128 634.309 151.977C634.309 168.826 645.297 181.279 662.145 181.279Z" fill="#001F29"/>
|
||||
<path d="M574.449 208.139C551.986 208.139 541.486 196.418 541.486 175.662V119.011H532.696C529.033 119.011 526.836 116.814 526.836 113.151V101.674C526.836 98.0115 529.033 95.8138 532.696 95.8138H541.486V67.2442C541.486 63.5815 543.684 61.3838 547.346 61.3838H566.147C569.81 61.3838 572.008 63.5815 572.008 67.2442V95.8138H590.076C593.739 95.8138 595.936 98.0115 595.936 101.674V113.151C595.936 116.814 593.739 119.011 590.076 119.011H572.008V170.779C572.008 183.965 580.065 184.453 587.146 184.453H588.855C592.518 184.453 594.715 186.651 594.715 190.313V202.278C594.715 205.941 592.518 208.139 588.855 208.139H574.449Z" fill="#001F29"/>
|
||||
<path d="M495.323 79.2091C487.022 79.2091 478.476 72.8603 478.476 62.1162C478.476 51.6162 487.022 46 495.323 46C503.381 46 512.171 51.6162 512.171 62.1162C512.171 72.8603 503.381 79.2091 495.323 79.2091ZM485.801 208.139C482.138 208.139 479.941 205.941 479.941 202.278V101.674C479.941 98.0114 482.138 95.8137 485.801 95.8137H504.846C508.509 95.8137 510.706 98.0114 510.706 101.674L510.462 202.278C510.462 205.941 508.264 208.139 504.602 208.139H485.801Z" fill="#001F29"/>
|
||||
<path d="M341.86 208.139C338.198 208.139 336 205.941 336 202.279V55.2794C336 51.6166 338.198 49.4189 341.86 49.4189H409.984C434.401 49.4189 456.132 65.291 456.132 94.1048C456.132 109.244 450.272 119.5 441.238 125.849C453.446 132.686 461.992 144.651 461.992 162.232C461.992 191.046 438.796 208.139 414.379 208.139H341.86ZM367.498 113.64H404.856C416.332 113.64 423.657 106.802 423.657 95.8141C423.657 84.8258 416.332 78.2328 404.856 78.2328H367.498V113.64ZM367.498 179.325H409.251C421.948 179.325 429.517 170.535 429.517 159.546C429.517 148.558 421.46 139.767 409.251 139.767H367.498V179.325Z" fill="#001F29"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1542_2219">
|
||||
<rect width="1623" height="256" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
@@ -172,7 +172,7 @@
|
||||
}
|
||||
|
||||
#wallets {
|
||||
@each $wallet in "ledger", "secalot", "trezor", "xumm", "trust", "gatehub", "bifrost", "keystone", "dcent", "coin", "gem", "joey" {
|
||||
@each $wallet in "ledger", "secalot", "trezor", "xumm", "trust", "gatehub", "bifrost", "bitget", "keystone", "dcent", "coin", "gem", "joey" {
|
||||
#wallet-#{$wallet} {
|
||||
content: url("../img/wallets/#{$wallet}.svg");
|
||||
}
|
||||
@@ -405,6 +405,7 @@
|
||||
"multichain": "svg",
|
||||
"xumm-wallet": "svg",
|
||||
"bifrost-wallet": "svg",
|
||||
"bitget-wallet": "svg",
|
||||
"gem-wallet": "svg",
|
||||
"aesthetes": "svg",
|
||||
"audiotarky": "svg",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
$infrastructure-logos: "xrp-ledger", "gatehub", "towolabs", "xrpscan", "xrp-toolkit", "bithomp", "onthedex";
|
||||
$developer-tooling-logos: "cryptum", "evernode", "threezy", "tokenize";
|
||||
$interoperability-logos: "multichain";
|
||||
$wallet-logos: "crossmark", "edge", "gem-wallet", "xumm", "joey-wallet", "bifrost-wallet";
|
||||
$wallet-logos: "crossmark", "edge", "gem-wallet", "xumm", "joey-wallet", "bifrost-wallet", "bitget-wallet";
|
||||
$nfts-logos: "aesthetes", "audiotarky", "nftmaster", "peerkat", "sologenic_dex", "xrp-cafe", "xrp-oval";
|
||||
$exchanges-logos: "sologenic_dex", "xpmarket", "orchestra-finance", "moai-finance", "first-ledger-bot";
|
||||
$gaming-logos: "forte", "ledger-city", "futureverse", "zerpmon";
|
||||
|
||||
@@ -573,6 +573,10 @@ pre {
|
||||
#wallet-joey {
|
||||
content: url("../img/wallets/lightmode/joey.svg");
|
||||
}
|
||||
|
||||
#wallet-bitget {
|
||||
content: url("../img/wallets/lightmode/bitget.svg");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -669,6 +673,7 @@ pre {
|
||||
'ripples-on-demand-liquidity': 'svg',
|
||||
'xumm-wallet': 'svg',
|
||||
'bifrost-wallet': 'svg',
|
||||
'bitget-wallet': 'svg',
|
||||
'sologenic-dex': 'svg',
|
||||
'joey-wallet': 'svg',
|
||||
'Crossmark': 'png'
|
||||
|
||||
Reference in New Issue
Block a user