[0x01] Web3 App w/ Solidity, Ether Smart Contract
[0x00] 스마트 컨트랙트 작성과 로컬 이더리움 네트워크에 배포하기
0x00: 환경 셋업
<로컬 이더리움 네트워크>
- 일단 시작하기에 앞서
로컬 이더리움 네트워크
를 세팅한다.
- 이를 통해, 앞으로 만들
스마트 컨트랙트 코드
에 대해 컴파일
, 테스트
등을 해볼 수 있다.
스마트 컨트랙트
란 블록체인 상에 있는 코드 조각
으로 기억하면 된다.
블록체인
이란 누구나 안전하게 정보를 읽고 쓸 수 있는 공간이다.
- AWS 같은 네트워크지만, 누구의 소유도 아닌 네트워크라 생각하면 된다.
- 본 튜토리얼의 전체적인 로드맵은 아래와 같다.
스마트 컨트랙트
를 작성한다.
- 서버의 코드와 같이 생각하면 된다.
- 작성한
스마트 컨트랙트
를 블록체인 상에 배포(deploy)
한다.
- 전 세계 누구든 우리로부터 허용되었다면
스마트 컨트랙트
에 접근
하고 실행
시킬 수 있다.
클라이언트 웹사이트
를 만든다.
- 일반 유저들이 우리의
스마트 컨트랙트
와 쉽게 상호작용 할 수 있도록 한다.
- 이 튜토리얼에서 궁극적으로 만들고자 하는 것은 본인에게 누군가
안녕
이라고 인사해주는 웹사이트를 만드는 것이다!
0x01: Hardhat
hardhat
이라는 툴
을 통해, 로컬 이더리움 네트워크
환경을 만들 수 있으며 fake 이더리움
, fake 계정
등을 이용해 테스트도 진행할 수 있다.
- 튜토리얼 내내 이용하는
서버
가 블록체인
임을 기억하도록 하자.
- 또한,
hardhat
을 통해 스마트 컨트랙트
를 컴파일
하는 것이 가능하다. 로컬 이더리움 네트워크
에서 이를 테스트
할 수도 있다.
hardhat
을 이용하기 위해서는 node/npm
이 필요하다.
- 설치에 관한 내용은 따로 다루도록 한다.
- 메모를 해두자면, Node.js 를 그냥 받으면 LTS가 아니라서 경고 메세지가 뜨기도 한다... 이를 해결하는 방법을 찾느라 나름 시간을 날렸으므로, 꼭 정리해둘 예정이다.
- 본 튜토리얼에서는
my-wave-portal
이라는 작업 디렉토리를 따로 만들어 진행하도록 한다.
npm
의 설치가 완료되었으면 아래 코드를 입력해 튜토리얼을 진행한다.
mkdir my-wave-portal
cd my-wave-portal
npm init -y
npm install --save-dev hardhat
0x02: 샘플 프로젝트
hardhat
을 설치 완료한 후 샘플 프로젝트를 받는 작업을 진행한다.
- 아래와 같이 입력한다.
npx hardhat
- 첫 번째 선택지인
Create a basic sample project
를 선택하면 몇 가지를 더 묻는데 모두 Enter
키로 넘기면 아래와 같이 설치되는 과정이 나온다.
- 잠시 후
Project created
라는 문구와 함께 샘플 프로젝트가 완성된 것을 확인할 수 있다.
- 이후
hardhat-waffle
과 hardhat-ethers
를 추가로 설치해야 한다. 아래의 명령을 입력하면 된다.
npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers
- 설치가 완료되었으면, 아래의 명령어를 실행한 뒤 결과를 확인할 수 있다.
npx hardhat accounts
- 위 사진의 결과는
hardhat
이 생성한 이더리움 주소
이다.
- 블록체인 상에서의 유저들로 생각하고
테스트
에 활용할 수 있다.
- 예시)
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (첫 번째 주소)
가 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (두 번째 주소)
에게 0.1 ETH
를 보낸다.
0x03: 실행하기
- 실행하기 위해서는 아래 명령들을 실행하면 된다.
npx hardhat compile
npx hardhat run
- 이후 튜토리얼 단계에서는 코드를 완전히 새로 작성할 예정이다.
- 따라서,
scripts
, contract
, test
디렉토리에 있는 모든 파일들을 지우도록 한다.
0x04: 스마트 컨트랙트 작성
- 사이트 상에 나한테 인사해주는 기능과 인사를 받은 횟수를 저장해두는 것을 구현할 예정이다.
contract
디렉토리에 WavePortal.sol
이라는 이름으로 솔리디티 파일을 하나 만든다.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import "hardhat/console.sol";
contract WavePortal {
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
}
- 코드를 하나 하나 살펴보면 다음과 같다.
// SPDX-License-Identifier: UNLICENSED
- 라이센스 (저작권) 에 관한 내용이다.
- Ref. https://devocean.sk.com/opensource/techBoardDetail.do?ID=159339
pragma solidity ^0.8.4;
- 우리의
스마트 컨트랙트
가 이용할 컴파일러
의 버전
을 명시한다.
- 중요 :
hardhat.config.js
에 명시된 것과 동일한 버전
을 사용해야 한다.
import "hardhat/console.sol";
console log
에 관한 코드를 import
한다.
hardhat
에서는 스마트 컨트랙트
를 쉽게 디버깅
할 수 있도록 console log
를 사용할 수 있는 코드를 제공한다.
contract WavePortal {
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
}
스마트 컨트랙트
의 구현에 대한 내용이다.
스마트 컨트랙트(=컨트랙트)
는 다른 언어에서의 클래스
와 상당히 비슷하게 보인다.
- 이
컨트랙트
를 초기화 하면, constructor(생성자)
가 호출되며 console
을 통해 문장을 출력할 것이다.
0x05: 로컬 테스트 블록체인 환경 만들기
스마트 컨트랙트
를 작성하였으므로, 아래 세 단계를 거쳐 이를 실행해 볼 수 있다.
컨트랙트
를 컴파일
한다.
로컬 블록체인 네트워크
에 컴파일 된 컨트랙트
를 배포(deploy)
한다.
블록체인 네트워크
상의 컨트랙트
를 호출하면 console.log()
가 실행된다.
- 실제
블록체인
에서도 컨트랙트
는 네트워크
상에 존재하며, 이를 누군가 호출하는 방식으로 동작한다.
- 기술적으로, 단순히
컨트랙트
를 컴파일
하고 실행하는 것은 가능하다.
- 하지만,
Solidity
가 블록체인 네트워크
, 그리고 이더리움 지갑(wallet)
과 어떻게 상호작용 할 수 있는지를 이해하는 것이 중요하다.
- 따라서,최대한 실제 환경을 모방(imitate)하여 상기한 세 단계를 실습해보도록 한다.
0x06: 컨트랙트 실행 스크립트(run.js) 작성
scripts
디렉토리에 run.js
라는 자바스크립트
파일을 만든다.
컨트랙트
를 실행하기 위해서는 컴파일
, 배포
, 실행
세 가지를 해야 한다.
- 스크립트 작성을 통해 상기한 세 가지를 손쉽게 수행할 수 있다.
const main = async () => {
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("Contract deployed to:", waveContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0); // exit Node process without error
} catch (error) {
console.log(error);
process.exit(1); // exit Node process while indicating 'Uncaught Fatal Exception' error
}
// Read more about Node exit ('process.exit(num)') status codes here: https://stackoverflow.com/a/47163396/7974948
};
runMain();
0x07: 스크립트 코드(run.js) 분석
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
컨트랙트
를 컴파일
하고 artifacts/
디렉토리에 컨트랙트
를 다루기 위해 필요한 파일들을 생성한다.
const waveContract = await waveContractFactory.deploy();
deploy()
메서드를 통해, hardhat
은 로컬 이더리움 네트워크
를 만든다.
- 그러나, 이 때 만들어진
로컬 이더리움 네트워크
는 스크립트
의 실행이 끝나면 삭제된다.
- 따라서,
컨트랙트
를 실행할 때 마다 네트워크
를 초기 상태로 다룰 수 있고, 이는 디버깅
등에 유용하다.
await waveContract.deployed();
컨트랙트
가 블록체인 네트워크
상에 잘 배포
될 때까지 기다린다.
배포
가 완료되면, constructor()
가 실행된다.
console.log("Contract deployed to:", waveContract.address);
배포
가 되면 블록체인 네트워크
상의 컨트랙트의 주소
를 받을 수 있다.
- 실제
블록체인 네트워크
상에는 무수히 많은 컨트랙트
들이 배포되어 있고, 주소
를 통해 우리가 배포
한 컨트랙트
를 찾아서 사용할 수 있다.
- 이제
스크립트
를 실제로 실행해보자.
npx hardhat run scripts/run.js
0x08: Hardhat & HRE
- 스크립트 코드에서, 반복적으로
hre.ethers
를 사용하고 있다.
- 공식 문서에 나온
HRE
에 관한 설명은 아래와 같다.
hre
는 Hardhat Runtime Environment
를 의미하며 일종의 객체(object)
이다.
hardhat
이 작업, 테스트 또는 스크립트를 실행할 때 표시하는 모든 기능을 포함한다.
- 따라서,
Hardhat
은 HRE
이다.
- 즉,
npx hardhat
으로 시작되는 명령을 터미널에서 입력할 때마다, 코드에 지정된 hardhat.config.js
를 사용해서 이 hre
라는 객체를 즉시 만들 수 있다.
- 쉽게 말해, 코드를 작성할 때 아래와 같이 할 필요가 없다.
const hre = require("hardhat");
0x09: 데이터 저장하기
컨트랙트
에 데이터를 저장
할 수 있다.
- 본 튜토리얼에서 구현하고자 하는 컨트랙트는 누군가로부터 인사를 받는 것이고, 이를
함수
로 구현할 수 있다.
- 이 떄,
함수
내에 인사
에 대한 정보를 저장하도록 한다.
블록체인 네트워크
를 클라우드 서버
처럼 생각하면 편하다.
- 이
서버
를 유지하는 전 세계의 수 많은 사람들을 보통 채굴자(miner)
라고 부른다.
- 우리는
블록체인 네트워크
의 코드를 실행하기 위해서 이런 채굴자
들에게 값을 지불하는 것이다.
- 같은 맥락으로,
스마트 컨트랙트
는 서버
상의 프로그램 코드
라 생각하면 편하다.
- 즉, 누구나
서버
상에 존재하는 프로그램
을 실행할 수 있는 것이다.
- 앞서 작성한 컨트랙트를 수정하면 아래와 같다.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import "hardhat/console.sol";
contract WavePortal {
uint256 totalWaves;
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
function wave() public {
totalWaves += 1;
console.log("%s has waved!", msg.sender);
}
function getTotalWaves() public view returns (uint256) {
console.log("We have %d total waves!", totalWaves);
return totalWaves;
}
}
- 코드를 하나씩 살펴보도록 한다.
uint256 totalWaves;
컨트랙트
상에 저장되는 상태 변수(state variable)
로, 블록체인
상에 기록된다.
- 즉,
컨트랙트
와 마찬가지로 한 번 블록체인에 기록되면 영원히 존재한다.
function wave() public {
totalWave += 1;
console.log("%s has waved!", msg.sender);
}
함수
를 선언했다.
public
키워드는 이 함수
가 누구나 호출할 수 있음을 의미한다.
totalWaves += 1;
는 산술 연산이 다른 언어들과 크게 다르지 않음을 보여준다.
- 주목해야 할 점은
msg.sender
에 관한 것이다.
- 여기서
msg.sender
는 이 컨트랙트
를 호출한 사람의 지갑 주소(wallet address)
이며, 빌트인 인증(built-in authentication)
과도 같다.
스마트 컨트랙트
를 호출할 때에도 유효한 지갑
이 필요함 반드시 필요하기 때문에,
우리는 이를 통해 누가 이 컨트랙트
를 호출했는지 알 수 있다.
- 이를 응용하면, 특정인만
컨트랙트
를 호출하도록 할 수 있다.
function getTotalWaves() public view returns (uint256) {
console.log("We have %d total waves!", totalWaves);
return totalWaves;
}
view
는 이 함수
에서 state variable
을 읽기
만 하고 쓰기
는 하지 않음을 명시한다.
return
값을 지정하는 방식이 조금 특이하다.
함수
의 바디
가 시작되기 직전에 returns
라는 키워드와 그 뒤에 (_type_)
형태로 자료형을 명시한다.
0x0A: 함수 호출을 위해 run.js 업데이트
- 우리가 만든
함수
들을 호출하기 위해 run.js
를 다시 수정할 필요가 있다.
- 기본적으로,
public
키워드를 사용한 함수들은 블록체인
에 배포
된 뒤 사용할 수 있게 된다.
public API endpoint
를 생각하면 편하다.
- 새로 추가된 코드들에 대해서 주석을 달아 두도록 하겠다.
const main = async () => {
// getSigners()
const [owner, randomPerson] = await hre.ethers.getSigners();
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
// logs
console.log("Contract deployed to:", waveContract.address);
console.log("Contract deployed by:", owner.address);
// counts the wave using getTotalWaves() from our contract
let waveCount = await waveContract.getTotalWaves();
// call wave()
let waveTxn = await waveContract.wave();
await waveTxn.wait();
// grab the waveCount one more to see if it changed
waveCount = await waveContract.getTotalWaves();
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
0x0B: 스크립트 코드(updated run.js) 분석
const [owner, randomPerson] = await hre.ethers.getSigners();
블록체인
에 어떤 것이든 배포
하기 위해서는 유효한 지갑 주소
가 필요하다.
hardhat
은 백그라운드에서 이것을 알아서 처리해주지만, 이 코드에서는 명시적으로 지갑 주소
를 가져오고 있다.
getSigners()
함수는 npx hardhat accounts
로 확인했던 지갑
들을 반환한다.
console.log("Contract deployed by:", owner.address);
컨트랙트
를 배포
한 사람이 누구인지 확인할 수 있다.
let waveCount = await waveContract.getTotalWaves();
let waveTxn = await waveContract.wave();
await waveTxn.wait();
waveCount = await waveContract.getTotalWaves();
- 보통
API
들을 사용하는 것과 같이, 여기서도 함수
들을 하나 하나 호출해야 한다.
컨트랙트
상의 totalWave
가 바뀌는지 확인하는 코드이다.
- 아래 명령을 통해
컨트랙트
를 실행하면 다음과 같은 결과가 나온다.
npx hardhat run scripts/run.js
wave()
함수에서 인사 받는 사람으로 msg.sender
를 했기 때문에, 나 자신에게 인사를 한 꼴이 된다.
-
현재 컨트랙트
에서 수행하는 동작은 아래와 같다.
wave()
함수를 호출한다. ( function call )
상태 변수(state variable)
를 수정한다. ( write )
상태 변수
의 새로운 값을 읽는다. ( read )
-
튜토리얼을 진행함에 따라, React
앱을 만들어서 동작하게 할 것이다.
0x0C: 다른 유저에게서 인사 받기
wave()
함수로 인사를 하는 사람도 나
이고 인사를 받는 사람도 나
인 점이 좀 어색하다.
- 따라서,
다른 유저
가 나
에게 인사하도록 코드를 조금 수정한다.
- 앞선 코드에서의
randomPerson
을 활용하면 아래와 같이 코드를 수정할 수 있다.
// counts the wave using getTotalWaves() from our contract
let waveCount = await waveContract.getTotalWaves();
// call wave(), but the msg.sender is __randomPerson__ now
let waveTxn = await waveContract.connect(randomPerson).wave();
await waveTxn.wait();
// grab the waveCount one more to see if it changed
waveCount = await waveContract.getTotalWaves();
wave()
함수를 호출하는 msg.sender
가 randomPerson
이 되었으므로, 실행하면 아래와 같은 결과가 나온다.
- 이전과는
다른 주소
가 나
에게 인사하고 있음을 확인할 수 있다.
0x0D: 배포 스크립트(deploy.js) 작성하기
0x04
~ 0x0C
까지의 내용은 아래와 같다.
스마트 컨트랙트
작성
- 실행을 위한
스크립트
작성
컨트랙트
는 블록체인 네트워크
로부터 호출된다고 했으므로, 이미 로컬 블록체인 네트워크
를 구축한 것이라 생각할 수 있다.
- 하지만,
0x07
에서 짧게 언급한 것처럼 스크립트
를 실행할 때 사용한 네트워크
는 스크립트 실행
이 끝남과 동시에 삭제
된다.
- 따라서, 일회성이 아닌
로컬 블록체인 네트워크
를 구축할 필요가 있다.
- 다행히
hardhat
에서는 이를 간단히 구현할 수 있도록 해준다.
- 아래의 명령을 새로운
터미널 윈도우
에서 실행한다.
npx hardhat node
- 실행 결과,
hardhat
이 로컬 블록체인 네트워크
를 돌리고 있는 것을 확인할 수 있다.
- 또한, 각 계정에 10000ETH (≒ 343억원, 2022년 2월 기준)의
이더리움
을 설정해 두었다.
- 현재
블록체인 네트워크
는 블록
이 하나도 없는 상태이다.
- 이제
새로운 블록
을 생성하고 우리의 컨트랙트
를 그 블록 위에 기록할 것이다.
script/
디렉토리에 deploy.js
라는 파일을 만들고 아래와 같이 코딩한다.
const main = async () => {
// get deployer
const [deployer] = await hre.ethers.getSigners();
// get balance of deployer
const accountBalance = await deployer.getBalance();
console.log("Deploying contracts with account: ", deployer.address);
console.log("Account balance: ", accountBalance.toString());
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("WavePortal address: ", waveContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
0x0E: 배포하기
- 이제 아래의 명령어를 통해
로컬 블록체인 네트워크
에 컨트랙트
를 배포
할 수 있다.
npx hardhat run scripts/deploy.js --network localhost
- 당연한 말이지만,
npx hardhat node
로 서버를 돌리고 있는 터미널이 아닌 다른 터미널 창에서 명령어를 입력해야 한다.
배포
하는 스크립트
를 4 번 실행한 결과, 블록
이 4개까지 만들어진 것을 확인할 수 있다.
- 앞서 이용한
run.js
도 생각해보면.. 코드
내에 deploy()
를 쓰고 있기 때문에 아래와 같이 로컬 블록체인 네트워크
에서 실행하는 것이 가능하다.
npx hardhat run ./scripts/run.js --network localhost
[0x01] 자신의 지갑, 그리고 스마트 컨트랙트와 연결되는 Web3 앱 만들기
0x0F: 클라이언트 세팅
- 이제
터미널
이 아니라 웹
상에서 Web3
를 이용하여, 우리가 만든 컨트랙트
를 활용해보도록 한다.
0x10: Replit
Replit
은 브라우저 기반 IDE
로, 웹 앱을 쉽게 빌드하고 배포할 수 있도록 해준다.
Replit
을 이용하기 위해서는 계정을 만들고, 로그인 하면 된다.
- 튜토리얼에서 제공하는 틀을
fork
해서 개발을 이어나가면 된다. (링크)
Replit
에서는 .js
대신 .jsx
확장자를 사용한다.
0x11: Metamask
이더리움 지갑
으로 Metamask
를 활용한다.
- 이
지갑
을 통해서 컨트랙트
상의 함수 호출 등을 할 수 있다.
- 마치 사이트에
로그인
하는 것처럼 활용할 수 있다.
0x12: 블록체인 상에 배포하기 위한 세팅
0x12
부터는 npx hardhat node
로 구축했던 로컬 블록체인 네트워크
를 사용하지 않는다.
0x12
부터는 실제 블록체인
을 이용해서 튜토리얼을 진행한다.
- 실제
블록체인 네트워크
에 컨트랙트
를 편리하게 배포하기 위해 Alchemy 를 이용하면 좋다.
0x13: 트랜잭션
이더리움
블록체인
상에서 행하는 모든 행위들은 모두 트랜잭션
이라 불린다.
- 예)
이더리움
을 전송, 컨트랙트
내의 변수
업데이트
- 따라서,
wave()
함수를 호출하고 내부에서 totalWaves += 1;
을 수행하면, 이것이 트랜잭션
인 것이다.
스마트 컨트랙트
를 배포
하는 것 자체도 트랜잭션이다.
블록체인
은 소유자가 없고, 네트워크
에 참여하는 모든 채굴자
가 블록체인 원장
을 갖고 있어야 함을 명심하자.
- 즉, 우리가
컨트랙트
를 블록체인 네트워크
상에 올리기 위해서는 다음의 과정을 거쳐야 한다.
컨트랙트 코드
에 대한 트랜잭션
을 채굴자
들이 블록
으로 만들 수 있도록 브로드캐스팅한다.
- 생성된
블록
을 브로드캐스팅하여 네트워크
참여자 모두에게 전송한다.
- 위 두 과정을 Alchemy 를 이용하면 쉽게 할 수 있다.
0x14: 테스트 넷(Rinkeby)
이더리움 메인넷
은 실제 돈을 사용해야 하고, 실습을 하는 데 그만한 돈을 지불하는 것은 크게 가치가 없다.
- 따라서,
가짜 이더리움
을 사용하는 테스트넷
에서 실습하는 것이 효과적이다.
- 하지만,
테스트넷
도 블록체인 네트워크
이기 때문에 블록
의 생성 과정 등 이더리움 메인넷
이 갖는 특성과 동일하므로 유의해야 한다.
테스트넷
에서 다음을 실습할 수 있다.
- 우리의
트랜잭션
을 브로드캐스트
한다.
채굴자
들에 의해 트랜잭션
이 선택될 떄까지 기다린다.
채굴
과정을 거친다.
- 생성된
블록
이 블록체인 네트워크
상의 모든 채굴자
들에게 브로드캐스트
되기를 기다린다.
0x15: Fake ETH 얻기
- 본 튜토리얼에서는
테스트넷
으로 Rinkeby
를 이용한다.
- 개인적으로 여기가 제일 확실한 것 같다. ( 링크 )
0x16: Rinkeby 테스트넷으로 배포하기
- 우선
hardhat.config.js
파일을 수정해야 한다.
require("@nomiclabs/hardhat-waffle");
module.exports = {
solidity: "0.8.4",
networks: {
rinkeby: {
url: "YOUR_ALCHEMY_API_URL",
accounts: ["YOUR_PRIVATE_RINKEBY_ACCOUNT_KEY"]
},
},
};
- 코드에 명시된 대로
Alchemy API URL
과 본인 지갑 계정
의 비밀키
를 넣으면 된다.
비밀키
는 마치 블록체인
에 로그인
할 때 사용되는 비밀번호 처럼 사용된다.
- 좀 더 자세히 말하자면,
트랜잭션
을 채굴자
에게 보낼 때, 전송자
가 본인
임을 인증하는 전자 서명
을 위해 비밀키
를 필요로 한다.
비밀키
를 사용하지 않으면 트랜잭션
의 유효성을 검사할 수 없기 때문에, 필요하다.
Rinkeby
네트워크로 배포
하는 것은 아래의 명령어로 할 수 있다.
npx hardhat run scripts/deploy.js ---network rinkeby
0x17: 테스트넷(Rinkeby)으로 배포 완료!
- 아래는 명령어의 실행 결과다.
- 여기서
WavePortal address:
뒤에 있는 내용이 블록
내의 컨트랙트
주소 이다.
- 즉, 실제
블록체인 네트워크
상에 우리가 만든 스마트 컨트랙트
를 올린 것이다.
0x18: window.ethereum() 사용하기
- 우리가 만들
웹 사이트
가 블록체인
과 상호작용하기 위해서는, 어쨋든 우리의 지갑
을 연결해야 한다.
지갑
을 연결하고 나면 스마트 컨트랙트
호출 권한을 받을 수 있다.
Replit
으로 가서 src/
디렉토리 밑에 있는 App.jsx
를 찾는다.
Metamask
에 로그인 되어 있다면, 윈도우에 ethereum
이라는 특별한 객체가 자동으로 삽입된다.
- 우선, 이
ethereum
이라는 객체가 존재하는지 부터 확인해보자.
- 아래 코드로
App.jsx
를 수정한다.
import React, { useEffect } from "react";
import "./App.css";
const App = () => {
const checkIfWalletIsConnected = () => {
/*
* First make sure we have access to window.ethereum
*/
const { ethereum } = window;
if (!ethereum) {
console.log("Make sure you have metamask!");
} else {
console.log("We have the ethereum object", ethereum);
}
}
/*
* This runs our function when the page loads.
*/
useEffect(() => {
checkIfWalletIsConnected();
}, [])
return (
<div className="mainContainer">
<div className="dataContainer">
<div className="header">
👋 Hey there!
</div>
<div className="bio">
I am farza and I worked on self-driving cars so that's pretty cool right? Connect your Ethereum wallet and wave at me!
</div>
<button className="waveButton" onClick={null}>
Wave at Me
</button>
</div>
</div>
);
}
export default App
-
Metamask가 있는 경우 아래와 같이 콘솔창에서 확인할 수 있다.
-
-
Metamask가 없는 경우 아래와 같이 콘솔창에서 확인할 수 있다.(시크릿탭 켜고 들어감)
-
0x19: 유저 계정에 접근할 수 있는지 확인
- 이제
지갑
이 연결되었는지 여부는 확인했으니 유저의 지갑 계정
에 접근할 수 있는지를 확인해야 한다.
Metamask
는 반드시 우리가 승인
한 웹 사이트
에서만 우리의 지갑 계정 정보
를 제공한다.
App.jsx
를 아래의 코드로 업데이트한다.
import React, { useEffect, useState } from "react";
import "./App.css";
const App = () => {
/*
* Just a state variable we use to store our user's public wallet.
*/
const [currentAccount, setCurrentAccount] = useState("");
const checkIfWalletIsConnected = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
console.log("Make sure you have metamask!");
return;
} else {
console.log("We have the ethereum object", ethereum);
}
/*
* Check if we're authorized to access the user's wallet
*/
const accounts = await ethereum.request({ method: "eth_accounts" });
if (accounts.length !== 0) {
const account = accounts[0];
console.log("Found an authorized account:", account);
setCurrentAccount(account)
} else {
console.log("No authorized account found")
}
} catch (error) {
console.log(error);
}
}
useEffect(() => {
checkIfWalletIsConnected();
}, [])
return (
<div className="mainContainer">
<div className="dataContainer">
<div className="header">
👋 Hey there!
</div>
<div className="bio">
I am farza and I worked on self-driving cars so that's pretty cool right? Connect your Ethereum wallet and wave at me!
</div>
<button className="waveButton" onClick={null}>
Wave at Me
</button>
</div>
</div>
);
}
export default App
- 여기서
eth_accounts
라는 특별한 메서드를 사용하여, 지갑
에 있는 계정
들 중 하나라도 접근할 수 있는지 확인할 수 있다.
- 유저는 하나의
지갑
에 여러 개의 계정
을 가질 수 있으므로, 여기서는 첫 번째 것을 사용하기로 한다.
0x1A: 지갑 연결 버튼 만들기
로컬 이더리움 네트워크
를 세팅한다.스마트 컨트랙트 코드
에 대해 컴파일
, 테스트
등을 해볼 수 있다.스마트 컨트랙트
란 블록체인 상에 있는 코드 조각
으로 기억하면 된다.블록체인
이란 누구나 안전하게 정보를 읽고 쓸 수 있는 공간이다.- AWS 같은 네트워크지만, 누구의 소유도 아닌 네트워크라 생각하면 된다.
스마트 컨트랙트
를 작성한다.- 서버의 코드와 같이 생각하면 된다.
- 작성한
스마트 컨트랙트
를 블록체인 상에배포(deploy)
한다.- 전 세계 누구든 우리로부터 허용되었다면
스마트 컨트랙트
에접근
하고실행
시킬 수 있다.
- 전 세계 누구든 우리로부터 허용되었다면
클라이언트 웹사이트
를 만든다.- 일반 유저들이 우리의
스마트 컨트랙트
와 쉽게 상호작용 할 수 있도록 한다.
- 일반 유저들이 우리의
안녕
이라고 인사해주는 웹사이트를 만드는 것이다!hardhat
이라는 툴
을 통해, 로컬 이더리움 네트워크
환경을 만들 수 있으며 fake 이더리움
, fake 계정
등을 이용해 테스트도 진행할 수 있다.서버
가 블록체인
임을 기억하도록 하자.hardhat
을 통해 스마트 컨트랙트
를 컴파일
하는 것이 가능하다. 로컬 이더리움 네트워크
에서 이를 테스트
할 수도 있다.hardhat
을 이용하기 위해서는 node/npm
이 필요하다.- 설치에 관한 내용은 따로 다루도록 한다.
- 메모를 해두자면, Node.js 를 그냥 받으면 LTS가 아니라서 경고 메세지가 뜨기도 한다... 이를 해결하는 방법을 찾느라 나름 시간을 날렸으므로, 꼭 정리해둘 예정이다.
my-wave-portal
이라는 작업 디렉토리를 따로 만들어 진행하도록 한다.npm
의 설치가 완료되었으면 아래 코드를 입력해 튜토리얼을 진행한다.mkdir my-wave-portal
cd my-wave-portal
npm init -y
npm install --save-dev hardhat
hardhat
을 설치 완료한 후 샘플 프로젝트를 받는 작업을 진행한다.npx hardhat
Create a basic sample project
를 선택하면 몇 가지를 더 묻는데 모두 Enter
키로 넘기면 아래와 같이 설치되는 과정이 나온다.Project created
라는 문구와 함께 샘플 프로젝트가 완성된 것을 확인할 수 있다.hardhat-waffle
과 hardhat-ethers
를 추가로 설치해야 한다. 아래의 명령을 입력하면 된다.npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers
npx hardhat accounts
hardhat
이 생성한 이더리움 주소
이다.테스트
에 활용할 수 있다.0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (첫 번째 주소)
가 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (두 번째 주소)
에게 0.1 ETH
를 보낸다.npx hardhat compile
npx hardhat run
scripts
, contract
, test
디렉토리에 있는 모든 파일들을 지우도록 한다.contract
디렉토리에 WavePortal.sol
이라는 이름으로 솔리디티 파일을 하나 만든다.// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import "hardhat/console.sol";
contract WavePortal {
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
}
// SPDX-License-Identifier: UNLICENSED
- 라이센스 (저작권) 에 관한 내용이다.
- Ref. https://devocean.sk.com/opensource/techBoardDetail.do?ID=159339
pragma solidity ^0.8.4;
- 우리의
스마트 컨트랙트
가 이용할컴파일러
의버전
을 명시한다. - 중요 :
hardhat.config.js
에 명시된 것과 동일한버전
을 사용해야 한다.
import "hardhat/console.sol";
console log
에 관한 코드를import
한다.hardhat
에서는스마트 컨트랙트
를 쉽게디버깅
할 수 있도록console log
를 사용할 수 있는 코드를 제공한다.
contract WavePortal {
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
}
스마트 컨트랙트
의 구현에 대한 내용이다.스마트 컨트랙트(=컨트랙트)
는 다른 언어에서의클래스
와 상당히 비슷하게 보인다.- 이
컨트랙트
를 초기화 하면,constructor(생성자)
가 호출되며console
을 통해 문장을 출력할 것이다.
스마트 컨트랙트
를 작성하였으므로, 아래 세 단계를 거쳐 이를 실행해 볼 수 있다.컨트랙트
를컴파일
한다.로컬 블록체인 네트워크
에컴파일 된 컨트랙트
를배포(deploy)
한다.블록체인 네트워크
상의컨트랙트
를 호출하면console.log()
가 실행된다.
블록체인
에서도 컨트랙트
는 네트워크
상에 존재하며, 이를 누군가 호출하는 방식으로 동작한다.컨트랙트
를 컴파일
하고 실행하는 것은 가능하다.Solidity
가 블록체인 네트워크
, 그리고 이더리움 지갑(wallet)
과 어떻게 상호작용 할 수 있는지를 이해하는 것이 중요하다.scripts
디렉토리에 run.js
라는 자바스크립트
파일을 만든다.컨트랙트
를 실행하기 위해서는 컴파일
, 배포
, 실행
세 가지를 해야 한다.const main = async () => {
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("Contract deployed to:", waveContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0); // exit Node process without error
} catch (error) {
console.log(error);
process.exit(1); // exit Node process while indicating 'Uncaught Fatal Exception' error
}
// Read more about Node exit ('process.exit(num)') status codes here: https://stackoverflow.com/a/47163396/7974948
};
runMain();
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
컨트랙트
를컴파일
하고artifacts/
디렉토리에컨트랙트
를 다루기 위해 필요한 파일들을 생성한다.
const waveContract = await waveContractFactory.deploy();
deploy()
메서드를 통해,hardhat
은로컬 이더리움 네트워크
를 만든다.- 그러나, 이 때 만들어진
로컬 이더리움 네트워크
는스크립트
의 실행이 끝나면 삭제된다. - 따라서,
컨트랙트
를 실행할 때 마다네트워크
를 초기 상태로 다룰 수 있고, 이는디버깅
등에 유용하다.
await waveContract.deployed();
컨트랙트
가블록체인 네트워크
상에 잘배포
될 때까지 기다린다.배포
가 완료되면,constructor()
가 실행된다.
console.log("Contract deployed to:", waveContract.address);
배포
가 되면블록체인 네트워크
상의컨트랙트의 주소
를 받을 수 있다.- 실제
블록체인 네트워크
상에는 무수히 많은컨트랙트
들이 배포되어 있고,주소
를 통해 우리가배포
한컨트랙트
를 찾아서 사용할 수 있다.
스크립트
를 실제로 실행해보자.npx hardhat run scripts/run.js
hre.ethers
를 사용하고 있다.HRE
에 관한 설명은 아래와 같다.hre
는Hardhat Runtime Environment
를 의미하며 일종의객체(object)
이다.hardhat
이 작업, 테스트 또는 스크립트를 실행할 때 표시하는 모든 기능을 포함한다.- 따라서,
Hardhat
은HRE
이다.
npx hardhat
으로 시작되는 명령을 터미널에서 입력할 때마다, 코드에 지정된 hardhat.config.js
를 사용해서 이 hre
라는 객체를 즉시 만들 수 있다.const hre = require("hardhat");
컨트랙트
에 데이터를 저장
할 수 있다.함수
로 구현할 수 있다.함수
내에 인사
에 대한 정보를 저장하도록 한다.블록체인 네트워크
를클라우드 서버
처럼 생각하면 편하다.- 이
서버
를 유지하는 전 세계의 수 많은 사람들을 보통채굴자(miner)
라고 부른다. - 우리는
블록체인 네트워크
의 코드를 실행하기 위해서 이런채굴자
들에게 값을 지불하는 것이다.
- 같은 맥락으로,
스마트 컨트랙트
는서버
상의프로그램 코드
라 생각하면 편하다. - 즉, 누구나
서버
상에 존재하는프로그램
을 실행할 수 있는 것이다.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import "hardhat/console.sol";
contract WavePortal {
uint256 totalWaves;
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
function wave() public {
totalWaves += 1;
console.log("%s has waved!", msg.sender);
}
function getTotalWaves() public view returns (uint256) {
console.log("We have %d total waves!", totalWaves);
return totalWaves;
}
}
uint256 totalWaves;
컨트랙트
상에 저장되는상태 변수(state variable)
로,블록체인
상에 기록된다.- 즉,
컨트랙트
와 마찬가지로 한 번 블록체인에 기록되면 영원히 존재한다.
function wave() public {
totalWave += 1;
console.log("%s has waved!", msg.sender);
}
함수
를 선언했다.public
키워드는 이함수
가 누구나 호출할 수 있음을 의미한다.totalWaves += 1;
는 산술 연산이 다른 언어들과 크게 다르지 않음을 보여준다.- 주목해야 할 점은
msg.sender
에 관한 것이다.- 여기서
msg.sender
는 이컨트랙트
를 호출한 사람의지갑 주소(wallet address)
이며,빌트인 인증(built-in authentication)
과도 같다.
스마트 컨트랙트
를 호출할 때에도유효한 지갑
이 필요함 반드시 필요하기 때문에,
우리는 이를 통해 누가 이컨트랙트
를 호출했는지 알 수 있다.- 이를 응용하면, 특정인만
컨트랙트
를 호출하도록 할 수 있다.
- 여기서
function getTotalWaves() public view returns (uint256) {
console.log("We have %d total waves!", totalWaves);
return totalWaves;
}
view
는 이함수
에서state variable
을읽기
만 하고쓰기
는 하지 않음을 명시한다.return
값을 지정하는 방식이 조금 특이하다.함수
의바디
가 시작되기 직전에returns
라는 키워드와 그 뒤에(_type_)
형태로 자료형을 명시한다.
함수
들을 호출하기 위해 run.js
를 다시 수정할 필요가 있다.public
키워드를 사용한 함수들은 블록체인
에 배포
된 뒤 사용할 수 있게 된다.public API endpoint
를 생각하면 편하다.const main = async () => {
// getSigners()
const [owner, randomPerson] = await hre.ethers.getSigners();
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
// logs
console.log("Contract deployed to:", waveContract.address);
console.log("Contract deployed by:", owner.address);
// counts the wave using getTotalWaves() from our contract
let waveCount = await waveContract.getTotalWaves();
// call wave()
let waveTxn = await waveContract.wave();
await waveTxn.wait();
// grab the waveCount one more to see if it changed
waveCount = await waveContract.getTotalWaves();
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
const [owner, randomPerson] = await hre.ethers.getSigners();
블록체인
에 어떤 것이든배포
하기 위해서는 유효한지갑 주소
가 필요하다.hardhat
은 백그라운드에서 이것을 알아서 처리해주지만, 이 코드에서는 명시적으로지갑 주소
를 가져오고 있다.getSigners()
함수는npx hardhat accounts
로 확인했던지갑
들을 반환한다.
console.log("Contract deployed by:", owner.address);
컨트랙트
를배포
한 사람이 누구인지 확인할 수 있다.
let waveCount = await waveContract.getTotalWaves();
let waveTxn = await waveContract.wave();
await waveTxn.wait();
waveCount = await waveContract.getTotalWaves();
- 보통
API
들을 사용하는 것과 같이, 여기서도함수
들을 하나 하나 호출해야 한다. 컨트랙트
상의totalWave
가 바뀌는지 확인하는 코드이다.
컨트랙트
를 실행하면 다음과 같은 결과가 나온다.npx hardhat run scripts/run.js
wave()
함수에서 인사 받는 사람으로 msg.sender
를 했기 때문에, 나 자신에게 인사를 한 꼴이 된다.현재 컨트랙트
에서 수행하는 동작은 아래와 같다.
wave()
함수를 호출한다. ( function call )상태 변수(state variable)
를 수정한다. ( write )상태 변수
의 새로운 값을 읽는다. ( read )
튜토리얼을 진행함에 따라, React
앱을 만들어서 동작하게 할 것이다.
wave()
함수로 인사를 하는 사람도 나
이고 인사를 받는 사람도 나
인 점이 좀 어색하다.다른 유저
가 나
에게 인사하도록 코드를 조금 수정한다.randomPerson
을 활용하면 아래와 같이 코드를 수정할 수 있다. // counts the wave using getTotalWaves() from our contract
let waveCount = await waveContract.getTotalWaves();
// call wave(), but the msg.sender is __randomPerson__ now
let waveTxn = await waveContract.connect(randomPerson).wave();
await waveTxn.wait();
// grab the waveCount one more to see if it changed
waveCount = await waveContract.getTotalWaves();
wave()
함수를 호출하는 msg.sender
가 randomPerson
이 되었으므로, 실행하면 아래와 같은 결과가 나온다.다른 주소
가 나
에게 인사하고 있음을 확인할 수 있다.0x04
~ 0x0C
까지의 내용은 아래와 같다.스마트 컨트랙트
작성- 실행을 위한
스크립트
작성
컨트랙트
는 블록체인 네트워크
로부터 호출된다고 했으므로, 이미 로컬 블록체인 네트워크
를 구축한 것이라 생각할 수 있다.0x07
에서 짧게 언급한 것처럼 스크립트
를 실행할 때 사용한 네트워크
는 스크립트 실행
이 끝남과 동시에 삭제
된다.로컬 블록체인 네트워크
를 구축할 필요가 있다.hardhat
에서는 이를 간단히 구현할 수 있도록 해준다.터미널 윈도우
에서 실행한다.npx hardhat node
hardhat
이 로컬 블록체인 네트워크
를 돌리고 있는 것을 확인할 수 있다.이더리움
을 설정해 두었다.블록체인 네트워크
는 블록
이 하나도 없는 상태이다.새로운 블록
을 생성하고 우리의 컨트랙트
를 그 블록 위에 기록할 것이다.script/
디렉토리에 deploy.js
라는 파일을 만들고 아래와 같이 코딩한다.const main = async () => {
// get deployer
const [deployer] = await hre.ethers.getSigners();
// get balance of deployer
const accountBalance = await deployer.getBalance();
console.log("Deploying contracts with account: ", deployer.address);
console.log("Account balance: ", accountBalance.toString());
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("WavePortal address: ", waveContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
로컬 블록체인 네트워크
에 컨트랙트
를 배포
할 수 있다.npx hardhat run scripts/deploy.js --network localhost
npx hardhat node
로 서버를 돌리고 있는 터미널이 아닌 다른 터미널 창에서 명령어를 입력해야 한다.배포
하는 스크립트
를 4 번 실행한 결과, 블록
이 4개까지 만들어진 것을 확인할 수 있다.- 앞서 이용한
run.js
도 생각해보면..코드
내에deploy()
를 쓰고 있기 때문에 아래와 같이로컬 블록체인 네트워크
에서 실행하는 것이 가능하다.npx hardhat run ./scripts/run.js --network localhost
0x0F: 클라이언트 세팅
- 이제
터미널
이 아니라웹
상에서Web3
를 이용하여, 우리가 만든컨트랙트
를 활용해보도록 한다.
0x10: Replit
Replit
은 브라우저 기반IDE
로, 웹 앱을 쉽게 빌드하고 배포할 수 있도록 해준다.Replit
을 이용하기 위해서는 계정을 만들고, 로그인 하면 된다.- 튜토리얼에서 제공하는 틀을
fork
해서 개발을 이어나가면 된다. (링크)
Replit
에서는.js
대신.jsx
확장자를 사용한다.
0x11: Metamask
이더리움 지갑
으로Metamask
를 활용한다.- 이
지갑
을 통해서컨트랙트
상의 함수 호출 등을 할 수 있다. - 마치 사이트에
로그인
하는 것처럼 활용할 수 있다.
0x12: 블록체인 상에 배포하기 위한 세팅
0x12
부터는npx hardhat node
로 구축했던로컬 블록체인 네트워크
를 사용하지 않는다.0x12
부터는 실제블록체인
을 이용해서 튜토리얼을 진행한다.- 실제
블록체인 네트워크
에컨트랙트
를 편리하게 배포하기 위해 Alchemy 를 이용하면 좋다.
0x13: 트랜잭션
이더리움
블록체인
상에서 행하는 모든 행위들은 모두트랜잭션
이라 불린다.- 예)
이더리움
을 전송,컨트랙트
내의변수
업데이트
- 따라서,
wave()
함수를 호출하고 내부에서totalWaves += 1;
을 수행하면, 이것이트랜잭션
인 것이다. 스마트 컨트랙트
를배포
하는 것 자체도 트랜잭션이다.
블록체인
은 소유자가 없고,네트워크
에 참여하는 모든채굴자
가블록체인 원장
을 갖고 있어야 함을 명심하자.- 즉, 우리가
컨트랙트
를블록체인 네트워크
상에 올리기 위해서는 다음의 과정을 거쳐야 한다.컨트랙트 코드
에 대한트랜잭션
을채굴자
들이블록
으로 만들 수 있도록 브로드캐스팅한다.- 생성된
블록
을 브로드캐스팅하여네트워크
참여자 모두에게 전송한다.
- 위 두 과정을 Alchemy 를 이용하면 쉽게 할 수 있다.
0x14: 테스트 넷(Rinkeby)
이더리움 메인넷
은 실제 돈을 사용해야 하고, 실습을 하는 데 그만한 돈을 지불하는 것은 크게 가치가 없다.- 따라서,
가짜 이더리움
을 사용하는테스트넷
에서 실습하는 것이 효과적이다. - 하지만,
테스트넷
도블록체인 네트워크
이기 때문에블록
의 생성 과정 등이더리움 메인넷
이 갖는 특성과 동일하므로 유의해야 한다.
테스트넷
에서 다음을 실습할 수 있다.- 우리의
트랜잭션
을브로드캐스트
한다. 채굴자
들에 의해트랜잭션
이 선택될 떄까지 기다린다.채굴
과정을 거친다.- 생성된
블록
이블록체인 네트워크
상의 모든채굴자
들에게브로드캐스트
되기를 기다린다.
- 우리의
0x15: Fake ETH 얻기
- 본 튜토리얼에서는
테스트넷
으로Rinkeby
를 이용한다. - 개인적으로 여기가 제일 확실한 것 같다. ( 링크 )
0x16: Rinkeby 테스트넷으로 배포하기
- 우선
hardhat.config.js
파일을 수정해야 한다.
require("@nomiclabs/hardhat-waffle");
module.exports = {
solidity: "0.8.4",
networks: {
rinkeby: {
url: "YOUR_ALCHEMY_API_URL",
accounts: ["YOUR_PRIVATE_RINKEBY_ACCOUNT_KEY"]
},
},
};
- 코드에 명시된 대로
Alchemy API URL
과 본인지갑 계정
의비밀키
를 넣으면 된다. 비밀키
는 마치블록체인
에로그인
할 때 사용되는 비밀번호 처럼 사용된다.
- 좀 더 자세히 말하자면,
트랜잭션
을채굴자
에게 보낼 때,전송자
가본인
임을 인증하는전자 서명
을 위해비밀키
를 필요로 한다. 비밀키
를 사용하지 않으면트랜잭션
의 유효성을 검사할 수 없기 때문에, 필요하다.
Rinkeby
네트워크로배포
하는 것은 아래의 명령어로 할 수 있다.
npx hardhat run scripts/deploy.js ---network rinkeby
0x17: 테스트넷(Rinkeby)으로 배포 완료!
- 아래는 명령어의 실행 결과다.
- 여기서
WavePortal address:
뒤에 있는 내용이블록
내의컨트랙트
주소 이다. - 즉, 실제
블록체인 네트워크
상에 우리가 만든스마트 컨트랙트
를 올린 것이다.
0x18: window.ethereum() 사용하기
- 우리가 만들
웹 사이트
가블록체인
과 상호작용하기 위해서는, 어쨋든 우리의지갑
을 연결해야 한다. 지갑
을 연결하고 나면스마트 컨트랙트
호출 권한을 받을 수 있다.
Replit
으로 가서src/
디렉토리 밑에 있는App.jsx
를 찾는다.Metamask
에 로그인 되어 있다면, 윈도우에ethereum
이라는 특별한 객체가 자동으로 삽입된다.- 우선, 이
ethereum
이라는 객체가 존재하는지 부터 확인해보자. - 아래 코드로
App.jsx
를 수정한다.
import React, { useEffect } from "react";
import "./App.css";
const App = () => {
const checkIfWalletIsConnected = () => {
/*
* First make sure we have access to window.ethereum
*/
const { ethereum } = window;
if (!ethereum) {
console.log("Make sure you have metamask!");
} else {
console.log("We have the ethereum object", ethereum);
}
}
/*
* This runs our function when the page loads.
*/
useEffect(() => {
checkIfWalletIsConnected();
}, [])
return (
<div className="mainContainer">
<div className="dataContainer">
<div className="header">
👋 Hey there!
</div>
<div className="bio">
I am farza and I worked on self-driving cars so that's pretty cool right? Connect your Ethereum wallet and wave at me!
</div>
<button className="waveButton" onClick={null}>
Wave at Me
</button>
</div>
</div>
);
}
export default App
-
Metamask가 있는 경우 아래와 같이 콘솔창에서 확인할 수 있다.
-
Metamask가 없는 경우 아래와 같이 콘솔창에서 확인할 수 있다.(시크릿탭 켜고 들어감)
0x19: 유저 계정에 접근할 수 있는지 확인
- 이제
지갑
이 연결되었는지 여부는 확인했으니 유저의지갑 계정
에 접근할 수 있는지를 확인해야 한다. Metamask
는 반드시 우리가승인
한웹 사이트
에서만 우리의지갑 계정 정보
를 제공한다.App.jsx
를 아래의 코드로 업데이트한다.
import React, { useEffect, useState } from "react";
import "./App.css";
const App = () => {
/*
* Just a state variable we use to store our user's public wallet.
*/
const [currentAccount, setCurrentAccount] = useState("");
const checkIfWalletIsConnected = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
console.log("Make sure you have metamask!");
return;
} else {
console.log("We have the ethereum object", ethereum);
}
/*
* Check if we're authorized to access the user's wallet
*/
const accounts = await ethereum.request({ method: "eth_accounts" });
if (accounts.length !== 0) {
const account = accounts[0];
console.log("Found an authorized account:", account);
setCurrentAccount(account)
} else {
console.log("No authorized account found")
}
} catch (error) {
console.log(error);
}
}
useEffect(() => {
checkIfWalletIsConnected();
}, [])
return (
<div className="mainContainer">
<div className="dataContainer">
<div className="header">
👋 Hey there!
</div>
<div className="bio">
I am farza and I worked on self-driving cars so that's pretty cool right? Connect your Ethereum wallet and wave at me!
</div>
<button className="waveButton" onClick={null}>
Wave at Me
</button>
</div>
</div>
);
}
export default App
- 여기서
eth_accounts
라는 특별한 메서드를 사용하여,지갑
에 있는계정
들 중 하나라도 접근할 수 있는지 확인할 수 있다. - 유저는 하나의
지갑
에 여러 개의계정
을 가질 수 있으므로, 여기서는 첫 번째 것을 사용하기로 한다.
0x1A: 지갑 연결 버튼 만들기
( 링크 )
Author And Source
이 문제에 관하여([0x01] Web3 App w/ Solidity, Ether Smart Contract), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@c0np4nn4/0x01-Web3-App-w-Solidity-Ether-Smart-Contract저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)