diff --git a/css/main.css b/css/main.css index 461e011..980608f 100644 --- a/css/main.css +++ b/css/main.css @@ -1173,6 +1173,16 @@ body { 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 { display: flex; align-items: flex-start; @@ -1220,6 +1230,14 @@ body { font-size: 1rem; } +.tx-direction.offer-create { + color: #87ceeb; /* Sky blue color */ +} + +.transaction-card.offer .tx-direction { + color: #87ceeb; +} + .tx-date { font-size: 0.875rem; color: var(--text-secondary); @@ -1249,6 +1267,40 @@ body { 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 { margin-bottom: 0.5rem; } @@ -1322,7 +1374,55 @@ body { /* Responsive design for transaction cards */ @media (max-width: 768px) { .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 { @@ -1354,6 +1454,7 @@ body { .tx-amount { font-size: 1rem; + margin-bottom: 0.5rem; } .tx-address-row, diff --git a/scripts/wallet.js b/scripts/wallet.js index d268301..aa6ef76 100644 --- a/scripts/wallet.js +++ b/scripts/wallet.js @@ -1120,26 +1120,94 @@ function displayTransactionsPage() { // Determine transaction direction and type const isIncoming = t.Destination === address; - const direction = isIncoming ? "Received" : "Sent"; - const directionIcon = isIncoming ? "fa-arrow-down" : "fa-arrow-up"; - const directionClass = isIncoming ? "incoming" : "outgoing"; + let direction = isIncoming ? "Received" : "Sent"; + let directionIcon = isIncoming ? "fa-arrow-down" : "fa-arrow-up"; + 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 let amount = "0"; - 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); + let currency = "XRP"; + let issuer = ""; + + // Special handling for OfferCreate transactions + if (t.TransactionType === "OfferCreate") { + // For OfferCreate, compute Buy/Sell lines: creator buys TakerPays, sells TakerGets + let takerGetsAmount = "N/A"; + let takerGetsCurrency = "N/A"; + let takerPaysAmount = "N/A"; + let takerPaysCurrency = "N/A"; + + // 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 { - 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 @@ -1168,37 +1236,59 @@ function displayTransactionsPage() {
- ${direction} + ${direction} ${formattedDate}, ${formattedTime}
-
- ${amount} XRP -
+ ${ + t.TransactionType === "OfferCreate" + ? `
+
+ Buy + ${offerBuyAmount} ${offerBuyCurrency} +
+
+ Sell + ${offerSellAmount} ${offerSellCurrency} +
+
` + : `
+ ${amount} ${ + currency === "XRP" && t.TransactionType !== "OfferCreate" + ? "XRP" + : "" + } +
` + }
+ ${ + t.TransactionType === "OfferCreate" + ? `
+ Account: + ${t.Account} +
` + : `
+ From: + ${t.Account} +
+ ${ + currency === "REN" && issuer + ? `
+ Issuer: + ${issuer} +
` + : "" + } +
+ To: + ${t.Destination || "N/A"} +
` + }
- From: - ${t.Account.substring( - 0, - 8 - )}...${t.Account.substring(t.Account.length - 6)} + Tx: + ${t.hash}
-
- To: - ${ - t.Destination - ? t.Destination.substring(0, 8) + - "..." + - t.Destination.substring(t.Destination.length - 6) - : "N/A" - } -
-
-
- Tx: - ${t.hash.substring( - 0, - 8 - )}...${t.hash.substring(t.hash.length - 6)}
@@ -2010,6 +2100,7 @@ async function checkTransactionDetails() { command: "tx", transaction: txHash, }); + console.log(txResponse); if (txResponse.result) { displayTransactionDetails(txResponse.result); @@ -2065,9 +2156,6 @@ function displayTransactionDetails(txData) { const txType = txData.TransactionType || "Unknown"; const account = txData.Account || "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 sequence = txData.Sequence || "N/A"; const ledgerIndex = txData.ledger_index || "N/A"; @@ -2077,6 +2165,84 @@ function displayTransactionDetails(txData) { : "N/A"; 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 = ` +
+ Buy: + ${takerPaysAmount} ${takerPaysCurrency} +
+
+ Sell: + ${takerGetsAmount} ${takerGetsCurrency} +
+ `; + } 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 = ` +
+ + + Amount: + + ${amountStr} +
+ ${ + issuerStr + ? `
+ + + Issuer: + + ${issuerStr} +
` + : "" + } + `; + } + detailsContainer.innerHTML = `
@@ -2093,13 +2259,7 @@ function displayTransactionDetails(txData) { ${txType}
-
- - - Amount: - - ${amount} -
+ ${amountInfo}
@@ -2118,7 +2278,7 @@ function displayTransactionDetails(txData) { ${account}
${ - destination !== "N/A" + destination !== "N/A" && txType !== "OfferCreate" ? `