Skip to content

Commit

Permalink
Merge branch 'main' into scaffold-config-readme
Browse files Browse the repository at this point in the history
  • Loading branch information
KcPele committed Jul 7, 2023
2 parents 9dc2d0b + fb3fcd6 commit c4270cd
Show file tree
Hide file tree
Showing 67 changed files with 1,528 additions and 1,932 deletions.
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ const {
} = useScaffoldEventHistory({
contractName: "YourContract",
eventName: "GreetingChange",
// Specify the starting block number from which to read events.
fromBlock: 31231,
// Specify the starting block number from which to read events, this is a bigint.
fromBlock: 31231n,
blockData: true,
// Apply filters to the event based on parameter names and values { [parameterName]: value },
filters: { premium: true }
Expand Down Expand Up @@ -312,13 +312,12 @@ const { data: yourContract } = useScaffoldContract({
await yourContract?.greeting();

// Used to write to a contract and can be called in any function
import { Signer } from "ethers";
import { useSigner } from "wagmi";
import { useWalletClient } from "wagmi";

const { data: signer, isError, isLoading } = useSigner();
const { data: walletClient } = useWalletClient();
const { data: yourContract } = useScaffoldContract({
contractName: "YourContract",
signerOrProvider: signer as Signer,
walletClient,
});
const setGreeting = async () => {
// Call the method in any function
Expand Down
23 changes: 18 additions & 5 deletions packages/hardhat/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
{
"arrowParens": "avoid",
"printWidth": 120,
"tabWidth": 2,
"trailingComma": "all"
}
"arrowParens": "avoid",
"printWidth": 120,
"tabWidth": 2,
"trailingComma": "all",
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 80,
"tabWidth": 4,
"useTabs": true,
"singleQuote": false,
"bracketSpacing": true,
"explicitTypes": "always"
}
}
]
}
117 changes: 63 additions & 54 deletions packages/hardhat/contracts/YourContract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity >=0.8.0 <0.9.0;

// Useful for debugging. Remove when deploying to a live network.
import "hardhat/console.sol";

// Use openzeppelin to inherit battle-tested implementations (ERC20, ERC721, etc)
// import "@openzeppelin/contracts/access/Ownable.sol";

Expand All @@ -12,67 +13,75 @@ import "hardhat/console.sol";
* @author BuidlGuidl
*/
contract YourContract {
// State Variables
address public immutable owner;
string public greeting = "Building Unstoppable Apps!!!";
bool public premium = false;
uint256 public totalCounter = 0;
mapping(address => uint) public userGreetingCounter;

// State Variables
address public immutable owner;
string public greeting = "Building Unstoppable Apps!!!";
bool public premium = false;
uint256 public totalCounter = 0;
mapping(address => uint) public userGreetingCounter;

// Events: a way to emit log statements from smart contract that can be listened to by external parties
event GreetingChange(address indexed greetingSetter, string newGreeting, bool premium, uint256 value);
// Events: a way to emit log statements from smart contract that can be listened to by external parties
event GreetingChange(
address indexed greetingSetter,
string newGreeting,
bool premium,
uint256 value
);

// Constructor: Called once on contract deployment
// Check packages/hardhat/deploy/00_deploy_your_contract.ts
constructor(address _owner) {
owner = _owner;
}
// Constructor: Called once on contract deployment
// Check packages/hardhat/deploy/00_deploy_your_contract.ts
constructor(address _owner) {
owner = _owner;
}

// Modifier: used to define a set of rules that must be met before or after a function is executed
// Check the withdraw() function
modifier isOwner() {
// msg.sender: predefined variable that represents address of the account that called the current function
require(msg.sender == owner, "Not the Owner");
_;
}
// Modifier: used to define a set of rules that must be met before or after a function is executed
// Check the withdraw() function
modifier isOwner() {
// msg.sender: predefined variable that represents address of the account that called the current function
require(msg.sender == owner, "Not the Owner");
_;
}

/**
* Function that allows anyone to change the state variable "greeting" of the contract and increase the counters
*
* @param _newGreeting (string memory) - new greeting to save on the contract
*/
function setGreeting(string memory _newGreeting) public payable {
// Print data to the hardhat chain console. Remove when deploying to a live network.
console.log("Setting new greeting '%s' from %s", _newGreeting, msg.sender);
/**
* Function that allows anyone to change the state variable "greeting" of the contract and increase the counters
*
* @param _newGreeting (string memory) - new greeting to save on the contract
*/
function setGreeting(string memory _newGreeting) public payable {
// Print data to the hardhat chain console. Remove when deploying to a live network.
console.log(
"Setting new greeting '%s' from %s",
_newGreeting,
msg.sender
);

// Change state variables
greeting = _newGreeting;
totalCounter += 1;
userGreetingCounter[msg.sender] += 1;
// Change state variables
greeting = _newGreeting;
totalCounter += 1;
userGreetingCounter[msg.sender] += 1;

// msg.value: built-in global variable that represents the amount of ether sent with the transaction
if (msg.value > 0) {
premium = true;
} else {
premium = false;
}
// msg.value: built-in global variable that represents the amount of ether sent with the transaction
if (msg.value > 0) {
premium = true;
} else {
premium = false;
}

// emit: keyword used to trigger an event
emit GreetingChange(msg.sender, _newGreeting, msg.value > 0, 0);
}
// emit: keyword used to trigger an event
emit GreetingChange(msg.sender, _newGreeting, msg.value > 0, 0);
}

/**
* Function that allows the owner to withdraw all the Ether in the contract
* The function can only be called by the owner of the contract as defined by the isOwner modifier
*/
function withdraw() isOwner public {
(bool success,) = owner.call{value: address(this).balance}("");
require(success, "Failed to send Ether");
}
/**
* Function that allows the owner to withdraw all the Ether in the contract
* The function can only be called by the owner of the contract as defined by the isOwner modifier
*/
function withdraw() public isOwner {
(bool success, ) = owner.call{ value: address(this).balance }("");
require(success, "Failed to send Ether");
}

/**
* Function that allows the contract to receive ETH
*/
receive() external payable {}
/**
* Function that allows the contract to receive ETH
*/
receive() external payable {}
}
6 changes: 4 additions & 2 deletions packages/nextjs/components/blockexplorer/AddressLogsTab.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Address } from "viem";
import { useContractLogs } from "~~/hooks/scaffold-eth";
import { replacer } from "~~/utils/scaffold-eth/common";

