Để tiếp tục với series bài viết về Blockchain Solana thì hôm nay mình sẽ giới thiệu và hướng dẫn các bạn xây dựng hệ thống Backend để gọi đến Solana thông qua Web3 để đúc NFT (mint NFT).
Bài viết sẽ gồm các 2 phần:

  • Phần 1:
    • Thiết kế hệ thống
    • Dựng hệ thống Backend API bằng Nodejs
    • Build và deploy SmartContract mint NFT
  • Phần 2:
    • Code API kết nối SmartContract
    • Code API thực hiện mint NFT

Chúng ta bắt đầu phần 1 nhé.

I. Thiết kế hệ thống

Có rất nhiều bài viết hướng dẫn xây dựng hệ thống Frontend dùng JS để kết nối tới Solana Network thông qua Web3, tuy nhiên nếu hệ thống Frontend thì khi muốn thao tác lưu lại các thông tin mà Solana trả về thì chúng ta lại cần gọi tiếp các API lên các hệ thống Backend. Vì vậy, mình sẽ thiết kế 1 hệ thống Backend API để có thể gọi lên Solana Network, sau khi nhận được kết quả thì có thể lưu vào Database luôn mà ko cần gọi thêm các API khác nữa. Database mình đang dùng ở đây là MongoDB.

Tổng quát thiết kế hệ thống:
1BLQMLz28VLAGSRKe2kmH-O83DzFV-xzK

II. Dựng hệ thống Backend API bằng NodeJS

Trong bài viết này, mình sẽ sử dụng NodeJS, cụ thể là framework Express để viết API Backend. Để thực hiện phần này, mình đang sử dụng môi trường như sau:

Sau khi cài đặt môi trường, chúng ta bắt đầu dựng hệ thống nhé.

Bước 1: Dựng base API:

$ git clone https://github.com/hagopj13/node-express-boilerplate vnlab-nft-certificate-backend
Cloning into 'vnlab-nft-certificate-backend'...
remote: Enumerating objects: 1494, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 1494 (delta 0), reused 0 (delta 0), pack-reused 1491
Receiving objects: 100% (1494/1494), 1.09 MiB | 3.03 MiB/s, done.
Resolving deltas: 100% (882/882), done.

$ cd vnlab-nft-certificate-backend/
$ yarn install
yarn install v1.22.19
...
husky - Git hooks installed
Done in 20.13s.

Bước 2: Config .env

Copy file môi trường và sửa nội dung file .env:

$ cp .env.example .env

Sau khi sửa lại file .env, nội dung file sẽ như thế này :

# Port number
PORT=3000

# URL of the Mongo DB
MONGODB_URL=mongodb://127.0.0.1:27017/node-boilerplate

# JWT
# JWT secret key
JWT_SECRET=thisisasamplesecret
# Number of minutes after which an access token expires
JWT_ACCESS_EXPIRATION_MINUTES=3000
# Number of days after which a refresh token expires
JWT_REFRESH_EXPIRATION_DAYS=30
# Number of minutes after which a reset password token expires
JWT_RESET_PASSWORD_EXPIRATION_MINUTES=1000
# Number of minutes after which a verify email token expires
JWT_VERIFY_EMAIL_EXPIRATION_MINUTES=10

# SMTP configuration options for the email service
# For testing, you can use a fake SMTP service like Ethereal: https://ethereal.email/create
#SMTP_HOST=email-server
#SMTP_PORT=587
#SMTP_USERNAME=email-server-username
#SMTP_PASSWORD=email-server-password
#EMAIL_FROM=support@yourapp.com

Để hiểu hơn về các cài đặt, các bạn có thể đọc thêm trong file README.md của mã nguồn.

Bước 3: Test hệ thống vừa dựng

Sau khi chỉnh sửa xong file .env và lưu lại, chúng ta chạy hệ thống vừa dựng:

