-
-
+
+ Test DAPP
+
+
+
+ - NetworkId : {{ web3Interact.networkId }}
+ - Account : {{ web3Interact.account }}
+ - CryptoZombies contract : {{
+ web3Interact.cryptoZombiesContract.options.address }}
+ - FundMe contract : {{
+ web3Interact.fundmeContract.options.address }}
+
+
CryptoZombies
-
+
+
FundMe
+
+
+
diff --git a/dapp/src/components/FundMeView.vue b/dapp/src/components/FundMeView.vue
new file mode 100644
index 0000000..ca6e56e
--- /dev/null
+++ b/dapp/src/components/FundMeView.vue
@@ -0,0 +1,33 @@
+
+
+
+
+ Balance : {{ balance }}
+
+
+
+
+
diff --git a/dapp/src/tests/web3.test.ts b/dapp/src/tests/web3.test.ts
index e165578..78cb55d 100644
--- a/dapp/src/tests/web3.test.ts
+++ b/dapp/src/tests/web3.test.ts
@@ -3,5 +3,5 @@ import { Web3Utils } from '../utils/web3utils';
test('init without provider', () => {
const web3: Web3Utils = new Web3Utils(undefined)
- expect(web3.ethInit()).toBe(false)
+ expect(web3.initialize()).toBe(false)
})
\ No newline at end of file
diff --git a/dapp/src/utils/web3utils.ts b/dapp/src/utils/web3utils.ts
index 35f5948..4ebb27d 100644
--- a/dapp/src/utils/web3utils.ts
+++ b/dapp/src/utils/web3utils.ts
@@ -1,14 +1,37 @@
import { MetaMaskInpageProvider } from "@metamask/providers";
-import Web3, { EventLog, Contract } from 'web3';
-import cryptozombiesABI from '../../abi/zombieownership.sol/ZombieOwnership.json';
+import Web3, { Contract, Web3ContractError } from 'web3';
+
+// Foundry generated contracts and broadcasts
+import cryptozombiesABI from '../../../contracts/out/zombieownership.sol/ZombieOwnership.json';
+import fundmeABI from '../../../contracts/out/FundMe.sol/FundMe.json';
+import cryptozombiesBroadcastLocal from '../../../contracts/broadcast/DeployZombieOwnership.s.sol/31337/run-latest.json';
+import fundmeBroadcastLocal from '../../../contracts/broadcast/DeployFundMe.s.sol/31337/run-latest.json';
+import fundmeBroadcastSepolia from '../../../contracts/broadcast/DeployFundMe.s.sol/11155111/run-latest.json';
export class Web3Utils {
private web3js!: Web3;
private ethereum!: MetaMaskInpageProvider;
- private readonly cryptoZombiesContractAddress: string = "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512";
public account!: string;
+ public networkId!: bigint;
public cryptoZombiesContract!: Contract
;
+ public fundmeContract!: Contract;
+
+ // Foundry broadcast data
+ private BROADCAST: { [key: number]: any } = {
+ 1: { // Mainnet
+ cryptoZombies: null,
+ fundme: null
+ },
+ 11155111: { // Sepolia
+ cryptoZombies: fundmeBroadcastSepolia,
+ fundme: fundmeBroadcastSepolia
+ },
+ 31337: { // Local
+ cryptoZombies: cryptozombiesBroadcastLocal,
+ fundme: fundmeBroadcastLocal
+ },
+ };
constructor(ethereum: MetaMaskInpageProvider | undefined) {
if (ethereum) {
@@ -19,24 +42,52 @@ export class Web3Utils {
}
}
- ethInit(): boolean {
- if (this.ethereum == undefined) return false;
- console.log("Init Web 3");
- this.ethereum.request({ method: 'eth_requestAccounts' });
- this.web3js = new Web3(this.ethereum);
- this.web3js.eth.getAccounts().then((accounts: string[]) => {
- this.account = this.web3js.utils.toChecksumAddress(accounts[0]);
- })
- this.cryptoZombiesContract = new this.web3js.eth.Contract(cryptozombiesABI.abi, this.cryptoZombiesContractAddress);
-
- this.cryptoZombiesContract.events.NewZombie()
- .on("data", (event: EventLog) => {
- let zombie = event.returnValues;
- console.log("A new zombie was born!", zombie.zombieId, zombie.name, zombie.dna);
- })
- //.on("error", console.error);
+ initialize(): void {
+ try {
+
+ console.log("Initialize web 3 utils");
+
+ if (this.ethereum == undefined) throw new Error("Provider not found");
+
+ this.ethereum.request({ method: 'eth_requestAccounts' });
+ this.web3js = new Web3(this.ethereum);
+
+ this.web3js.eth.getAccounts().then((accounts) => {
+ this.account = this.web3js.utils.toChecksumAddress(accounts[0]);
+ console.log("Account: " + this.account);
+ });
+
+ this.web3js.eth.net.getId().then((id: bigint) => {
+ this.networkId = id
+ const cryptozombiesContractAddress = this.getCryptozombiesContractAddress(this.networkId) as string
+ const fundmeContractAddress = this.getFundmeContractAddress(this.networkId) as string
+ this.cryptoZombiesContract = new this.web3js.eth.Contract(cryptozombiesABI.abi, cryptozombiesContractAddress);
+ this.fundmeContract = new this.web3js.eth.Contract(fundmeABI.abi, fundmeContractAddress);
+ });
- return true;
+ } catch (error) {
+ throw new Error("Error during initialize Web 3 " + this.networkId + " " + this.account);
+ }
+ }
+
+ getFundmeContractAddress(networkId: bigint): string | null {
+ if (this.BROADCAST[Number(networkId)]?.fundme == null) throw new Error("No contract found for network " + networkId);
+ for (const transaction of this.BROADCAST[Number(networkId)].fundme.transactions) {
+ if (transaction.contractName === "FundMe") {
+ return transaction.contractAddress;
+ }
+ }
+ return null;
+ }
+
+ getCryptozombiesContractAddress(networkId: bigint): string | null {
+ if (this.BROADCAST[Number(networkId)]?.cryptoZombies == null) throw new Error("No contract found for network " + networkId);
+ for (const transaction of this.BROADCAST[Number(networkId)].cryptoZombies.transactions) {
+ if (transaction.contractName === "ZombieOwnership") {
+ return transaction.contractAddress;
+ }
+ }
+ return null;
}
createRandomZombie(name: string) {
@@ -53,7 +104,10 @@ export class Web3Utils {
});
}
- getZombiesForAccount(): Zombie[] {
+ async getZombiesForAccount(): Promise {
+
+ if (this.cryptoZombiesContract == null) { throw new Error("Contract not initialized"); }
+
const zombies: Zombie[] = [];
console.log("getZombiesByOwner " + this.account);
this.cryptoZombiesContract.methods.getZombiesByOwner(this.account).call().then(
@@ -78,6 +132,81 @@ export class Web3Utils {
return this.cryptoZombiesContract.methods.zombieToOwner(id).call();
}
+ withdraw() {
+ console.log(`Withdrawing...`)
+ try {
+ const transaction = this.fundmeContract.methods.withdraw();
+
+ transaction.send({ from: this.account })
+ .on('transactionHash', function (hash: string) {
+ console.log(hash);
+ })
+ .on('confirmation', function (confirmation: { confirmations: bigint, receipt: { transactionHash: string, transactionIndex: bigint, blockHash: string, blockNumber: bigint, from: string }, latestBlockHash: string }) {
+ console.log(confirmation);
+ })
+ .on('receipt', function (receipt: any) { // type ReceiptOutput
+ console.log(receipt);
+ })
+ .on('error', function (error: Web3ContractError) {
+ console.log(error);
+ }).then(function (receipt: any) { // type ReceiptOutput
+ console.log(receipt)
+ })
+ .catch((error: any) => {
+ console.error(error);
+ });
+
+ } catch (error) {
+ console.error(error)
+ }
+ }
+
+ fund(ethAmount: any) {
+ console.log(`Funding with ${ethAmount}`)
+ try {
+
+ const transaction = this.fundmeContract.methods.fund({
+ value: this.web3js.utils.toWei(ethAmount, "ether"),
+ });
+
+ transaction.send({ from: this.account })
+ .on('transactionHash', function (hash: string) {
+ console.log(hash);
+ })
+ .on('confirmation', function (confirmation: { confirmations: bigint, receipt: { transactionHash: string, transactionIndex: bigint, blockHash: string, blockNumber: bigint, from: string }, latestBlockHash: string }) {
+ console.log(confirmation);
+ })
+ .on('receipt', function (receipt: any) { // type ReceiptOutput
+ console.log(receipt);
+ })
+ .on('error', function (error: Web3ContractError) {
+ console.log(error);
+ })
+ .then(function (receipt: any) { // type ReceiptOutput
+ console.log(receipt)
+ })
+ .catch((error: any) => {
+ console.error(error);
+ });
+
+ } catch (error) {
+ console.error(error)
+ }
+ }
+
+ async getBalance(): Promise {
+ let res: string = "?"
+ try {
+ const balance = await this.web3js.eth.getBalance(String(this.fundmeContract.options.address))
+ res = this.web3js.utils.fromWei(balance, "ether")
+ } catch (error) {
+ console.log(error)
+ }
+ return res;
+ }
+
+
+
}
export interface Zombie {
name?: string;