HTML LAUNCHPAD
<html lang="es">
<head>
<meta charset="UTF-8"></meta>
<meta content="width=device-width, initial-scale=1" name="viewport"></meta>
<title>Launchpad – Envía Hbar y recibe tokens</title>
<style>
body { font-family: Arial, sans-serif; background:#f4f4f4; padding:20px; }
h2 { margin: 8px 0; }
table { width:100%; border-collapse:collapse; background:#fff; margin-top:10px; }
th, td { border:1px solid #ccc; padding:6px; font-size:13px; vertical-align:top; }
th { background:#222; color:#fff; }
th.number, td.number { text-align:right; }
.in { color:green; font-weight:bold; }
.out { color:red; font-weight:bold; }
.controls { margin-bottom:10px; }
button { padding:6px 10px; margin:0 5px 10px 0; cursor:pointer; }
.total-row { background:#eee; font-weight:bold; }
.group-header { font-weight:bold; }
</style>
</head>
<body>
<div class="container">
<h2>Launchpad – Enviar HBAR a Wallet 0.0.10240210-sknqw</h2>
<h2>MAGALU.h – Tokens de Recompensas 0.0.10206372</h2>
<p><strong>Objetivos: :</strong> 50$ Nueva pool KANARY/BTCH</p>
<div class="token-info">
<p><strong>Token a recibir:</strong> Mismo Valor en HBAR</p>
<p><strong>Detalles del token:</strong></p>
<ul>
<li><strong>TOKEN ID:</strong> 0.0.7973590</li>
<li><strong>Nombre:</strong> KANARY</li>
</ul>
<p style="color: darkred;">
Si no se pueden entregar las monedas, se devolverán los HBAR.
</p>
<p style="color: darkred;">
Por la compra de 20 HBAR recibes 1 NFTBTCH GRATIS.
</p>
</div>
<div class="controls">
<button onclick="prevPage()">⬅ PREV</button>
<button onclick="nextPage()">NEXT ➡</button>
</div>
<div id="hbarBalance" style="font-weight: bold; margin-bottom: 10px;"></div>
<h3>Grupo 1 – Grupos de Transacciones</h3>
<table>
<thead>
<tr>
<th>Fecha<br /><small>(Hora transacción)</small></th>
<th>Contraparte<br /><small>(Wallet involucrada)</small></th>
<th>Transacción<br /><small>(Hash/ID)</small></th>
<th>Token ID<br /><small>HBAR o Token</small></th>
<th>Nombre Token<br /><small>(Nombre del token)</small></th>
<th class="number">Precio USD<br /><small>Unitario</small></th>
<th class="number">Cantidad<br /><small>Token/HBAR</small></th>
<th class="number">USD fila<br /><small>Cantidad × Precio</small></th>
</tr>
</thead>
<tbody id="txBody"></tbody>
<tfoot>
<tr class="total-row">
<td colspan="7">Total USD página</td>
<td class="number" id="totalUSD">$0</td>
</tr>
</tfoot>
</table>
<h3>Grupo 2 – Sorteos, Recompensas</h3>
<table>
<thead>
<tr>
<th>Fecha<br /><small>(Hora transacción)</small></th>
<th>Contraparte<br /><small>(Wallet involucrada)</small></th>
<th>Transacción<br /><small>(Hash/ID)</small></th>
<th>Token ID<br /><small>HBAR o Token</small></th>
<th>Nombre Token<br /><small>(Nombre del token)</small></th>
<th class="number">Precio USD<br /><small>Unitario</small></th>
<th class="number">Cantidad<br /><small>Token/HBAR</small></th>
<th class="number">USD fila<br /><small>Cantidad × Precio</small></th>
</tr>
</thead>
<tbody id="txBodySingle"></tbody>
<tfoot>
<tr class="total-row">
<td colspan="7">Total USD página</td>
<td class="number" id="totalUSDSingle">$0</td>
</tr>
</tfoot>
</table>
<script>
const MIRROR = "https://mainnet-public.mirrornode.hedera.com";
const SAUCER_API_KEY = "875e1017-87b8-4b12-8301-6aa1f1aa073b";
const LIMIT = 100;
let ACCOUNT_ID = "0.0.10240210";
let allTxs = [];
let currentPage = 0;
let hbarPrice = 0;
const EXCLUDED_WALLETS = ["0.0.10", "0.0.98", "0.0.800", "0.0.801", "0.0.24", "0.0.10231006"];
const tokenInfoCache = {};
const tokenPriceCache = {};
const colors = ["#f0f8ff","#f5f5dc"];
function formatNumber(v,d=4){ return Number(v).toLocaleString("es-ES",{minimumFractionDigits:d,maximumFractionDigits:d}); }
function isExcludedRange(id){
const parts=id.split(".");
if(parts.length!==3) return false;
const num=Number(parts[2]);
return parts[0]==="0" && parts[1]==="0" && num>=1 && num<=99;
}
function getActiveCounterparty(tx, account){
const s=new Set();
if(tx.transfers){
const me=tx.transfers.find(t=>t.account===account);
if(me) tx.transfers.forEach(t=>{
if(t.account!==account && t.account!=="0.0.0" && !EXCLUDED_WALLETS.includes(t.account) && !isExcludedRange(t.account) && Math.sign(t.amount)!==Math.sign(me.amount))
s.add(t.account);
});
}
if(tx.token_transfers){
const me=tx.token_transfers.find(t=>t.account===account);
if(me) tx.token_transfers.forEach(t=>{
if(t.account!==account && !EXCLUDED_WALLETS.includes(t.account) && !isExcludedRange(t.account) && Math.sign(t.amount)!==Math.sign(me.amount))
s.add(t.account);
});
}
return [...s].join(", ") || "UNKNOWN";
}
function formatTimestamp(ts) {
const d = new Date(Number(ts.split(".")[0]) * 1000);
return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')} ` +
`${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}:${String(d.getSeconds()).padStart(2,'0')}`;
}
async function loadHbarPrice(){
try{
const r=await fetch("https://api.coingecko.com/api/v3/simple/price?ids=hedera-hashgraph&vs_currencies=usd");
const d=await r.json();
hbarPrice=d["hedera-hashgraph"].usd||0;
}catch{}
}
async function getTokenInfo(id){
if(tokenInfoCache[id]) return tokenInfoCache[id];
const r=await fetch(`${MIRROR}/api/v1/tokens/${id}`);
const d=await r.json();
return tokenInfoCache[id]={name:d.name||id,decimals:d.decimals||0};
}
async function getTokenUSD(id){
if(tokenPriceCache[id]!==undefined) return tokenPriceCache[id];
try{
const r=await fetch(`https://api.saucerswap.finance/tokens/${id}`,{ headers:{ "x-api-key":SAUCER_API_KEY } });
const d=await r.json();
return tokenPriceCache[id]=Number(d.priceUsd||0);
}catch{return tokenPriceCache[id]=0;}
}
async function loadFilteredTransactions(){
allTxs=[];
let url = `${MIRROR}/api/v1/transactions?account.id=${ACCOUNT_ID}&limit=${LIMIT}&order=desc`;
while(url && allTxs.length<2000){
const r=await fetch(url);
const d=await r.json();
allTxs=allTxs.concat(d.transactions);
url=d.links?.next ? MIRROR+d.links.next : null;
}
renderPage();
}
async function renderPage(){
await renderGrupo1();
await renderGrupo2Single();
}
// --- Grupo 1 ---
async function renderGrupo1(){
const totalUSDEl = document.getElementById("totalUSD");
const txBody = document.getElementById("txBody");
txBody.innerHTML="";
let totalUSD=0;
const groups={};
allTxs.forEach(tx=>{
const k=getActiveCounterparty(tx,ACCOUNT_ID);
if(k==="UNKNOWN") return;
(groups[k]=groups[k]||[]).push(tx);
});
// Filtrar contrapartes con más de 1 transacción
const filteredKeys = Object.keys(groups).filter(k=>groups[k].length>1);
const sortedKeys = filteredKeys.sort((a,b)=>{
const latestA = Math.max(...groups[a].map(tx=>Number(tx.consensus_timestamp.split(".")[0])));
const latestB = Math.max(...groups[b].map(tx=>Number(tx.consensus_timestamp.split(".")[0])));
return latestB - latestA;
});
let ci=0;
const fragment = document.createDocumentFragment();
for(const k of sortedKeys.slice(currentPage*20,(currentPage+1)*20)){
const bg=colors[ci++%colors.length];
const trHeader = document.createElement("tr");
trHeader.className="group-header";
trHeader.style.background=bg;
trHeader.innerHTML=`<td colspan="8">Contrapartes activas: ${k}</td>`;
fragment.appendChild(trHeader);
for(const tx of groups[k]){
const fechaStr = formatTimestamp(tx.consensus_timestamp);
// HBAR
if(tx.transfers){
const t=tx.transfers.find(x=>x.account===ACCOUNT_ID);
if(t && t.amount/1e8 >= 0.90){ // HBAR >= 0.90
const rowUSD=t.amount/1e8*hbarPrice;
totalUSD+=rowUSD;
const tr = document.createElement("tr");
tr.style.background=bg;
tr.innerHTML=`<td>${fechaStr}</td><td>${k}</td><td><a target="_blank" href="https://hashscan.io/mainnet/transaction/${tx.transaction_id}">${tx.transaction_id}</a></td>
<td>HBAR</td><td>Hedera</td>
<td class="number">$${formatNumber(hbarPrice,6)}</td>
<td class="number ${t.amount>0?'in':'out'}">${formatNumber(t.amount/1e8,6)}</td>
<td class="number">$${formatNumber(rowUSD,2)}</td>`;
fragment.appendChild(tr);
}
}
// Tokens
if(tx.token_transfers){
const filteredTransfers = tx.token_transfers.filter(x=>x.account===ACCOUNT_ID);
for(const t of filteredTransfers){
const info = await getTokenInfo(t.token_id);
const price = await getTokenUSD(t.token_id);
const amount = t.amount/10**info.decimals;
const rowUSD = amount*price;
totalUSD+=rowUSD;
const tr = document.createElement("tr");
tr.style.background=bg;
tr.innerHTML=`<td>${fechaStr}</td><td>${k}</td><td><a target="_blank" href="https://hashscan.io/mainnet/transaction/${tx.transaction_id}">${tx.transaction_id}</a></td>
<td>${t.token_id}</td><td>${info.name}</td>
<td class="number">$${formatNumber(price,6)}</td>
<td class="number ${t.amount>0?'in':'out'}">${formatNumber(amount,6)}</td>
<td class="number">$${formatNumber(rowUSD,2)}</td>`;
fragment.appendChild(tr);
}
}
}
}
txBody.appendChild(fragment);
totalUSDEl.innerText="$"+formatNumber(totalUSD,2);
renderHbarBalance();
}
// --- Grupo 2 ---
async function renderGrupo2Single(){
const totalUSDEl = document.getElementById("totalUSDSingle");
const txBody = document.getElementById("txBodySingle");
txBody.innerHTML="";
let totalUSD=0;
// Contar cuántas transacciones tiene cada contraparte (solo HBAR>=0.90 y tokens)
const counterpartyCounts = {};
allTxs.forEach(tx=>{
const k=getActiveCounterparty(tx,ACCOUNT_ID);
if(k==="UNKNOWN") return;
let validTx=false;
if(tx.transfers){
const t=tx.transfers.find(x=>x.account===ACCOUNT_ID);
if(t && t.amount/1e8 >=0.90) validTx=true;
}
if(tx.token_transfers){
const t=tx.token_transfers.find(x=>x.account===ACCOUNT_ID);
if(t) validTx=true;
}
if(validTx) counterpartyCounts[k] = (counterpartyCounts[k] || 0) + 1;
});
let ci=0;
const fragment = document.createDocumentFragment();
for(const tx of allTxs){
const k=getActiveCounterparty(tx,ACCOUNT_ID);
if(counterpartyCounts[k]!==1) continue; // Solo 1 transacción
const bg = colors[ci++ % colors.length];
const fechaStr = formatTimestamp(tx.consensus_timestamp);
// HBAR
if(tx.transfers){
const t=tx.transfers.find(x=>x.account===ACCOUNT_ID);
if(t && t.amount/1e8 >=0.90){
const rowUSD=t.amount/1e8*hbarPrice;
totalUSD+=rowUSD;
const trHeader = document.createElement("tr");
trHeader.className="group-header";
trHeader.style.background=bg;
trHeader.innerHTML=`<td colspan="8">Contraparte con 1 sola transacción: ${k}</td>`;
fragment.appendChild(trHeader);
const tr = document.createElement("tr");
tr.style.background=bg;
tr.innerHTML=`<td>${fechaStr}</td><td>${k}</td><td><a target="_blank" href="https://hashscan.io/mainnet/transaction/${tx.transaction_id}">${tx.transaction_id}</a></td>
<td>HBAR</td><td>Hedera</td>
<td class="number">$${formatNumber(hbarPrice,6)}</td>
<td class="number ${t.amount>0?'in':'out'}">${formatNumber(t.amount/1e8,6)}</td>
<td class="number">$${formatNumber(rowUSD,2)}</td>`;
fragment.appendChild(tr);
}
}
// Tokens
if(tx.token_transfers){
for(const t of tx.token_transfers.filter(x=>x.account===ACCOUNT_ID)){
const info = await getTokenInfo(t.token_id);
const price = await getTokenUSD(t.token_id);
const amount = t.amount/10**info.decimals;
const rowUSD = amount*price;
totalUSD+=rowUSD;
const trHeader = document.createElement("tr");
trHeader.className="group-header";
trHeader.style.background=bg;
trHeader.innerHTML=`<td colspan="8">Contraparte con 1 sola transacción: ${k}</td>`;
fragment.appendChild(trHeader);
const tr = document.createElement("tr");
tr.style.background=bg;
tr.innerHTML=`<td>${fechaStr}</td><td>${k}</td><td><a target="_blank" href="https://hashscan.io/mainnet/transaction/${tx.transaction_id}">${tx.transaction_id}</a></td>
<td>${t.token_id}</td><td>${info.name}</td>
<td class="number">$${formatNumber(price,6)}</td>
<td class="number ${t.amount>0?'in':'out'}">${formatNumber(amount,6)}</td>
<td class="number">$${formatNumber(rowUSD,2)}</td>`;
fragment.appendChild(tr);
}
}
}
txBody.appendChild(fragment);
totalUSDEl.innerText="$"+formatNumber(totalUSD,2);
}
function nextPage(){
currentPage++;
renderPage();
}
function prevPage(){if(currentPage>0){currentPage--;renderPage();}}
function renderHbarBalance() {
let totalHbar = 0;
allTxs.forEach(tx => {
if(tx.transfers){
const t = tx.transfers.find(x => x.account === ACCOUNT_ID);
if(t && t.amount/1e8 >=0.90){
totalHbar += t.amount / 1e8;
}
}
});
const totalUSD = totalHbar * hbarPrice;
const balanceDiv = document.getElementById("hbarBalance");
balanceDiv.innerText = `💰 Recaudación total HBAR ${formatNumber(totalHbar,6)} HBAR $${formatNumber(totalUSD,2)}`;
}
(async()=>{
await loadHbarPrice();
await loadFilteredTransactions();
})();
</script>
</div></body>
</html>
Comentarios
Publicar un comentario