Add OfferCreate transaction handling and styling for transaction cards
This commit is contained in:
parent
73da6ae580
commit
b5678ce8ad
103
css/main.css
103
css/main.css
@ -1173,6 +1173,16 @@ body {
|
|||||||
border-left: 4px solid var(--danger-color);
|
border-left: 4px solid var(--danger-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* OfferCreate styling - sky blue like a third category */
|
||||||
|
.transaction-card.offer {
|
||||||
|
border-left: 4px solid #87ceeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-card.offer .tx-icon {
|
||||||
|
background: rgba(135, 206, 235, 0.15);
|
||||||
|
color: #87ceeb;
|
||||||
|
}
|
||||||
|
|
||||||
.tx-main {
|
.tx-main {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
@ -1220,6 +1230,14 @@ body {
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tx-direction.offer-create {
|
||||||
|
color: #87ceeb; /* Sky blue color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-card.offer .tx-direction {
|
||||||
|
color: #87ceeb;
|
||||||
|
}
|
||||||
|
|
||||||
.tx-date {
|
.tx-date {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
@ -1249,6 +1267,40 @@ body {
|
|||||||
color: var(--danger-color);
|
color: var(--danger-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.transaction-card.offer .tx-amount {
|
||||||
|
color: #87ceeb; /* Sky blue color */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make OfferCreate text white-ish */
|
||||||
|
.transaction-card.offer .tx-direction,
|
||||||
|
.transaction-card.offer .tx-amount {
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OfferCreate Buy/Sell layout */
|
||||||
|
.tx-offer-lines {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offer-line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offer-label {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.offer-value {
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
.tx-addresses {
|
.tx-addresses {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
@ -1322,7 +1374,55 @@ body {
|
|||||||
/* Responsive design for transaction cards */
|
/* Responsive design for transaction cards */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.transaction-card {
|
.transaction-card {
|
||||||
padding-right: 1rem;
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make address information in one line for OfferCreate transactions on small screens */
|
||||||
|
.transaction-card.offer .tx-addresses {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-card.offer .tx-address-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-card.offer .address-label {
|
||||||
|
min-width: auto;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-card.offer .address-value {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* General styling for address rows on small screens */
|
||||||
|
.tx-addresses {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Truncate address values on small screens */
|
||||||
|
.tx-address-row .address-value,
|
||||||
|
.tx-address-row .hash-value {
|
||||||
|
max-width: 50vw;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tx-address-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tx-main {
|
.tx-main {
|
||||||
@ -1354,6 +1454,7 @@ body {
|
|||||||
|
|
||||||
.tx-amount {
|
.tx-amount {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tx-address-row,
|
.tx-address-row,
|
||||||
|
|||||||
@ -1120,26 +1120,94 @@ function displayTransactionsPage() {
|
|||||||
|
|
||||||
// Determine transaction direction and type
|
// Determine transaction direction and type
|
||||||
const isIncoming = t.Destination === address;
|
const isIncoming = t.Destination === address;
|
||||||
const direction = isIncoming ? "Received" : "Sent";
|
let direction = isIncoming ? "Received" : "Sent";
|
||||||
const directionIcon = isIncoming ? "fa-arrow-down" : "fa-arrow-up";
|
let directionIcon = isIncoming ? "fa-arrow-down" : "fa-arrow-up";
|
||||||
const directionClass = isIncoming ? "incoming" : "outgoing";
|
let directionClass = isIncoming ? "incoming" : "outgoing";
|
||||||
|
|
||||||
|
// Special handling for OfferCreate transactions
|
||||||
|
if (t.TransactionType === "OfferCreate") {
|
||||||
|
direction = "Offer Create";
|
||||||
|
directionIcon = "fa-exchange-alt";
|
||||||
|
directionClass = "offer";
|
||||||
|
}
|
||||||
|
|
||||||
// Get amount - handle different formats
|
// Get amount - handle different formats
|
||||||
let amount = "0";
|
let amount = "0";
|
||||||
if (
|
let currency = "XRP";
|
||||||
meta.delivered_amount &&
|
let issuer = "";
|
||||||
typeof meta.delivered_amount === "string" &&
|
|
||||||
!isNaN(Number(meta.delivered_amount))
|
// Special handling for OfferCreate transactions
|
||||||
) {
|
if (t.TransactionType === "OfferCreate") {
|
||||||
amount = xrpl.dropsToXrp(meta.delivered_amount);
|
// For OfferCreate, compute Buy/Sell lines: creator buys TakerPays, sells TakerGets
|
||||||
} else if (
|
let takerGetsAmount = "N/A";
|
||||||
t.Amount &&
|
let takerGetsCurrency = "N/A";
|
||||||
typeof t.Amount === "string" &&
|
let takerPaysAmount = "N/A";
|
||||||
!isNaN(Number(t.Amount))
|
let takerPaysCurrency = "N/A";
|
||||||
) {
|
|
||||||
amount = xrpl.dropsToXrp(t.Amount);
|
// Handle TakerGets
|
||||||
|
if (t.TakerGets) {
|
||||||
|
if (typeof t.TakerGets === "string") {
|
||||||
|
// XRP in drops
|
||||||
|
takerGetsAmount = xrpl.dropsToXrp(t.TakerGets);
|
||||||
|
takerGetsCurrency = "XRP";
|
||||||
|
} else if (typeof t.TakerGets === "object") {
|
||||||
|
// IOU
|
||||||
|
takerGetsAmount = t.TakerGets.value;
|
||||||
|
takerGetsCurrency = t.TakerGets.currency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle TakerPays
|
||||||
|
if (t.TakerPays) {
|
||||||
|
if (typeof t.TakerPays === "string") {
|
||||||
|
// XRP in drops
|
||||||
|
takerPaysAmount = xrpl.dropsToXrp(t.TakerPays);
|
||||||
|
takerPaysCurrency = "XRP";
|
||||||
|
} else if (typeof t.TakerPays === "object") {
|
||||||
|
// IOU
|
||||||
|
takerPaysAmount = t.TakerPays.value;
|
||||||
|
takerPaysCurrency = t.TakerPays.currency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display strings kept for backward compatibility (not used in markup)
|
||||||
|
amount = `${takerPaysAmount} ${takerPaysCurrency} for ${takerGetsAmount} ${takerGetsCurrency}`;
|
||||||
|
// Map for UI
|
||||||
|
var offerBuyAmount = takerPaysAmount;
|
||||||
|
var offerBuyCurrency = takerPaysCurrency;
|
||||||
|
var offerSellAmount = takerGetsAmount;
|
||||||
|
var offerSellCurrency = takerGetsCurrency;
|
||||||
} else {
|
} else {
|
||||||
amount = "N/A"; // Non-payment tx or unsupported format
|
// Handle currency objects (including "ren" currency)
|
||||||
|
if (t.Amount && typeof t.Amount === "object") {
|
||||||
|
if (t.Amount.currency === "ren") {
|
||||||
|
amount = `${t.Amount.value}`;
|
||||||
|
} else {
|
||||||
|
amount = `${t.Amount.value} ${t.Amount.currency}`;
|
||||||
|
}
|
||||||
|
currency = t.Amount.currency;
|
||||||
|
issuer = t.Amount.issuer || "";
|
||||||
|
} else if (
|
||||||
|
meta.delivered_amount &&
|
||||||
|
typeof meta.delivered_amount === "string" &&
|
||||||
|
!isNaN(Number(meta.delivered_amount))
|
||||||
|
) {
|
||||||
|
amount = xrpl.dropsToXrp(meta.delivered_amount);
|
||||||
|
} else if (
|
||||||
|
t.Amount &&
|
||||||
|
typeof t.Amount === "string" &&
|
||||||
|
!isNaN(Number(t.Amount))
|
||||||
|
) {
|
||||||
|
amount = xrpl.dropsToXrp(t.Amount);
|
||||||
|
} else if (t.Amount && typeof t.Amount === "object") {
|
||||||
|
// Handle other currency objects
|
||||||
|
amount = t.Amount.value;
|
||||||
|
currency = t.Amount.currency;
|
||||||
|
issuer = t.Amount.issuer || "";
|
||||||
|
amount = `${amount} ${currency}`;
|
||||||
|
} else {
|
||||||
|
amount = "N/A"; // Non-payment tx or unsupported format
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format date
|
// Format date
|
||||||
@ -1168,37 +1236,59 @@ function displayTransactionsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="tx-info">
|
<div class="tx-info">
|
||||||
<div class="tx-header">
|
<div class="tx-header">
|
||||||
<span class="tx-direction">${direction}</span>
|
<span class="tx-direction ${
|
||||||
|
t.TransactionType === "OfferCreate" ? "offer-create" : ""
|
||||||
|
}">${direction}</span>
|
||||||
<span class="tx-date">${formattedDate}, ${formattedTime}</span>
|
<span class="tx-date">${formattedDate}, ${formattedTime}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tx-amount ${directionClass}">
|
${
|
||||||
${amount} XRP
|
t.TransactionType === "OfferCreate"
|
||||||
</div>
|
? `<div class="tx-offer-lines">
|
||||||
|
<div class="offer-line">
|
||||||
|
<span class="offer-label">Buy</span>
|
||||||
|
<span class="offer-value">${offerBuyAmount} ${offerBuyCurrency}</span>
|
||||||
|
</div>
|
||||||
|
<div class="offer-line">
|
||||||
|
<span class="offer-label">Sell</span>
|
||||||
|
<span class="offer-value">${offerSellAmount} ${offerSellCurrency}</span>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
: `<div class="tx-amount ${directionClass}">
|
||||||
|
${amount} ${
|
||||||
|
currency === "XRP" && t.TransactionType !== "OfferCreate"
|
||||||
|
? "XRP"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
<div class="tx-addresses">
|
<div class="tx-addresses">
|
||||||
|
${
|
||||||
|
t.TransactionType === "OfferCreate"
|
||||||
|
? `<div class="tx-address-row">
|
||||||
|
<span class="address-label">Account:</span>
|
||||||
|
<span class="address-value">${t.Account}</span>
|
||||||
|
</div>`
|
||||||
|
: `<div class="tx-address-row">
|
||||||
|
<span class="address-label">From:</span>
|
||||||
|
<span class="address-value">${t.Account}</span>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
currency === "REN" && issuer
|
||||||
|
? `<div class="tx-address-row">
|
||||||
|
<span class="address-label">Issuer:</span>
|
||||||
|
<span class="address-value">${issuer}</span>
|
||||||
|
</div>`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
<div class="tx-address-row">
|
||||||
|
<span class="address-label">To:</span>
|
||||||
|
<span class="address-value">${t.Destination || "N/A"}</span>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
<div class="tx-address-row">
|
<div class="tx-address-row">
|
||||||
<span class="address-label">From:</span>
|
<span class="address-label">Tx:</span>
|
||||||
<span class="address-value">${t.Account.substring(
|
<span class="hash-value">${t.hash}</span>
|
||||||
0,
|
|
||||||
8
|
|
||||||
)}...${t.Account.substring(t.Account.length - 6)}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tx-address-row">
|
|
||||||
<span class="address-label">To:</span>
|
|
||||||
<span class="address-value">${
|
|
||||||
t.Destination
|
|
||||||
? t.Destination.substring(0, 8) +
|
|
||||||
"..." +
|
|
||||||
t.Destination.substring(t.Destination.length - 6)
|
|
||||||
: "N/A"
|
|
||||||
}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tx-hash">
|
|
||||||
<span class="hash-label">Tx:</span>
|
|
||||||
<span class="hash-value">${t.hash.substring(
|
|
||||||
0,
|
|
||||||
8
|
|
||||||
)}...${t.hash.substring(t.hash.length - 6)}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tx-status ${statusClass}">
|
<div class="tx-status ${statusClass}">
|
||||||
@ -2010,6 +2100,7 @@ async function checkTransactionDetails() {
|
|||||||
command: "tx",
|
command: "tx",
|
||||||
transaction: txHash,
|
transaction: txHash,
|
||||||
});
|
});
|
||||||
|
console.log(txResponse);
|
||||||
|
|
||||||
if (txResponse.result) {
|
if (txResponse.result) {
|
||||||
displayTransactionDetails(txResponse.result);
|
displayTransactionDetails(txResponse.result);
|
||||||
@ -2065,9 +2156,6 @@ function displayTransactionDetails(txData) {
|
|||||||
const txType = txData.TransactionType || "Unknown";
|
const txType = txData.TransactionType || "Unknown";
|
||||||
const account = txData.Account || "N/A";
|
const account = txData.Account || "N/A";
|
||||||
const destination = txData.Destination || "N/A";
|
const destination = txData.Destination || "N/A";
|
||||||
const amount = txData.Amount
|
|
||||||
? parseFloat(txData.Amount) / 1000000 + " XRP"
|
|
||||||
: "N/A";
|
|
||||||
const fee = txData.Fee ? parseFloat(txData.Fee) / 1000000 + " XRP" : "N/A";
|
const fee = txData.Fee ? parseFloat(txData.Fee) / 1000000 + " XRP" : "N/A";
|
||||||
const sequence = txData.Sequence || "N/A";
|
const sequence = txData.Sequence || "N/A";
|
||||||
const ledgerIndex = txData.ledger_index || "N/A";
|
const ledgerIndex = txData.ledger_index || "N/A";
|
||||||
@ -2077,6 +2165,84 @@ function displayTransactionDetails(txData) {
|
|||||||
: "N/A";
|
: "N/A";
|
||||||
const validated = txData.validated ? "Validated" : "Not Validated";
|
const validated = txData.validated ? "Validated" : "Not Validated";
|
||||||
|
|
||||||
|
// Special handling for OfferCreate transactions
|
||||||
|
let amountInfo = "";
|
||||||
|
if (txType === "OfferCreate") {
|
||||||
|
// Handle TakerGets/Pays and build Buy/Sell lines
|
||||||
|
let takerGetsAmount = "N/A";
|
||||||
|
let takerGetsCurrency = "N/A";
|
||||||
|
if (txData.TakerGets) {
|
||||||
|
if (typeof txData.TakerGets === "string") {
|
||||||
|
// XRP in drops
|
||||||
|
takerGetsAmount = xrpl.dropsToXrp(txData.TakerGets);
|
||||||
|
takerGetsCurrency = "XRP";
|
||||||
|
} else if (typeof txData.TakerGets === "object") {
|
||||||
|
// IOU
|
||||||
|
takerGetsAmount = txData.TakerGets.value;
|
||||||
|
takerGetsCurrency = txData.TakerGets.currency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle TakerPays
|
||||||
|
let takerPaysAmount = "N/A";
|
||||||
|
let takerPaysCurrency = "N/A";
|
||||||
|
if (txData.TakerPays) {
|
||||||
|
if (typeof txData.TakerPays === "string") {
|
||||||
|
// XRP in drops
|
||||||
|
takerPaysAmount = xrpl.dropsToXrp(txData.TakerPays);
|
||||||
|
takerPaysCurrency = "XRP";
|
||||||
|
} else if (typeof txData.TakerPays === "object") {
|
||||||
|
// IOU
|
||||||
|
takerPaysAmount = txData.TakerPays.value;
|
||||||
|
takerPaysCurrency = txData.TakerPays.currency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
amountInfo = `
|
||||||
|
<div class="tx-detail-row">
|
||||||
|
<span class="tx-detail-label"><i class="fas fa-arrow-circle-up"></i> Buy:</span>
|
||||||
|
<span class="tx-detail-value amount">${takerPaysAmount} ${takerPaysCurrency}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tx-detail-row">
|
||||||
|
<span class="tx-detail-label"><i class="fas fa-arrow-circle-down"></i> Sell:</span>
|
||||||
|
<span class="tx-detail-value amount">${takerGetsAmount} ${takerGetsCurrency}</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Handle regular payment transactions (XRP or IOU like REN)
|
||||||
|
let amountStr = "N/A";
|
||||||
|
let issuerStr = "";
|
||||||
|
if (txData.Amount) {
|
||||||
|
if (typeof txData.Amount === "string") {
|
||||||
|
amountStr = parseFloat(txData.Amount) / 1000000 + " XRP";
|
||||||
|
} else if (typeof txData.Amount === "object") {
|
||||||
|
amountStr = `${txData.Amount.value} ${txData.Amount.currency}`;
|
||||||
|
issuerStr = txData.Amount.issuer || "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
amountInfo = `
|
||||||
|
<div class="tx-detail-row">
|
||||||
|
<span class="tx-detail-label">
|
||||||
|
<i class="fas fa-coins"></i>
|
||||||
|
Amount:
|
||||||
|
</span>
|
||||||
|
<span class="tx-detail-value amount">${amountStr}</span>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
issuerStr
|
||||||
|
? `<div class="tx-detail-row">
|
||||||
|
<span class="tx-detail-label">
|
||||||
|
<i class="fas fa-building"></i>
|
||||||
|
Issuer:
|
||||||
|
</span>
|
||||||
|
<span class="tx-detail-value">${issuerStr}</span>
|
||||||
|
</div>`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
detailsContainer.innerHTML = `
|
detailsContainer.innerHTML = `
|
||||||
<div class="tx-detail-card">
|
<div class="tx-detail-card">
|
||||||
<div class="tx-detail-row">
|
<div class="tx-detail-row">
|
||||||
@ -2093,13 +2259,7 @@ function displayTransactionDetails(txData) {
|
|||||||
</span>
|
</span>
|
||||||
<span class="tx-detail-value">${txType}</span>
|
<span class="tx-detail-value">${txType}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tx-detail-row">
|
${amountInfo}
|
||||||
<span class="tx-detail-label">
|
|
||||||
<i class="fas fa-coins"></i>
|
|
||||||
Amount:
|
|
||||||
</span>
|
|
||||||
<span class="tx-detail-value amount">${amount}</span>
|
|
||||||
</div>
|
|
||||||
<div class="tx-detail-row">
|
<div class="tx-detail-row">
|
||||||
<span class="tx-detail-label">
|
<span class="tx-detail-label">
|
||||||
<i class="fas fa-receipt"></i>
|
<i class="fas fa-receipt"></i>
|
||||||
@ -2118,7 +2278,7 @@ function displayTransactionDetails(txData) {
|
|||||||
<span class="tx-detail-value">${account}</span>
|
<span class="tx-detail-value">${account}</span>
|
||||||
</div>
|
</div>
|
||||||
${
|
${
|
||||||
destination !== "N/A"
|
destination !== "N/A" && txType !== "OfferCreate"
|
||||||
? `
|
? `
|
||||||
<div class="tx-detail-row">
|
<div class="tx-detail-row">
|
||||||
<span class="tx-detail-label">
|
<span class="tx-detail-label">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user