Skip to content

Commit

Permalink
refactor: move app into all functions
Browse files Browse the repository at this point in the history
caused some type issues related
to the two different permit types
and passing them to all UI
functions.
  • Loading branch information
0x4007 committed Feb 22, 2024
1 parent b9f9c77 commit f307223
Show file tree
Hide file tree
Showing 14 changed files with 181 additions and 200 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/conventional-commits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ name: Conventional Commits

on:
push:
pull_request:

jobs:
conventional-commits:
name: Conventional Commits
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: ubiquity/action-conventional-commits@master
37 changes: 23 additions & 14 deletions static/scripts/rewards/app-state.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import { JsonRpcProvider } from "@ethersproject/providers";
import { networkExplorers } from "./constants";
import { ClaimTx } from "./render-transaction/tx-type";
import { RewardPermit } from "./render-transaction/tx-type";

export class AppState {
public claims: ClaimTx[] = [];
public claims: RewardPermit[] = [];
private _provider!: JsonRpcProvider;
private _currentIndex = 0;
private _signer;

get signer() {
return this._signer;
}

set signer(value) {
this._signer = value;
}

get networkId(): number | null {
return this.transaction?.networkId || null;
return this.permit?.networkId || null;
}

get provider(): JsonRpcProvider {
Expand All @@ -19,33 +28,33 @@ export class AppState {
this._provider = value;
}

get transactionIndex(): number {
get permitIndex(): number {
return this._currentIndex;
}

get transaction(): ClaimTx | null {
return this.transactionIndex < this.claims.length ? this.claims[this.transactionIndex] : null;
get permit(): RewardPermit {
return this.permitIndex < this.claims.length ? this.claims[this.permitIndex] : this.claims[0];
}

get transactionNetworkId() {
return this.transaction?.networkId;
get permitNetworkId() {
return this.permit?.networkId;
}

get currentExplorerUrl(): string {
if (!this.transaction) {
if (!this.permit) {
return "https://etherscan.io";
}
return networkExplorers[this.transaction.networkId] || "https://etherscan.io";
return networkExplorers[this.permit.networkId] || "https://etherscan.io";
}

nextTx(): ClaimTx | null {
nextPermit(): RewardPermit | null {
this._currentIndex = Math.min(this.claims.length - 1, this._currentIndex + 1);
return this.transaction;
return this.permit;
}

previousTx(): ClaimTx | null {
previousPermit(): RewardPermit | null {
this._currentIndex = Math.max(0, this._currentIndex - 1);
return this.transaction;
return this.permit;
}
}

Expand Down
3 changes: 2 additions & 1 deletion static/scripts/rewards/init.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { app } from "./app-state";
import { readClaimDataFromUrl } from "./render-transaction/read-claim-data-from-url";
import { grid } from "./the-grid";

displayCommitHash(); // @DEV: display commit hash in footer
grid(document.getElementById("grid") as HTMLElement); // @DEV: display grid background

readClaimDataFromUrl().catch(console.error); // @DEV: read claim data from URL
readClaimDataFromUrl(app).catch(console.error); // @DEV: read claim data from URL

declare const commitHash: string; // @DEV: passed in at build time check build/esbuild-build.ts
function displayCommitHash() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { setPagination } from "./set-pagination";
import { removeAllEventListeners } from "./utils";

export function claimRewardsPagination(rewardsCount: HTMLElement) {
rewardsCount.innerHTML = `${app.transactionIndex + 1}/${app.claims.length} reward`;
rewardsCount.innerHTML = `${app.permitIndex + 1}/${app.claims.length} reward`;

const nextTxButton = document.getElementById("nextTx");
if (nextTxButton) {
nextTxButton.addEventListener("click", () => {
claimButton.element = removeAllEventListeners(claimButton.element) as HTMLButtonElement;
app.nextTx();
rewardsCount.innerHTML = `${app.transactionIndex + 1}/${app.claims.length} reward`;
table.setAttribute(`data-claim`, "none");
app.nextPermit();
rewardsCount.innerHTML = `${app.permitIndex + 1}/${app.claims.length} reward`;
table.setAttribute(`data-claim`, "error");
renderTransaction(true).catch(console.error);
});
}
Expand All @@ -23,9 +23,9 @@ export function claimRewardsPagination(rewardsCount: HTMLElement) {
if (prevTxButton) {
prevTxButton.addEventListener("click", () => {
claimButton.element = removeAllEventListeners(claimButton.element) as HTMLButtonElement;
app.previousTx();
rewardsCount.innerHTML = `${app.transactionIndex + 1}/${app.claims.length} reward`;
table.setAttribute(`data-claim`, "none");
app.previousPermit();
rewardsCount.innerHTML = `${app.permitIndex + 1}/${app.claims.length} reward`;
table.setAttribute(`data-claim`, "error");
renderTransaction(true).catch(console.error);
});
}
Expand Down
12 changes: 8 additions & 4 deletions static/scripts/rewards/render-transaction/insert-table-data.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { BigNumber, ethers } from "ethers";
import { app } from "../app-state";
import { Erc20Permit, Erc721Permit } from "./tx-type";
import { AppState, app } from "../app-state";
import { Erc721Permit } from "./tx-type";

export function shortenAddress(address: string): string {
return `${address.slice(0, 10)}...${address.slice(-8)}`;
}

export function insertErc20PermitTableData(
permit: Erc20Permit,
app: AppState,
table: Element,
treasury: { balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }
): Element {
const permit = app.permit;
const requestedAmountElement = document.getElementById("rewardAmount") as Element;
renderToFields(permit.transferDetails.to, app.currentExplorerUrl);
renderTokenFields(permit.permit.permitted.token, app.currentExplorerUrl);
renderDetailsFields([
{ name: "From", value: `<a target="_blank" rel="noopener noreferrer" href="${app.currentExplorerUrl}/address/${permit.owner}">${permit.owner}</a>` },
{
name: "Expiry",
value: permit.permit.deadline.lte(Number.MAX_SAFE_INTEGER.toString()) ? new Date(permit.permit.deadline.toNumber()).toLocaleString() : undefined,
value: (() => {
const deadline = BigNumber.isBigNumber(permit.permit.deadline) ? permit.permit.deadline : BigNumber.from(permit.permit.deadline);
return deadline.lte(Number.MAX_SAFE_INTEGER.toString()) ? new Date(deadline.toNumber()).toLocaleString() : undefined;
})(),
},
{ name: "Balance", value: treasury.balance.gte(0) ? `${ethers.utils.formatUnits(treasury.balance, treasury.decimals)} ${treasury.symbol}` : "N/A" },
{ name: "Allowance", value: treasury.allowance.gte(0) ? `${ethers.utils.formatUnits(treasury.allowance, treasury.decimals)} ${treasury.symbol}` : "N/A" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,46 @@
import { Type } from "@sinclair/typebox";
import { Value } from "@sinclair/typebox/value";
import { app } from "../app-state";
import { setClaimMessage } from "./set-claim-message";
import { claimTxT } from "./tx-type";
import { AppState, app } from "../app-state";
import { useFastestRpc } from "../rpc-optimization/get-optimal-provider";
import { connectWallet } from "../web3/connect-wallet";
import { verifyCurrentNetwork } from "../web3/verify-current-network";
import { claimRewardsPagination } from "./claim-rewards-pagination";
import { renderTransaction } from "./render-transaction";
import { getOptimalProvider } from "../rpc-optimization/get-optimal-provider";
import { setClaimMessage } from "./set-claim-message";
import { claimTxT } from "./tx-type";

export const table = document.getElementsByTagName(`table`)[0];
const urlParams = new URLSearchParams(window.location.search);
const base64encodedTxData = urlParams.get("claim");

export async function readClaimDataFromUrl() {
export async function readClaimDataFromUrl(app: AppState) {
if (!base64encodedTxData) {
// No claim data found
setClaimMessage({ type: "Notice", message: `No claim data found.` });
table.setAttribute(`data-claim`, "none");
table.setAttribute(`data-claim`, "error");
return;
}

decodeClaimData(base64encodedTxData);

await getOptimalProvider(app);

app.claims = decodeClaimData(base64encodedTxData);
app.provider = await useFastestRpc(app);
const networkId = app.permit?.networkId || app.networkId;
app.signer = await connectWallet(networkId).catch(console.error);
displayRewardDetails();
displayRewardPagination();

renderTransaction(true)
// .then(() => verifyCurrentNetwork(app.transaction?.networkId || app.networkId)) // @todo: verifyCurrentNetwork
.then(() => verifyCurrentNetwork(networkId))
.catch(console.error);
}

function decodeClaimData(base64encodedTxData: string) {
try {
const claimTxs = Value.Decode(Type.Array(claimTxT), JSON.parse(atob(base64encodedTxData)));
app.claims = claimTxs;
return Value.Decode(Type.Array(claimTxT), JSON.parse(atob(base64encodedTxData)));
} catch (error) {
console.error(error);
setClaimMessage({ type: "Error", message: `Invalid claim data passed in URL` });
table.setAttribute(`data-claim`, "error");
throw error;
}
}

Expand All @@ -56,7 +58,6 @@ function displayRewardPagination() {
function displayRewardDetails() {
let isDetailsVisible = false;
table.setAttribute(`data-details-visible`, isDetailsVisible.toString());

const additionalDetails = document.getElementById(`additionalDetails`) as HTMLElement;
additionalDetails.addEventListener("click", () => {
isDetailsVisible = !isDetailsVisible;
Expand Down
46 changes: 23 additions & 23 deletions static/scripts/rewards/render-transaction/render-transaction.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { app } from "../app-state";
import { networkExplorers } from "../constants";
import { claimButton, hideLoader } from "../toaster";
import { claimErc20PermitHandlerWrapper, fetchTreasury, generateInvalidatePermitAdminControl } from "../web3/erc20-permit";
import { claimErc20PermitHandlerWrapper, fetchFundingWallet, generateInvalidatePermitAdminControl } from "../web3/erc20-permit";
import { claimErc721PermitHandler } from "../web3/erc721-permit";
import { verifyCurrentNetwork } from "../web3/verify-current-network";
import { insertErc20PermitTableData, insertErc721PermitTableData } from "./insert-table-data";
Expand All @@ -15,64 +15,64 @@ export async function renderTransaction(nextTx?: boolean): Promise<Success> {
const table = document.getElementsByTagName(`table`)[0];

if (nextTx) {
app.nextTx();
app.nextPermit();
if (!app.claims || app.claims.length <= 1) {
// already hidden
} else {
setPagination(document.getElementById("nextTx"), document.getElementById("previousTx"));

const rewardsCount = document.getElementById("rewardsCount") as Element;
rewardsCount.innerHTML = `${app.transactionIndex + 1}/${app.claims.length} reward`;
table.setAttribute(`data-claim`, "none");
rewardsCount.innerHTML = `${app.permitIndex + 1}/${app.claims.length} reward`;
table.setAttribute(`data-claim`, "error");
}
}

if (!app.transaction) {
if (!app.permit) {
hideLoader();
return false;
}

verifyCurrentNetwork(app.transaction.networkId).catch(console.error);
verifyCurrentNetwork(app.permit.networkId).catch(console.error);

if (app.transaction.type === "erc20-permit") {
const treasury = await fetchTreasury(app.transaction, app.provider);
if (app.permit.type === "erc20-permit") {
const treasury = await fetchFundingWallet(app);

// insert tx data into table
const requestedAmountElement = insertErc20PermitTableData(app.transaction, table, treasury);
table.setAttribute(`data-claim`, "ok");
const requestedAmountElement = insertErc20PermitTableData(app, table, treasury);

renderTokenSymbol({
tokenAddress: app.transaction.permit.permitted.token,
ownerAddress: app.transaction.owner,
amount: app.transaction.transferDetails.requestedAmount,
explorerUrl: networkExplorers[app.transaction.networkId],
tokenAddress: app.permit.permit.permitted.token,
ownerAddress: app.permit.owner,
amount: app.permit.transferDetails.requestedAmount,
explorerUrl: networkExplorers[app.permit.networkId],
table,
requestedAmountElement,
provider: app.provider,
}).catch(console.error);

const toElement = document.getElementById(`rewardRecipient`) as Element;
renderEnsName({ element: toElement, address: app.transaction.transferDetails.to }).catch(console.error);
renderEnsName({ element: toElement, address: app.permit.transferDetails.to }).catch(console.error);

generateInvalidatePermitAdminControl(app.transaction).catch(console.error);
generateInvalidatePermitAdminControl(app).catch(console.error);

claimButton.element.addEventListener("click", claimErc20PermitHandlerWrapper(app.transaction));
} else if (app.transaction.type === "erc721-permit") {
const requestedAmountElement = insertErc721PermitTableData(app.transaction, table);
claimButton.element.addEventListener("click", claimErc20PermitHandlerWrapper(app));
table.setAttribute(`data-claim`, "ok");
} else if (app.permit.type === "erc721-permit") {
const requestedAmountElement = insertErc721PermitTableData(app.permit, table);
table.setAttribute(`data-claim`, "ok");

renderNftSymbol({
tokenAddress: app.transaction.nftAddress,
explorerUrl: networkExplorers[app.transaction.networkId],
tokenAddress: app.permit.nftAddress,
explorerUrl: networkExplorers[app.permit.networkId],
table,
requestedAmountElement,
provider: app.provider,
}).catch(console.error);

const toElement = document.getElementById(`rewardRecipient`) as Element;
renderEnsName({ element: toElement, address: app.transaction.request.beneficiary }).catch(console.error);
renderEnsName({ element: toElement, address: app.permit.request.beneficiary }).catch(console.error);

claimButton.element.addEventListener("click", claimErc721PermitHandler(app.transaction));
claimButton.element.addEventListener("click", claimErc721PermitHandler(app.permit));
}

return true;
Expand Down
34 changes: 24 additions & 10 deletions static/scripts/rewards/render-transaction/tx-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ const erc20PermitT = T.Object({
type: T.Literal("erc20-permit"),
permit: T.Object({
permitted: T.Object({
token: addressT,
amount: bigNumberT,
token: T.RegExp(/^0x[a-fA-F0-9]{40}$/),
amount: T.Union([T.RegExp(/^\d+$/), T.Number()]),
}),
nonce: bigNumberT,
deadline: bigNumberT,
nonce: T.Union([T.RegExp(/^\d+$/), T.Number()]),
deadline: T.Union([T.RegExp(/^\d+$/), T.Number()]),
}),
transferDetails: T.Object({
to: addressT,
requestedAmount: bigNumberT,
to: T.RegExp(/^0x[a-fA-F0-9]{40}$/),
requestedAmount: T.Union([T.RegExp(/^\d+$/), T.Number()]),
}),
owner: addressT,
signature: signatureT,
networkId: networkIdT,
owner: T.RegExp(/^0x[a-fA-F0-9]{40}$/),
signature: T.RegExp(/^0x[a-fA-F0-9]+$/),
networkId: T.Number(),
});

export type Erc20Permit = StaticDecode<typeof erc20PermitT>;
Expand All @@ -59,10 +59,24 @@ const erc721Permit = T.Object({
nftAddress: addressT,
networkId: networkIdT,
signature: signatureT,
// @whilefoo: they should have matching key names.
owner: addressT,
permit: T.Object({
permitted: T.Object({
token: addressT,
amount: bigNumberT,
}),
nonce: bigNumberT,
deadline: bigNumberT,
}),
transferDetails: T.Object({
to: T.RegExp(/^0x[a-fA-F0-9]{40}$/),
requestedAmount: T.Union([T.RegExp(/^\d+$/), T.Number()]),
}),
});

export type Erc721Permit = StaticDecode<typeof erc721Permit>;

export const claimTxT = T.Union([erc20PermitT, erc721Permit]);

export type ClaimTx = StaticDecode<typeof claimTxT>;
export type RewardPermit = StaticDecode<typeof claimTxT>;
Loading

0 comments on commit f307223

Please sign in to comment.