export const AddressLogsTab = ({ address }: { address: string }) => {
export const AddressLogsTab = ({ address }: { address: Address }) => {
const contractLogs = useContractLogs(address);

return (
Expand All @@ -9,7 +11,7 @@ export const AddressLogsTab = ({ address }: { address: string }) => {
<pre className="px-5 whitespace-pre-wrap break-words">
{contractLogs.map((log, i) => (
<div key={i}>
<strong>Log:</strong> {JSON.stringify(log, null, 2)}
<strong>Log:</strong> {JSON.stringify(log, replacer, 2)}
</div>
))}
</pre>
Expand Down
14 changes: 10 additions & 4 deletions packages/nextjs/components/blockexplorer/AddressStorageTab.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { useEffect, useState } from "react";
import { localhost } from "wagmi/chains";
import { getLocalProvider } from "~~/utils/scaffold-eth";
import { createPublicClient, http, toHex } from "viem";
import { hardhat } from "wagmi/chains";

const provider = getLocalProvider(localhost);
const publicClient = createPublicClient({
chain: hardhat,
transport: http(),
});

export const AddressStorageTab = ({ address }: { address: string }) => {
const [storage, setStorage] = useState<string[]>([]);
Expand All @@ -14,7 +17,10 @@ export const AddressStorageTab = ({ address }: { address: string }) => {
let idx = 0;

while (true) {
const storageAtPosition = await provider?.getStorageAt(address, idx);
const storageAtPosition = await publicClient.getStorageAt({
address: address,
slot: toHex(idx),
});

if (storageAtPosition === "0x" + "0".repeat(64)) break;

Expand Down
15 changes: 8 additions & 7 deletions packages/nextjs/components/blockexplorer/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { useState } from "react";
import { useRouter } from "next/router";
import { ethers } from "ethers";
import { localhost } from "wagmi/chains";
import { getLocalProvider } from "~~/utils/scaffold-eth";
import { isAddress, isHex } from "viem";
import { usePublicClient } from "wagmi";
import { hardhat } from "wagmi/chains";

const provider = getLocalProvider(localhost);
export const SearchBar = () => {
const [searchInput, setSearchInput] = useState("");
const router = useRouter();

const client = usePublicClient({ chainId: hardhat.id });

const handleSearch = async (event: React.FormEvent) => {
event.preventDefault();
if (ethers.utils.isHexString(searchInput)) {
if (isHex(searchInput)) {
try {
const tx = await provider?.getTransaction(searchInput);
const tx = await client.getTransaction({ hash: searchInput });
if (tx) {
router.push(`/blockexplorer/transaction/${searchInput}`);
return;
Expand All @@ -23,7 +24,7 @@ export const SearchBar = () => {
}
}

if (ethers.utils.isAddress(searchInput)) {
if (isAddress(searchInput)) {
router.push(`/blockexplorer/address/${searchInput}`);
return;
}
Expand Down
14 changes: 7 additions & 7 deletions packages/nextjs/components/blockexplorer/TransactionsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ethers } from "ethers";
import { formatEther } from "viem";
import { TransactionHash } from "~~/components/blockexplorer/TransactionHash";
import { Address } from "~~/components/scaffold-eth";
import { getTargetNetwork } from "~~/utils/scaffold-eth";
import { TransactionWithFunction, getTargetNetwork } from "~~/utils/scaffold-eth";
import { TransactionsTableProps } from "~~/utils/scaffold-eth/";

export const TransactionsTable = ({ blocks, transactionReceipts, isLoading }: TransactionsTableProps) => {
Expand Down Expand Up @@ -36,10 +36,10 @@ export const TransactionsTable = ({ blocks, transactionReceipts, isLoading }: Tr
) : (
<tbody>
{blocks.map(block =>
block.transactions.map(tx => {
(block.transactions as TransactionWithFunction[]).map(tx => {
const receipt = transactionReceipts[tx.hash];
const timeMined = new Date(block.timestamp * 1000).toLocaleString();
const functionCalled = tx.data.substring(0, 10);
const timeMined = new Date(Number(block.timestamp) * 1000).toLocaleString();
const functionCalled = tx.input.substring(0, 10);

return (
<tr key={tx.hash} className="hover text-sm">
Expand All @@ -52,7 +52,7 @@ export const TransactionsTable = ({ blocks, transactionReceipts, isLoading }: Tr
<span className="badge badge-primary font-bold text-xs">{functionCalled}</span>
)}
</td>
<td className="w-1/12">{block.number}</td>
<td className="w-1/12">{block.number?.toString()}</td>
<td className="w-2/12">{timeMined}</td>
<td className="w-2/12">
<Address address={tx.from} size="sm" />
Expand All @@ -68,7 +68,7 @@ export const TransactionsTable = ({ blocks, transactionReceipts, isLoading }: Tr
)}
</td>
<td className="text-right">
{ethers.utils.formatEther(tx.value)} {targetNetwork.nativeCurrency.symbol}
{formatEther(tx.value)} {targetNetwork.nativeCurrency.symbol}
</td>
</tr>
);
Expand Down
9 changes: 6 additions & 3 deletions packages/nextjs/components/example-ui/ContractData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ export const ContractData = () => {
useScaffoldEventSubscriber({
contractName: "YourContract",
eventName: "GreetingChange",
listener: (greetingSetter, newGreeting, premium, value) => {
console.log(greetingSetter, newGreeting, premium, value);
listener: logs => {
logs.map(log => {
const { greetingSetter, value, premium, newGreeting } = log.args;
console.log("📡 GreetingChange event", greetingSetter, value, premium, newGreeting);
});
},
});

Expand All @@ -45,7 +48,7 @@ export const ContractData = () => {
} = useScaffoldEventHistory({
contractName: "YourContract",
eventName: "GreetingChange",
fromBlock: Number(process.env.NEXT_PUBLIC_DEPLOY_BLOCK) || 0,
fromBlock: process.env.NEXT_PUBLIC_DEPLOY_BLOCK ? BigInt(process.env.NEXT_PUBLIC_DEPLOY_BLOCK) : 0n,
filters: { greetingSetter: address },
blockData: true,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const ContractInteraction = () => {
className={`btn btn-primary rounded-full capitalize font-normal font-white w-24 flex items-center gap-1 hover:gap-2 transition-all tracking-widest ${
isLoading ? "loading" : ""
}`}
onClick={writeAsync}
onClick={() => writeAsync()}
>
{!isLoading && (
<>
Expand Down
9 changes: 4 additions & 5 deletions packages/nextjs/components/scaffold-eth/Address.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useEffect, useState } from "react";
import Link from "next/link";
import { ethers } from "ethers";
import { isAddress } from "ethers/lib/utils";
import Blockies from "react-blockies";
import { CopyToClipboard } from "react-copy-to-clipboard";
import { isAddress } from "viem";
import { useEnsAvatar, useEnsName } from "wagmi";
import { hardhat } from "wagmi/chains";
import { CheckCircleIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline";
Expand Down Expand Up @@ -36,8 +35,8 @@ export const Address = ({ address, disableAddressLink, format, size = "base" }:

const { data: fetchedEns } = useEnsName({ address, enabled: isAddress(address ?? ""), chainId: 1 });
const { data: fetchedEnsAvatar } = useEnsAvatar({
address,
enabled: isAddress(address ?? ""),
name: fetchedEns,
enabled: Boolean(fetchedEns),
chainId: 1,
cacheTime: 30_000,
});
Expand All @@ -63,7 +62,7 @@ export const Address = ({ address, disableAddressLink, format, size = "base" }:
);
}

if (!ethers.utils.isAddress(address)) {
if (!isAddress(address)) {
return <span className="text-error">Wrong address</span>;
}

Expand Down
Loading

0 comments on commit c4270cd

Please sign in to comment.