diff --git a/packages/foundry/script/DeployHelpers.s.sol b/packages/foundry/script/DeployHelpers.s.sol
index 7338ac1..e2e9017 100644
--- a/packages/foundry/script/DeployHelpers.s.sol
+++ b/packages/foundry/script/DeployHelpers.s.sol
@@ -5,74 +5,72 @@ import "forge-std/Script.sol";
import "forge-std/Vm.sol";
contract ScaffoldETHDeploy is Script {
- error InvalidChain();
+ error InvalidChain();
- struct Deployment {
- string name;
- address addr;
- }
+ struct Deployment {
+ string name;
+ address addr;
+ }
- string root;
- string path;
- Deployment[] public deployments;
+ string root;
+ string path;
+ Deployment[] public deployments;
- function setupLocalhostEnv() internal returns (uint256 localhostPrivateKey) {
- if (block.chainid == 31337) {
- root = vm.projectRoot();
- path = string.concat(root, "/localhost.json");
- string memory json = vm.readFile(path);
- bytes memory mnemonicBytes = vm.parseJson(json, ".wallet.mnemonic");
- string memory mnemonic = abi.decode(mnemonicBytes, (string));
- return vm.deriveKey(mnemonic, 0);
- } else {
- return vm.envUint("DEPLOYER_PRIVATE_KEY");
+ function setupLocalhostEnv() internal returns (uint256 localhostPrivateKey) {
+ if (block.chainid == 31337) {
+ root = vm.projectRoot();
+ path = string.concat(root, "/localhost.json");
+ string memory json = vm.readFile(path);
+ bytes memory mnemonicBytes = vm.parseJson(json, ".wallet.mnemonic");
+ string memory mnemonic = abi.decode(mnemonicBytes, (string));
+ return vm.deriveKey(mnemonic, 0);
+ } else {
+ return vm.envUint("DEPLOYER_PRIVATE_KEY");
+ }
}
- }
- function exportDeployments() internal {
- // fetch already existing contracts
- root = vm.projectRoot();
- path = string.concat(root, "/deployments/");
- string memory chainIdStr = vm.toString(block.chainid);
- path = string.concat(path, string.concat(chainIdStr, ".json"));
+ function exportDeployments() internal {
+ // fetch already existing contracts
+ root = vm.projectRoot();
+ path = string.concat(root, "/deployments/");
+ string memory chainIdStr = vm.toString(block.chainid);
+ path = string.concat(path, string.concat(chainIdStr, ".json"));
- string memory jsonWrite;
+ string memory jsonWrite;
- uint256 len = deployments.length;
+ uint256 len = deployments.length;
- for (uint256 i = 0; i < len; i++) {
- vm.serializeString(
- jsonWrite, vm.toString(deployments[i].addr), deployments[i].name
- );
- }
+ for (uint256 i = 0; i < len; i++) {
+ vm.serializeString(jsonWrite, vm.toString(deployments[i].addr), deployments[i].name);
+ }
- string memory chainName;
+ string memory chainName;
- try this.getChain() returns (Chain memory chain) {
- chainName = chain.name;
- } catch {
- chainName = findChainName();
+ try this.getChain() returns (Chain memory chain) {
+ chainName = chain.name;
+ } catch {
+ chainName = findChainName();
+ }
+ jsonWrite = vm.serializeString(jsonWrite, "networkName", chainName);
+ vm.writeJson(jsonWrite, path);
}
- jsonWrite = vm.serializeString(jsonWrite, "networkName", chainName);
- vm.writeJson(jsonWrite, path);
- }
- function getChain() public returns (Chain memory) {
- return getChain(block.chainid);
- }
+ function getChain() public returns (Chain memory) {
+ return getChain(block.chainid);
+ }
- function findChainName() public returns (string memory) {
- uint256 thisChainId = block.chainid;
- string[2][] memory allRpcUrls = vm.rpcUrls();
- for (uint256 i = 0; i < allRpcUrls.length; i++) {
- try vm.createSelectFork(allRpcUrls[i][1]) {
- if (block.chainid == thisChainId) {
- return allRpcUrls[i][0];
+ function findChainName() public returns (string memory) {
+ uint256 thisChainId = block.chainid;
+ string[2][] memory allRpcUrls = vm.rpcUrls();
+ for (uint256 i = 0; i < allRpcUrls.length; i++) {
+ try vm.createSelectFork(allRpcUrls[i][1]) {
+ if (block.chainid == thisChainId) {
+ return allRpcUrls[i][0];
+ }
+ } catch {
+ continue;
+ }
}
- } catch {
- continue;
- }
+ revert InvalidChain();
}
- revert InvalidChain();
- }
}
diff --git a/packages/foundry/script/VerifyAll.s.sol b/packages/foundry/script/VerifyAll.s.sol
index 75c6ab2..e8b88f8 100644
--- a/packages/foundry/script/VerifyAll.s.sol
+++ b/packages/foundry/script/VerifyAll.s.sol
@@ -11,129 +11,91 @@ import "solidity-bytes-utils/BytesLib.sol";
* @notice will be deleted once the forge/std is updated
*/
struct FfiResult {
- int32 exit_code;
- bytes stdout;
- bytes stderr;
+ int32 exit_code;
+ bytes stdout;
+ bytes stderr;
}
interface tempVm {
- function tryFfi(
- string[] calldata
- ) external returns (FfiResult memory);
+ function tryFfi(string[] calldata) external returns (FfiResult memory);
}
contract VerifyAll is Script {
- uint96 currTransactionIdx;
+ uint96 currTransactionIdx;
- function run() external {
- string memory root = vm.projectRoot();
- string memory path = string.concat(
- root,
- "/broadcast/Deploy.s.sol/",
- vm.toString(block.chainid),
- "/run-latest.json"
- );
- string memory content = vm.readFile(path);
+ function run() external {
+ string memory root = vm.projectRoot();
+ string memory path =
+ string.concat(root, "/broadcast/Deploy.s.sol/", vm.toString(block.chainid), "/run-latest.json");
+ string memory content = vm.readFile(path);
- while (this.nextTransaction(content)) {
- _verifyIfContractDeployment(content);
- currTransactionIdx++;
+ while (this.nextTransaction(content)) {
+ _verifyIfContractDeployment(content);
+ currTransactionIdx++;
+ }
}
- }
- function _verifyIfContractDeployment(
- string memory content
- ) internal {
- string memory txType = abi.decode(
- vm.parseJson(content, searchStr(currTransactionIdx, "transactionType")),
- (string)
- );
- if (keccak256(bytes(txType)) == keccak256(bytes("CREATE"))) {
- _verifyContract(content);
+ function _verifyIfContractDeployment(string memory content) internal {
+ string memory txType =
+ abi.decode(vm.parseJson(content, searchStr(currTransactionIdx, "transactionType")), (string));
+ if (keccak256(bytes(txType)) == keccak256(bytes("CREATE"))) {
+ _verifyContract(content);
+ }
}
- }
- function _verifyContract(
- string memory content
- ) internal {
- string memory contractName = abi.decode(
- vm.parseJson(content, searchStr(currTransactionIdx, "contractName")),
- (string)
- );
- address contractAddr = abi.decode(
- vm.parseJson(content, searchStr(currTransactionIdx, "contractAddress")),
- (address)
- );
- bytes memory deployedBytecode = abi.decode(
- vm.parseJson(content, searchStr(currTransactionIdx, "transaction.data")),
- (bytes)
- );
- bytes memory compiledBytecode = abi.decode(
- vm.parseJson(_getCompiledBytecode(contractName), ".bytecode.object"),
- (bytes)
- );
- bytes memory constructorArgs = BytesLib.slice(
- deployedBytecode,
- compiledBytecode.length,
- deployedBytecode.length - compiledBytecode.length
- );
+ function _verifyContract(string memory content) internal {
+ string memory contractName =
+ abi.decode(vm.parseJson(content, searchStr(currTransactionIdx, "contractName")), (string));
+ address contractAddr =
+ abi.decode(vm.parseJson(content, searchStr(currTransactionIdx, "contractAddress")), (address));
+ bytes memory deployedBytecode =
+ abi.decode(vm.parseJson(content, searchStr(currTransactionIdx, "transaction.data")), (bytes));
+ bytes memory compiledBytecode =
+ abi.decode(vm.parseJson(_getCompiledBytecode(contractName), ".bytecode.object"), (bytes));
+ bytes memory constructorArgs =
+ BytesLib.slice(deployedBytecode, compiledBytecode.length, deployedBytecode.length - compiledBytecode.length);
- string[] memory inputs = new string[](9);
- inputs[0] = "forge";
- inputs[1] = "verify-contract";
- inputs[2] = vm.toString(contractAddr);
- inputs[3] = contractName;
- inputs[4] = "--chain";
- inputs[5] = vm.toString(block.chainid);
- inputs[6] = "--constructor-args";
- inputs[7] = vm.toString(constructorArgs);
- inputs[8] = "--watch";
+ string[] memory inputs = new string[](9);
+ inputs[0] = "forge";
+ inputs[1] = "verify-contract";
+ inputs[2] = vm.toString(contractAddr);
+ inputs[3] = contractName;
+ inputs[4] = "--chain";
+ inputs[5] = vm.toString(block.chainid);
+ inputs[6] = "--constructor-args";
+ inputs[7] = vm.toString(constructorArgs);
+ inputs[8] = "--watch";
- FfiResult memory f = tempVm(address(vm)).tryFfi(inputs);
+ FfiResult memory f = tempVm(address(vm)).tryFfi(inputs);
- if (f.stderr.length != 0) {
- console.logString(
- string.concat(
- "Submitting verification for contract: ", vm.toString(contractAddr)
- )
- );
- console.logString(string(f.stderr));
- } else {
- console.logString(string(f.stdout));
+ if (f.stderr.length != 0) {
+ console.logString(string.concat("Submitting verification for contract: ", vm.toString(contractAddr)));
+ console.logString(string(f.stderr));
+ } else {
+ console.logString(string(f.stdout));
+ }
+ return;
}
- return;
- }
- function nextTransaction(
- string memory content
- ) external view returns (bool) {
- try this.getTransactionFromRaw(content, currTransactionIdx) {
- return true;
- } catch {
- return false;
+ function nextTransaction(string memory content) external view returns (bool) {
+ try this.getTransactionFromRaw(content, currTransactionIdx) {
+ return true;
+ } catch {
+ return false;
+ }
}
- }
- function _getCompiledBytecode(
- string memory contractName
- ) internal view returns (string memory compiledBytecode) {
- string memory root = vm.projectRoot();
- string memory path =
- string.concat(root, "/out/", contractName, ".sol/", contractName, ".json");
- compiledBytecode = vm.readFile(path);
- }
+ function _getCompiledBytecode(string memory contractName) internal view returns (string memory compiledBytecode) {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/out/", contractName, ".sol/", contractName, ".json");
+ compiledBytecode = vm.readFile(path);
+ }
- function getTransactionFromRaw(
- string memory content,
- uint96 idx
- ) external pure {
- abi.decode(vm.parseJson(content, searchStr(idx, "hash")), (bytes32));
- }
+ function getTransactionFromRaw(string memory content, uint96 idx) external pure {
+ abi.decode(vm.parseJson(content, searchStr(idx, "hash")), (bytes32));
+ }
- function searchStr(
- uint96 idx,
- string memory searchKey
- ) internal pure returns (string memory) {
- return string.concat(".transactions[", vm.toString(idx), "].", searchKey);
- }
+ function searchStr(uint96 idx, string memory searchKey) internal pure returns (string memory) {
+ return string.concat(".transactions[", vm.toString(idx), "].", searchKey);
+ }
}
diff --git a/packages/nextjs/app/api/transactions/route.ts b/packages/nextjs/app/api/transactions/route.ts
index ff4f444..177396e 100644
--- a/packages/nextjs/app/api/transactions/route.ts
+++ b/packages/nextjs/app/api/transactions/route.ts
@@ -1,28 +1,26 @@
+import { NextResponse } from "next/server";
import { TransactionType } from "~~/types/transaction";
let nextId = 0;
let transactions: TransactionType[] = [];
-export async function GET(request: Request) {
- return Response.json(transactions)
+export async function GET() {
+ return NextResponse.json(transactions);
}
export async function POST(request: Request) {
- const body = await request.json();
- const newTx = body as TransactionType;
- newTx.id = nextId;
- transactions.push(newTx)
- nextId++;
- return Response.json(newTx);
+ const body = await request.json();
+ const newTx = body as TransactionType;
+ newTx.id = nextId;
+ transactions.push(newTx);
+ nextId++;
+ return NextResponse.json(newTx);
}
export async function PUT(request: Request) {
+ const body = await request.json();
+ const updatedTransaction = body as TransactionType;
+ transactions = transactions.map(tx => (tx.id === updatedTransaction.id ? { ...tx, ...updatedTransaction } : tx));
- const body = await request.json();
- const updatedTransaction = body as TransactionType;
- transactions = transactions.map(tx =>
- tx.id === updatedTransaction.id ? { ...tx, ...updatedTransaction } : tx
- );
-
- return Response.json(updatedTransaction)
+ return NextResponse.json(updatedTransaction);
}
diff --git a/packages/nextjs/app/transactions/_components/Banner.tsx b/packages/nextjs/app/transactions/_components/Banner.tsx
index 35a01a7..a747463 100644
--- a/packages/nextjs/app/transactions/_components/Banner.tsx
+++ b/packages/nextjs/app/transactions/_components/Banner.tsx
@@ -1,15 +1,16 @@
export const Banner = () => {
- return (
- <>
-
-
Transactions
-
- Select a type of transaction to create and wait for other signers to validate it.
-
Then it will be executed automatically
-
-
- >
- )
-}
+ return (
+ <>
+
+
Transactions
+
+ Select a type of transaction to create and wait for other signers to validate it.
+
+ Then it will be executed automatically
+
+
+ >
+ );
+};
-export default Banner;
\ No newline at end of file
+export default Banner;
diff --git a/packages/nextjs/app/transactions/_components/CreateTransaction.tsx b/packages/nextjs/app/transactions/_components/CreateTransaction.tsx
index 0f3dd38..dbb5193 100644
--- a/packages/nextjs/app/transactions/_components/CreateTransaction.tsx
+++ b/packages/nextjs/app/transactions/_components/CreateTransaction.tsx
@@ -1,143 +1,144 @@
-
-import type { NextPage } from "next";
import { useState } from "react";
+import type { NextPage } from "next";
+import { keccak256 } from "viem";
+import { useAccount, useWalletClient } from "wagmi";
import { AddressInput, InputBase, IntegerInput } from "~~/components/scaffold-eth";
import { useScaffoldContract, useScaffoldReadContract } from "~~/hooks/scaffold-eth";
import { useTransactionStore } from "~~/services/store/transactionStore";
-import { useAccount, useWalletClient } from 'wagmi';
import { Signature, TransactionType } from "~~/types/transaction";
-import { keccak256 } from 'viem';
export const CreateTransaction: NextPage = () => {
- const METHODS = ["addSigner", "removeSigner", "transferFunds"];
- const transactionStore = useTransactionStore();
-
- const { data: walletClient } = useWalletClient();
-
- const { data: initialNonce } = useScaffoldReadContract({
- contractName: "MetaMultisigWallet",
- functionName: "s_nonce"
- });
- const { data: initialRequiredSigners } = useScaffoldReadContract({
- contractName: "MetaMultisigWallet",
- functionName: "s_numRequiredSigners"
+ const METHODS = ["addSigner", "removeSigner", "transferFunds"];
+ const transactionStore = useTransactionStore();
+
+ const { data: walletClient } = useWalletClient();
+
+ const { data: initialNonce } = useScaffoldReadContract({
+ contractName: "MetaMultisigWallet",
+ functionName: "s_nonce",
+ });
+ const { data: initialRequiredSigners } = useScaffoldReadContract({
+ contractName: "MetaMultisigWallet",
+ functionName: "s_numRequiredSigners",
+ });
+
+ const [funcSelected, setFuncSelected] = useState("addSigner");
+ const [ethValue, setEthValue] = useState("");
+ const [newReqSigners, setNewReqSigners] = useState(0);
+ const [callData, setCallData] = useState("");
+ const [signer, setSigner] = useState("");
+
+ const { data: multisigWalletContract } = useScaffoldContract({
+ contractName: "MetaMultisigWallet",
+ });
+ const { address: sender } = useAccount();
+ if (sender == undefined) {
+ return;
+ }
+
+ const handleCreate = async () => {
+ const newTx: TransactionType = {
+ id: 0,
+ function: funcSelected + "(address,uint256)",
+ to: signer as `0x${string}`,
+ amount: funcSelected == "addSigner" || funcSelected == "removeSigner" ? BigInt(0) : (ethValue as bigint),
+ requiredSigners: Number(initialRequiredSigners),
+ signatures: [],
+ executed: false,
+ };
+
+ const argument = funcSelected == "transferFunds" ? newTx.amount : BigInt(newTx.requiredSigners);
+ newTx.callData = (await multisigWalletContract?.read.getHash([newTx.function, newTx.to, argument])) as `0x{string}`;
+ setCallData(newTx.callData);
+
+ const messageHash = keccak256(newTx.callData);
+ const sign: any = await walletClient?.signMessage({
+ message: { raw: messageHash },
});
-
- const [funcSelected, setFuncSelected] = useState("addSigner");
- const [ethValue, setEthValue] = useState("");
- const [newReqSigners, setNewReqSigners] = useState(0);
- const [callData, setCallData] = useState("");
- const [signer, setSigner] = useState("");
-
- const { data: multisigWalletContract } = useScaffoldContract({
- contractName: "MetaMultisigWallet"
- })
- const { address: sender } = useAccount();
- if (sender == undefined) {
- return;
- }
-
- const handleCreate = async () => {
- const newTx: TransactionType = {
- id: 0,
- function: funcSelected + "(address,uint256)",
- to: signer as `0x${string}`,
- amount: (funcSelected == "addSigner" || funcSelected == "removeSigner") ? BigInt(0) : ethValue as bigint,
- requiredSigners: Number(initialRequiredSigners),
- signatures: [],
- executed: false
- }
-
- const argument = (funcSelected == "transferFunds") ? newTx.amount : BigInt(newTx.requiredSigners);
- newTx.callData = await multisigWalletContract?.read.getHash([newTx.function, newTx.to, argument]) as `0x{string}`;
- setCallData(newTx.callData);
-
- const messageHash = keccak256(newTx.callData);
- const sign: any = await walletClient?.signMessage({
- message: { raw: messageHash }
- });
- const signatureObject: Signature = {
- signature: sign,
- address: sender
- }
- newTx.signatures.push(signatureObject);
-
-
- transactionStore.addTransaction(newTx);
- }
-
- return (
-
-
-
-
-
- {
- null;
- }}
- />
-
-
-
-
-
-
-
-
-
setSigner(signer)}
- />
-
- {funcSelected === "transferFunds" && (
- {
- setEthValue(val);
- }}
- />
- )}
-
- {funcSelected !== "transferFunds" && (
- {
- setNewReqSigners(val)
- }}
- placeholder="Set new required signers"
- />
- )}
-
- {
- null;
- }}
- disabled
- />
-
-
-
-
+ const signatureObject: Signature = {
+ signature: sign,
+ address: sender as `0x${string}`,
+ };
+ newTx.signatures.push(signatureObject);
+
+ transactionStore.addTransaction(newTx);
+ };
+
+ return (
+
+
+
+
+
+ {
+ null;
+ }}
+ />
+
+
+
+
+
+
+
+
setSigner(signer)}
+ />
+
+ {funcSelected === "transferFunds" && (
+ {
+ setEthValue(val);
+ }}
+ />
+ )}
+
+ {funcSelected !== "transferFunds" && (
+ {
+ setNewReqSigners(val);
+ }}
+ placeholder="Set new required signers"
+ />
+ )}
+
+ {
+ null;
+ }}
+ disabled
+ />
+
+
+
- );
-}
+
+
+ );
+};
diff --git a/packages/nextjs/app/transactions/_components/TransactionRow.tsx b/packages/nextjs/app/transactions/_components/TransactionRow.tsx
index 4dffc16..f23d82e 100644
--- a/packages/nextjs/app/transactions/_components/TransactionRow.tsx
+++ b/packages/nextjs/app/transactions/_components/TransactionRow.tsx
@@ -1,87 +1,95 @@
-import { Signature, TransactionType } from "~~/types/transaction";
+import { useAccount, useWalletClient } from "wagmi";
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
-import { useAccount, useWalletClient } from 'wagmi';
-import { useTransactionStore } from "~~/services/store/transactionStore";
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";
+import { useTransactionStore } from "~~/services/store/transactionStore";
+import { Signature, TransactionType } from "~~/types/transaction";
export const TransactionRow = ({ tx }: { tx: TransactionType }) => {
- const { writeContractAsync: writeMetaMultisigAsync } = useScaffoldWriteContract("MetaMultisigWallet");
- const { data: walletClient } = useWalletClient();
- const { address: sender } = useAccount();
- if (sender == undefined) {
- return;
- }
-
- const { data: isOwner } = useScaffoldReadContract({
- contractName: "MetaMultisigWallet",
- functionName: "isOwnerActive",
- args: [sender],
- });
- const updateTransaction = useTransactionStore(state => state.updateTransaction);
-
- const handleSign = async (tx: TransactionType) => {
- const sign: any = await walletClient?.signMessage({
- message: { raw: tx.callData as `0x${string}` }
- });
+ const { writeContractAsync: writeMetaMultisigAsync } = useScaffoldWriteContract("MetaMultisigWallet");
+ const { data: walletClient } = useWalletClient();
+ let { address: sender } = useAccount();
+ if (sender == undefined) {
+ sender = "0x0" as `0x${string}`;
+ }
- const signatureObject: Signature = {
- signature: sign,
- address: sender
- }
+ const { data: isOwner } = useScaffoldReadContract({
+ contractName: "MetaMultisigWallet",
+ functionName: "isOwnerActive",
+ args: [sender],
+ });
+ const updateTransaction = useTransactionStore(state => state.updateTransaction);
- tx.signatures.push(signatureObject);
- updateTransaction(tx.id, tx);
+ const handleSign = async (tx: TransactionType) => {
+ const sign: any = await walletClient?.signMessage({
+ message: { raw: tx.callData as `0x${string}` },
+ });
- }
+ const signatureObject: Signature = {
+ signature: sign,
+ address: sender as `0x${string}`,
+ };
- const handleExec = async (tx: TransactionType) => {
- try {
- await writeMetaMultisigAsync({
- functionName: "executeTransaction",
- args: [tx.callData, tx.signatures.map(sig => sig.signature)],
- });
- } catch (error) {
- console.log(error)
- }
- }
+ tx.signatures.push(signatureObject);
+ updateTransaction(tx.id, tx);
+ };
- const hasAlreadySigned = (transaction: TransactionType, address: `0x${string}`): boolean => {
- return transaction.signatures.some(signature => signature.address === address);
+ const handleExec = async (tx: TransactionType) => {
+ try {
+ await writeMetaMultisigAsync({
+ functionName: "executeTransaction",
+ args: [tx.callData, tx.signatures.map(sig => sig.signature)],
+ });
+ } catch (error) {
+ console.log(error);
}
- const amountToTransfer = (transaction: TransactionType) => {
- if (transaction.function == "transferFunds(address,uint256)") {
-
- return Number(transaction.amount) / 1000000000000000000;
- }
+ };
- return "";
+ const hasAlreadySigned = (transaction: TransactionType, address: `0x${string}`): boolean => {
+ return transaction.signatures.some(signature => signature.address === address);
+ };
+ const amountToTransfer = (transaction: TransactionType) => {
+ if (transaction.function == "transferFunds(address,uint256)") {
+ return Number(transaction.amount) / 1000000000000000000;
}
- return (
-
- {tx.id} |
- {tx.function} {amountToTransfer(tx).toString()} ETH |
- {tx.signatures?.length || 0} / {tx.requiredSigners} |
-
- {isOwner ? (
- <>
-
-
- >
- ) : (
- No rights 😶
- )}
+ return "";
+ };
- |
-
- )
-}
+ return (
+
+ {tx.id} |
+
+ {tx.function} {amountToTransfer(tx).toString()} ETH
+ |
+
+ {tx.signatures?.length || 0} / {tx.requiredSigners}{" "}
+ |
+
+ {isOwner ? (
+ <>
+
+
+ >
+ ) : (
+ No rights 😶
+ )}
+ |
+
+ );
+};
export default TransactionRow;
diff --git a/packages/nextjs/app/transactions/_components/Transactions.tsx b/packages/nextjs/app/transactions/_components/Transactions.tsx
index 9905aa3..17d704d 100644
--- a/packages/nextjs/app/transactions/_components/Transactions.tsx
+++ b/packages/nextjs/app/transactions/_components/Transactions.tsx
@@ -1,52 +1,50 @@
-import { type FC, useEffect, useState } from "react";
-import type { NextPage } from "next";
+import { useEffect } from "react";
import TransactionRow from "./TransactionRow";
+import type { NextPage } from "next";
import { useTransactionStore } from "~~/services/store/transactionStore";
export const TransactionsList: NextPage = () => {
- const transactions = useTransactionStore((state) => state.transactions);
- const fetchTransactions = useTransactionStore((state) => state.fetchTransactions);
+ const transactions = useTransactionStore(state => state.transactions);
+ const fetchTransactions = useTransactionStore(state => state.fetchTransactions);
- useEffect(() => {
- fetchTransactions();
- }, [fetchTransactions]);
+ useEffect(() => {
+ fetchTransactions();
+ }, [fetchTransactions]);
- return (
-
-
-
-
-
-
- {transactions?.length ? (
-
-
- Current transactions
-
-
-
- ID. |
- TYPE |
- SIGNERS |
- |
-
-
-
- {transactions.map((tx) => (
-
- ))}
-
-
- ) : (
-
-
No transactions available
-
- )}
-
-
-
-
+ return (
+
+
+
+
+
+
+ {transactions?.length ? (
+
+ Current transactions
+
+
+ ID. |
+ TYPE |
+ SIGNERS |
+ |
+
+
+
+ {transactions.map(tx => (
+
+ ))}
+
+
+ ) : (
+
+
No transactions available
+
+ )}
+
+
- )
-}
\ No newline at end of file
+
+
+ );
+};
diff --git a/packages/nextjs/app/transactions/_components/index.tsx b/packages/nextjs/app/transactions/_components/index.tsx
index 599d9ad..4d70332 100644
--- a/packages/nextjs/app/transactions/_components/index.tsx
+++ b/packages/nextjs/app/transactions/_components/index.tsx
@@ -1,3 +1,3 @@
export * from "./CreateTransaction";
export * from "./Transactions";
-export * from "./Banner";
\ No newline at end of file
+export * from "./Banner";
diff --git a/packages/nextjs/app/transactions/page.tsx b/packages/nextjs/app/transactions/page.tsx
index 1ec19f8..fb8f917 100644
--- a/packages/nextjs/app/transactions/page.tsx
+++ b/packages/nextjs/app/transactions/page.tsx
@@ -1,75 +1,69 @@
"use client";
-import { type FC, useEffect, useState } from "react";
+import { useEffect, useState } from "react";
+import { Banner, CreateTransaction, TransactionsList } from "./_components";
import type { NextPage } from "next";
-import { CreateTransaction, TransactionsList, Banner } from "./_components";
-import { AddressInput, EtherInput, InputBase } from "~~/components/scaffold-eth";
import { useScaffoldEventHistory } from "~~/hooks/scaffold-eth";
import { Signer } from "~~/types/transaction";
const Transactions: NextPage = () => {
- const [signers, setSigners] = useState
([]);
- const {
- data: events,
- isLoading: isLoadingEvents,
- error: errorReadingEvents,
- } = useScaffoldEventHistory({
- contractName: "MetaMultisigWallet",
- eventName: "SignerAdded",
- fromBlock: 0n,
- watch: true,
- blockData: true,
- });
+ const [signers, setSigners] = useState([]);
+ const { data: events } = useScaffoldEventHistory({
+ contractName: "MetaMultisigWallet",
+ eventName: "SignerAdded",
+ fromBlock: 0n,
+ watch: true,
+ blockData: true,
+ });
- useEffect(() => {
- if (events) {
- const newSigners: Signer[] = events.map(event => {
- return { address: event.args.who } as Signer;
- });
- setSigners(newSigners);
- }
- }, [events]);
+ useEffect(() => {
+ if (events) {
+ const newSigners: Signer[] = events.map(event => {
+ return { address: event.args.who } as Signer;
+ });
+ setSigners(newSigners);
+ }
+ }, [events]);
-
- return (
- <>
-
-
-
-
-
-
-
-
- Owners:
- {signers?.length ? (
-
- {signers.map((signer, i) => (
- - {signer.address}
- ))}
-
- ) : (
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
+ return (
+ <>
+
+
+
+
+
+
+
+
+ Owners:
+ {signers?.length ? (
+
+ {signers.map((signer, i) => (
+ - {signer.address}
+ ))}
+
+ ) : (
+
+ )}
+
+
- >
- );
+
+
+
+
+ >
+ );
};
export default Transactions;
diff --git a/packages/nextjs/components/Footer.tsx b/packages/nextjs/components/Footer.tsx
index a256e3f..0cf9ec3 100644
--- a/packages/nextjs/components/Footer.tsx
+++ b/packages/nextjs/components/Footer.tsx
@@ -4,7 +4,6 @@ import { hardhat } from "viem/chains";
import { CurrencyDollarIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { HeartIcon } from "@heroicons/react/24/outline";
import { SwitchTheme } from "~~/components/SwitchTheme";
-import { BuidlGuidlLogo } from "~~/components/assets/BuidlGuidlLogo";
import { Faucet } from "~~/components/scaffold-eth";
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
import { useGlobalState } from "~~/services/store/store";
@@ -47,7 +46,12 @@ export const Footer = () => {
diff --git a/packages/nextjs/services/store/transactionStore.ts b/packages/nextjs/services/store/transactionStore.ts
index 0f20501..dce43c8 100644
--- a/packages/nextjs/services/store/transactionStore.ts
+++ b/packages/nextjs/services/store/transactionStore.ts
@@ -1,65 +1,60 @@
-import { create } from 'zustand';
+import { create } from "zustand";
import { TransactionType } from "~~/types/transaction";
type TransactionState = {
- nextId: number;
- transactions: TransactionType[];
- fetchTransactions: () => Promise
;
- addTransaction: (transaction: TransactionType) => Promise;
- updateTransaction: (id: number, updatedData: Partial) => Promise;
+ nextId: number;
+ transactions: TransactionType[];
+ fetchTransactions: () => Promise;
+ addTransaction: (transaction: TransactionType) => Promise;
+ updateTransaction: (id: number, updatedData: Partial) => Promise;
};
export const useTransactionStore = create((set, get) => ({
- transactions: [],
- nextId: 1,
+ transactions: [],
+ nextId: 1,
- fetchTransactions: async () => {
- const response = await fetch('/api/transactions');
- const data: any[] = await response.json();
- const transactions = data.map((transaction) => ({
- ...transaction,
- requiredSigners: transaction.requiredSigners,
- }));
- set({ transactions });
- },
+ fetchTransactions: async () => {
+ const response = await fetch("/api/transactions");
+ const data: any[] = await response.json();
+ const transactions = data.map(transaction => ({
+ ...transaction,
+ requiredSigners: transaction.requiredSigners,
+ }));
+ set({ transactions });
+ },
- addTransaction: async (transaction: TransactionType) => {
- const id = get().nextId;
- const transactionWithId = { ...transaction, id };
- const response = await fetch('/api/transactions', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(
- transaction,
- (key, value) => (typeof value === "bigint" ? value.toString() : value),
- ),
- });
- const newTransaction = await response.json();
- set((state) => ({
- transactions: [...state.transactions, newTransaction],
- nextId: state.nextId + 1,
- }));
- },
+ addTransaction: async (transaction: TransactionType) => {
+ const id = get().nextId;
+ const transactionWithId = { ...transaction, id };
+ const response = await fetch("/api/transactions", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(transactionWithId, (key, value) => (typeof value === "bigint" ? value.toString() : value)),
+ });
+ const newTransaction = await response.json();
+ set(state => ({
+ transactions: [...state.transactions, newTransaction],
+ nextId: state.nextId + 1,
+ }));
+ },
- updateTransaction: async (id: number, updatedData: Partial) => {
- const response = await fetch(`/api/transactions`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(
- updatedData,
- // stringifying bigint
- (key, value) => (typeof value === "bigint" ? value.toString() : value),
- ),
- });
- const updatedTransaction = await response.json();
- set((state) => ({
- transactions: state.transactions.map((transaction) =>
- transaction.id === id ? updatedTransaction : transaction
- ),
- }));
- },
+ updateTransaction: async (id: number, updatedData: Partial) => {
+ const response = await fetch(`/api/transactions`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(
+ updatedData,
+ // stringifying bigint
+ (key, value) => (typeof value === "bigint" ? value.toString() : value),
+ ),
+ });
+ const updatedTransaction = await response.json();
+ set(state => ({
+ transactions: state.transactions.map(transaction => (transaction.id === id ? updatedTransaction : transaction)),
+ }));
+ },
}));
diff --git a/packages/nextjs/types/transaction.ts b/packages/nextjs/types/transaction.ts
index 69f6fa2..75ba281 100644
--- a/packages/nextjs/types/transaction.ts
+++ b/packages/nextjs/types/transaction.ts
@@ -1,19 +1,19 @@
export type TransactionType = {
- id: number,
- function: string,
- to: `0x${string}`,
- amount: bigint,
- callData?: `0x${string}`,
- signatures: Signature[],
- requiredSigners: number,
- executed: boolean
-}
+ id: number;
+ function: string;
+ to: `0x${string}`;
+ amount: bigint;
+ callData?: `0x${string}`;
+ signatures: Signature[];
+ requiredSigners: number;
+ executed: boolean;
+};
export type Signature = {
- address: `0x${string}`,
- signature: `0x${string}`
-}
+ address?: `0x${string}`;
+ signature: `0x${string}`;
+};
export type Signer = {
- address: `0x${string}`
-}
+ address: `0x${string}`;
+};