技術共有

6-5、Web3 ブラウザーがブロックチェーンにリンク (React ブロックチェーンの実践)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

6-5 Web3ブラウザがブロックチェーンにリンク(メタマスクとリンクするための読み書きコントラクトを呼び出す)

これはブラウザとスマートコントラクト間のやり取りです

2つの図書館

ウェブ3
Truffle コントラクト //truffle はフロントエンド コントラクトをリンク内にラップするだけなので、使いやすくなります。

来る反応プロジェクトルート ディレクトリ (第 1 章で作成)、
ここに画像の説明を挿入します

ここで反応プロジェクトを再作成します
https://blog.csdn.net/u012118993/article/details/87288516
反応新しいプロジェクトを作成するcreat-react-app を使用して反応プロジェクトをすばやく作成します

(1)npm install -g create-react-app グローバルインストール(全体にインストール)

(2)create-react-app reactproject 新しい反応プロジェクトを作成し、名前を付けます (注: プロジェクト名には大文字を使用できません)

(3)cd reactproject コマンドでフォルダーに入り、プロジェクトを実行する準備をします。

(4)npm start プロジェクトを実行する

E:trufflewoniu-pet-shop
  • 1

truffle ディレクトリに作成される
ここに画像の説明を挿入します

以下のファイルを反応プロジェクトの下にインストールします
web3のインストール(以下のフォルダにインストール)

npm install web3 --save
  • 1

ここに画像の説明を挿入します

次に、truffle-contractをインストールします

npm install truffle-contract --save
  • 1

デモが完了しました

1.リンク契約
2. コントラクトの内部機能を実行する
3. ant.design ui ライブラリのサポートを追加
4. プロジェクトを完了する

ここに画像の説明を挿入します

新しいことに注意してください
ここに画像の説明を挿入します

App.jsの内容
次のように

import React from 'react'
import Web3 from 'web3'
import TruffleContract from 'truffle-contract'
import AdoptionJson from './truffle/build/contracts/Adoption.json'	//引入前面智能合约编译好得到的json文件





class App extends React.Component{
	constructor(props){
		super(props)
		this.web3 = null
		this.Adoption = null
		this.init()

		this.state = {
			//name:'woniu'
		}
	}

	init(){
		//如果网页中的web3不是undefined
		if(typeof window.web3 != 'undefined'){
		}
	}

