Skip to content

Commit

Permalink
chore: pagination and permit to reward
Browse files Browse the repository at this point in the history
  • Loading branch information
Keyrxng committed Feb 25, 2024
1 parent 8392fb7 commit b7483f7
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 86 deletions.
40 changes: 40 additions & 0 deletions scripts/typescript/generate-erc20-permit-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,28 @@ export async function generateERC20Permit() {
process.env.CHAIN_ID ? Number(process.env.CHAIN_ID) : 1
);
const signature = await myWallet._signTypedData(domain, types, values);

const permitTransferFromData2: PermitTransferFrom = {
permitted: {
// token we are permitting to be transferred
token: process.env.PAYMENT_TOKEN_ADDRESS || "",
// amount we are permitting to be transferred
amount: ethers.utils.parseUnits("9" || "", 18),
},
// who can transfer the tokens
spender: process.env.BENEFICIARY_ADDRESS || "",
nonce: BigNumber.from(`0x${randomBytes(32).toString("hex")}`),
// signature deadline
deadline: MaxUint256,
};

const {
domain: d,
types: t,
values: v,
} = SignatureTransfer.getPermitData(permitTransferFromData2, PERMIT2_ADDRESS, process.env.CHAIN_ID ? Number(process.env.CHAIN_ID) : 1);
const sig = await myWallet._signTypedData(d, t, v);

