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
+
+
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;