	render(){
		return <button></button>//hello,{this.state.name}
	}
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

ここに画像の説明を挿入します

ブラウザにメタマスクプラグインがインストールされている場合

グローバル変数はブラウザ内の値を持ちます
ここに画像の説明を挿入します

メタマスクは手動または自動でリンク可能
ここに画像の説明を挿入します

スクリプトを開始します。この時点では web3 は空の Web ページだったので、ブラウザー コンソールで定義されていませんでした。

React プロジェクトによって構築されたペットショップから始めましょう

Npm start
  • 1

ブラウザで開く
http://localhost:3000/

ビデオエフェクト
ここに画像の説明を挿入します

新しいパッケージをインストールするビデオ
ここに画像の説明を挿入します
ここに画像の説明を挿入します

init関数が保存されていないためエラーが発生しました。

ここに画像の説明を挿入します

成功後の実際の効果は次のとおりです。
ここに画像の説明を挿入します

ここに画像の説明を挿入します

新しく加わった

init(){
		//如果网页中的web3不是undefined
		if(typeof window.web3 != 'undefined'){
			this.web3Provider = window.web3.currentProvider;	//metamask内置了web3的实例,实际可以手动链接
		}else{
			alert('请按照metamask')
		}
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

変更したコードを保存した後、閉じずにネットワークに再度アクセスし、npm を再起動します

今すぐ更新してください
もちろん、この時点ではポップアップ ウィンドウは表示されません。メタマスク ウォレットを削除すると、ポップアップ ウィンドウが表示されます。

現時点では、ウォレットを使用せずにChromeブラウザを使用してアクセスしてください
ここに画像の説明を挿入します

ポップアップウィンドウが表示されるが、一部文字化けが発生する

再度コードを追加します

ここに画像の説明を挿入します

すべてのコードは次のとおりです

import React from 'react'
import Web3 from 'web3'
import TruffleContract from 'truffle-contract'
import AdoptionJson from './truffle/build/contracts/Adoption.json'	//引入前面智能合约编译好得到的json文件

//1.链接合约
//2.执行一下合约内部函数
//3.添加ant.design ui库支持
//4.完成项目
class App extends React.Component{
	constructor(props){
		super(props)
		this.web3 = null
		this.Adoption = null
		this.init()

		this.state = {
			//name:'woniu'
		}
	}

	init(){
		//如果网页中的web3不是undefined
		if(typeof window.web3 != 'undefined'){
			this.web3Provider = window.web3.currentProvider;	//metamask内置了web3的实例,实际可以手动链接
		}else{
			alert('please install metamask')
		}
		
		this.web3 = new Web3(this.web3Provider)		//将我们的this.web3Provider装载进来
		this.initAdoption()

	}

	initAdoption(){
		this.Adoption = TruffleContract(AdoptionJson)	//使用TruffleContract传入编译后的合约,然后创建实例,可以调用合约内部函数
		this.Adoption.setProvider(this.web3Provider)	//设置来源,链接合约
		return this.markAdopted()
	}
	
	//部署,这个是异步的,使用this.Adoption.deployed().then()也可以,这里用
	//this.markAdopted(){
		//部署链接一下
	//	const adoptionInstance = this.Adoption.deployed().then()	

	//}

	async markAdopted(){
		//部署链接一下
		//await同步方式获取异步数据
		const adoptionInstance = await this.Adoption.deployed()	//部署,这个是异步的,使用this.Adoption.deployed().then()也可以,这里用
		//调用合约内部函数getAdopters
		const adopters = await adoptionInstance.getAdopters.call()
		console.log(adopters)
	}

	render(){
		return <button></button>//hello,{this.state.name}
	}
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

次のようにインターフェースを更新します
ここに画像の説明を挿入します

契約書のアドレスを取得しました
ここに画像の説明を挿入します

上記の変数を使用して、ローカル アドレスとメタマスクのデフォルトのアカウント アドレスを取得します。
ここに画像の説明を挿入します

https://blog.csdn.net/weixin_41937552/article/details/106990561?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-1&spm=1001.2101.3001.4242

ここでメタマスクのアドレスが取得できない理由は上記の通りです
https://blog.csdn.net/weixin_39421014/article/details/103323245

最初にメタマスクのプライバシー許可をオフにすることができます。
https://www.freesion.com/article/8518937500/
プライバシーモードの設定と対応JSコード
ここに画像の説明を挿入します

https://blog.csdn.net/JackieDYH/article/details/115380677?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242
アカウント情報を取得する

コードを修正したら、初期化関数部分を修正します。

メタマスクを使用して Web サイトにリンクし、現在のメタマスク アドレスを印刷できます。
ここに画像の説明を挿入します

次に、クリック イベントのコードを変更します。
ここに画像の説明を挿入します

ここで養子縁組をクリックすると、書き込み関数を呼び出してチェーンに書き込む必要があるため、支払い用のボックスが表示されます。養子縁組のために送金する必要はありませんが、親の手数料が必要です。

ブロックチェーンに書き込む必要がある関数をローカルで正常に呼び出します (ボタンをクリックすると次のようになります)。
ここに画像の説明を挿入します

最終的に正常に実行されたすべてのコードは次のとおりです。

import React from 'react'
import Web3 from 'web3'
import TruffleContract from 'truffle-contract'
import AdoptionJson from './truffle/build/contracts/Adoption.json'	//引入前面智能合约编译好得到的json文件

//1.链接合约
//2.执行一下合约内部函数
//3.添加ant.design ui库支持
//4.完成项目
class App extends React.Component{
	constructor(props){
		super(props)
		this.web3 = null
		this.Adoption = null
		this.init()

		this.state = {
			//name:'woniu'
		}
	}

	async init(){
		//如果网页中的web3不是undefined
		//if(typeof window.web3 != 'undefined'){
		//	this.web3Provider = window.web3.currentProvider;	//metamask内置了web3的实例,实际可以手动链接
		//}else{
		//	alert('please install metamask')
		//}
		
		//this.web3 = new Web3(this.web3Provider)		//将我们的this.web3Provider装载进来
		//this.initAdoption()
		
		/* 新版的方式 */
	  //var web3Provider;
	  if (window.ethereum) {
		this.web3Provider = window.ethereum;
		try {
		  // 请求用户授权
		  await window.ethereum.enable();
		} catch (error) {
		  // 用户不授权时
		  console.error("User denied account access")
		}
	  } else if (window.web3) {   // 老版 MetaMask Legacy dapp browsers...
		this.web3Provider = window.web3.currentProvider;
	  } else {
		this.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
	  }
	  this.web3 = new Web3(this.web3Provider);//web3js就是你需要的web3实例
	  

	  this.web3.eth.getAccounts(function (error, result) {
		if (!error)
		  console.log(result)//授权成功后result能正常获取到账号了
		  //this.account = result
	  });
	  //this.account =result
	  //this.account =account
	  this.initAdoption()
	}

	initAdoption(){
		this.Adoption = TruffleContract(AdoptionJson)	//使用TruffleContract传入编译后的合约,然后创建实例,可以调用合约内部函数
		this.Adoption.setProvider(this.web3Provider)	//设置来源,链接合约
		return this.markAdopted()
	}
	
	//部署,这个是异步的,使用this.Adoption.deployed().then()也可以,这里用
	//this.markAdopted(){
		//部署链接一下
	//	const adoptionInstance = this.Adoption.deployed().then()	

	//}

	async markAdopted(){
		//部署链接一下
		//await同步方式获取异步数据
		const adoptionInstance = await this.Adoption.deployed()	//部署,这个是异步的,使用this.Adoption.deployed().then()也可以,这里用
		//调用合约内部函数getAdopters
		const adopters = await adoptionInstance.getAdopters.call()
		console.log(adopters)
	}
	
	async adopt(petId){
		//const account = window.web3.eth.defaultAccount		//获取metamask中默认的账户
		// 授权获取账户
	    const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
        const myAccount = accounts[0];	//获取当前metamask的地址

		const adoptionInstance = await this.Adoption.deployed()		//再次进行部署
		await adoptionInstance.adopt(petId,{from:myAccount})	//调用adopt只传递唯一一个参数,以及来源之前获取的地址,进行写入函数
		this.markAdopted()
	}

	render(){
		//onclick点击事件,调用领养函数
		return <button onClick={()=>this.adopt(2)}>领养第二个</button>//hello,{this.state.name}
	}
}

export default App
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

読み取りおよび書き込み機能を含むすべての機能が正常に実行されました。

このコードにはまだいくつかの欠陥があり、トランザクションが失敗するとエラーが報告され、ページでもエラーが報告されます。
拒否または直接終了をクリックした場合
ここに画像の説明を挿入します

ここに画像の説明を挿入します

次のステップは UI を美しくすることです