DAPP: Crowdfunding project (3) Goland+react develops dapp

Continue to the previous article, let's develop our front end! !

1. Create a directory structure:

eth directory: Mainly to realize contract interaction and provide methods for operating contracts

display directory: main display interface

Utils: Mainly web3 is responsible for providing the common code for introducing web3

2. Initialize the Web3 instance

      Create the InitWeb3.js file in the utils directory, define the code for web3 instantiation in the InitWeb3.js file, and export the web3 instance

Create a constructor under app.js to get web3 test

Then open the browser, you will report this error, so why? Because we can’t find the user’s provider

The solution is to install the metamask plug-in on the browser to automatically create a web3 instance

Add-ons-extensions-metamask plugin

Okay, hello is back. .

..... But another question arises, why can't web3.eth.getAccounts() get user accounts? ? Can't use it? ?

       After repeated trials, the original installed version is too high, metaMask has been set up for privacy protection, and you do not have permission to access it.

      So how to make the higher version of metaMask call web3?

Use it window.ethereumto determine whether the new version of metamask, if so, call the ethereum.enable() method to request user authorization, which will pop up an authorization dialog box on the user web page, the code is as follows:

var web3Provider;
if (window.ethereum) {
    web3Provider = window.ethereum;
    try {
        // 请求用户授权
        // 不用同步的方式
        window.ethereum.enable();
    } catch (error) {
        // 用户不授权时
        console.error("User denied account access")
    }
} else if (window.web3) {   // 老版 MetaMask Legacy dapp browsers...
    web3Provider = window.web3.currentProvider;
} else {
    web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
}
window.web3 = new Web3(web3Provider);//web3就是你需要的web3实例

     When Connected appears, it means you are successful. Let us take a look at the obtained account information.     

   

3. Instantiate the contract

Step 1: Create an instance.js file in the eth directory.

Step 2: Copy abi.

Step 3: Copy the contract address.

node 02-deploy.js 
contract instance address :  0x48f294B386669c069dB01D5b9b38446328AD724d

Step 4: Add the following code to the instance.js file to create and export a contract instance.

2. Interface construction

     Main interface construction:

(1) Create a TabCenter.js file in the display directory, and define a Tab component in the file.

Find components,

(2) Display the main interface content in the App.js file

(3) Import css in the index.js file.

4) Create three subpages, corresponding to the contents of Tab1, Tab2, and Tab3 respectively.

Modify the main interface:

In this way, you can directly rewrite the sub-interface code. Now let's take a look at the show! !

(5). Display the array of contracts I initiated

Get the crowdfunding initiated by me in the componentWillMount method and set it to the state

Get our created crowdfunding contract

   state ={
        creatorFundings :[],
    }
    //在componentWillMount方法中获取我发起的众筹,并设置到state中。
    async componentWillMount() {
        let creatorFundings = await fundingFactoryInstance.methods.getCreatorFundings().call()
        console.log(creatorFundings)
        this.setState({
            creatorFundings
        })
    }
//在render方法中从state获取数据。
    render(){
        return(
            <p>{this.state.creatorFundings}</p>
        )
    }
}

(6) Get the detailed information of each contract (name, amount...)

           Next, we will obtain the detailed information of the contract according to the contract address, and then display it on the interface.

              a, get contract instance

                              abi, ruins

                   Modify the instance.js file and define variables to save the ABI and contract address of FundingFactory and Funding respectively.

// ABI接口
let factoryABI = [...]
//地址先不指定,在程序中动态增加,完成实例化
let fundingInstance = new web3.eth.Contract(fundingABI)
// 导出合约实例
export {fundingFactoryInstance,fundingInstance,}

                   Create instances of FundingFactory and Funding. Because a crowdfunding contract corresponds to a Funding instance, it is necessary to create multiple Funding instances here. Moreover, the contract address does not need to be passed in when creating a Funding instance, it can be set dynamically.

              b, use method to call fundingInstance.methods.projectName().call()

  let details =creatorFundings.map(async  function(fundingAddress){
            console.log(fundingAddress)
            //1.把funding实例拿过来

            // 2.对实例进行填充地址,可以使用了
            let newInstance=newFundingInstance()
            newInstance.options.address = fundingAddress
            //3.使用方法调用fundingInstance.methods.projectName().call()
            let manager = await newInstance.methods.manager().call()
            let projectName = await newInstance.methods.projectName().call()
            let targetMoney = await newInstance.methods.targetMoney().call()
            let supportMoney = await newInstance.methods.supportMoney().call()
            let leftTime = await newInstance.methods.getLeftTime().call()
            let detail ={manager,projectName,targetMoney,supportMoney,leftTime}
            //console.table(detail)
            return detail
        })
        //4.	把多个promise处理成一个promise
        let detailInfo = Promise.all(details)
        detailInfo.then(detail =>{
            console.table(detail)
        })

            Take a look at the results:

           Extract the implementation details to the interface:

Create a new common subdirectory in the display directory, and then create a new CardList.js file in the subdirectory.

Define a CardList method in the file, which is responsible for setting the contract information in the details to the Card component. For the specific usage of the card component of semantic-ui, please refer to it yourself: https://react.semantic-ui.com/views/card/#variations-colored

import React from "react";
import {Card,Image,Icon,List, Progress} from "semantic-ui-react";
const src ='/images/daniel.jpg'
const CardList =(props)=>{
    let details=props.details
    console.log('bbb',details)
    let cards = details.map(detail =>{
        return <CardFunding key={detail.fundingAddress} detail1={detail}/>
    })
    return(
    <Card.Group itemsPerRow={4}>
        {
            cards
        }
    </Card.Group>
)}

const CardFunding = (props) => {
    let detail2 =props.detail1
    console.log('de2:'.detail2)
    let {fundingAddress,manager, projectName, targetMoney, supportMoney, leftTime,balance,investorCount}=detail2
    let percent =parseFloat(balance)/parseFloat(targetMoney)*100
    return(
        <Card>
            <Image src='/images/daniel.jpg'/>
            <Card.Content>
                <Card.Header>{projectName}</Card.Header>
                <Card.Meta>
                    <span className='date'>剩余时间:{leftTime}</span>
                    <Progress percent={percent} progress size='small'/>
                </Card.Meta>
                <Card.Description>参加临港公路比赛</Card.Description>
            </Card.Content>
            <Card.Content extra>
                <List horizontal style={
   
   {display: 'flex', justifyContent: 'space-around'}}>
                    <List.Item>
                        <List.Content>
                            <List.Header>已筹</List.Header>
                            <List.Description>{balance}eth</List.Description>
                        </List.Content>
                    </List.Item>
                    <List.Item>
                        <List.Content>
                            <List.Header>已达</List.Header>
                            <List.Description>{percent}%</List.Description>
                        </List.Content>
                    </List.Item>
                    <List.Item>
                        <List.Content>
                            <List.Header>参与人数</List.Header>
                            <List.Description>{investorCount}人</List.Description>
                        </List.Content>
                    </List.Item>
                </List>
            </Card.Content>
        </Card>
)}

export default CardList

The writing is a bit silly, and too much code has been changed. . . . Write an article right away. . .

 

 

Guess you like

Origin blog.csdn.net/qq_38798147/article/details/109259045