From a5586f6c8ceab017d9af4198149232556a526cca Mon Sep 17 00:00:00 2001 From: alexiscolin Date: Sat, 9 Nov 2024 23:05:28 +0900 Subject: [PATCH] feat: add airdrop tracker --- README.md | 23 +++++- site/static/main.css | 49 +++++++++---- site/static/main.js | 143 +++++++++++++++++++++++++++++++++++++ site/templates/footer.html | 7 +- 4 files changed, 202 insertions(+), 20 deletions(-) create mode 100644 site/static/main.js diff --git a/README.md b/README.md index ee930c7..c4d8a2e 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,11 @@ will output the instructions required to use the expected go version. ### Setting recommendations -| minimum-gas-prices | 0.001uatone | -|--------------------|------------------------------------------------------| +| minimum-gas-prices | 0.001uatone | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------- | | seeds | see [seeds.txt](https://github.com/atomone-hub/atomone-validator-community/blob/main/atomone-1/seeds.txt) | | persistent_peers | see [persistent_peers.txt](https://github.com/atomone-hub/atomone-validator-community/blob/main/atomone-1/persistent_peers.txt) | - ### Hardware recommendations AtomOne is a relatively simple and vanilla Cosmos SDK chain with minor modifications. The recommended minimum hardware requirements should be enough to comfortably be able to run a validator node. @@ -54,6 +53,24 @@ The following public RPC and API endpoints are available: Addtional explorers, RPCs, seed nodes, persistent_peers, etc. may be listed on [cosmos.directory/atomone](https://cosmos.directory/atomone) +### Check your AtomOne allocation + +
+ +
+ + + + + + +
+ ### Discord channel For more immediate communication, you are also welcome to use [the validator channel on Discord](https://discord.com/channels/1050058681414340701/1052259303924445204). diff --git a/site/static/main.css b/site/static/main.css index 5aabaea..6ea5b58 100644 --- a/site/static/main.css +++ b/site/static/main.css @@ -170,14 +170,14 @@ footer { } .footer-socials { - display: flex; - justify-content: center; - list-style: none; - gap: 1rem; + display: flex; + justify-content: center; + list-style: none; + gap: 1rem; } -.footer-socials li{ - display: flex; +.footer-socials li { + display: flex; } .markdown-alert { @@ -292,24 +292,45 @@ footer { fill: #ddd; } -.ProgressBar{ - align-items: center; - gap:10px; +.ProgressBar { + align-items: center; + gap: 10px; } .ProgressBar-svg { - height: 1px !important; + height: 1px !important; } .ProgressBar-svg rect { - rx: 0px !important; + rx: 0px !important; } .ProgressBar-background, .ProgressBar-percentage { - fill: white !important; - fill-opacity: .4 !important; + fill: white !important; + fill-opacity: 0.4 !important; } .ProgressBar-percentage { - fill-opacity: 1 !important; + fill-opacity: 1 !important; +} + +.is-hidden { + display: none; } +.tracker-input { + width: 22rem; + max-width: 50vw; +} + +.tracker-balance { + font-weight: bold; + margin: 1rem 0; +} + +.tracker-info { + font-style: italic; +} + +.tracker-balance-detail { + font-size: 0.8em; +} diff --git a/site/static/main.js b/site/static/main.js new file mode 100644 index 0000000..706dbfc --- /dev/null +++ b/site/static/main.js @@ -0,0 +1,143 @@ +(() => { + class Tracker { + constructor(el) { + this.DOM = { + tracker: el, + }; + + this.balance = 0; + this.detail = ""; + + this.init(); + } + + init() { + this.DOM.result = [...this.DOM.tracker.querySelectorAll(".js-tracker-result")]; + this.DOM.balanceTotal = this.DOM.tracker.querySelector(".js-tracker-balanceTotal"); + this.DOM.balanceResult = this.DOM.tracker.querySelector(".js-tracker-balanceResult"); + this.DOM.detail = this.DOM.tracker.querySelector(".js-tracker-detail"); + this.DOM.input = this.DOM.tracker.querySelector(".js-tracker-input"); + this.DOM.check = this.DOM.tracker.querySelector(".js-tracker-check"); + + this.DOM.check.addEventListener("click", () => this.checkBalance()); + } + + async checkBalance() { + const data = await this._getBalance(this.DOM.input.value); + const balanceTotal = this._normalizeAmount(data.amount); + + this.DOM.balanceResult.textContent = +data.amount > 0 ? `You have received: ${balanceTotal} ATONE` : `You may not be eligible to the AtomOne airdrop`; + this.DOM.balanceTotal.textContent = balanceTotal; + + this.DOM.result.forEach((result) => result.classList.remove("is-hidden")); + } + + _rounder(figure) { + return Math.round(+figure * 100) / 100; + } + _normalizeAmount(amount) { + const roundedAmount = this._rounder(+amount / 1000000); + return roundedAmount.toLocaleString(undefined, { maximumFractionDigits: 2 }); + } + + async _getBalance(cosmosAddress) { + const queryAtomeOneBalance = ` + query ($addr: String!) { + votes848(where: { address: { _eq: $addr } }) { + address + total_atone_amount + factor + + yes_atom_amount + yes_atone_amount + yes_bonus_malus + yes_multiplier + + no_atom_amount + no_atone_amount + no_bonus_malus + no_multiplier + + nwv_atom_amount + nwv_atone_amount + nwv_bonus_malus + nwv_multiplier + + abs_atom_amount + abs_atone_amount + abs_bonus_malus + abs_multiplier + + dnv_atom_amount + dnv_atone_amount + dnv_bonus_malus + dnv_multiplier + + liquid_atom_amount + liquid_atone_amount + liquid_bonus_malus + liquid_multiplier + } + } + `; + + const transformGraphQLResult = (result) => { + const createDetail = (type, atomAmt, atoneAmt, bonusMalus, multiplier, factor) => ({ + type, + atomAmt, + atoneAmt, + bonusMalus, + multiplier, + factor, + }); + + return { + amount: result.total_atone_amount, + denom: "uatone", + detail: { + yesDetail: createDetail("yes", result.yes_atom_amount, result.yes_atone_amount, result.yes_bonus_malus, result.yes_multiplier, result.factor), + noDetail: createDetail("no", result.no_atom_amount, result.no_atone_amount, result.no_bonus_malus, result.no_multiplier, result.factor), + nwvDetail: createDetail("nwv", result.nwv_atom_amount, result.nwv_atone_amount, result.nwv_bonus_malus, result.nwv_multiplier, result.factor), + absDetail: createDetail("abs", result.abs_atom_amount, result.abs_atone_amount, result.abs_bonus_malus, result.abs_multiplier, result.factor), + dnvDetail: createDetail("dnv", result.dnv_atom_amount, result.dnv_atone_amount, result.dnv_bonus_malus, result.dnv_multiplier, result.factor), + liquidDetail: createDetail("liquid", result.liquid_atom_amount, result.liquid_atone_amount, result.liquid_bonus_malus, result.liquid_multiplier, result.factor), + }, + }; + }; + + try { + const response = await fetch("https://graphql-dapp.govgen.io/v1/graphql", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: queryAtomeOneBalance, + variables: { addr: cosmosAddress }, + }), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const json = await response.json(); + const data = json.data.votes848?.[0]; + + if (data) { + return transformGraphQLResult(data); + } else { + return { denom: "uatone", amount: "0" }; + } + } catch (error) { + console.error("Error fetching AtomOne balance:", error); + throw new Error("Could not get AtomOne balances"); + } + } + } + + window.addEventListener("load", () => { + const trackers = [...document.querySelectorAll(".js-tracker")]; + trackers.forEach((el) => new Tracker(el)); + }); +})(); diff --git a/site/templates/footer.html b/site/templates/footer.html index 7cefbe7..874c726 100644 --- a/site/templates/footer.html +++ b/site/templates/footer.html @@ -1,9 +1,10 @@