Einführung
In diesem Artikel werde ich versuchen, alle Punkte der Erstellung einer vollwertigen dezentralen Anwendung im Ethereum-Netzwerk so kurz und informativ wie möglich mithilfe des JavaScript-Frameworks - Vue zum Erstellen einer Webanwendung und der Bibliothek ethers.js für die Kommunikation - durchzugehen mit einem klugen Vertrag. Wir werden auch einige Punkte zum Installieren und Anschließen einer Brieftasche, zum Bereitstellen eines Vertrags im Netzwerk mithilfe von Trüffeln usw. berücksichtigen .
Einige Punkte scheinen sehr offensichtlich und nicht schwierig zu sein, sodass Sie sie überspringen können.
Was Sie wissen müssen, bevor Sie beginnen:
Gute Kenntnisse von js, insbesondere von Vue.js
Verständnis der Prinzipien von Blockchain (Smart Contracts)
Grundkenntnisse der Sprache pr. Solidität
Brieftasche installieren
Wir werden die Metamask- Brieftasche verwenden, um Transaktionen zu bestätigen, mit dem Vertrag zu kommunizieren und einige Parameter dieser Transaktionen zu überprüfen . Er ist ziemlich gut und ich hatte fast nie Probleme mit seiner Arbeit. Ich werde den Installationsprozess nicht zeigen, dort ist alles offensichtlich.
Wenn die Erweiterung installiert ist, werden Sie aufgefordert, eine Brieftasche zu erstellen oder zu importieren, falls verfügbar. Nach dem Erstellen eines Kontos wird eine mnemonische Phrase für Sie generiert. Geben Sie es NIEMALS an Dritte weiter. Und voila - wir haben eine fertige Brieftaschenadresse)
- , . 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>
Sie können den Code der Marketplace.vue- Komponente in meinem Repository überprüfen , um den Artikel nicht mit unnötigem Code zu überladen.
Nach dem Starten des Projekts sollte ein Brieftaschenverbindungsfenster wie das folgende angezeigt werden:
Wenn wir danach auf die Schaltfläche Details abrufen klicken, erhalten wir die Daten, die wir bei der Bereitstellung des Vertrags eingegeben haben.
Und so sieht die Ausgabe aus, wenn Sie eine Transaktion durchführen:
Fazit
Dies ist mein erster Artikel. Ich würde mich über einige Fragen und sogar Kritik freuen, da ich selbst noch kein Profi bin.
Link zum Vertrag, in dem Sie die Transaktionen überprüfen können.