From 321ed22999054d0b73cacb9f88e76177ac2ea79d Mon Sep 17 00:00:00 2001 From: bertan <22911469+barebind@users.noreply.github.com> Date: Tue, 5 Mar 2024 17:20:42 +0900 Subject: [PATCH] feat: add view claim button --- static/index.html | 10 +++++-- static/scripts/rewards/app-state.ts | 1 + .../read-claim-data-from-url.ts | 20 ++++++++++++++ .../render-transaction/render-transaction.ts | 20 +++++++++----- static/scripts/rewards/toaster.ts | 22 ++++++++++++++++ static/scripts/rewards/web3/erc20-permit.ts | 26 ++++++++++++++++++- static/styles/rewards/claim-table.css | 3 +++ 7 files changed, 93 insertions(+), 9 deletions(-) diff --git a/static/index.html b/static/index.html index 4209cb33..54b2380d 100644 --- a/static/index.html +++ b/static/index.html @@ -159,8 +159,14 @@
Collect
+ d="M252.309-180.001q-30.308 0-51.308-21t-21-51.308V-360H240v107.691q0 4.616 3.846 8.463 3.847 3.846 8.463 3.846h455.382q4.616 0 8.463-3.846 3.846-3.847 3.846-8.463V-360h59.999v107.691q0 30.308-21 51.308t-51.308 21H252.309ZM480-335.386 309.233-506.153l42.153-43.383 98.615 98.615v-336.001h59.998v336.001l98.615-98.615 42.153 43.383L480-335.386Z" /> + + + diff --git a/static/scripts/rewards/app-state.ts b/static/scripts/rewards/app-state.ts index 9a95075a..00d5fdbe 100644 --- a/static/scripts/rewards/app-state.ts +++ b/static/scripts/rewards/app-state.ts @@ -4,6 +4,7 @@ import { RewardPermit } from "./render-transaction/tx-type"; export class AppState { public claims: RewardPermit[] = []; + public claimTxs: Record = {}; private _provider!: JsonRpcProvider; private _currentIndex = 0; private _signer; diff --git a/static/scripts/rewards/render-transaction/read-claim-data-from-url.ts b/static/scripts/rewards/render-transaction/read-claim-data-from-url.ts index 6115f7f0..0afb43a5 100644 --- a/static/scripts/rewards/render-transaction/read-claim-data-from-url.ts +++ b/static/scripts/rewards/render-transaction/read-claim-data-from-url.ts @@ -8,6 +8,12 @@ import { renderTransaction } from "./render-transaction"; import { setClaimMessage } from "./set-claim-message"; import { RewardPermit, claimTxT } from "./tx-type"; import { Type } from "@sinclair/typebox"; +import { createClient } from "@supabase/supabase-js"; + +declare const SUPABASE_URL: string; +declare const SUPABASE_ANON_KEY: string; + +const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY); export const table = document.getElementsByTagName(`table`)[0]; const urlParams = new URLSearchParams(window.location.search); @@ -22,9 +28,11 @@ export async function readClaimDataFromUrl(app: AppState) { } app.claims = decodeClaimData(base64encodedTxData).flat(); + app.claimTxs = await getClaimedTxs(app); app.provider = await useFastestRpc(app); const networkId = app.reward?.networkId || app.networkId; app.signer = await connectWallet().catch(console.error); + displayRewardDetails(); displayRewardPagination(); @@ -33,6 +41,18 @@ export async function readClaimDataFromUrl(app: AppState) { .catch(console.error); } +async function getClaimedTxs(app: AppState): Promise> { + const txs: Record = Object.create(null); + for (const claim of app.claims) { + const { data } = await supabase.from("permits").select("transaction").eq("nonce", claim.permit.nonce.toString()); + + if (data?.length == 1 && data[0].transaction !== null) { + txs[claim.permit.nonce.toString()] = data[0].transaction as string; + } + } + return txs; +} + function decodeClaimData(base64encodedTxData: string): RewardPermit[] { let permit; diff --git a/static/scripts/rewards/render-transaction/render-transaction.ts b/static/scripts/rewards/render-transaction/render-transaction.ts index 4a1ef014..9e4e17ba 100644 --- a/static/scripts/rewards/render-transaction/render-transaction.ts +++ b/static/scripts/rewards/render-transaction/render-transaction.ts @@ -1,6 +1,5 @@ import { AppState } from "../app-state"; -import { networkExplorers } from "../constants"; -import { claimButton, hideLoader } from "../toaster"; +import { claimButton, viewClaimButton, hideLoader, hideClaimButton, showClaimButton, hideViewClaimButton, showViewClaimButton } from "../toaster"; import { claimErc20PermitHandlerWrapper, fetchFundingWallet, generateInvalidatePermitAdminControl } from "../web3/erc20-permit"; import { claimErc721PermitHandler } from "../web3/erc721-permit"; import { verifyCurrentNetwork } from "../web3/verify-current-network"; @@ -46,7 +45,7 @@ export async function renderTransaction(app: AppState, nextTx?: boolean): Promis tokenAddress: app.reward.permit.permitted.token, ownerAddress: app.reward.owner, amount: app.reward.transferDetails.requestedAmount, - explorerUrl: networkExplorers[app.reward.networkId], + explorerUrl: app.currentExplorerUrl, table, requestedAmountElement, provider: app.provider, @@ -56,8 +55,17 @@ export async function renderTransaction(app: AppState, nextTx?: boolean): Promis renderEnsName({ element: toElement, address: app.reward.transferDetails.to }).catch(console.error); generateInvalidatePermitAdminControl(app).catch(console.error); - - claimButton.element.addEventListener("click", claimErc20PermitHandlerWrapper(app)); + if (app.claimTxs[app.reward.permit.nonce.toString()] !== undefined) { + hideClaimButton(); + showViewClaimButton(); + viewClaimButton.element.addEventListener("click", () => { + window.open(`${app.currentExplorerUrl}/tx/${app.claimTxs[app.reward.permit.nonce.toString()]}`); + }); + } else { + hideViewClaimButton(); + showClaimButton(); + claimButton.element.addEventListener("click", claimErc20PermitHandlerWrapper(app)); + } table.setAttribute(`data-claim`, "ok"); } else { const requestedAmountElement = insertErc721PermitTableData(app.reward, table); @@ -65,7 +73,7 @@ export async function renderTransaction(app: AppState, nextTx?: boolean): Promis renderNftSymbol({ tokenAddress: app.reward.permit.permitted.token, - explorerUrl: networkExplorers[app.reward.networkId], + explorerUrl: app.currentExplorerUrl, table, requestedAmountElement, provider: app.provider, diff --git a/static/scripts/rewards/toaster.ts b/static/scripts/rewards/toaster.ts index da19ac6f..4c2462f8 100644 --- a/static/scripts/rewards/toaster.ts +++ b/static/scripts/rewards/toaster.ts @@ -15,6 +15,12 @@ export const claimButton = { element: document.getElementById("claimButton") as HTMLButtonElement, }; +export const viewClaimButton = { + // loading: loadingClaimButton, + // reset: resetClaimButton, + element: document.getElementById("viewClaimButton") as HTMLButtonElement, +}; + const notifications = document.querySelector(".notifications") as HTMLUListElement; export function createToast(meaning: keyof typeof toaster.icons, text: string) { @@ -63,6 +69,22 @@ export function hideLoader() { claimButton.element.className = "hide-cl"; } +export function hideClaimButton() { + claimButton.element.classList.add("hide"); +} + +export function showClaimButton() { + claimButton.element.classList.remove("hide"); +} + +export function hideViewClaimButton() { + viewClaimButton.element.classList.add("hide"); +} + +export function showViewClaimButton() { + viewClaimButton.element.classList.remove("hide"); +} + export function errorToast(error: MetaMaskError, errorMessage?: string) { // If a custom error message is provided, use it if (errorMessage) { diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index 33dabe9a..ca774c1d 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -8,6 +8,12 @@ import { tokens } from "../render-transaction/render-token-symbol"; import { renderTransaction } from "../render-transaction/render-transaction"; import { getErc20Contract } from "../rpc-optimization/getErc20Contract"; import { MetaMaskError, claimButton, errorToast, showLoader, toaster } from "../toaster"; +import { createClient } from "@supabase/supabase-js"; + +declare const SUPABASE_URL: string; +declare const SUPABASE_ANON_KEY: string; + +const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY); export async function fetchFundingWallet(app: AppState): Promise<{ balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }> { const reward = app.reward; @@ -94,7 +100,7 @@ async function waitForTransaction(tx: TransactionResponse) { try { receipt = await tx.wait(); toaster.create("success", `Claim Complete.`); - console.log(receipt.transactionHash); // @TODO: post to database + console.log(receipt.transactionHash); } catch (error: unknown) { if (error instanceof Error) { const e = error as unknown as MetaMaskError; @@ -134,6 +140,9 @@ export function claimErc20PermitHandlerWrapper(app: AppState) { const receipt = await waitForTransaction(tx); if (!receipt) return; + const isHashUpdated = await updatePermitTxHash(app, receipt.transactionHash); + if (!isHashUpdated) return; + claimButton.element.removeEventListener("click", claimErc20PermitHandler); await renderTx(app); @@ -276,3 +285,18 @@ export function nonceBitmap(nonce: BigNumberish): { wordPos: BigNumber; bitPos: const bitPos = BigNumber.from(nonce).and(255).toNumber(); return { wordPos, bitPos }; } + +export async function updatePermitTxHash(app: AppState, hash: string): Promise { + const { error } = await supabase + .from("permits") + .update({ transaction: hash }) + // using only nonce in the condition as it's defined unique on db + .eq("nonce", app.reward.permit.nonce.toString()); + + if (error !== null) { + console.error(error); + throw error; + } + + return true; +} diff --git a/static/styles/rewards/claim-table.css b/static/styles/rewards/claim-table.css index be7eb874..186e89ec 100644 --- a/static/styles/rewards/claim-table.css +++ b/static/styles/rewards/claim-table.css @@ -134,6 +134,9 @@ table[data-claim-rendered] #controls { table[data-claim-rendered] button { opacity: 0.5; } +table[data-claim-rendered] button.hide { + display:none !important; +} table[data-claim-rendered] button:disabled { opacity: 0.5; pointer-events: none;