기술나눔

6-5, web3 브라우저가 블록체인에 연결됨 (리액트 블록체인 실습)

2024-07-12

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

6-5 web3 브라우저가 블록체인에 연결됩니다(읽기-쓰기 계약을 호출하여 메타마스크와 연결).

브라우저와 스마트 계약 간의 상호 작용은 다음과 같습니다.

두 개의 도서관

웹3
트러플 계약 //truffle은 단순히 프런트엔드 계약을 링크에 래핑하므로 사용하기가 더 쉽습니다.

오다반응 프로젝트루트 디렉터리(1장에서 생성)
여기에 이미지 설명을 삽입하세요.

여기에서 반응 프로젝트를 다시 생성하세요.
https://blog.csdn.net/u012118993/article/details/87288516
반응새 프로젝트 만들기create-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

트러플 디렉토리에 생성됨
여기에 이미지 설명을 삽입하세요.

반응 프로젝트 아래에 다음 파일을 설치하십시오.
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가 현재 빈 웹페이지였기 때문에 브라우저 콘솔에서 정의되지 않았습니다.

React 프로젝트로 만든 애완동물 가게에서 시작해보세요

Npm start
  • 1

브라우저에서 열려
http://로컬호스트:3000/

비디오 효과
여기에 이미지 설명을 삽입하세요.

새 패키지 설치 영상
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

초기화 함수가 저장되지 않아서 오류가 발생했습니다.

여기에 이미지 설명을 삽입하세요.

성공 후 실제 효과는 다음과 같습니다.
여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.

새로 합류한

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 start를 다시 시작하세요.

지금 새로고침하세요
물론 이때는 팝업창이 뜨지 않습니다. 메타마스크 지갑 삭제 후 팝업창이 뜨게 됩니다.

이때 지갑 없이 크롬 브라우저를 이용하여 접속하시기 바랍니다.
여기에 이미지 설명을 삽입하세요.

팝업 창이 나타나지만 일부 문자가 깨져 표시됩니다.

코드를 다시 추가하세요

여기에 이미지 설명을 삽입하세요.

모든 코드는 다음과 같습니다

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
계정 정보 얻기

코드 수정 후 초기화 함수 부분을 수정합니다.

메타마스크를 사용하여 해당 웹사이트에 연결하고 현재 메타마스크 주소를 출력할 수 있습니다.
여기에 이미지 설명을 삽입하세요.

다음으로 클릭 이벤트의 코드를 변경합니다.
여기에 이미지 설명을 삽입하세요.

여기에서 입양을 클릭하면 결제 상자가 나타납니다. 쓰기 기능을 호출하여 체인에 써야 하기 때문입니다. 여기서 입양을 위해 돈을 이체할 필요는 없지만 부모 처리 수수료가 필요합니다.

블록체인에 로컬로 작성해야 하는 함수를 성공적으로 호출합니다. (버튼을 클릭하면 다음과 같습니다)
여기에 이미지 설명을 삽입하세요.

최종적으로 성공적으로 실행된 모든 코드는 다음과 같습니다.

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를 아름답게 만드는 것입니다.