const txData = [
{
type: "erc20-permit",
Expand All @@ -50,6 +72,24 @@ export async function generateERC20Permit() {
signature: signature,
networkId: Number(process.env.CHAIN_ID),
},
{
type: "erc20-permit",
permit: {
permitted: {
token: permitTransferFromData2.permitted.token,
amount: permitTransferFromData2.permitted.amount.toString(),
},
nonce: permitTransferFromData2.nonce.toString(),
deadline: permitTransferFromData2.deadline.toString(),
},
transferDetails: {
to: permitTransferFromData2.spender,
requestedAmount: permitTransferFromData2.permitted.amount.toString(),
},
owner: myWallet.address,
signature: sig,
networkId: Number(process.env.CHAIN_ID),
},
];

const base64encodedTxData = Buffer.from(JSON.stringify(txData)).toString("base64");
Expand Down
52 changes: 52 additions & 0 deletions scripts/typescript/generate-erc721-permit-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ export async function generateERC721Permit() {
deadline: MaxUint256,
};

const erc721TransferFromData2: PermitTransferFrom = {
permitted: {
token: network == "localhost" ? NFT_REWARDS_ANVIL_DEPLOYMENT : NFT_ADDRESS,
amount: 1,
},
spender: network == "localhost" ? ANVIL_ACC_1_ADDRESS : myWallet.address,
nonce: 3137,
deadline: MaxUint256,
};

const domain = {
name: SIGNING_DOMAIN_NAME,
version: SIGNING_DOMAIN_VERSION,
Expand Down Expand Up @@ -69,6 +79,16 @@ export async function generateERC721Permit() {
values: [GITHUB_ORGANIZATION_NAME, GITHUB_REPOSITORY_NAME, GITHUB_ISSUE_ID, GITHUB_USERNAME, GITHUB_CONTRIBUTION_TYPE],
};

const mintRequest2 = {
beneficiary: network == "localhost" ? ANVIL_ACC_1_ADDRESS : myWallet.address,
deadline: MaxUint256,
keys: valueBytes,
nonce: 3137,
values: [GITHUB_ORGANIZATION_NAME, GITHUB_REPOSITORY_NAME, GITHUB_ISSUE_ID, GITHUB_USERNAME, GITHUB_CONTRIBUTION_TYPE],
};

const sig = await myWallet._signTypedData(domain, types, mintRequest2);

const signature = await myWallet._signTypedData(domain, types, mintRequest);

const txData721 = [
Expand Down Expand Up @@ -104,6 +124,38 @@ export async function generateERC721Permit() {
values: [GITHUB_ORGANIZATION_NAME, GITHUB_REPOSITORY_NAME, GITHUB_ISSUE_ID, GITHUB_USERNAME, GITHUB_CONTRIBUTION_TYPE],
},
},
{
type: "erc721-permit",
permit: {
permitted: {
token: erc721TransferFromData2.permitted.token,
amount: erc721TransferFromData2.permitted.amount.toString(),
},
nonce: erc721TransferFromData2.nonce.toString(),
deadline: erc721TransferFromData2.deadline.toString(),
},
transferDetails: {
to: erc721TransferFromData2.spender,
requestedAmount: erc721TransferFromData2.permitted.amount.toString(),
},
owner: myWallet.address,
signature: sig,
networkId: CHAIN_ID,
nftMetadata: {
GITHUB_ORGANIZATION_NAME,
GITHUB_REPOSITORY_NAME,
GITHUB_ISSUE_ID,
GITHUB_USERNAME,
GITHUB_CONTRIBUTION_TYPE,
},
request: {
beneficiary: network == "localhost" ? ANVIL_ACC_1_ADDRESS : myWallet.address,
deadline: erc721TransferFromData2.deadline.toString(),
keys: valueBytes,
nonce: erc721TransferFromData2.nonce.toString(),
values: [GITHUB_ORGANIZATION_NAME, GITHUB_REPOSITORY_NAME, GITHUB_ISSUE_ID, GITHUB_USERNAME, GITHUB_CONTRIBUTION_TYPE],
},
},
];

const base64encodedTxData721 = Buffer.from(JSON.stringify(txData721)).toString("base64");
Expand Down
20 changes: 10 additions & 10 deletions static/scripts/rewards/app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class AppState {
}

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

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

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

get permit(): RewardPermit {
return this.permitIndex < this.claims.length ? this.claims[this.permitIndex] : this.claims[0];
get reward(): RewardPermit {
return this.rewardIndex < this.claims.length ? this.claims[this.rewardIndex] : this.claims[0];
}

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

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

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

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

Expand Down
4 changes: 2 additions & 2 deletions static/scripts/rewards/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const networkNames = {
[NetworkIds.Mainnet]: "Ethereum Mainnet",
[NetworkIds.Goerli]: "Goerli Testnet",
[NetworkIds.Gnosis]: "Gnosis Chain",
[NetworkIds.Anvil]: "Anvil Development",
[NetworkIds.Anvil]: "http://127.0.0.1:8545",
};

export const networkCurrencies: Record<number, object> = {
Expand Down Expand Up @@ -49,7 +49,7 @@ export const networkRpcs: Record<number, string[]> = {
[NetworkIds.Mainnet]: ["https://rpc-pay.ubq.fi/v1/mainnet", ...(extraRpcs[NetworkIds.Mainnet] || [])],
[NetworkIds.Goerli]: ["https://rpc-pay.ubq.fi/v1/goerli", ...(extraRpcs[NetworkIds.Goerli] || [])],
[NetworkIds.Gnosis]: [...(extraRpcs[NetworkIds.Gnosis] || [])],
[NetworkIds.Anvil]: ["http://localhost:8545"],
[NetworkIds.Anvil]: ["http://127.0.0.1:8545"],
};

export const permit2Address = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import { setPagination } from "./set-pagination";
import { removeAllEventListeners } from "./utils";

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

const nextTxButton = document.getElementById("nextTx");
if (nextTxButton) {
nextTxButton.addEventListener("click", () => {
claimButton.element = removeAllEventListeners(claimButton.element) as HTMLButtonElement;
app.nextPermit();
rewardsCount.innerHTML = `${app.permitIndex + 1}/${app.claims.length} reward`;
rewardsCount.innerHTML = `${app.rewardIndex + 1}/${app.claims.length} reward`;
table.setAttribute(`data-claim`, "error");
renderTransaction(true).catch(console.error);
renderTransaction(app).catch(console.error);
});
}

Expand All @@ -24,9 +24,9 @@ export function claimRewardsPagination(rewardsCount: HTMLElement) {
prevTxButton.addEventListener("click", () => {
claimButton.element = removeAllEventListeners(claimButton.element) as HTMLButtonElement;
app.previousPermit();
rewardsCount.innerHTML = `${app.permitIndex + 1}/${app.claims.length} reward`;
rewardsCount.innerHTML = `${app.rewardIndex + 1}/${app.claims.length} reward`;
table.setAttribute(`data-claim`, "error");
renderTransaction(true).catch(console.error);
renderTransaction(app, true).catch(console.error);
});
}

Expand Down
27 changes: 14 additions & 13 deletions static/scripts/rewards/render-transaction/insert-table-data.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BigNumber, ethers } from "ethers";
import { AppState, app } from "../app-state";
import { Erc721Permit } from "./tx-type";
import { Erc20Permit, Erc721Permit } from "./tx-type";

export function shortenAddress(address: string): string {
return `${address.slice(0, 10)}...${address.slice(-8)}`;
Expand All @@ -11,16 +11,16 @@ export function insertErc20PermitTableData(
table: Element,
treasury: { balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }
): Element {
const permit = app.permit;
const reward = app.reward as Erc20Permit;
const requestedAmountElement = document.getElementById("rewardAmount") as Element;
renderToFields(permit.transferDetails.to, app.currentExplorerUrl);
renderTokenFields(permit.permit.permitted.token, app.currentExplorerUrl);
renderToFields(reward.transferDetails.to, app.currentExplorerUrl);
renderTokenFields(reward.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: "From", value: `<a target="_blank" rel="noopener noreferrer" href="${app.currentExplorerUrl}/address/${reward.owner}">${reward.owner}</a>` },
{
name: "Expiry",
value: (() => {
const deadline = BigNumber.isBigNumber(permit.permit.deadline) ? permit.permit.deadline : BigNumber.from(permit.permit.deadline);
const deadline = BigNumber.isBigNumber(reward.permit.deadline) ? reward.permit.deadline : BigNumber.from(reward.permit.deadline);
return deadline.lte(Number.MAX_SAFE_INTEGER.toString()) ? new Date(deadline.toNumber()).toLocaleString() : undefined;
})(),
},
Expand All @@ -31,19 +31,19 @@ export function insertErc20PermitTableData(
return requestedAmountElement;
}

export function insertErc721PermitTableData(permit: Erc721Permit, table: Element): Element {
export function insertErc721PermitTableData(reward: Erc721Permit, table: Element): Element {
const requestedAmountElement = document.getElementById("rewardAmount") as Element;
renderToFields(permit.transferDetails.to, app.currentExplorerUrl);
renderTokenFields(permit.permit.permitted.token, app.currentExplorerUrl);
const { GITHUB_REPOSITORY_NAME, GITHUB_CONTRIBUTION_TYPE, GITHUB_ISSUE_ID, GITHUB_ORGANIZATION_NAME, GITHUB_USERNAME } = permit.nftMetadata;
renderToFields(reward.transferDetails.to, app.currentExplorerUrl);
renderTokenFields(reward.permit.permitted.token, app.currentExplorerUrl);
const { GITHUB_REPOSITORY_NAME, GITHUB_CONTRIBUTION_TYPE, GITHUB_ISSUE_ID, GITHUB_ORGANIZATION_NAME, GITHUB_USERNAME } = reward.nftMetadata;
renderDetailsFields([
{
name: "NFT address",
value: `<a target="_blank" rel="noopener noreferrer" href="${app.currentExplorerUrl}/address/${permit.permit.permitted.token}">${permit.permit.permitted.token}</a>`,
value: `<a target="_blank" rel="noopener noreferrer" href="${app.currentExplorerUrl}/address/${reward.permit.permitted.token}">${reward.permit.permitted.token}</a>`,
},
{
name: "Expiry",
value: permit.permit.deadline.lte(Number.MAX_SAFE_INTEGER.toString()) ? new Date(permit.permit.deadline.toNumber()).toLocaleString() : undefined,
value: reward.permit.deadline.lte(Number.MAX_SAFE_INTEGER.toString()) ? new Date(reward.permit.deadline.toNumber()).toLocaleString() : undefined,
},
{
name: "GitHub Organization",
Expand Down Expand Up @@ -84,6 +84,7 @@ function renderDetailsFields(additionalDetails: { name: string; value: string |
function renderTokenFields(tokenAddress: string, explorerUrl: string) {
const tokenFull = document.querySelector("#Token .full") as Element;
const tokenShort = document.querySelector("#Token .short") as Element;

tokenFull.innerHTML = `<div>${tokenAddress}</div>`;
tokenShort.innerHTML = `<div>${shortenAddress(tokenAddress)}</div>`;

Expand All @@ -95,7 +96,7 @@ function renderToFields(receiverAddress: string, explorerUrl: string) {
const toFull = document.querySelector("#rewardRecipient .full") as Element;
const toShort = document.querySelector("#rewardRecipient .short") as Element;

// after a single claim toFull returns null as creates a toaster error
// if the for address is an ENS name neither will be found
if (!toFull || !toShort) return;

toFull.innerHTML = `<div>${receiverAddress}</div>`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { verifyCurrentNetwork } from "../web3/verify-current-network";
import { claimRewardsPagination } from "./claim-rewards-pagination";
import { renderTransaction } from "./render-transaction";
import { setClaimMessage } from "./set-claim-message";
import { claimTxT } from "./tx-type";
import { RewardPermit, claimTxT } from "./tx-type";
import { Type } from "@sinclair/typebox";

export const table = document.getElementsByTagName(`table`)[0];
const urlParams = new URLSearchParams(window.location.search);
Expand All @@ -20,19 +21,19 @@ export async function readClaimDataFromUrl(app: AppState) {
return;
}

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

renderTransaction(true)
renderTransaction(app)
.then(() => verifyCurrentNetwork(networkId as number))
.catch(console.error);
}

function decodeClaimData(base64encodedTxData: string) {
function decodeClaimData(base64encodedTxData: string): RewardPermit[] {
let permit;

try {
Expand All @@ -43,9 +44,8 @@ function decodeClaimData(base64encodedTxData: string) {
table.setAttribute(`data-claim`, "error");
throw error;
}

try {
return [Value.Decode(claimTxT, permit[0])];
return [Value.Decode(Type.Array(claimTxT), permit)];
} catch (error) {
console.error(error);
setClaimMessage({ type: "Error", message: `2. Invalid claim data passed in URL` });
Expand Down
Loading

0 comments on commit b7483f7

Please sign in to comment.