Skip to content

Commit

Permalink
Introduce Deployed Resolvers
Browse files Browse the repository at this point in the history
  • Loading branch information
lucemans committed Nov 22, 2023
1 parent 5b020d3 commit 6317da7
Show file tree
Hide file tree
Showing 7 changed files with 378 additions and 2 deletions.
29 changes: 27 additions & 2 deletions web/components/organisms/deploy/DeployResolver.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Button, Card, FlameSVG, GasPumpSVG, Input, OutlinkSVG, WalletSVG } from "@ensdomains/thorin";
import { useChains, useModal } from "connectkit";
import { FactoryABI } from "../../../pages/abi/factory_abi";
import { FC, useMemo, useState } from "react";
import { FC, useEffect, useMemo, useState } from "react";
import { Address, useAccount, useChainId, useContractWrite, useFeeData, usePrepareContractWrite, useWaitForTransaction } from "wagmi";
import { formatEther } from "viem";
import { useDeployedResolvers } from "../../../stores/deployed_resolvers";

// https url that must include '{sender}'
const gatewayRegex = new RegExp("^https://.*{sender}.*$");
// const gatewayRegex = new RegExp("^https://.*{sender}.*$");
const gatewayRegex = new RegExp("^https://.*$");
// address[] that must include 0x and are seperated by ,
const signersRegex = new RegExp("^\\[0x[0-9a-fA-F]{40}(,0x[0-9a-fA-F]{40})*\\]$");

Expand Down Expand Up @@ -45,6 +47,8 @@ export const DeployResolverCard: FC = () => {

const { data: FeeData } = useFeeData({ chainId, formatUnits: chainId == 5 ? 'kwei' : 'gwei' });

const { transactions, logTransaction, logTransactionSuccess } = useDeployedResolvers();

const { config, data: EstimateData, error, isSuccess, isLoading } = usePrepareContractWrite({
address: factoryAddress,
chainId,
Expand All @@ -70,6 +74,27 @@ export const DeployResolverCard: FC = () => {
}
}, [FeeData, EstimateData]);

console.log({ receipt: receipt?.data });

useEffect(() => {
if (!data) return;

logTransaction(data.hash, chainId.toString());
}, [data]);

useEffect(() => {
if (!receipt?.data) return;

const x = receipt.data;

const first = x.logs[0];
const address = first.address;

console.log('Contracted Deployed at: ' + address);

logTransactionSuccess(receipt.data.transactionHash, chainId.toString(), address);
}, [receipt?.data]);

return (
<Card className="leading-6 gap-2">
<div className="">
Expand Down
116 changes: 116 additions & 0 deletions web/components/organisms/deployed_resolvers/DeployedResolvers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { FC } from "react";
import { TransactionState, TransactionStateDeployed, TransactionStatePending, useDeployedResolvers } from "../../../stores/deployed_resolvers";
import { useChainId, useContractRead, useTransaction } from "wagmi";
import { Card, Input } from "@ensdomains/thorin";
import { formatEther } from "viem";
import { FiExternalLink, FiFile } from 'react-icons/fi';

export const DeployedResolvers = () => {
const transactions = useDeployedResolvers(e => e.transactions);
const chain = useChainId();

const transactionForChain = transactions.filter(transaction => transaction.chain == chain.toString());

return (
<div className="flex flex-col gap-2">
<Card className="!gap-0 !p-4">
<h2 className="font-bold">Deployed Resolvers</h2>
<span>These are the resolvers you have deployed</span>
</Card>
<div className="flex flex-col gap-2">
{
transactionForChain.map((transaction) => transaction.status == "deployed" ?
<DeployedResolver key={transaction.hash} transaction={transaction} /> : <PendingTransaction key={transaction.hash} transaction={transaction} />).reverse()
}
</div>
</div>
)
};

export const PendingTransaction: FC<{ transaction: TransactionState }> = ({ transaction: { hash, chain } }) => {

return (
<div className="bg-ens-light-background-primary bg-ens-light-border rounded-lg">
<div>Pending</div>
<div>{hash}</div>
<div>{chain}</div>
</div>
);
};

const explorer_urls: Record<number, {
transaction: string,
address: string,
}> = {
1: {
transaction: 'https://etherscan.io/tx/:hash',
address: 'https://etherscan.io/address/:address'
},
5: {
transaction: 'https://goerli.etherscan.io/tx/:hash',
address: 'https://goerli.etherscan.io/address/:address'
},
};

export const DeployedResolver: FC<{ transaction: TransactionStateDeployed }> = ({ transaction }) => {
const { data: gateway_data } = useContractRead({
address: transaction.contract_address as any,
abi: [{ name: 'url', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ name: 'url', type: 'string' }] }],
functionName: 'url',
enabled: true,
});
const { data: transactionData } = useTransaction({
hash: transaction.hash as `0x${string}`,
chainId: Number.parseInt(transaction.chain),
});

const explorer_url = explorer_urls[Number.parseInt(transaction.chain)];
const gateway_url = gateway_data as string;

return (
<Card className="!p-4">
<div className="flex gap-1 items-center">
<FiFile />
<a href={explorer_url.address.replace(":address", transaction.contract_address)} target="_blank" className="flex items-center justify-center gap-1 text-sm">
<span>
{transaction.contract_address}
</span>
<FiExternalLink />
</a>
</div>
<div className="">
<div>
Deployed at
<div className="flex gap-2 items-center justify-center">
<div className="truncate text-sm font-bold">
{transaction.hash}
</div>
<a href={explorer_url.transaction.replace(":hash", transaction.hash)} target="_blank" className="flex items-center justify-center gap-1 text-sm">
TxHsh <FiExternalLink />
</a>
</div>
</div>
<div className="flex justify-between">
<div>
Total Gas Fees
</div>
<div className="flex items-center gap-1 text-sm">
<span>
🔥
</span>
<span className="items-center text-ens-light-red-bright">
{
formatEther(
transactionData?.gasPrice?.mul(transactionData?.gasLimit).toBigInt() ?? BigInt(0))
}
</span>
</div>
</div>
<div className="pt-2">
<Input label="Gateway Url" defaultValue={gateway_url} />
</div>
</div>
</Card>

)
};
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.43.9",
"react-icons": "^4.12.0",
"styled-components": "^5.3.9",
"tailwindcss": "^3.3.1",
"viem": "^0.2.5",
Expand Down
2 changes: 2 additions & 0 deletions web/pages/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Configuration } from '../components/organisms/Configuration';
import { Thing } from './thing';
import { BannerCard } from '../components/organisms/BannerCard';
import { DeployResolverCard } from '../components/organisms/deploy/DeployResolver';
import { DeployedResolvers } from '../components/organisms/deployed_resolvers/DeployedResolvers';

