• Create your first Ethereum dAPP with Web3 and vue.js (Part 3)
  • Alt Street
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: sakila1012
  • Proofread by: allenlongbaobao, talisk

Create your first Ethereum decentralized application using Web3 and vue.js (Part 3)

Hello and welcome to the last part of this series. If you’re not already in the mood, we’re going to create a simple decentralized application for the Ethereum blockchain. You can always check out Parts 1 and 2!

  • Create your first Ethereum-centric application using Web3 and vue.js (Part 1)
  • Create your first Ethereum-centric application using Web3 and vue.js (Part 2)

And then we start at the end of part two

So far, our application has been able to retrieve and display account data from Metamask. However, when an account is changed, the data is not updated unless the page is reloaded. This is not optimal, and we want to ensure that data is updated in a responsive manner.

Our approach is slightly different from simply initializing web3 instances. Metamask doesn’t support WebSockets yet, so we’ll have to poll data every once in a while for changes. We do not want to schedule operations without changes, so our operations will only be scheduled with their respective payloads if a condition (specific change) is met.

Perhaps the above approach is not optimal among many solutions, but it works within the constraints of a strict schema, so it works fine. Create a new file called pollweb3.js in the util folder. Here’s what we’ll do:

  • Import Web3 so that we are not dependent on Metamask instances
  • Import into our store so we can compare and distribute data
  • Create a Web3 instance
  • Set an interval to check if the address has changed, and if not, to see if the balance has changed
  • If the address or balance changes, we will update our store. Because of ourhello-metamaskThe component has aComputedProperty, this change is reactive

import Web3 from 'web3'
import {store} from '.. /store/'

let pollWeb3 = function (state) {
  let web3 = window.web3
  web3 = new Web3(web3.currentProvider)

  setInterval(() => {
    if (web3 && store.state.web3.web3Instance) {
      if(web3.eth.coinbase ! == store.state.web3.coinbase) {let newCoinbase = web3.eth.coinbase
        web3.eth.getBalance(web3.eth.coinbase, function (err, newBalance) {
          if (err) {
            console.log(err)
          } else {
            store.dispatch('pollWeb3', {
              coinbase: newCoinbase,
              balance: parseInt(newBalance, 10)
            })
          }
        })
      } else {
        web3.eth.getBalance(store.state.web3.coinbase, (err, polledBalance) => {
          if (err) {
            console.log(err)
          } else if(parseInt(polledBalance, 10) ! == store.state.web3.balance) { store.dispatch('pollWeb3', {
              coinbase: store.state.web3.coinbase,
              balance: polledBalance
            })
          }
        })
      }
    }
  }, 500)
}

export default pollWeb3
Copy the code

Now, once our web3 instance is initialized, we’ll start polling for updates. So, open Store/index.js, import the pollweb3.js file, and add it to the bottom of our regierWeb3Instance() method to execute after the state changes.

import pollWeb3 from '.. /util/pollWeb3'

registerWeb3Instance (state, payload) {
 console.log('registerWeb3instance Mutation being executed', payload)
 let result = payload
 let web3Copy = state.web3
 web3Copy.coinbase = result.coinbase
 web3Copy.networkId = result.networkId
 web3Copy.balance = parseInt(result.balance, 10)
 web3Copy.isInjected = result.injectedWeb3
 web3Copy.web3Instance = result.web3
 state.web3 = web3Copy
 pollWeb3()
 }
Copy the code

Since we are scheduling the operation, we need to add it to the Store and mutate it to commit the changes. We could commit the changes directly, but for schema consistency, we don’t. We will add some console logs so that you can watch the wonderful process from the console. Add this to the Actions object:

pollWeb3 ({commit}, payload) {
 console.log('pollWeb3 action being executed')
 commit('pollWeb3Instance', payload)
 }
Copy the code

Now we just need to make changes to the two variables passed in

