Cách tương tác với Smart Contract từ một web app


Juan Cruz Martinez sẽ hướng dẫn chúng ta tạo một smart contract (hợp đồng thông minh) nhỏ để lưu trữ và truy xuất dữ liệu trên Ethereum blockchain và tạo một web app cho phép truy cập và thay đổi dữ liệu trên smart contract này.





Hãy thực hành cùng Gambaru nhé!











Smart Contract





Đầu tiên, tôi sẽ trình bày về smart contract mà ta sẽ sử dụng để xây dựng các ứng dụng web.





Vì bài viết tập trung vào việc liên kết JavaScript với blockchain, nên tôi tạo contract càng đơn giản càng tốt:





Tạo một Smart Contract đơn giản
Tạo một Smart Contract đơn giản. Xem code gốc ở đây




Hợp đồng CoolNumberContract chứa một biến trên blockchain được gọi là coolNumber với giá trị ban đầu là 10.





Biến này là public, nghĩa là ta có thể truy cập giá trị của nó từ blockchain mà không cần tạo hàm getter.





Ngoài ra, contract này chứa một hàm publicsetCoolNumber, sẽ thay đổi giá trị của biến trên blockchain.





Điều quan trọng cần nhớ ở đây là bất kỳ thay đổi nào trong dữ liệu blockchain đều cần được thể hiện bằng một giao dịch.





Có nghĩa là việc gọi phương thức setCoolNumber sẽ yêu cầu một giao dịch và giao dịch đó sẽ có phí gas đi kèm.





Hãy triển khai hợp đồng trên một test network trước khi tiếp tục.





Thiết lập project và dependency





Để tương tác với bất kỳ Ethereum blockchain nào từ JavaScript, bạn sẽ cần một library.





Trong trường hợp này, hãy sử dụng web3 https://web3js.readthedocs.io/en/v1.3.0/





Web3 sẽ cho phép tương tác với bất kỳ Ethereum network nào thông qua MetaMask hoặc provider của web3 như Ganache.





Hãy bắt đầu một project mới. Tôi sẽ sử dụng JavaScript HTML, nhưng mọi người có thể sử dụng bất kỳ framework nào mình muốn như React hoặc Vue.





Tất cả code sẽ đi vào một file là index.html và hãy bắt đầu với cấu trúc sau:





Thiết lập project và dependency
Thiết lập project và dependency. Xem code gốc ở đây




Hãy xem thử thẻ body.





Đây là một giao diện người dùng đơn giản với hai button và một khoảng biểu thị trạng thái.





Cả hai button đều gọi các hàm JavaScript mà hiện tại vẫn chưa được định nghĩa.





Trên thẻ head, thẻ quan trọng là script ta đang import. Đó là thành phần phụ thuộc vào web3.





Hãy thêm thành phần phụ thuộc này vào code như tôi đã làm hoặc nếu đang sử dụng một framework, chỉ cần import package này với:





Import Package
Import Package




Nếu chưa cài đặt library, bạn có thể thông qua NPM:





Cài thông qua NPM
Cài thông qua NPM




Cuối cùng, trước khi tiếp tục, lời khuyên là hãy cài đặt tiện ích mở rộng MetaMask.





Nếu muốn sử dụng bất kỳ provider nào khác, bạn có thể phải thay đổi các phần của code cho phù hợp, vì các sample được cung cấp sử dụng provider web3 được MetaMask đưa vào.





Kết nối web app với Ethereum Blockchain





Khi cấu trúc cơ bản và các thành phần phụ thuộc sẵn sàng, ta có thể thêm code để kết nối ứng dụng với blockchain.





Bên trong script tag ở body, hãy thêm:





Kết nối web app với Ethereum Blockchain
Kết nối web app với Ethereum Blockchain. Xem code gốc ở đây




Các đoạn code trên khá đơn giản ngoại trừ hàm loadWeb3.





Chức năng này chịu trách nhiệm thiết lập kết nối và cấp quyền tương tác với blockchain.





Để làm việc với smart contract này, ta sẽ cần một instance Web3 mới. Khi tạo instance này, cần chỉ định provider ta muốn sử dụng.





Vì đang sử dụng MetaMask làm proxy nên hãy dùng provider window.ethereum được đưa vào bởi tiện ích mở rộng MetaMask.





Khi truy cập trình duyệt và tải trang (bằng file hoặc trình duyệt web), ta sẽ thấy luồng ủy quyền MetaMask như sau:





Cấp quyền kết nối cho app thông qua MetaMask
Cấp quyền kết nối cho app thông qua MetaMask




Hãy nhấn Next Connect.





Truy cập vào smart contract





Đến lúc này, code đã có quyền truy cập để tương tác với blockchain.





Tạo một chức năng mới để tạo một contract instance phù hợp với giao diện contract.





