Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions public/data/itn2/rewardsErc20.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[
{ "ethAddress": "0xabcDEF0123456789", "reward_dusk": 42.0 },
{ "ethAddress": "0x1234abcd5678ef90", "reward_dusk": 21.5 }
]
7 changes: 7 additions & 0 deletions public/data/itn2/rewardsGenerators.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{ "generatorBlsPubkey": "genKey1", "reward_dusk": 50000.12345678 },
{ "generatorBlsPubkey": "genKey2", "reward_dusk": 25000.00000000 },
{ "generatorBlsPubkey": "genKey3", "reward_dusk": 12500.5 },
{ "generatorBlsPubkey": "genKey4", "reward_dusk": 7500.98765432 },
{ "generatorBlsPubkey": "genKey5", "reward_dusk": 3000.25 }
]
105 changes: 105 additions & 0 deletions src/components/RewardLookup.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<section>
<p>Enter your address to see your reward.</p>

<div>
<input id="address" placeholder="Paste your address here" />
<button id="check">Check</button>
</div>

<div id="status"></div>

<div id="reward" class="hidden">
<span>Reward:</span>
<span id="rewardValue"></span>
</div>
</section>

<style>
.hidden {
display: none;
}
</style>

<script is:inline>
(async () => {
const $ = (id) => document.getElementById(id);
const address = $("address");
const btn = $("check");
const status = $("status");
const rewardBox = $("reward");
const rewardValueEl = $("rewardValue");

function format(number, f = 2) {
return Number(number).toLocaleString(undefined, {
maximumFractionDigits: f,
});
}

function resetUI() {
status.textContent = "";
rewardValueEl.textContent = "";
rewardBox.classList.add("hidden");
}

// Normalize ETH and BLS addresses
const normEth = (v) => v.trim().toLowerCase();
const normBls = (v) => v.trim().toLowerCase();

// Prefetch both datasets once
const maps = { generators: new Map(), erc20: new Map() };

async function loadJson(url) {
const response = await fetch(url, { cache: "no-store" });
if (!response.ok) throw new Error("HTTP " + response.status);
return response.json();
}

try {
const [gen, erc] = await Promise.all([
loadJson("/data/itn2/rewardsGenerators.json"),
loadJson("/data/itn2/rewardsErc20.json"),
]);

for (const row of gen || []) {
const k = normBls(String(row.generatorBlsPubkey ?? ""));
if (k) maps.generators.set(k, row);
}
for (const row of erc || []) {
const k = normEth(String(row.ethAddress ?? ""));
if (k) maps.erc20.set(k, row);
}
} catch (e) {
console.error(e);
status.textContent = "Failed to load reward data.";
}

function check() {
resetUI();

const raw = (address.value || "").trim();
if (!raw) {
status.textContent = "Please enter an address.";
return;
}

// Try BLS first, then ETH
const hit =
maps.generators.get(normBls(raw)) ?? maps.erc20.get(normEth(raw));

if (!hit) {
status.textContent = "Address not found.";
return;
}

status.textContent = "";
rewardValueEl.textContent = `${format(hit.reward_dusk ?? 0, 2)} DUSK`;
rewardBox.classList.remove("hidden");
}

btn.addEventListener("click", check);
address.addEventListener("keydown", (e) => {
if (e.key === "Enter") check();
});
address.addEventListener("input", resetUI);
})();
</script>