풀스택 솔라나 dApp (Rust, Anchor, Phantom, Vue3)
Solana, Vue3, Phantom을 통한 dApp을 구축하는 법
구축할 프로젝트는 카운터입니다.
이 튜토리얼은 맥 환경에 최적화되어 있습니다.
프로젝트 개요
사용할 도구 모음
Solana tool : Solana 네트워크와 상호작요하기 위한 문서화된 cli가 포함 되어 있습니다.
Anchor Framework: Anchor는 여러 편리한 개발자 도구를 제공하는 Solana dApp 개발 프레임워크입니다.
참조
The Complete Guide to Full Stack Solana Development
https://github.com/lorisleiva/solana-vue3-counter
ok so what the fuck is the deal with solana anyway
개발환경
- Node.js (^16.11.0)
- Solana tool suite
- Anchor
- Phantom
- Vue3
시작
개발환경이 갖춰져 있다고 가정하고 시작합니다.
% solana config getConfig File: /Users/user/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: /Users/user/.config/solana/id.json
Commitment: confirmed
Keypair Path가 없는 경우, https://docs.solana.com/wallet-guide/paper-wallet#seed-phrase-generation를 참조
다음과 같이 네트워크를 변경 가능합니다.
[mainnet-beta, testnet, devnet, localhost]# 로컬호스트
% solana config set --url localhost
Config File: /Users/user/.config/solana/cli/config.yml
RPC URL: http://localhost:8899
WebSocket URL: ws://localhost:8900/ (computed)
Keypair Path: /Users/user/.config/solana/id.json
Commitment: confirmed# 개발 네트워크
% solana config set --url devnet
Config File: /Users/user/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: /Users/user/.config/solana/id.json
Commitment: confirmed# 메인 네트워크
% solana config set --url mainnet-beta
Config File: /Users/user/.config/solana/cli/config.yml
RPC URL: https://api.mainnet-beta.solana.com
WebSocket URL: wss://api.mainnet-beta.solana.com/ (computed)
Keypair Path: /Users/user/.config/solana/id.json
Commitment: confirmed
현재 로컬 지갑을 확인해 봅니다.
# 현재 로컬 지갑 주소 확인
% solana address
C7XoqXNJgAXR1orY9YZ4F2k3V3B1FfBqDcX5hNztq3f# 현재 지갑에 세부 정보 확인
% solana account C7XoqXNJgAXR1orY9YZ4F2k3V3B1FfBqDcX5hNztq3fPublic Key: C7XoqXNJgAXR1orY9YZ4F2k3V3B1FfBqDcX5hNztq3f
Balance: 0 SOL
Owner: 11111111111111111111111111111111
Executable: false
Rent Epoch: 204
먼저 localhost
네트워크에서 개발한 다음 네트워크로 전환 devnet
합니다.
% solana config set --url localhost
Config File: /Users/user/.config/solana/cli/config.yml
RPC URL: http://localhost:8899
WebSocket URL: ws://localhost:8900/ (computed)
Keypair Path: /Users/user/.config/solana/id.json
Commitment: confirmed
다른 터미널에서 solana-test-validator 실행
% solana-test-validator
--faucet-sol argument ignored, ledger already exists
Ledger location: test-ledger
Log: test-ledger/validator.log
Identity: 4eQjXA76HfYzzMCXez4BH54qEyeGF39x2WDpo7mLN5xU
Genesis Hash: EcfPLt2mvHnPgEHxRWZGR7o2a4VTivbuVSFnfXRVaygJ
Version: 1.8.0
Shred Version: 53958
Gossip Address: 127.0.0.1:1024
TPU Address: 127.0.0.1:1027
JSON RPC URL: http://127.0.0.1:8899
⠚ 00:02:40 | Processed Slot: 1196 | Confirmed Slot: 1196 | Finalized Slot: 1164
원래 터미널에서 에러드랍 100
% solana airdrop 100
Requesting airdrop of 100 SOLSignature: RY7TWUDy9YYLHK9mAtBbEzxB68jRu9jxbJu5qjgpd6aY3n8nwmQAHxyWRSYsSKV9z2BFxXawb5jFtZdxMNTj1n9100 SOL# 제대로 100솔 받아졌는지 확인
% solana balance
100 SOL# 지갑 상세 확인
% solana account C7XoqXNJgAXR1orY9YZ4F2k3V3B1FfBqDcX5hNztq3fPublic Key: C7XoqXNJgAXR1orY9YZ4F2k3V3B1FfBqDcX5hNztq3f
Balance: 100 SOL
Owner: 11111111111111111111111111111111
Executable: false
Rent Epoch: 0
Anchor를 사용해서 프로젝트 생성
% anchor init mysolanaapp...% cd mysolanaappmysolanaapp % tree -L 1.├── Anchor.toml├── Cargo.toml├── app├── migrations├── node_modules├── package.json├── programs├── tests└── yarn.lock5 directories, 4 files
app : 프론트 엔드 코드 위치
programs: Rust 코드 위치
tests: 자바스크립트 테스트 코드 위치
migrations: 기본 배포 스크립트
이제 Rust 코드를 확인해 봅니다.
initialize
호출될 때, 프로그램을 성공적으로 종료하는 함수를 정의하고 있습니다.
빌드해 봅니다.
mysolanaapp % anchor build
...mysolanaapp % tree -L 1.├── Anchor.toml├── Cargo.lock├── Cargo.toml├── app├── migrations├── node_modules├── package.json├── programs├── target├── tests└── yarn.lock
빌드가 완료되면 target 이라는 새 폴더가 표시되어야 합니다 .
mysolanaapp % tree ./target/idl./target/idl└── mysolanaapp.json0 directories, 1 file
생성된 IDL도 확인할 수 있습니다.
mysolanaapp % tree ./tests./tests└── mysolanaapp.js0 directories, 1 file
또한 테스트 코드도 확인 가능합니다.
Anchor를 사용하여, Solana 프로그램을 호출하려면 일반적으로 두 가지 주요 사항이 필요합니다.
Provider: Provider
은 일반적으로 Connection, Wallet 및 Commitment로 구성된 Solana 네트워크에 대한 연결의 추상화입니다 .
테스트에서 Anchor 프레임워크는 환경( anchor.Provider.env()
)을 기반으로 공급자를 생성 하지만 클라이언트에서는 사용자의 Solana 지갑을 사용하여 공급자를 직접 구성해야 합니다.
Program: program
는 Provider
, idl
, 및 programID
(프로그램이 빌드될 때 생성됨) 을 결합한 추상화이며 프로그램 RPC
에 대해 메서드 를 호출할 수 있도록 합니다.
이 두 가지가 있으면 프로그램에서 함수 호출을 시작할 수 있습니다.
예를 들어, 우리 프로그램에는 initialize
함수가 있습니다. 테스트에서 다음을 사용하여 해당 함수를 직접 호출할 수 있음을 알 수 있습니다
const tx = await program.rpc.initialize();
이것은 Anchor로 작업할 때 많이 사용할 매우 일반적인 패턴이며, 작동 방식을 이해하면 Solana 프로그램에 연결하고 상호 작용하기가 정말 쉽습니다.
이제 test
스크립트 를 실행하여 프로그램을 테스트할 수 있습니다 .
mysolanaapp % anchor deploy
...mysolanaapp % anchor test
...
✔ Is initialized! (460ms)1 passing (463ms)
에러가 난다면, Anchor.toml에 program id와 배포된 program id가 같은지 확인하고, 다른 터미널에서 solana-test-validator가 실행 중인지 확인하세요.
카운터 프로그램 작성
우리가 만들 프로그램을 사용하면, 클라이언트 응용 프로그램에서 호출할 때마다 증가하는 카운터를 만들 수 있습니다.
./programs/mysolanaapp/src/lib.rs를 열고 다음 코드로 업데이트합니다.
이제 우리는 프론트에서 호출 할 수 있는 두개의 함수(create, increment)를 가졌습니다.
#[account(…)]은 제약 조건을 정의합니다. 이러한 조건을 유지하지 않으면, 명령이 실행되지 않습니다.
Solana 내에서는 상태저장이 없으며, 계정이 버퍼같이 사용되어, 모든 상태를 보유합니다.
프로그램을 빌드합니다.
mysolanaapp % anchor build
이제, 테스트를 작성합니다.
mysolanaapp % anchor test
어떤 이유인지 알 수 없어도, 테스트 진행 전에 solana-test-validator를 중지해야 테스트가 통과합니다.
이제, 네트워크를 devnet으로 바꾸고 다시 빌드/테스트합니다. 그리고 테스트 전에, 에어드랍으로 충분한 코인을 확보하세요. 전 3개 정도 받았습니다.
mysolanaapp % solana config set --url devnet
mysolanaapp % solana airdrop 1
mysolanaapp % solana airdrop 1
mysolanaapp % solana airdrop 1
mysolanaapp % anchor build
mysolanaapp % anchor test
배포하기 전에 빌드에 의해 생성된 동적으로 생성된 프로그램 ID를 얻고 싶습니다. 프로젝트를 생성할 때, 프로그램 ID를 대체하기 위해, Rust 프로그램에서 이 ID를 사용해야 합니다. 이 ID를 얻으려면 다음 명령을 실행할 수 있습니다.
mysolanaapp % solana address -k target/deploy/mysolanaapp-keypair.json9WSTCnLnpovgyoyCEbhpzAfSLezPXmkS3F67rSUWAeam
이제 ./programs/mysolanaapp/src/lib.rs에서 프로그램 ID를 업데이트할 수 있습니다 .
use anchor_lang::prelude::*;declare_id!("9WSTCnLnpovgyoyCEbhpzAfSLezPXmkS3F67rSUWAeam");
또한 ./Anchor.toml를 수정합니다.
[programs.devnet]mysolanaapp = "9WSTCnLnpovgyoyCEbhpzAfSLezPXmkS3F67rSUWAeam"[registry]url = "https://anchor.projectserum.com"[provider]cluster = "devnet"wallet = "/Users/user/.config/solana/id.json"[scripts]test = "mocha -t 1000000 tests/"
이제 배포합니다.
mysolanaapp % anchor deployDeploying workspace: https://api.devnet.solana.comUpgrade authority: /Users/user/.config/solana/id.jsonDeploying program "mysolanaapp"...Program path: /Users/user/Workspace/mysolanaapp/target/deploy/mysolanaapp.so...Program Id: 9WSTCnLnpovgyoyCEbhpzAfSLezPXmkS3F67rSUWAeamDeploy success
배포가 잘안되시면, 코인양을 확인하세요.
이제 프런트엔드를 구축해야 합니다.
Vuejs 3.x
기존 app 폴더에 덮어쓰도록, Vuejs 프로젝트를 만듭니다.
mysolanaapp % yarn global add @vue/cli
mysolanaapp % vue create app
프론트엔드 앱의 실행
mysolanaapp % cd app
app % yarn
app % yarn serve
웹 브라우저에서 Vue3의 데모 프로젝트를 볼 수 있습니다.
@project-serum/anchor와 @solana/web3.js를 추가합니다.
app % yarn add @project-serum/anchor @solana/web3.js
Solana 지갑 어댑터를 사용하기 위한 종속성을 추가합니다.
yarn add @solana/wallet-adapter-base \
@solana/wallet-adapter-wallets \
@solana/wallet-adapter-vue \
@solana/wallet-adapter-vue-ui
./assets 폴더에, ../target/idl/mysolanaapp.json를 복사해서 새 파일(idl.json)을 만듭니다.
app % cp ../target/idl/mysolanaapp.json ./src/assets/idl.json
./src/Counter.vue 파일을 아래와 같이 만듭니다.
./src/App.vue를 아래와 같이 수정합니다.
이제 실행해봅니다.
app % yarn serve
Phantom 지갑을 연결 하기전에, 지갑의 네트워크를 Devnet으로 바꿉니다.
지갑 주소로 충분한 코인을 에어드랍하는 것도 잊지마세요.
참고 : https://github.com/kjaylee/mysolanaapp
저의 삽질이 도움이 되셨으면 합니다.