export const App = () => {
return (
Expand All @@ -24,6 +25,7 @@ export const App = () => {
<DeployResolverCard />
{/* <Configuration /> */}
{/* <CheckName /> */}
<DeployedResolvers />
</div>
</div>
</Thing>
Expand Down
11 changes: 11 additions & 0 deletions web/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions web/stores/deployed_resolvers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { type } from 'os';
import { create } from 'zustand';
import { createJSONStorage, persist } from 'zustand/middleware';

export type TransactionStatePending = { status: 'pending', hash: string, chain: string };
export type TransactionStateDeployed = { status: 'deployed', hash: string, chain: string, contract_address: string };

export type TransactionState = TransactionStatePending | TransactionStateDeployed;

interface DeployedResolverState {
transactions: TransactionState[];
logTransaction: (transaction_hash: string, chain_id: string) => void;
logTransactionSuccess: (transaction_hash: string, chain_id: string, contract_address: string) => void;
}

export const useDeployedResolvers = create(
persist<DeployedResolverState>(
(set) => ({
transactions: [],
logTransaction(transaction_hash, chain_id) {
set((state) => ({ transactions: [...state.transactions, { status: 'pending', hash: transaction_hash, chain: chain_id }] }))
},
logTransactionSuccess(transaction_hash, chain_id, contract_address) {
set((state): Partial<DeployedResolverState> => {
const transactions = state.transactions.map((transaction) => {
if (transaction.hash === transaction_hash) {
return { ...transaction, status: 'deployed', contract_address } as TransactionStateDeployed;
} else {
return transaction;
}
});

return { transactions };
})
},
}), { name: '@ccip-tools/resolvers', storage: createJSONStorage(() => localStorage) }));
Loading

0 comments on commit 6317da7

Please sign in to comment.