pollWeb3Instance (state, payload) {
 console.log('pollWeb3Instance mutation being executed', payload)
 state.web3.coinbase = payload.coinbase
 state.web3.balance = parseInt(payload.balance, 10)
 }
Copy the code

Done! If we now change the Metamask address, or the balance changes, we will see page updates without reloading in our application. When we change the network, the page will reload and we will re-register a new instance. However, in production, we want to display a warning to change to the correct network for the deployment contract.

I know it’s a long road. But in the next section, we’ll finally dive into our smart protocol connection to our application. This is actually quite easy compared to what we’ve already done.

Instantiate our protocol

First, we’ll write the code, then deploy the protocol and insert the ABI and Address into the application. To create our long-awaited Casino component, do the following:

  • An input field is required so that the user can enter the bet amount
  • You need a button that represents the bet number, and when the user clicks on a number, it will bet the entered amount on that number
  • The onClick function calls the bet() function on the SMART protocol
  • Displays a load spinner to show that a transaction is in progress
  • After the transaction is completed, we will display whether the user won and how much

But first, we need our applications to be able to interact with our intelligent protocols. We will approach this problem in the same way we have already done it. Create a new file called getContract.js in the util folder.

Import Web3 from 'Web3' import {address, ABI} from '. / constants/casinoContract 'let getContract = new Promise(function (resolve, reject) {
 let web3 = new Web3(window.web3.currentProvider)
 let casinoContract = web3.eth.contract(ABI)
 let casinoContractInstance = casinoContract.at(address)
 // casinoContractInstance = () => casinoContractInstance
 resolve(casinoContractInstance)
})

export default getContract
Copy the code

The first thing to note is that we are importing a file that does not yet exist, which we will fix later when we deploy the protocol.

First, we create a protocol object for the robustness protocol by passing the ABI(which we’ll return to) into the web3.eth.Contact() method. We can then initialize the object at an address. In this instance, we can call our methods and events.

However, this would be incomplete without actions and variations. So add the following to the casino-component.vue script tag.

exportThe default {name: "casino",mounted() {console.log(' Peer getContractInstance ') this.$storeDispatch (' getContractInstance ')}}Copy the code

Action and variants are now in the store. Start by importing the getContract.js file, which I’m sure you now know how to do. Then, during our creation, call it:

GetContractInstance ({commit}) {getContract.then(result => {commit (' registerContractInstance ', result) }).catch(e => console.log(e)) }Copy the code

Pass the results to our variant:

RegisterContractInstance (state, payload) {console.log(' Casino Contract instance: ', payload) state.contractInstance = () => payload}Copy the code

This will store our protocol instance in store for use in components.

Interact with our protocol

First, we will add a data attribute (in the export) to our Casino component so that we can have variables with reactive properties. These values will be winEvent, Amount, and Pending.

data () {
 return {
 amount: null,
 pending: false,
 winEvent: null
 }
 }
Copy the code

We’ll create an onclick function to listen for user clicks on a number. This triggers the bet() function on the protocol, which displays the spinner, and when it receives the event, hides the spinner and displays the event parameters. Under the Data property, add a property called Methods that accepts an object in which we will place our function.