$ yarn dev
yarn run v1.22.19
$ cross-env NODE_ENV=development nodemon src/index.js
[nodemon] 2.0.9
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node src/index.js`
info: Connected to MongoDB
info: Listening to port 3000
warn: Unable to connect to email server. Make sure you have configured the SMTP options in .env

Mở trình duyệt và truy cập url: http://localhost:3000/v1/docs/ . Đây là trang tài liệu API được viết sẵn bằng Swagger, có giao diện để chúng ta có thể test API.

Thử test API auth/register để lấy token:
Curl:

  'http://localhost:3000/v1/auth/register' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "fake name",
  "email": "fake2@example.com",
  "password": "password1"
}'

Response:

{
  "user": {
    "role": "user",
    "isEmailVerified": false,
    "name": "fake name",
    "email": "fake2@example.com",
    "id": "632838d9df923b6c08bc2e4c"
  },
  "tokens": {
    "access": {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MzI4MzhkOWRmOTIzYjZjMDhiYzJlNGMiLCJpYXQiOjE2NjM1ODAzNzcsImV4cCI6MTY2Mzc2MDM3NywidHlwZSI6ImFjY2VzcyJ9.7uHRxjZ_Iomb4WuE6s9Skm8rR5h0YrrTtYOUX9iF_6Q",
      "expires": "2022-09-21T11:39:37.618Z"
    },
    "refresh": {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MzI4MzhkOWRmOTIzYjZjMDhiYzJlNGMiLCJpYXQiOjE2NjM1ODAzNzcsImV4cCI6MTY2NjE3MjM3NywidHlwZSI6InJlZnJlc2gifQ.au5qEFvGiTqmh5aR53tu_snTLRqca2Z09yLlmFrrheM",
      "expires": "2022-10-19T09:39:37.620Z"
    }
  }
}

Token này dùng để gọi các API khác, các lần sau cần lấy token, các bạn sử dụng API auth/login để lấy nhé. Như vậy là chúng ta đã dựng xong code base API bằng NodeJS để chuẩn bị viết API cho việc gọi lên Solana network.

III. Build và deploy SmartContract để mint NFT

Để hiểu hơn về smartcontract solana, các bạn có thể đọc thêm bài này: [Solana Blockchain] Phát triển ứng dụng Blockchain trên Solana Network bằng Anchor Framework (1). Mình có tham khảo bài viết này để dựng hệ thống với môi trường như sau:

  • Hệ điều hành: Ubuntu 20.10 (Cài đặt trên máy ảo của windows 10)
  • solana-cli 1.9.22
  • anchor-cli 0.24.2
  • Công cụ deploy: Git, npm, yarn

Bước 1: Tạo các Account và setup môi trường

Tạo Token Account dùng để trả phí cho việc deploy và thực thi các giao dịch

Nếu bạn chưa có Token Account bạn có thể tạo bằng command sau

solana-keygen new 

Mặc định thì keypair được lưu tại ~/.config/solana/id.json

Chỉ định DevNet để deploy Smart Contract

$ solana config set --url devnet
Config File: /home/vagrant/.config/solana/cli/config.yml
RPC URL: https://api.devnet.solana.com
WebSocket URL: wss://api.devnet.solana.com/ (computed)
Keypair Path: /home/vagrant/.config/solana/id.json
Commitment: confirmed

Airdrop để lấy Sol trả phí cho các giao dịch:

$ solana airdrop 2
Requesting airdrop of 2 SOL

Signature: 62L46ZdVUd2WMgJcU9rszedJ2ZyNVrCFrkTTieBSC65NPqfGp2MKGVXJGZfJYvScAhM9ghW7QmR7yFhnXhh99NQT

2.80521464 SOL

Bước 2: Dựng source code logic của smart-contract:

$ git clone https://github.com/gmo-vietnamlab/sol-mint-nft.git vnlab-sol-mint-nft
Cloning into 'vnlab-sol-mint-nft'...
remote: Enumerating objects: 145, done.
remote: Counting objects: 100% (145/145), done.
remote: Compressing objects: 100% (122/122), done.
remote: Total 145 (delta 55), reused 90 (delta 5), pack-reused 0
Receiving objects: 100% (145/145), 666.45 KiB | 2.40 MiB/s, done.
Resolving deltas: 100% (55/55), done.

$ cd vnlab-sol-mint-nft/
$ yarn
yarn install v1.22.19
warning package.json: No license field
warning No license field
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@project-serum/anchor > @solana/web3.js > sinon-chai@3.7.0" has unmet peer dependency "sinon@>=4.0.0".
[4/4] Building fresh packages...
success Saved lockfile.
Done in 12.11s.

Bước 3: Build Smartcontract bằng anchor:

$ anchor build
BPF SDK: /home/vagrant/.local/share/solana/install/releases/stable-0fd793565846b0c12cfe2797ca0f087f7609bdf2/solana-release/bin/sdk/bpf
...
...
To deploy this program:
  $ solana program deploy /home/vagrant/vm-playbook/vnlab-sol-mint-nft/target/deploy/sol_mint_nft.so
The program address will default to this keypair (override with --program-id):
  /home/vagrant/vm-playbook/vnlab-sol-mint-nft/target/deploy/sol_mint_nft-keypair.json

$ anchor keys list
sol_mint_nft: D8zZ4Vh5tjfotLQYES8xGtYkaeU5BDrhyFesjHxiFe7E

Thay key D8zZ4Vh5tjfotLQYES8xGtYkaeU5BDrhyFesjHxiFe7E vào declare_id!() của file vnlab-sol-mint-nft/programs/sol-mint-nft/src/lib.rs:

declare_id!("D8zZ4Vh5tjfotLQYES8xGtYkaeU5BDrhyFesjHxiFe7E");

Sau đó build lại:

$ anchor build
BPF SDK: /home/vagrant/.local/share/solana/install/releases/stable-0fd793565846b0c12cfe2797ca0f087f7609bdf2/solana-release/bin/sdk/bpf
...
...
To deploy this program:
  $ solana program deploy /home/vagrant/vm-playbook/vnlab-sol-mint-nft/target/deploy/sol_mint_nft.so
The program address will default to this keypair (override with --program-id):
  /home/vagrant/vm-playbook/vnlab-sol-mint-nft/target/deploy/sol_mint_nft-keypair.json

Bước 4: Deploy Smartcontract:

$ solana program deploy /home/vagrant/vm-playbook/vnlab-sol-mint-nft/target/deploy/sol_mint_nft.so
Program Id: D8zZ4Vh5tjfotLQYES8xGtYkaeU5BDrhyFesjHxiFe7E

Ở bước này, các bạn cần lưu lại 2 thông tin sau để phục vụ cho các bước sau:

  • File idl: vnlab-sol-mint-nft/target/idl/sol_mint_nft.json
  • Program Id: D8zZ4Vh5tjfotLQYES8xGtYkaeU5BDrhyFesjHxiFe7E

Như vậy, sau bước này là chúng ta đã tạo được smart-contract để mint NFT, và đẩy lên Solana Devnet. Các bạn có thể kiểm tra smart-contract này ở đây: https://explorer.solana.com/address/D8zZ4Vh5tjfotLQYES8xGtYkaeU5BDrhyFesjHxiFe7E?cluster=devnet

1_zMOPrRItljK8sO0XOa-opElBuVFBBfC

IV. Mã nguồn và bài viết tham khảo

Trong bài viết này, mình đã hướng dẫn các bạn cách dựng API backend bằng nodejs, và build, deploy 1 smart-contract để chuẩn bị cho việc viết API mint NFT ở phần 2.
Mã nguồn cho bài viết, các bạn có thể xem ở đây:

Trong bài viết có sử dụng open source và một số tài liệu tham khảo: