Compare commits

...

28 Commits

Author SHA1 Message Date
amarantha-k
d837d848b1 configuring llmstxt 2026-03-02 11:10:56 -08:00
Amarantha Kulkarni
61fc160523 Merge pull request #3521 from XRPLF/vulnerability-disclosure-report-feb2026
Vulnerability disclosure report February 2026
2026-02-26 14:13:20 -08:00
Amarantha Kulkarni
dc3db2c4f2 Apply suggestions from code review
Co-authored-by: oeggert <117319296+oeggert@users.noreply.github.com>
2026-02-26 14:06:37 -08:00
Amarantha Kulkarni
3ca8de9646 Apply suggestions from code review
Co-authored-by: oeggert <117319296+oeggert@users.noreply.github.com>
2026-02-26 13:54:57 -08:00
Maria Shodunke
2ca8706e41 Merge pull request #3519 from XRPLF/remove-batch-sav-setup
Don't use Batch for SAV tutorials setup
2026-02-26 18:05:43 +00:00
oeggert
dc0778b666 Merge pull request #3522 from XRPLF/update-lending-setup
Update lending tutorial setup scripts
2026-02-26 09:50:00 -08:00
Oliver Eggert
7268a0e52e add warnings for obsolete amendments 2026-02-26 09:45:35 -08:00
Amarantha Kulkarni
025c262f3e Merge pull request #3489 from XRPLF/add-bitget-wallet
Add Bitget wallet to XRP and Uses pages
2026-02-26 09:43:02 -08:00
Maria Shodunke
f26c5921b8 Apply review comments 2026-02-26 15:11:26 +00:00
amarantha-k
4094d1f76a Fix syntax for links 2026-02-25 13:33:53 -08:00
Oliver Eggert
62288d6c3b mark batch and fixbatchinnersigs as obsolete 2026-02-25 13:29:39 -08:00
amarantha-k
f5f08d8690 Incorporate review feedback 2026-02-25 13:14:46 -08:00
Oliver Eggert
88c28dfd05 update lending_setup.py to use tickets instead of batch 2026-02-25 12:56:32 -08:00
amarantha-k
c297fc5960 Fix typo in attribution 2026-02-25 12:33:58 -08:00
amarantha-k
fa9ddb8d67 Add attribution to post 2026-02-25 12:32:14 -08:00
amarantha-k
3c14520ad0 Add disclosure report for Batch 2026-02-25 12:08:39 -08:00
Oliver Eggert
a83e6e3a1a update lendingSetup.js to use tickets instead of batch 2026-02-25 11:40:52 -08:00
Maria Shodunke
79e800baae Add amendment badge to Batch concept doc 2026-02-25 18:00:51 +00:00
Maria Shodunke
646d4a7381 Don't use Batch for SAV tutorials setup 2026-02-25 17:29:21 +00:00
oeggert
62238e2ba8 Merge pull request #3511 from XRPLF/blog-3.1.1
Add 3.1.1 blog
2026-02-23 16:50:50 -08:00
Oliver Eggert
f211351f4c add reviewer suggestions 2026-02-23 16:47:53 -08:00
Oliver Eggert
7c41d016db add 3.1.1 blog 2026-02-23 15:49:01 -08:00
amarantha-k
9af8e7849e Update logo image for dark mode 2026-02-12 11:18:09 -08:00
mDuo13
c62d5090d0 Fix typo causing Bitget logo to not apear 2026-02-11 04:03:45 -08:00
amarantha-k
19ec38e7d8 Update number of wallets to 7 2026-02-10 20:34:49 -08:00
amarantha-k
f119214cea replace corrupted image files 2026-02-10 20:24:23 -08:00
amarantha-k
69d4113536 Add missing image files 2026-02-10 16:37:14 -08:00
amarantha-k
f5988554db Add Bitget wallet to XRP and Uses pages 2026-02-10 16:23:43 -08:00
22 changed files with 897 additions and 380 deletions

View File