methods: {
    clickNumber (event) {
      console.log(event.target.innerHTML, this.amount)
      this.winEvent = null
      this.pending = true
      this.$store.state.contractInstance().bet(event.target.innerHTML, {
        gas: 300000,
        value: this.$store.state.web3.web3Instance().toWei(this.amount, 'ether'),
        from: this.$store.state.web3.coinbase
      }, (err, result) => {
        if (err) {
          console.log(err)
          this.pending = false
        } else {
          let Won = this.$store.state.contractInstance().Won()
          Won.watch((err, result) => {
            if (err) {
              console.log('could not get event Won()')}else {
              this.winEvent = result.args
              this.pending = false}})}})}Copy the code

Bet () function of the first parameter is defined in the protocol of the parameter u Number. The Event. The Target. The innerHTML, next, reference we will create Numbers in the list of tags. Then there is an object that defines the transaction parameters, which is where we enter the amount of money the user has bet. The third argument is the callback function. When that’s done, we’ll listen for the event.

Now we will create the HTML and CSS for the component. Just copy and paste it, I think it’s pretty obvious. After that, we will deploy the protocol and get the ABI and Address.

<template> <div class= "casino" > < H1 >Welcome to the casino </ H1 > <h4>Please pick a number between 1 and 10</h4> Amount to bet: <input V-model = "amount" placeholder= "0 Ether" > <ul> <li V-on :click= "clickNumber" >1</li> <li V-on :click= "clickNumber" >2</li> <li V-on :click= "clickNumber" >3</li> <li V-on :click= "clickNumber" >4</li> <li V-on :click= "clickNumber" >5</li> <li V-on :click= "clickNumber" >6</li> <li V-on :click= "clickNumber" >7</li> <li V-on :click= "clickNumber" >8</li> <li V-on :click= "clickNumber" >9</li> <li V-on :click= "clickNumber" >10</li> </ul> <img V - if = "pending" id = "loader" SRC = "https://loading.io/spinners/double-ring/lg.double-ring-spinner.gif" > < div class = "event" V-if = "winEvent" > Won: {{winEvent._status}} Amount: {{ winEvent._amount }} Wei </div> </div> </template> <style scoped> .casino { margin-top: 50px; text-align:center; }#loader {
 width:150px;
}
ul {
 margin: 25px;
 list-style-type: none;
 display: grid;
 grid-template-columns: repeat(5, 1fr);
 grid-column-gap:25px;
 grid-row-gap:25px;
}
li{
 padding: 20px;
 margin-right: 5px;
 border-radius: 50%;
 cursor: pointer;
 background-color:#fff;
 border: -2px solid #bf0d9b;
 color: #bf0d9b;
 box-shadow:3px 5px #bf0d9b;
}
li:hover{
 background-color:#bf0d9b;
 color:white;
 box-shadow:0px 0px #bf0d9b;} li: active {opacity: 0.7; } *{ color:# 444444;
}
</style>
Copy the code

Ropsten Network and Metamask (for first time users)

Don’t worry if you are unfamiliar with Metamask or Ethereum networks.

  1. Open the browser and the Metamask plug-in. Accept the terms of use and create a password.
  2. Store seed phrases in a safe place (this is to restore your wallet if you lose it).
  3. Click on “Ethereum Main Network” and switch to Ropsten test network.
  4. Click Buy, and then click Ropsten Testnet Fucet. Here we can get some free testing – Ethereum.
  5. On the Faucet website, click “Request 1 ether from Faucet” several times.

When everything is familiar and done, your Metamask should look like this:

Deployment and Connection

Open remix, and our agreement should still be there. If not, go to this bullet point and copy and paste. To the right of roP in ReMix, make sure our environment is set to “InsistedWeb 3(Ropsten)” and our address is selected.

The deployment is the same as in Part 1. We preload the protocol by entering a few parameters in the Value field, enter the constructor parameters, and click Create. This time, Metamask will prompt you to accept/reject the transaction (convention deployment). Click Accept and wait for the transaction to complete.

When TX is complete click on it and this will take you to the TX atrophy block chain browser. We can find the protocol address under the “to” field. Your agreements are different, but they look similar.

Our protocol address is in the “to” field.

So that gives us the address, and now ABI. Go back to Remix and switch to the Compile TAB (top right). Next to the protocol name, we’ll see a button called Details. Click on it. The fourth area is our ABI.

Good, now we just need to create a file that didn’t exist in the previous section. So create a new file called casinocontract.js in the util/constents folder. Create two variables, paste the necessary content, and export the variables so that they can be accessed by the content we import from above.

Const address = '0 x..................... . 'const ABI = [...]export {address, ABI}
Copy the code

Well done!

