introduction
Dans cet article, je vais essayer de passer en revue tous les points de création d'une application décentralisée à part entière sur le réseau Ethereum aussi brièvement et informativement que possible en utilisant le framework JavaScript - Vue pour créer une application Web et la bibliothèque ethers.js pour communiquer avec un contrat intelligent. Nous examinerons également quelques points sur la façon d'installer et de connecter un portefeuille, comment déployer un contrat sur le réseau à l'aide de truffe , etc.
Certains points peuvent sembler très évidents et pas difficiles, vous pouvez donc les ignorer.
Ce que vous devez savoir avant de commencer:
Bonne connaissance de js, en particulier Vue.js
Comprendre les principes de la Blockchain (contrats intelligents)
Connaissance de base de la langue pr. Solidité
Installer un portefeuille
Nous utiliserons le portefeuille Metamask pour confirmer les transactions, communiquer avec le contrat et vérifier certains paramètres de ces transactions . Il est plutôt bon et je n'ai presque jamais eu de problèmes avec son travail. Je ne montrerai pas le processus d'installation, tout y est évident.
Lorsque l'extension est installée, il vous sera demandé de créer un portefeuille ou d'importer si disponible. Après avoir créé un compte, une phrase mnémotechnique sera générée pour vous. NE JAMAIS le divulguer à quiconque. Et voila - nous avons une adresse de portefeuille prête à l'emploi)
- , . Ropsten.
-. . README ( ). - -. - , . , . IDE Remix.
Truffle.js. node.js. npm ( ): npm install -g truffle
npm install -g @truffle/hdwallet-provider
, Truffle truffle init.
truffle-config.js. . Infura Ethereum -> Create New Project (UI) dApps - Ethereum. Infura , Ethereum , . -> Settings -> Endpoints Ropsten .
, , truffle-config.js. -, .secret . dotenv, , truffle. -, :
const HDWalletProvider = require('@truffle/hdwallet-provider');
const fs = require('fs');
const mnemonic = fs.readFileSync(".secret").toString().trim();
ropsten: {
provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
network_id: 3, // Ropsten's id
gas: 5500000, // Ropsten has a lower block limit than mainnet
confirmations: 2, // # of confs to wait between deployments. (default: 0)
timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
},
HDWalletProvider
.
-, .sol contracts, . migrations js :
const SimpleMarketplace = artifacts.require("SimpleMarketplace");
module.exports = function (deployer) {
deployer.deploy(SimpleMarketplace, 'description', 1000);
};
, migrations 1_initial_migrations.js, 2.
- deploy : description price . , , SimpleMarketplace.
truffle compile
. : , @truffle/hdwallet-provider,(Error: Cannot find module '@truffle/hdwallet-provider')
, npm install @truffle/hdwallet-provider
. -g
. Compiled successfully using...
.
truffle migrate --network ropsten --reset
. ropsten
- , truffle-config.js, --reset , ( ).: : var e = new Error('ETIMEDOUT')
, truffle-config.js HDWalletProvider
, Infura - wss://ropsten.infura.io/ws/v3/YOUR-PROJECT-ID.
Etherscan , - , blockchain .
Vue.js
. assets ( Vue.js, ), HelloWorld.vue components App.vue ( HelloWorld.vue, components <div id="app">
).
<template>
<div id="app">
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
npm run serve
, , , .
- UI -. components , , Marketplace.vue. core core.js , , ./build/contracts JSON - ( ). - - , . , . . - npm install ethers
.
core.js , JSON - :
const { ethers } = require('ethers')
const ContractArtifact = require('./SimpleMarketplace.json')
const CONTRACT_ADDRESS = ContractArtifact.networks['3'].address
ABI, , ( . public , public view returns ethers ):
const ABI = [
'function InstanceOwner () public view returns(address)',
'function Description () public view returns(string)',
'function AskingPrice () public view returns(int)',
'function InstanceBuyer () public view returns(address)',
'function OfferPrice () public view returns(int)',
'function MakeOffer(int offerPrice) public',
'function Reject() public',
'function AcceptOffer() public'
]
:
let provider = new ethers.providers.Web3Provider(window.ethereum)
// Blockcain
let readOnlyContract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider)
// view
let signer = provider.getSigner()
//
let contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer)
let contractSigner = contract.connect(signer)
//
Vue :
export default {
async getDescription() {
const description = await readOnlyContract.Description()
return {description: description}
}
}
, . - :
const { ethers } = require('ethers')
const ContractArtifact = require('./SimpleMarketplace.json')
const CONTRACT_ADDRESS = ContractArtifact.networks['3'].address
const ABI = [
'function InstanceOwner () public view returns(address)',
'function Description () public view returns(string)',
'function AskingPrice () public view returns(int)',
'function InstanceBuyer () public view returns(address)',
'function OfferPrice () public view returns(int)',
'function MakeOffer(int offerPrice) public',
'function Reject() public',
'function AcceptOffer() public'
]
let provider = new ethers.providers.Web3Provider(window.ethereum)
let readOnlyContract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider)
let signer = provider.getSigner()
let contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer)
let contractSigner = contract.connect(signer)
export default {
async getInstanceOwner() {
const instanceOwner = await readOnlyContract.InstanceOwner()
return {instanceOwner: instanceOwner}
},
async getDescription() {
const description = await readOnlyContract.Description()
return {description: description}
},
async getAskingPrice() {
const askingPrice = await readOnlyContract.AskingPrice()
return {askingPrice: askingPrice}
},
async getInstanceBuyer() {
const instanceBuyer = await readOnlyContract.InstanceBuyer()
return {instanceBuyer: instanceBuyer}
},
async getOfferPrice() {
const offerPrice = await readOnlyContract.OfferPrice()
return {offerPrice: offerPrice}
},
async makeOffer(offerPrice) {
const txResponse = await contractSigner.MakeOffer(offerPrice, {gasLimit: 300000})
const txReceipt = await txResponse.wait()
return {transaction: txReceipt.transactionHash}
},
async reject() {
const txResponse = await contractSigner.Reject({gasLimit: 300000})
const txReceipt = await txResponse.wait()
return {transaction: txReceipt.transactionHash}
},
async acceptOffer() {
const txResponse = await contractSigner.AcceptOffer({gasLimit: 300000})
const txReceipt = await txResponse.wait()
return {transaction: txReceipt.transactionHash}
}
}
App.vue mounted $root core.js:
const core = require('./core/core')
/*
-
*/
mounted() {
window.ethereum.request({ method: 'eth_requestAccounts' })
this.$root.core = core.default
}
, data details methods :
data() {
return {
instanceOwner: '',
description: '',
askingPrice: '',
instanceBuyer: '',
offerPrice: ''
}
},
methods: {
async details() {
this.instanceOwner = (await this.$root.core.getInstanceOwner()).instanceOwner
this.description = (await this.$root.core.getDescription()).description
this.askingPrice = (await this.$root.core.getAskingPrice()).askingPrice
this.instanceBuyer = (await this.$root.core.getInstanceBuyer()).instanceBuyer
this.offerPrice = (await this.$root.core.getOfferPrice()).offerPrice
}
},
:
<button v-on:click="details">Get details</button>
<h3>Instance owner: {{ instanceOwner }}</h3>
<h3>Description: {{ description }}</h3>
<h3>Asking price: {{ askingPrice }}</h3>
<h3>Instance buyer: {{ instanceBuyer }}</h3>
<h3>Offer price: {{ offerPrice }}</h3>
Vous pouvez vérifier le code du composant Marketplace.vue dans mon référentiel afin de ne pas encombrer l'article avec du code inutile.
Après avoir démarré le projet, vous devriez voir une fenêtre de connexion de portefeuille comme celle-ci:
Et après cela, lorsque nous cliquons sur le bouton Obtenir les détails , nous recevrons les données que nous avons saisies lors du déploiement du contrat.
Et voici à quoi ressemble la sortie si vous effectuez une transaction:
Conclusion
Ceci est mon premier article. Je serais heureux d'avoir des questions et même des critiques, car je ne suis pas moi-même encore un pro dans tout cela.
Lien vers le contrat où vous pouvez vérifier les transactions.