@@ -3,7 +3,7 @@
import xrpl from 'xrpl'
import fs from 'fs'
process.stdout.write('Setting up tutorial: 0/6\r')
process.stdout.write('Setting up tutorial: 0/7\r')
const client = new xrpl.Client('wss://s.devnet.rippletest.net:51233')
await client.connect()
@@ -21,10 +21,45 @@ const [
client.fundWallet()
])
process.stdout.write('Setting up tutorial: 1/6\r')
process.stdout.write('Setting up tutorial: 1/7\r')
// Create tickets for parallel transactions
const extractTickets = (response) =>
response.result.meta.AffectedNodes
.filter(node => node.CreatedNode?.LedgerEntryType === 'Ticket')
.map(node => node.CreatedNode.NewFields.TicketSequence)
const [ciTicketResponse, lbTicketResponse, brTicketResponse, dpTicketResponse] = await Promise.all([
client.submitAndWait({
TransactionType: 'TicketCreate',
Account: credentialIssuer.address,
TicketCount: 4
}, { wallet: credentialIssuer, autofill: true }),
client.submitAndWait({
TransactionType: 'TicketCreate',
Account: loanBroker.address,
TicketCount: 4
}, { wallet: loanBroker, autofill: true }),
client.submitAndWait({
TransactionType: 'TicketCreate',
Account: borrower.address,
TicketCount: 2
}, { wallet: borrower, autofill: true }),
client.submitAndWait({
TransactionType: 'TicketCreate',
Account: depositor.address,
TicketCount: 2
}, { wallet: depositor, autofill: true })
])
const ciTickets = extractTickets(ciTicketResponse)
const lbTickets = extractTickets(lbTicketResponse)
const brTickets = extractTickets(brTicketResponse)
const dpTickets = extractTickets(dpTicketResponse)
process.stdout.write('Setting up tutorial: 2/7\r')
// Issue MPT with depositor
// Create tickets for later use with loanBroker
// Set up credentials and domain with credentialIssuer
const credentialType = xrpl.convertStringToHex('KYC-Verified')
const mptData = {
@@ -56,12 +91,7 @@ const mptData = {
}
}
const [ticketCreateResponse, mptIssuanceResponse] = await Promise.all([
client.submitAndWait({
TransactionType: 'TicketCreate',
Account: loanBroker.address,
TicketCount: 2
}, { wallet: loanBroker, autofill: true }),
const [mptIssuanceResponse, domainSetResponse] = await Promise.all([
client.submitAndWait({
TransactionType: 'MPTokenIssuanceCreate',
Account: depositor.address,
@@ -74,104 +104,87 @@ const [ticketCreateResponse, mptIssuanceResponse] = await Promise.all([
MPTokenMetadata: xrpl.encodeMPTokenMetadata(mptData)
}, { wallet: depositor, autofill: true }),
client.submitAndWait({
TransactionType: 'Batch',
TransactionType: 'PermissionedDomainSet',
Account: credentialIssuer.address,
Flags: xrpl.BatchFlags.tfAllOrNothing,
RawTransactions: [
AcceptedCredentials: [
{
RawTransaction: {
TransactionType: 'CredentialCreate',
Account: credentialIssuer.address,
Subject: loanBroker.address,
CredentialType: credentialType,
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
},
{
RawTransaction: {
TransactionType: 'CredentialCreate',
Account: credentialIssuer.address,
Subject: borrower.address,
CredentialType: credentialType,
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
},
{
RawTransaction: {
TransactionType: 'CredentialCreate',
Account: credentialIssuer.address,
Subject: depositor.address,
CredentialType: credentialType,
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
},
{
RawTransaction: {
TransactionType: 'PermissionedDomainSet',
Account: credentialIssuer.address,
AcceptedCredentials: [
{
Credential: {
Issuer: credentialIssuer.address,
CredentialType: credentialType
}
}
],
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
Credential: {
Issuer: credentialIssuer.address,
CredentialType: credentialType
}
}
]
],
Sequence: 0,
TicketSequence: ciTickets[0]
}, { wallet: credentialIssuer, autofill: true }),
client.submitAndWait({
TransactionType: 'CredentialCreate',
Account: credentialIssuer.address,
Subject: loanBroker.address,
CredentialType: credentialType,
Sequence: 0,
TicketSequence: ciTickets[1]
}, { wallet: credentialIssuer, autofill: true }),
client.submitAndWait({
TransactionType: 'CredentialCreate',
Account: credentialIssuer.address,
Subject: borrower.address,
CredentialType: credentialType,
Sequence: 0,
TicketSequence: ciTickets[2]
}, { wallet: credentialIssuer, autofill: true }),
client.submitAndWait({
TransactionType: 'CredentialCreate',
Account: credentialIssuer.address,
Subject: depositor.address,
CredentialType: credentialType,
Sequence: 0,
TicketSequence: ciTickets[3]
}, { wallet: credentialIssuer, autofill: true })
])
// Extract ticket sequence numbers
const tickets = ticketCreateResponse.result.meta.AffectedNodes
.filter(node => node.CreatedNode?.LedgerEntryType === 'Ticket')
.map(node => node.CreatedNode.NewFields.TicketSequence)
// Extract MPT issuance ID
const mptID = mptIssuanceResponse.result.meta.mpt_issuance_id
// Get domain ID
const credentialIssuerObjects = await client.request({
command: 'account_objects',
account: credentialIssuer.address,
ledger_index: 'validated'
})
const domainID = credentialIssuerObjects.result.account_objects.find(node =>
node.LedgerEntryType === 'PermissionedDomain'
).index
// Extract domain ID
const domainID = domainSetResponse.result.meta.AffectedNodes.find(node =>
node.CreatedNode?.LedgerEntryType === 'PermissionedDomain'
).CreatedNode.LedgerIndex
process.stdout.write('Setting up tutorial: 2/6\r')
process.stdout.write('Setting up tutorial: 3/7\r')
// Accept credentials and authorize MPT for each account
await Promise.all([
...([loanBroker, borrower].map(wallet =>
client.submitAndWait({
TransactionType: 'Batch',
Account: wallet.address,
Flags: xrpl.BatchFlags.tfAllOrNothing,
RawTransactions: [
{
RawTransaction: {
TransactionType: 'CredentialAccept',
Account: wallet.address,
Issuer: credentialIssuer.address,
CredentialType: credentialType,
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
},
{
RawTransaction: {
TransactionType: 'MPTokenAuthorize',
Account: wallet.address,
MPTokenIssuanceID: mptID,
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
}
]
}, { wallet, autofill: true })
)),
client.submitAndWait({
TransactionType: 'CredentialAccept',
Account: loanBroker.address,
Issuer: credentialIssuer.address,
CredentialType: credentialType,
Sequence: 0,
TicketSequence: lbTickets[0]
}, { wallet: loanBroker, autofill: true }),
client.submitAndWait({
TransactionType: 'MPTokenAuthorize',
Account: loanBroker.address,
MPTokenIssuanceID: mptID,
Sequence: 0,
TicketSequence: lbTickets[1]
}, { wallet: loanBroker, autofill: true }),
client.submitAndWait({
TransactionType: 'CredentialAccept',
Account: borrower.address,
Issuer: credentialIssuer.address,
CredentialType: credentialType,
Sequence: 0,
TicketSequence: brTickets[0]
}, { wallet: borrower, autofill: true }),
client.submitAndWait({
TransactionType: 'MPTokenAuthorize',
Account: borrower.address,
MPTokenIssuanceID: mptID,
Sequence: 0,
TicketSequence: brTickets[1]
}, { wallet: borrower, autofill: true }),
// Depositor only needs to accept credentials
client.submitAndWait({
TransactionType: 'CredentialAccept',
@@ -181,7 +194,7 @@ await Promise.all([
}, { wallet: depositor, autofill: true })
])
process.stdout.write('Setting up tutorial: 3/6\r')
process.stdout.write('Setting up tutorial: 4/7\r')
// Create private vault and distribute MPT to accounts
const [vaultCreateResponse] = await Promise.all([
@@ -195,35 +208,26 @@ const [vaultCreateResponse] = await Promise.all([
DomainID: domainID
}, { wallet: loanBroker, autofill: true }),
client.submitAndWait({
TransactionType: 'Batch',
TransactionType: 'Payment',
Account: depositor.address,
Flags: xrpl.BatchFlags.tfAllOrNothing,
RawTransactions: [
{
RawTransaction: {
TransactionType: 'Payment',
Account: depositor.address,
Destination: loanBroker.address,
Amount: {
mpt_issuance_id: mptID,
value: '5000'
},
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
},
{
RawTransaction: {
TransactionType: 'Payment',
Account: depositor.address,
Destination: borrower.address,
Amount: {
mpt_issuance_id: mptID,
value: '2500'
},
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
}
]
Destination: loanBroker.address,
Amount: {
mpt_issuance_id: mptID,
value: '5000'
},
Sequence: 0,
TicketSequence: dpTickets[0]
}, { wallet: depositor, autofill: true }),
client.submitAndWait({
TransactionType: 'Payment',
Account: depositor.address,
Destination: borrower.address,
Amount: {
mpt_issuance_id: mptID,
value: '2500'
},
Sequence: 0,
TicketSequence: dpTickets[1]
}, { wallet: depositor, autofill: true })
])
@@ -231,7 +235,7 @@ const vaultID = vaultCreateResponse.result.meta.AffectedNodes.find(node =>
node.CreatedNode?.LedgerEntryType === 'Vault'
).CreatedNode.LedgerIndex
process.stdout.write('Setting up tutorial: 4/6\r')
process.stdout.write('Setting up tutorial: 5/7\r')
// Create LoanBroker and deposit MPT into vault
const [loanBrokerSetResponse] = await Promise.all([
@@ -255,7 +259,7 @@ const loanBrokerID = loanBrokerSetResponse.result.meta.AffectedNodes.find(node =
node.CreatedNode?.LedgerEntryType === 'LoanBroker'
).CreatedNode.LedgerIndex
process.stdout.write('Setting up tutorial: 5/6\r')
process.stdout.write('Setting up tutorial: 6/7\r')
// Create 2 identical loans with complete repayment due in 30 days
@@ -289,8 +293,8 @@ async function createLoan (ticketSequence) {
}
const [submitResponse1, submitResponse2] = await Promise.all([
createLoan(tickets[0]),
createLoan(tickets[1])
createLoan(lbTickets[2]),
createLoan(lbTickets[3])
])
const loanID1 = submitResponse1.result.meta.AffectedNodes.find(node =>
@@ -301,7 +305,7 @@ const loanID2 = submitResponse2.result.meta.AffectedNodes.find(node =>
node.CreatedNode?.LedgerEntryType === 'Loan'
).CreatedNode.LedgerIndex
process.stdout.write('Setting up tutorial: 6/6\r')
process.stdout.write('Setting up tutorial: 7/7\r')
// Write setup data to JSON file
const setupData = {

View File

@@ -8,9 +8,6 @@ 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,
@@ -34,7 +31,7 @@ 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")
print("Setting up tutorial: 0/7", end="\r")
# Create and fund wallets
loan_broker, borrower, depositor, credential_issuer = await asyncio.gather(
@@ -44,10 +41,61 @@ async def main():
generate_faucet_wallet(client),
)
print("Setting up tutorial: 1/6", end="\r")
print("Setting up tutorial: 1/7", end="\r")
# Create tickets for parallel transactions
def extract_tickets(response):
return [
node["CreatedNode"]["NewFields"]["TicketSequence"]
for node in response.result["meta"]["AffectedNodes"]
if node.get("CreatedNode", {}).get("LedgerEntryType") == "Ticket"
]
ci_ticket_response, lb_ticket_response, br_ticket_response, dp_ticket_response = (
await asyncio.gather(
submit_and_wait(
TicketCreate(
account=credential_issuer.address,
ticket_count=4,
),
client,
credential_issuer,
),
submit_and_wait(
TicketCreate(
account=loan_broker.address,
ticket_count=4,
),
client,
loan_broker,
),
submit_and_wait(
TicketCreate(
account=borrower.address,
ticket_count=2,
),
client,
borrower,
),
submit_and_wait(
TicketCreate(
account=depositor.address,
ticket_count=2,
),
client,
depositor,
),
)
)
ci_tickets = extract_tickets(ci_ticket_response)
lb_tickets = extract_tickets(lb_ticket_response)
br_tickets = extract_tickets(br_ticket_response)
dp_tickets = extract_tickets(dp_ticket_response)
print("Setting up tutorial: 2/7", 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")
@@ -80,15 +128,7 @@ async def main():
},
}
ticket_create_response, mpt_issuance_response, _ = await asyncio.gather(
submit_and_wait(
TicketCreate(
account=loan_broker.address,
ticket_count=2,
),
client,
loan_broker,
),
mpt_issuance_response, domain_set_response, *_ = await asyncio.gather(
submit_and_wait(
MPTokenIssuanceCreate(
account=depositor.address,
@@ -105,104 +145,112 @@ async def main():
depositor,
),
submit_and_wait(
Batch(
PermissionedDomainSet(
account=credential_issuer.address,
flags=BatchFlag.TF_ALL_OR_NOTHING,
raw_transactions=[
CredentialCreate(
account=credential_issuer.address,
subject=loan_broker.address,
accepted_credentials=[
Credential(
issuer=credential_issuer.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,
),
],
),
],
sequence=0,
ticket_sequence=ci_tickets[0],
),
client,
credential_issuer,
),
submit_and_wait(
CredentialCreate(
account=credential_issuer.address,
subject=loan_broker.address,
credential_type=credential_type,
sequence=0,
ticket_sequence=ci_tickets[1],
),
client,
credential_issuer,
),
submit_and_wait(
CredentialCreate(
account=credential_issuer.address,
subject=borrower.address,
credential_type=credential_type,
sequence=0,
ticket_sequence=ci_tickets[2],
),
client,
credential_issuer,
),
submit_and_wait(
CredentialCreate(
account=credential_issuer.address,
subject=depositor.address,
credential_type=credential_type,
sequence=0,
ticket_sequence=ci_tickets[3],
),
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",
))
# Extract domain ID
domain_id = next(
node["index"]
for node in credential_issuer_objects.result["account_objects"]
if node["LedgerEntryType"] == "PermissionedDomain"
node["CreatedNode"]["LedgerIndex"]
for node in domain_set_response.result["meta"]["AffectedNodes"]
if node.get("CreatedNode", {}).get("LedgerEntryType") == "PermissionedDomain"
)
print("Setting up tutorial: 2/6", end="\r")
print("Setting up tutorial: 3/7", end="\r")
# Accept credentials and authorize MPT for each account
await asyncio.gather(
submit_and_wait(
Batch(
CredentialAccept(
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,
),
],
issuer=credential_issuer.address,
credential_type=credential_type,
sequence=0,
ticket_sequence=lb_tickets[0],
),
client,
loan_broker,
),
submit_and_wait(
Batch(
MPTokenAuthorize(
account=loan_broker.address,
mptoken_issuance_id=mpt_id,
sequence=0,
ticket_sequence=lb_tickets[1],
),
client,
loan_broker,
),
submit_and_wait(
CredentialAccept(
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,
),
],
issuer=credential_issuer.address,
credential_type=credential_type,
sequence=0,
ticket_sequence=br_tickets[0],
),
client,
borrower,
),
submit_and_wait(
MPTokenAuthorize(
account=borrower.address,
mptoken_issuance_id=mpt_id,
sequence=0,
ticket_sequence=br_tickets[1],
),
client,
borrower,
),
# Depositor only needs to accept credentials
submit_and_wait(
CredentialAccept(
account=depositor.address,
@@ -214,10 +262,10 @@ async def main():
),
)
print("Setting up tutorial: 3/6", end="\r")
print("Setting up tutorial: 4/7", end="\r")
# Create private vault and distribute MPT to accounts
vault_create_response, _ = await asyncio.gather(
vault_create_response, *_ = await asyncio.gather(
submit_and_wait(
VaultCreate(
account=loan_broker.address,
@@ -229,21 +277,23 @@ async def main():
loan_broker,
),
submit_and_wait(
Batch(
Payment(
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"),
),
],
destination=loan_broker.address,
amount=MPTAmount(mpt_issuance_id=mpt_id, value="5000"),
sequence=0,
ticket_sequence=dp_tickets[0],
),
client,
depositor,
),
submit_and_wait(
Payment(
account=depositor.address,
destination=borrower.address,
amount=MPTAmount(mpt_issuance_id=mpt_id, value="2500"),
sequence=0,
ticket_sequence=dp_tickets[1],
),
client,
depositor,
@@ -256,7 +306,7 @@ async def main():
if node.get("CreatedNode", {}).get("LedgerEntryType") == "Vault"
)
print("Setting up tutorial: 4/6", end="\r")
print("Setting up tutorial: 5/7", end="\r")
# Create LoanBroker and deposit MPT into vault
loan_broker_set_response, _ = await asyncio.gather(
@@ -285,10 +335,10 @@ async def main():
if node.get("CreatedNode", {}).get("LedgerEntryType") == "LoanBroker"
)
print("Setting up tutorial: 5/6", end="\r")
print("Setting up tutorial: 6/7", 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(
@@ -312,8 +362,8 @@ async def main():
return submit_response
submit_response_1, submit_response_2 = await asyncio.gather(
create_loan(tickets[0]),
create_loan(tickets[1]),
create_loan(lb_tickets[2]),
create_loan(lb_tickets[3]),
)
loan_id_1 = next(
@@ -328,7 +378,7 @@ async def main():
if node.get("CreatedNode", {}).get("LedgerEntryType") == "Loan"
)
print("Setting up tutorial: 6/6", end="\r")
print("Setting up tutorial: 7/7", end="\r")
# Write setup data to JSON file
setup_data = {

View File

@@ -1,9 +1,16 @@
import xrpl from 'xrpl'
import fs from 'fs'
// Helper function to extract ticket sequences from a TicketCreate transaction result
function getTicketSequences(ticketCreateResult) {
return ticketCreateResult.result.meta.AffectedNodes
.filter(node => node.CreatedNode?.LedgerEntryType === 'Ticket')
.map(node => node.CreatedNode.NewFields.TicketSequence)
}
// Setup script for vault tutorials
process.stdout.write('Setting up tutorial: 0/5\r')
process.stdout.write('Setting up tutorial: 0/6\r')
const client = new xrpl.Client('wss://s.devnet.rippletest.net:51233')
await client.connect()
@@ -21,11 +28,37 @@ const [
client.fundWallet()
])
// Step 1: Create MPT issuance, permissioned domain, and credentials in parallel
process.stdout.write('Setting up tutorial: 1/5\r')
// Step 1: Create tickets for domain owner and depositor to submit transactions concurrently
process.stdout.write('Setting up tutorial: 1/6\r')
const credType = 'VaultAccess'
const [mptCreateResult] = await Promise.all([
const [domainOwnerTicketCreateResult, depositorTicketCreateResult] = await Promise.all([
client.submitAndWait(
{
TransactionType: 'TicketCreate',
Account: domainOwner.address,
TicketCount: 2
},
{ wallet: domainOwner, autofill: true }
),
client.submitAndWait(
{
TransactionType: 'TicketCreate',
Account: depositor.address,
TicketCount: 2
},
{ wallet: depositor, autofill: true }
)
])
// Get the ticket sequences from transaction results
const domainOwnerTicketSequences = getTicketSequences(domainOwnerTicketCreateResult)
const depositorTicketSequences = getTicketSequences(depositorTicketCreateResult)
// Step 2: Create MPT issuance, permissioned domain, and credentials in parallel
process.stdout.write('Setting up tutorial: 2/6\r')
const [mptCreateResult, domainSetResult] = await Promise.all([
client.submitAndWait(
{
TransactionType: "MPTokenIssuanceCreate",
@@ -71,35 +104,29 @@ const [mptCreateResult] = await Promise.all([
),
client.submitAndWait(
{
TransactionType: "Batch",
TransactionType: "PermissionedDomainSet",
Account: domainOwner.address,
Flags: xrpl.BatchFlags.tfAllOrNothing,
RawTransactions: [
AcceptedCredentials: [
{
RawTransaction: {
TransactionType: "PermissionedDomainSet",
Account: domainOwner.address,
AcceptedCredentials: [
{
Credential: {
Issuer: domainOwner.address,
CredentialType: xrpl.convertStringToHex(credType),
},
},
],
Flags: xrpl.GlobalFlags.tfInnerBatchTxn,
},
},
{
RawTransaction: {
TransactionType: "CredentialCreate",
Account: domainOwner.address,
Subject: depositor.address,
Credential: {
Issuer: domainOwner.address,
CredentialType: xrpl.convertStringToHex(credType),
Flags: xrpl.GlobalFlags.tfInnerBatchTxn,
},
},
],
TicketSequence: domainOwnerTicketSequences[0],
Sequence: 0
},
{ wallet: domainOwner, autofill: true },
),
client.submitAndWait(
{
TransactionType: "CredentialCreate",
Account: domainOwner.address,
Subject: depositor.address,
CredentialType: xrpl.convertStringToHex(credType),
TicketSequence: domainOwnerTicketSequences[1],
Sequence: 0
},
{ wallet: domainOwner, autofill: true },
),
@@ -107,44 +134,34 @@ const [mptCreateResult] = await Promise.all([
const mptIssuanceId = mptCreateResult.result.meta.mpt_issuance_id
// Get domain ID
const domainOwnerObjects = await client.request({
command: 'account_objects',
account: domainOwner.address,
ledger_index: 'validated'
})
const domainId = domainOwnerObjects.result.account_objects.find(
(node) => node.LedgerEntryType === 'PermissionedDomain'
).index
// Get domain ID from transaction result
const domainNode = domainSetResult.result.meta.AffectedNodes.find(
(node) => node.CreatedNode?.LedgerEntryType === 'PermissionedDomain'
)
const domainId = domainNode.CreatedNode.LedgerIndex
// Step 2: Depositor accepts credential, authorizes MPT, and creates vault in parallel
process.stdout.write('Setting up tutorial: 2/5\r')
// Step 3: Depositor accepts credential, authorizes MPT, and creates vault in parallel
process.stdout.write('Setting up tutorial: 3/6\r')
const [, vaultCreateResult] = await Promise.all([
const [, , vaultCreateResult] = await Promise.all([
client.submitAndWait(
{
TransactionType: 'Batch',
TransactionType: 'CredentialAccept',
Account: depositor.address,
Flags: xrpl.BatchFlags.tfAllOrNothing,
RawTransactions: [
{
RawTransaction: {
TransactionType: 'CredentialAccept',
Account: depositor.address,
Issuer: domainOwner.address,
CredentialType: xrpl.convertStringToHex(credType),
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
},
{
RawTransaction: {
TransactionType: 'MPTokenAuthorize',
Account: depositor.address,
MPTokenIssuanceID: mptIssuanceId,
Flags: xrpl.GlobalFlags.tfInnerBatchTxn
}
}
]
Issuer: domainOwner.address,
CredentialType: xrpl.convertStringToHex(credType),
TicketSequence: depositorTicketSequences[0],
Sequence: 0
},
{ wallet: depositor, autofill: true }
),
client.submitAndWait(
{
TransactionType: 'MPTokenAuthorize',
Account: depositor.address,
MPTokenIssuanceID: mptIssuanceId,
TicketSequence: depositorTicketSequences[1],
Sequence: 0
},
{ wallet: depositor, autofill: true }
),
@@ -196,8 +213,8 @@ const vaultNode = vaultCreateResult.result.meta.AffectedNodes.find(
const vaultID = vaultNode.CreatedNode.LedgerIndex
const vaultShareMPTIssuanceId = vaultNode.CreatedNode.NewFields.ShareMPTID
// Step 3: Issuer sends payment to depositor
process.stdout.write('Setting up tutorial: 3/5\r')
// Step 4: Issuer sends payment to depositor
process.stdout.write('Setting up tutorial: 4/6\r')
const paymentResult = await client.submitAndWait(
{
@@ -218,8 +235,8 @@ if (paymentResult.result.meta.TransactionResult !== 'tesSUCCESS') {
process.exit(1)
}
// Step 4: Make an initial deposit so withdraw example has shares to work with
process.stdout.write('Setting up tutorial: 4/5\r')
// Step 5: Make an initial deposit so withdraw example has shares to work with
process.stdout.write('Setting up tutorial: 5/6\r')
const initialDepositResult = await client.submitAndWait(
{
@@ -240,8 +257,8 @@ if (initialDepositResult.result.meta.TransactionResult !== 'tesSUCCESS') {
process.exit(1)
}
// Step 5: Save setup data to file
process.stdout.write('Setting up tutorial: 5/5\r')
// Step 6: Save setup data to file
process.stdout.write('Setting up tutorial: 6/6\r')
const setupData = {
mptIssuer: {

View File

@@ -6,11 +6,10 @@ from xrpl.asyncio.clients import AsyncWebsocketClient
from xrpl.asyncio.transaction import submit_and_wait
from xrpl.asyncio.wallet import generate_faucet_wallet
from xrpl.models import (
Batch, BatchFlag, CredentialAccept, CredentialCreate, MPTokenAuthorize,
CredentialAccept, CredentialCreate, MPTokenAuthorize,
MPTokenIssuanceCreate, MPTokenIssuanceCreateFlag, Payment,
PermissionedDomainSet, VaultDeposit
PermissionedDomainSet, TicketCreate, VaultDeposit
)
from xrpl.models.requests import AccountObjects
from xrpl.models.transactions.deposit_preauth import Credential
from xrpl.models.transactions.vault_create import (
VaultCreate, VaultCreateFlag, WithdrawalPolicy
@@ -18,9 +17,17 @@ from xrpl.models.transactions.vault_create import (
from xrpl.utils import encode_mptoken_metadata, str_to_hex
def get_ticket_sequences(ticket_create_result):
"""Extract ticket sequences from a TicketCreate transaction result."""
return [
node["CreatedNode"]["NewFields"]["TicketSequence"]
for node in ticket_create_result.result["meta"]["AffectedNodes"]
if "CreatedNode" in node and node["CreatedNode"].get("LedgerEntryType") == "Ticket"
]
async def main():
# Setup script for vault tutorials
print("Setting up tutorial: 0/5", end="\r")
print("Setting up tutorial: 0/6", end="\r")
async with AsyncWebsocketClient("wss://s.devnet.rippletest.net:51233") as client:
# Create and fund all wallets concurrently
@@ -31,11 +38,39 @@ async def main():
generate_faucet_wallet(client),
)
# Step 1: Create MPT issuance, permissioned domain, and credentials in parallel
print("Setting up tutorial: 1/5", end="\r")
# Step 1: Create tickets for domain owner and depositor to submit transactions concurrently
print("Setting up tutorial: 1/6", end="\r")
cred_type = "VaultAccess"
mpt_create_result, _ = await asyncio.gather(
domain_owner_ticket_create_result, depositor_ticket_create_result = await asyncio.gather(
submit_and_wait(
TicketCreate(
account=domain_owner.address,
ticket_count=2
),
client,
domain_owner,
autofill=True
),
submit_and_wait(
TicketCreate(
account=depositor.address,
ticket_count=2
),
client,
depositor,
autofill=True
)
)
# Get the ticket sequences from transaction results
domain_owner_ticket_sequences = get_ticket_sequences(domain_owner_ticket_create_result)
depositor_ticket_sequences = get_ticket_sequences(depositor_ticket_create_result)
# Step 2: Create MPT issuance, permissioned domain, and credentials in parallel
print("Setting up tutorial: 2/6", end="\r")
mpt_create_result, domain_set_result, _ = await asyncio.gather(
submit_and_wait(
MPTokenIssuanceCreate(
account=mpt_issuer.address,
@@ -82,25 +117,28 @@ async def main():
autofill=True
),
submit_and_wait(
Batch(
PermissionedDomainSet(
account=domain_owner.address,
flags=BatchFlag.TF_ALL_OR_NOTHING,
raw_transactions=[
PermissionedDomainSet(
account=domain_owner.address,
accepted_credentials=[
Credential(
issuer=domain_owner.address,
credential_type=str_to_hex(cred_type)
)
],
),
CredentialCreate(
account=domain_owner.address,
subject=depositor.address,
credential_type=str_to_hex(cred_type),
),
accepted_credentials=[
Credential(
issuer=domain_owner.address,
credential_type=str_to_hex(cred_type)
)
],
ticket_sequence=domain_owner_ticket_sequences[0],
sequence=0
),
client,
domain_owner,
autofill=True
),
submit_and_wait(
CredentialCreate(
account=domain_owner.address,
subject=depositor.address,
credential_type=str_to_hex(cred_type),
ticket_sequence=domain_owner_ticket_sequences[1],
sequence=0
),
client,
domain_owner,
@@ -110,36 +148,35 @@ async def main():
mpt_issuance_id = mpt_create_result.result["meta"]["mpt_issuance_id"]
# Get domain ID
domain_owner_objects = await client.request(AccountObjects(
account=domain_owner.address,
ledger_index="validated",
))
domain_id = next(
node["index"]
for node in domain_owner_objects.result["account_objects"]
if node["LedgerEntryType"] == "PermissionedDomain"
# Get domain ID from transaction result
domain_node = next(
node for node in domain_set_result.result["meta"]["AffectedNodes"]
if "CreatedNode" in node and node["CreatedNode"].get("LedgerEntryType") == "PermissionedDomain"
)
domain_id = domain_node["CreatedNode"]["LedgerIndex"]
# Step 2: Depositor accepts credential, authorizes MPT, and creates vault in parallel
print("Setting up tutorial: 2/5", end="\r")
# Step 3: Depositor accepts credential, authorizes MPT, and creates vault in parallel
print("Setting up tutorial: 3/6", end="\r")
_, vault_create_result = await asyncio.gather(
_, _, vault_create_result = await asyncio.gather(
submit_and_wait(
Batch(
CredentialAccept(
account=depositor.address,
flags=BatchFlag.TF_ALL_OR_NOTHING,
raw_transactions=[
CredentialAccept(
account=depositor.address,
issuer=domain_owner.address,
credential_type=str_to_hex(cred_type),
),
MPTokenAuthorize(
account=depositor.address,
mptoken_issuance_id=mpt_issuance_id,
),
],
issuer=domain_owner.address,
credential_type=str_to_hex(cred_type),
ticket_sequence=depositor_ticket_sequences[0],
sequence=0
),
client,
depositor,
autofill=True
),
submit_and_wait(
MPTokenAuthorize(
account=depositor.address,
mptoken_issuance_id=mpt_issuance_id,
ticket_sequence=depositor_ticket_sequences[1],
sequence=0
),
client,
depositor,
@@ -194,8 +231,8 @@ async def main():
vault_id = vault_node["CreatedNode"]["LedgerIndex"]
vault_share_mpt_issuance_id = vault_node["CreatedNode"]["NewFields"]["ShareMPTID"]
# Step 3: Issuer sends payment to depositor
print("Setting up tutorial: 3/5", end="\r")
# Step 4: Issuer sends payment to depositor
print("Setting up tutorial: 4/6", end="\r")
payment_result = await submit_and_wait(
Payment(
@@ -215,8 +252,8 @@ async def main():
print(f"\nPayment failed: {payment_result.result['meta']['TransactionResult']}", file=sys.stderr)
sys.exit(1)
# Step 4: Make an initial deposit so withdraw example has shares to work with
print("Setting up tutorial: 4/5", end="\r")
# Step 5: Make an initial deposit so withdraw example has shares to work with
print("Setting up tutorial: 5/6", end="\r")
initial_deposit_result = await submit_and_wait(
VaultDeposit(
@@ -236,8 +273,8 @@ async def main():
print(f"\nInitial deposit failed: {initial_deposit_result.result['meta']['TransactionResult']}", file=sys.stderr)
sys.exit(1)
# Step 5: Save setup data to file
print("Setting up tutorial: 5/5", end="\r")
# Step 6: Save setup data to file
print("Setting up tutorial: 6/6", end="\r")
setup_data = {
"mpt_issuer": {

View File

@@ -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."
},

View File

@@ -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" },
];

142
blog/2026/rippled-3.1.1.md Normal file
View File

@@ -0,0 +1,142 @@
---
category: 2026
date: "2026-02-23"
template: '../../@theme/templates/blogpost'
seo:
title: Introducing XRP Ledger version 3.1.1 and upcoming Devnet reset
description: rippled version 3.1.1 is now available. This version disables the Batch and fixBatchInnerSigs amendments. Devnet is also scheduled to reset on Tuesday, March 3, 2026 to prevent validators from becoming amendment blocked.
labels:
- rippled Release Notes
markdown:
editPage:
hide: true
---
# Introducing XRP Ledger version 3.1.1 and Upcoming Devnet Reset
Version 3.1.1 of `rippled`, the reference server implementation of the XRP Ledger protocol, is now available. This release supersedes version 3.1.0, disabling the `Batch` and `fixBatchInnerSigs` amendments due to a severe bug.
## Upcoming Devnet Reset
Devnet is scheduled for a reset on **Tuesday, March 3, 2026**. The `Batch` amendment requires more development and is now set to unsupported in version 3.1.1. To prevent validators that upgrade to this version from becoming amendment blocked, Devnet must be reset.
### Impact
This reset affects Devnet only. Other networks will continue to operate as usual, including XRPL Mainnet, XRPL Testnet, Xahau, and the Hooks Testnet.
The reset will delete all ledger data in Devnet, including all accounts, transactions, balances, settings, offers, AMMs, escrows, and other data. This means all balances will be reset to zero and the block number will start at one again. No changes are anticipated to services such as Devnet APIs, faucets, Explorers, access rights, and wallet integrations; these services usually manage resets without issues.
Any existing accounts or other data will need new test XRP from the faucet and will need to be re-created.
If code relies on specific addresses, a request to the faucet can fund the same address again. However, any AMMs or Vaults that are re-created after the reset will have different pseudo-account addresses. As a reminder, it's best not to use the same addresses or key pairs on Mainnet and any developer networks.
## Action Required
If you run an XRP Ledger server, upgrade to version 3.1.1 as soon as possible to ensure service continuity.
### Add New GPG Key
As a reminder, [Ripple rotated the GPG key](./gpg-key-rotation.md) used to sign `rippled` packages. You must download and trust the new key before upgrading to version 3.1.1.
{% tabs %}
{% tab label="Red Hat / CentOS" %}
```bash
sudo rpm --import https://repos.ripple.com/repos/rippled-rpm/stable/repodata/repomd.xml.key
rpm -qi gpg-pubkey-ab06faa6 | gpg --show-keys --fingerprint
```
{% /tab %}
{% tab label="Ubuntu / Debian" %}
```bash
sudo install -d -m 0755 /etc/apt/keyrings && \
curl -fsSL https://repos.ripple.com/repos/api/gpg/key/public \
| gpg --dearmor \
| sudo tee /etc/apt/keyrings/ripple.gpg > /dev/null
gpg --show-keys --fingerprint /etc/apt/keyrings/ripple.gpg
```
Ensure the `signed-by` path in your Ripple source list refers to the location the key was downloaded. For example, on an Ubuntu 22.04 Jammy installation, `/etc/apt/sources.list.d/ripple.list` would contain:
```
deb [signed-by=/etc/apt/keyrings/ripple.gpg] https://repos.ripple.com/repos/rippled-deb jammy stable
```
{% /tab %}
{% /tabs %}
The output should include an entry for Ripple such as the following:
```
pub ed25519 2026-02-16 [SC] [expires: 2033-02-14]
E057 C1CF 72B0 DF1A 4559 E857 7DEE 9236 AB06 FAA6
uid TechOps Team at Ripple <techops+rippled@ripple.com>
sub ed25519 2026-02-16 [S] [expires: 2029-02-15]
```
{% admonition type="danger" name="Warning" %}
Only trust this key if its fingerprint exactly matches: `E057 C1CF 72B0 DF1A 4559 E857 7DEE 9236 AB06 FAA6`.
{% /admonition %}
### Install / Upgrade
On supported platforms, see the [instructions on installing or updating `rippled`](../../docs/infrastructure/installation/index.md).
| Package | SHA-256 |
|:--------|:--------|
| [RPM for Red Hat / CentOS (x86-64)](https://repos.ripple.com/repos/rippled-rpm/stable/rippled-3.1.1-1.el9.x86_64.rpm) | `c6d028db1e2a4da898df68e5a92a893bebf1d167a0539d15ae27435f2155ccb2` |
| [DEB for Ubuntu / Debian (x86-64)](https://repos.ripple.com/repos/rippled-deb/pool/stable/rippled_3.1.1-1_amd64.deb) | `cc30c33012bd83ed793b38738870cf931a96ae106fde60b71685c766da1d22e3` |
For other platforms, please [build from source](https://github.com/XRPLF/rippled/blob/master/BUILD.md). The most recent commit in the git log should be the change setting the version:
```text
commit c5988233d05bedddac28866ed37607f4869855f9
Author: Ed Hennis <ed@ripple.com>
Date: Mon Feb 23 16:47:09 2026 -0400
Set version to 3.1.1 (#6410)
```
### Delete Devnet Database
If you run a `rippled` server that is connected to Devnet, after the reset you should delete your database data and restart the server. Database files and folders are defined in your config file in the `[database_path]` and `[node_db]` stanzas. If you use the default config, you can run the following commands:
```sh
rm -r /var/lib/rippled/db/*
systemctl restart rippled.service
```
## Full Changelog
### Amendments
- **Batch** - A bug was discovered in `Batch`, and the amendment was disabled. The fix for this feature will be included in a future release as `BatchV1_1`. ([#6402](https://github.com/XRPLF/rippled/pull/6402))
- **fixBatchInnerSigs** - A bug was discovered in `Batch`, so this amendment was also disabled. This fix will be included in a future release as part of `BatchV1_1`. ([#6402](https://github.com/XRPLF/rippled/pull/6402))
### CI/Build
- CI: Update `prepare-runner` action to fix macOS build environment. ([#6402](https://github.com/XRPLF/rippled/pull/6402))
## Credits
Thanks to Pranamya Keshkamat and Cantina AI for discovering and responsibly disclosing the `Batch` issue.
The following RippleX teams contributed to this release:
- RippleX Engineering
- RippleX Docs
- RippleX Product
## Bug Bounties and Responsible Disclosures
We welcome reviews of the `rippled` code and urge researchers to responsibly disclose any issues they may find.
For more information, see:
- [Ripple's Bug Bounty Program](https://ripple.com/legal/bug-bounty/)
- [rippled Security Policy](https://github.com/XRPLF/rippled/blob/develop/SECURITY.md)

View File

@@ -0,0 +1,113 @@
---
category: 2026
date: "2026-02-26"
template: '../../@theme/templates/blogpost'
seo:
description: This vulnerability disclosure report contains technical details of the XRP Ledger bug reported on February 19, 2026.
labels:
- Advisories
markdown:
editPage:
hide: true
---
# Vulnerability Disclosure Report: XRPL Batch Amendment Unauthorized Inner Transaction Execution
_By XRPL Labs_
This vulnerability disclosure report contains technical details of the XRPL `Batch` amendment bug reported on February 19, 2026.
**Date Reported:** February 19, 2026
**Affected Version(s):** rippled 3.1.0 (with the `Batch` amendment enabled)
## Summary of Vulnerability
On February 19, 2026, **Pranamya Keshkamat** and **Cantina AI** identified a critical logic flaw in the signature-validation logic of the XRPL `Batch` amendment. The bug allowed an attacker to execute inner transactions on behalf of arbitrary victim accounts without their private keys, enabling unauthorized fund transfers and ledger state changes. The amendment was in its voting phase and had not been activated on mainnet; no funds were at risk. Note that even before this bug was reported, the `Batch` amendment was disabled due to extra caution around ensuring the `fixBatchInnerSigs` amendment activated first.
UNL validators were immediately advised to vote "No" on the amendment. The emergency release **rippled 3.1.1** marks both `Batch` and `fixBatchInnerSigs` as unsupported, preventing activation. A corrected replacement, `BatchV1_1`, has been implemented and is currently under review; no release date has been set.
## Impact
If the `Batch` amendment had activated before this bug was caught, an attacker could have:
- **Stolen funds:** executed inner `Payment` transactions draining victim accounts down to the reserve, without access to victim private keys.
- **Modified ledger state:** submitted `AccountSet`, `TrustSet`, and potentially `AccountDelete` transactions from victim accounts without authorization.
- **Destabilized the ecosystem:** a successful large-scale exploit could have caused substantial loss of confidence in XRPL, with potentially significant disruption for the broader ecosystem.
## Technical Details
### Discovery
**Pranamya Keshkamat** and the autonomous AI security tool **Apex** (developed by **Cantina AI**) identified the vulnerability via static analysis of the rippled codebase and submitted a responsible disclosure report. Ripple engineering teams promptly validated the report with an independent proof-of-concept and a full unit-test reproduction. Remediation began the same evening.
### Root Cause
When the `Batch` amendment is enabled, inner transactions in a batch are intentionally unsigned; authorization is delegated entirely to the outer batch's list of batch signers. The function responsible for validating those signers contained a critical loop error: when it encountered a signer whose account did not yet exist on the ledger and whose signing key matched their own account (the normal case for a brand-new account), it immediately declared success and exited, skipping validation of all remaining signers entirely.
### Exploit Path
1. The attacker constructs a batch transaction containing three inner transactions: one that creates a new account they control (account B), one simple transaction from that new account (making it a required signer), and one payment from the victim account to the attacker.
2. The attacker provides two batch signer entries: a legitimate one for account B signed with B's own key, and a forged one claiming to authorize the victim account but signed with the attacker's own key.
3. Because account B does not yet exist at validation time, the signer check exits successfully after the first entry and never validates the second.
4. The victim's payment executes without the victim's keys ever being involved.
## Remediation
- UNL validators were contacted and advised to vote "No" on the `Batch` amendment.
- **rippled 3.1.1** was published on February 23, 2026. This release marks `Batch` and `fixBatchInnerSigs` as unsupported, preventing them from receiving validator votes or being activated on the network. This is the immediate remediation and does not contain the underlying logic fix.
- The full logic fix removing the early-exit, adding additional authorization guards, and tightening the scope of the signing check has been implemented and is undergoing a thorough review process prior to release under the `BatchV1_1` amendment. Given the sensitivity of the changes, no timeline has been set.
## Security Enhancements Roadmap
- Adding AI-assisted code audit pipelines as a standard step in the review process.
- Extending static analysis coverage to flag premature success returns inside signer-iteration loops.
- Adding explicit comments and invariant assertions documenting expected behavior for uncreated accounts at validation time.
- Reviewing all other locations in the codebase where early success returns occur inside loops to confirm no similar patterns exist.
## Steps to Reproduce
1. Fund two attacker-controlled accounts and leave a third unfunded. Construct a batch transaction containing a payment that creates the unfunded account, a simple transaction from that account, and a payment from the victim account to the attacker.
2. Sign the batch message with the unfunded account's master key for its signer entry, and with the attacker's own key for a second signer entry that falsely claims to authorize the victim account.
3. Submit the batch transaction to the network.
**Pre-fix behavior:**
- The batch transaction succeeds.
- The victim account's balance is reduced by the payment amount without the victim's keys being used.
- The attacker's balance increases by the net amount minus the batch fee.
**Expected post-fix behavior:**
- The batch transaction is rejected with an authorization error.
- No account balances change.
## Fixes / Patches Available
[**rippled 3.1.1**](https://xrpl.org/blog/2026/rippled-3.1.1) is available now. The corrected `BatchV1_1` amendment will be included in a future release following completion of its review; no date has been set.
## Acknowledgements
Thanks to **Pranamya Keshkamat** and **Cantina AI** (whose autonomous security tool *Apex* identified the vulnerability) for responsible and thorough disclosure. Their detailed bug report, proof-of-concept, and constructive collaboration throughout the remediation process were invaluable.
Thanks also to the UNL validators who moved swiftly to vote against the affected amendment, the Ripple and XRPL Foundation engineering teams for the expedited review and emergency release, and the broader community of validators, developers, and contributors who keep the XRP Ledger safe and secure.
## References
- [rippled 3.1.1 release](https://xrpl.org/blog/2026/rippled-3.1.1)
- [Community post on X](https://x.com/hrkrshnn/status/2025336360010387613)
## Contact
To report security issues, contact [security@ripple.com](mailto:security@ripple.com).
## Incident Response Timeline
| Key Action | Timestamp | Description |
|---|---|---|
| Initial Discovery | February 19, 2026 | Bug reported by Pranamya Keshkamat & Cantina AI. Engineering teams validated the report and opened an emergency response channel. |
| Validator Notification | February 19, 2026 | UNL validators advised to vote "No" on `Batch`. Several validators applied vetoes the same evening. |
| Unit Test Reproduction | February 19, 2026 | Independent unit-test reproduction confirmed. Proof-of-concept script validated by multiple engineers. |
| Patch In Review | February 21, 2026 | Fix created in a private repository and currently under review. |
| Emergency Release | February 23, 2026 | rippled 3.1.1 published. Operators advised to upgrade. |
| Report Published | February 25, 2026 | Public vulnerability disclosure report published. |

View File

@@ -10,6 +10,8 @@
- group: '2026'
expanded: false
items:
- page: 2026/vulnerabilitydisclosurereport-bug-feb2026.md
- page: 2026/rippled-3.1.1.md
- page: 2026/gpg-key-rotation.md
- page: 2026/rippled-3.1.0.md
- page: 2026/clio-2.7.0.md

View File

@@ -10,6 +10,8 @@ status: not_enabled
XRPL Batch Transactions let you package multiple [transactions](/docs/concepts/transactions) together and execute them as a single unit. It eliminates the risk of partial completion and unexpected outcomes, giving you a more reliable and predictable experience for complex operations. Up to eight transactions can be submitted in a single batch.
{% amendment-disclaimer name="Batch" /%}
## XRPL Batch Use Cases
Some potential uses for `Batch` include the following.

View File

@@ -43,6 +43,49 @@ metadataGlobs:
redocly_category: Community
seo:
siteUrl: https://xrpl.org/
llmstxt:
hide: false
title: XRPL Developer Portal & Documentation
description: >-
Explore XRP Ledger documentation, blog, announcements, and other
blockchain developer resources needed to start building and
integrating with the ledger.
details:
content: >-
XRP Ledger documentation, tutorials, samples, and other blockchain
developer resources. Also, stay up to date with release announcements
and more through XRPL Blog.
# toplevel link to alternate language file; will appear at head of llms.txt
sections:
- title: Docs (English)
description: XRP Ledger documentation and tutorials (english only)
includeFiles:
- docs/**/*.*
excludeFiles:
- '@l10n/**' # drop all localized copies
- title: Blog (2023+)
description: Recent XRPL Blog posts (showing 2023 and newer)
includeFiles:
- blog/2023/**/*.md
- blog/2024/**/*.md
- blog/2025/**/*.md
- blog/2026/**/*.md
- title: Resources
description: Code samples, dev tools, and other resources
includeFiles:
- resources/**/*.*
- title: Community
description: Connect with the XRPL community, find events, funding
opportunities, and more.
includeFiles:
- community/**/*.*
- title: About
description: Learn about the XRP Ledger, its history, impact, and
more.
includeFiles:
- about/**/*.*
# configuration for generating additional locale-specific file(s)
analytics:
gtm:
includeInDevelopment: true

View File

@@ -35,6 +35,8 @@ The following is a list of known [amendments](../docs/concepts/networks-and-serv
| Name | Introduced | Status |
|:----------------------------------|:-----------|:------------------------------|
| [fixBatchInnerSigs] | v3.1.0 | {% badge href="https://xrpl.org/blog/2026/rippled-3.1.1" %}Obsolete: Removed in v3.1.1{% /badge %} |
| [Batch] | v2.5.0 | {% badge href="https://xrpl.org/blog/2026/rippled-3.1.1" %}Obsolete: Removed in v3.1.1{% /badge %} |
| [PermissionDelegation] | v2.5.0 | {% badge href="https://xrpl.org/blog/2025/rippled-2.6.1" %}Obsolete: Removed in v2.6.1{% /badge %} |
| [fixNFTokenNegOffer][] | v1.9.2 | {% badge %}Obsolete: To Be Removed{% /badge %} |
| [fixNFTokenDirV1][] | v1.9.1 | {% badge %}Obsolete: To Be Removed{% /badge %} |
@@ -105,12 +107,16 @@ For details, see the [XLS-73: AMMClawback specification](https://github.com/XRPL
| Amendment | Batch |
|:-------------|:------|
| Amendment ID | 894646DD5284E97DECFE6674A6D6152686791C4A95F8C132CCA9BAF9E5812FB6 |
| Status | Open for Voting |
| Status | Obsolete |
| Default Vote (Latest stable release) | No |
| Pre-amendment functionality retired? | No |
Allows multiple transactions to be bundled into a batch that's processed all together. Standard: [XLS-56](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0056-batch)
{% admonition type="danger" name="Warning" %}
This amendment was disabled in v3.1.1 due to a bug. It will be replaced by `BatchV1_1` in a future release.
{% /admonition %}
### CheckCashMakesTrustLine
[CheckCashMakesTrustLine]: #checkcashmakestrustline
@@ -746,12 +752,16 @@ Adds several fixes to Automated Market Maker code, specifically:
| Amendment | fixBatchInnerSigs |
|:-------------|:----------------|
| Amendment ID | 267624F8F744C4A4F1B5821A7D54410BCEBABE987F0172EE89E5FC4B6EDBC18A |
| Status | Open for Voting |
| Status | Obsolete |
| Default Vote (Latest stable release) | No |
| Pre-amendment functionality retired? | No |
This amendment fixes an issue where inner transactions of a `Batch` transaction would be flagged as having valid signatures. Since inner transactions aren't signed directly, they should never have valid signatures.
{% admonition type="danger" name="Warning" %}
This amendment was disabled in v3.1.1 due to a bug. It will be replaced by `BatchV1_1` in a future release.
{% /admonition %}
### fixCheckThreading
[fixCheckThreading]: #fixcheckthreading
@@ -1699,9 +1709,11 @@ For more information, see the [Payment Channels Tutorial](../docs/tutorials/how-
| Default Vote (Latest stable release) | No |
| Pre-amendment functionality retired? | No |
Allows accounts to delegate some permissions to other accounts. This amendment was disabled in v2.6.1 due to a bug. It will be replaced by `PermissionDelegationV1_1` in a future release.
Allows accounts to delegate some permissions to other accounts. Specification: [XLS-75](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0075-permission-delegation).
Specification: [XLS-75](https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0075-permission-delegation).
{% admonition type="danger" name="Warning" %}
This amendment was disabled in v2.6.1 due to a bug. It will be replaced by `PermissionDelegationV1_1` in a future release.
{% /admonition %}
### PermissionedDEX

File diff suppressed because one or more lines are too long

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View 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

View 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

View File

@@ -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",

View File

@@ -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";

View File

@@ -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'