Now we can test our application by running NPM start on the terminal and localhost: 8080 in the browser. Enter the amount and click a number. Metamask will prompt you to accept the transaction and the spinner will start. After 30 seconds to a minute, we got the first confirmation, and therefore the confirmation of the event. Our balance has changed, so PollWeb 3 triggers its action to update the balance:

End result (left) and life cycle (right).

If you can make it this far in this series, I applaud you. I’m not a professional writer, so it’s not easy to read sometimes. Our application is already set up on the backbone, we just need to make it nice and friendly. We will do this in the next section, although this is optional.

Focus on what needs it

We’ll be done in a minute. It will just be some HTML, CSS, and VUE conditional statements with V-if/V-else.

** In app. vue **, add the container class to our div element and define the class in CSS:

.container { padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } @media (min-width: 768px) { .container { width: 750px; }}Copy the code

** In main.js, ** imports the library of font-awesome we already have installed (I know, this is not the best way to get the two ICONS we need) :

Import 'the font - awesome/CSS font - awesome. CSS'Copy the code

In hello-metanask.vue, we’ll make some changes. We will use the mapState helper in our Computed property instead of the current function. We will also use V-if to check isInjected and display different HTML on this basis. The final component looks like this:

<template>
  <div class='metamask-info'>
    <p v-if="isInjected" id="has-metamask"><i aria-hidden="true" class="fa fa-check"></i> Metamask installed</p>
    <p v-else id="no-metamask"><i aria-hidden="true" class="fa fa-times"></i> Metamask not found</p>
    <p>Network: {{ network }}</p>
    <p>Account: {{ coinbase }}</p>
    <p>Balance: {{ balance }} Wei </p>
  </div>
</template>

<script>
import {NETWORKS} from '.. /util/constants/networks'
import {mapState} from 'vuex'
export default {
  name: 'hello-metamask',
  computed: mapState({
    isInjected: state => state.web3.isInjected,
    network: state => NETWORKS[state.web3.networkId],
    coinbase: state => state.web3.coinbase,
    balance: state => state.web3.balance
  })
}
</script>

<style scoped>
#has-metamask {
  color: green;
}
#no-metamask {
  color:red;
}</style>
Copy the code

We’ll execute the same V-if/V-else methods to design our event, which will return -component.vue inside the casino:

<div class= "event" V-if = "winEvent" >< p v-if= "winEvent._status" id= "has-won" >< I aria-hidden="true"Class =" fa fa - check "> < / I > Congragulations, You have won {{winevent. _amount}} WEI </p> <p v-else id= "has-lost" >< I aria-hidden="true"Class =" fa fa-check "></ I > Sorry you lost, please try again.</p> </div>#has-won {
  color: green;
}
#has-lost {
  color:red;
}
Copy the code

Finally, in our clickNumber() function, add a line under this.winEvent= result.args: :

this.winEvent._amount = parseInt(result.args._amount, 10)
Copy the code

Congratulations, you’ve done it!

First of all, the project of complete code available under the main branch: https://github.com/kyriediculous/dapp-tutorial/tree/master!

The final application after losing the bet:

There are still some warnings in our application. We didn’t handle errors correctly anywhere, we didn’t need all the console logging statements, it wasn’t a very perfect application (I’m not a designer), and so on. However, the app does a good job.

Hopefully, this tutorial series will help you build more and better decentralized applications. I sincerely hope you enjoyed reading this article as much as I did.

I’m not a software engineer with 20 + years of experience. So if you have any suggestions or improvements, please feel free to comment. I like to learn new things and improve myself within my ability. thank you

Update: Added ethereum balance display

Feel free to follow us on Twitter, visit our website, and leave a comment if you enjoyed this tutorial!

  • Alt Street(@Alt_strt)Twitter: The latest from Alt Street (@alt_strt). Blockchain is love, blockchain is life. We develop proof of concept and… twitter.com

  • Alt Street- Blockchain consulting firmBlockchain proof of concept and token sales… AltStreet.io

TIPJAR: x6d31cb338b5590adafec46462a1b095ebdc37d50 ETH – 0


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.