Tạo Contract Instance
Tạo Contract Instance




Để có được một instance của bất kỳ contract nào trên blockchain, tất cả những gì chúng ta cần là: thông số ABI của contract và địa chỉ contract, cả hai đều có thể trích xuất từ ​​Remix.





Để có thông số kỹ thuật ABI của contract, hãy đến Remix trên tab Compile. Compile và nhấp vào ABI.





Sao chép ABI specification của contract
Sao chép ABI specification của contract




Nút này sẽ sao chép thông số ABI cho contract dưới dạng một JSON array trên clipboard mà ta có thể sử dụng trực tiếp như một phần của tham số đầu tiên.





Tham số thứ hai là địa chỉ contract đã triển khai, có thể lấy từ Remix tại thời điểm triển khai hoặc Etherscan.





Sao chép địa chỉ contract từ Remix
Sao chép địa chỉ contract từ Remix




Sao chép địa chỉ contract từ Remix
Sao chép địa chỉ contract từ Remix




Code chức năng hoàn chỉnh cho contract này sẽ như sau:





Code chức năng hoàn chỉnh cho Contract
Code chức năng hoàn chỉnh cho Contract. Xem code gốc ở đây




Sau khi hoàn tất, ta có thể chỉ cần gọi loadContract từ hàm loader:





Gọi loadcontract từ hàm loader
Gọi loadcontract từ hàm loader




Đọc các giá trị từ smart contract





Nay ta đã sẵn sàng để bắt đầu gọi các chức năng của smart contract và sẽ bắt đầu bằng cách lấy coolNumber từ contract này.





Có thể lấy dữ liệu từ contract rất nhanh nhờ web3. Đây là một ví dụ để lấy giá trị của biến public coolNumber:





Lấy giá trị của biến public coolNumber
Lấy giá trị của biến public coolNumber. Xem code gốc ở đây




Siêu dễ đúng không?





Sử dụng instance contract từ phần trước, hãy lấy các phương thức và gọi một hàm với tên biến (đây là getter đã được đề cập ở phần đầu), và cuối cùng, sử dụng lệnh call để bắt đầu yêu cầu từ xa.





Cập nhật các giá trị vào smart contract





Cuối cùng, cần đảm bảo rằng ta cũng có thể giao dịch với smart contract.





Do đó, hãy hiển thị một instance bằng cách truy cập hàm setter để thay đổi coolNumber được lưu trữ trong contract.





Chức năng change sẽ chỉ định một số ngẫu nhiên mới và lưu nó trên blockchain:





Truy cập hàm setter để thay đổi coolNumber
Truy cập hàm setter để thay đổi coolNumber. Xem code gốc ở đây




Có hai điều cần chú ý:





  • Đầu tiên, chúng ta đề cập đến một hàm getCurrentAccount() hiện chưa được định nghĩa. Ta sẽ làm việc này sau.
  • Thứ hai là cách gọi setter. Hãy chú ý đến dòng gọi phương thức setCoolNumber từ contract, nó trông hơi khác so với những gì đã làm cho caller:




Cách gọi setter
Cách gọi setter




Thay vì sử dụng phương thức call, ta đang sử dụng phương thức send. Ta cần xác định tài khoản người gửi. Tại sao? Phải cần một giao dịch để thay đổi các giá trị trên blockchain. Như đã nói, một giao dịch yêu cầu tài khoản từ và đến phải hợp lệ – từ người khởi tạo giao dịch và trong trường hợp này, là địa chỉ của smart contract này.





Có thể sử dụng bất kỳ tài khoản nào làm từ giá trị không? Không! Đó phải là tài khoản bạn có quyền truy cập (và trong trường hợp này, tài khoản được đăng ký trên ví MetaMask của bạn), vì bạn sẽ cần ủy quyền giao dịch và xác nhận hóa đơn tiền gas.





Vấn đề đã được giải quyết, hãy xây dựng phương thức getCurrentAccount():





Xây dựng phương thức getCurrentAccountxây dựng phương thức getCurrentAccount
Xây dựng phương thức getCurrentAccount




Web3 thực sự tuyệt vời. Mọi người có thể tương tác với blockchain và ví của mình, vì vậy có thể thông qua Web3 để yêu cầu thông tin về các tài khoản đã đăng ký trên ví. Trong trường hợp này, chỉ cần lấy tất cả và sử dụng tài khoản đầu tiên để thực hiện các giao dịch.





Vận dụng những gì đã học





Tôi đã tải code lên GitHub gist để bạn so sánh và tham khảo. Hãy thử xây dựng dự án nhỏ nhưng thú vị này nào!





Application Flow
Application Flow




Nếu thành công, bạn hãy comment phía dưới cho Gambaru biết nhé!





Theo Juan Cruz Martinez