Market Information
The "MarketInfo" component highlights a comparison of On-Chain SDEX information to Overall Centralized Exchange information for XLM.
Features
- Automatically updates and interval refreshes.
- Provides DEX highs, lows and volume.
- Provides Centralized Exchange supply, market cap, current price, price change, highs, lows and volume.
- Provides a way to compare centralized traffic to SDEX completion.
Additional Resources
Instead of relying on the buy and sell orders of decentralized exchanges, AMMs keep assets in an ecosystem liquid 24/7 using liquidity pools.
Review the documentation below to learn more about AMMs on Stellar
C#
Install the PakanaRazorSDEX NuGet package via the NuGet Package Manager Console.
.Net8.0 or greater is required.
dotnet add package PakanaRazorSDEX --version 0.0.4
??
Stellar Horizon Dependency will install automatically
NuGet Package Implementation
<PakanaRazorSDEX.Component.MarketInfo/>
C#
@page "/MarketInfo"
@rendermode InteractiveAuto
@using Microsoft.JSInterop
<div class="market-information">
<!-- Market Stats Section -->
<div class="market-stats">
<div class="stat-item">
<div class="stat-label">On-Chain High</div>
<div id="highPrice" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">On-Chain Low</div>
<div id="lowPrice" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">On-Chain Vol (24hr)</div>
<div id="onChainVolume" class="stat-value">-</div>
</div>
</div>
<!-- Exchange Stats Section -->
<div class="exchange-stats">
<div class="stat-item">
<div class="stat-label">Exchange Market Cap (USD)</div>
<div id="exchangeMarketCap" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">XLM Exchange Volume (24Hr)</div>
<div id="exchangeVolumeXLM" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">Exchange Supply (XLM)</div>
<div id="exchangeSupply" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">Current Price (XLM/USD)</div>
<div id="currentPrice" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">Change (24Hr)</div>
<div id="priceChange" class="stat-value">-</div>
</div>
</div>
</div>
@code {
// Properties for displaying market information
public string HighPrice { get; set; } = "-";
public string LowPrice { get; set; } = "-";
public string OnChainVolume { get; set; } = "-";
public string ExchangeMarketCap { get; set; } = "-";
public string ExchangeVolumeXLM { get; set; } = "-";
public string ExchangeSupply { get; set; } = "-";
public string CurrentPrice { get; set; } = "-";
public string PriceChange { get; set; } = "-";
protected override async Task OnInitializedAsync()
{
// Any server-side initialization logic can go here if needed.
await FetchInitialData();
}
private async Task FetchInitialData()
{
// Placeholder for fetching initial data, if required.
// For example, calling APIs to pre-populate some fields.
await Task.CompletedTask;
}
// Methods to update UI (invoked from JavaScript if required)
public void UpdateHighPrice(string value) => HighPrice = value;
public void UpdateLowPrice(string value) => LowPrice = value;
public void UpdateOnChainVolume(string value) => OnChainVolume = value;
public void UpdateExchangeMarketCap(string value) => ExchangeMarketCap = value;
public void UpdateExchangeVolumeXLM(string value) => ExchangeVolumeXLM = value;
public void UpdateExchangeSupply(string value) => ExchangeSupply = value;
public void UpdateCurrentPrice(string value) => CurrentPrice = value;
public void UpdatePriceChange(string value) => PriceChange = value;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/stellar-sdk/13.0.0/stellar-sdk.min.js"></script>
<script src="./_content/PakanaRazorSDEX/js/marketInfo.js"></script>
<script src="./_content/PakanaRazorSDEX/js/global.js"></script>
Javascript
We've provided simple HTML and JavaScript that can be used in your project as partial-components or be customized and integrated into your existing codebase.
Stellar CDN
*Current Version as of 2024-24-02*
<script src="https://cdnjs.cloudflare.com/ajax/libs/stellar-sdk/11.2.2/stellar-sdk.js"></script>
JavaScript
<script>
async function fetchExchangeData() {
try {
const response = await fetch('https://api.coincap.io/v2/assets/stellar');
const data = await response.json();
const {
marketCapUsd,
volumeUsd24Hr,
supply,
priceUsd,
changePercent24Hr
} = data.data;
// Format Market Cap
const formattedMarketCap = formatMarketCap(marketCapUsd);
document.getElementById('exchangeMarketCap').textContent = formattedMarketCap;
// Format Exchange Volume (24Hr XLM)
const formattedVolumeXLM = volumeUsd24Hr ? formatNumberWithUnits(volumeUsd24Hr) : '-';
document.getElementById('exchangeVolumeXLM').textContent = `${formattedVolumeXLM} USD`;
// Format Supply
const formattedSupply = supply ? formatNumberWithUnits(supply) : '-';
document.getElementById('exchangeSupply').textContent = formattedSupply;
// Format Current Price (1 XLM in USD)
const formattedPrice = priceUsd ? `$${parseFloat(priceUsd).toFixed(6)}` : '-';
document.getElementById('currentPrice').textContent = formattedPrice;
// Format Change (24Hr)
const formattedChange = changePercent24Hr ? formatChange(changePercent24Hr) : '-';
document.getElementById('priceChange').innerHTML = formattedChange;
} catch (error) {
console.error('Error fetching exchange data:', error);
}
}
function formatMarketCap(marketCap) {
const number = parseFloat(marketCap);
if (isNaN(number)) return '-';
if (number >= 1e12) return (number / 1e12).toFixed(2) + ' T';
if (number >= 1e9) return (number / 1e9).toFixed(2) + ' B';
if (number >= 1e6) return (number / 1e6).toFixed(2) + ' M';
return number.toLocaleString();
}
function formatNumberWithUnits(number) {
const num = parseFloat(number);
if (isNaN(num)) return '-';
if (num >= 1e12) return (num / 1e12).toFixed(2) + ' T';
if (num >= 1e9) return (num / 1e9).toFixed(2) + ' B';
if (num >= 1e6) return (num / 1e6).toFixed(2) + ' M';
return num.toFixed(2);
}
function formatChange(changePercent) {
const change = parseFloat(changePercent);
const sign = change >= 0 ? '?' : '?';
const colorClass = change >= 0 ? 'change-up' : 'change-down';
const formattedChange = `${sign} ${Math.abs(change).toFixed(2)}%`;
return `<span class="${colorClass}">${formattedChange}</span>`;
}
async function fetchOnChainData() {
try {
const orderBook = await server.orderbook(usdcAsset, xlmAsset).call();
// Debugging: Log the raw order book data to check for any issues
console.log('Raw Order Book:', orderBook);
// Process Bids and Asks
const bids = processOrders(orderBook.bids, true);
const asks = processOrders(orderBook.asks, false);
// Debugging: Log processed bids and asks
console.log('Processed Bids:', bids);
console.log('Processed Asks:', asks);
// Calculate On-Chain Volume (Total XLM volume from all bids and asks)
const onChainVolume = calculateOnChainVolume(orderBook);
console.log('Calculated On-Chain Volume:', onChainVolume); // Debugging volume
document.getElementById('onChainVolume').textContent = `${onChainVolume} XLM`;
// Check if we have valid bids and filter out invalid values
const validBids = bids.filter(bid => !isNaN(bid.price) && bid.price > 0);
console.log('Valid Bids:', validBids); // Debugging valid bids
// If there are no valid bids, we can't calculate the high
if (validBids.length === 0) {
console.error('No valid bids found!');
document.getElementById('highPrice').textContent = '-';
return;
}
// Get the highest bid from the valid bids
const high = Math.max(...validBids.map(bid => bid.price));
console.log('Calculated Highest Bid:', high); // Debugging log for the highest bid
// Check for asks, and calculate the reciprocal for the lowest ask
const low = asks.length > 0 ? Math.min(...asks.map(ask => ask.price)) : '-';
console.log('Calculated Lowest Ask:', low); // Debugging log for the lowest ask
// Apply reciprocal to the low price (for sell orders)
const reciprocalLow = low !== '-' ? (1 / low).toFixed(6) : '-'; // Reciprocal for low
const formattedHigh = high !== '-' ? (1 / high).toFixed(6) : '-'; // Format the highest bid
// Update the display for On-Chain High and Low
document.getElementById('highPrice').textContent = `$${formattedHigh}`; // Display highest bid
document.getElementById('lowPrice').textContent = `$${reciprocalLow}`; // Display reciprocal of lowest ask
} catch (error) {
console.error('Error fetching on-chain data:', error);
}
}
function processOrders(orders, isBid) {
// Process and return orders as valid price/amount objects
return orders.map(order => ({
price: isBid ? parseFloat(order.price) : parseFloat(order.price),
cumulativeVolume: parseFloat(order.amount)
}));
}
function calculateOnChainVolume(orderBook) {
// Calculate the total XLM volume from bids and asks
const totalBidsVolume = orderBook.bids.reduce((total, bid) => total + parseFloat(bid.amount), 0);
const totalAsksVolume = orderBook.asks.reduce((total, ask) => total + parseFloat(ask.amount), 0);
const totalVolume = totalBidsVolume + totalAsksVolume;
return totalVolume.toFixed(2); // Round total volume to 2 decimal places
}
function init() {
fetchExchangeData();
fetchOnChainData();
setInterval(fetchOnChainData, 1500); // Update every 0.5 seconds
setInterval(fetchExchangeData, 500); // Update every 5 seconds for exchange data
}
init();
</script>
HTML
<body>
<div class="market-information">
<!-- Market Stats Section -->
<div class="market-stats">
<div class="stat-item">
<div class="stat-label">On-Chain High</div>
<div id="highPrice" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">On-Chain Low</div>
<div id="lowPrice" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">On-Chain Vol (24hr)</div>
<div id="onChainVolume" class="stat-value">-</div>
</div>
</div>
<!-- Exchange Stats Section -->
<div class="exchange-stats">
<div class="stat-item">
<div class="stat-label">Exchange Market Cap (USD)</div>
<div id="exchangeMarketCap" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">XLM Exchange Volume (24Hr)</div>
<div id="exchangeVolumeXLM" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">Exchange Supply (XLM)</div>
<div id="exchangeSupply" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">Current Price (XLM/USD)</div>
<div id="currentPrice" class="stat-value">-</div>
</div>
<div class="stat-item">
<div class="stat-label">Change (24Hr)</div>
<div id="priceChange" class="stat-value">-</div>
</div>
</div>
</div>
</body>