Các bài viết trước trong chuỗi bài “Xây dựng Dapp” :
- Xây dựng ứng dụng phi tập trung (Dapp)
- Xây dựng ứng dụng phi tập trung (Dapp) với Reacjs
- Xây dựng ứng dụng phi tập trung (Dapp) với Vuejs
- Xây dựng ứng dụng phi tập trung (Dapp) với Cocos Creator
- Xây dựng ứng dụng phi tập trung (Dapp) với Unity
- Xây dựng ứng dụng phi tập trung (Dapp) với Angular
Quay trở lại loạt bài xậy dựng dapp trên các nền tảng khác nhau, thì hôm nay là thành viên non kinh nghiệm nhất trong team, mình xin tiếp tục với một bài về xây dựng dapp blockchain bằng Python(Flask) sử dụng trong môi trường docker
Mô Hình
Trên đây là mô hình chung cho một Dapp blockchain sẽ vẫn từ application rồi sử dụng Web3 để tương tác với mạng blockchain của Ethereum. Nhưng vì đây không phải là môi trường Javascript mà là môi trường Python nên thay vì sử dụng Web3.js
chúng ta sẽ sử dụng Web3.py
Chuẩn Bị
Môi trường vẫn luôn là nỗi đau đầu cho mọi bất cứ lập trình viên nào. Và chính bản thân mình cũng là nạn nhân khi cài mãi không được web3.py
do lỗi gì đó của thằng python
trên máy, mà ông đối diện cài phát ăn ngay. Vậy là mình quyết định chốt phương án cho nó lên thớt bằng cách sử dụng Docker
cho nó nhanh.
- Docker : hãy chắc chắn trong máy đã cài docker
$ docker --version
- Tiếp theo là… à mà cần cài giữa đâu mà tiếp theo nhỉ
Triển khai
Sau đây sẽ là phần cấu hình Dockerfile và Dokcer-composer
- Dockerfile
Yêu cầu của
Web3.py
là từ Python 3.6 trở lên nha123456789101112<span class="token comment"># Dockerfile</span><span class="token keyword">FROM</span> python<span class="token punctuation">:</span>3.7<span class="token keyword">WORKDIR</span> /app<span class="token keyword">COPY</span> . .<span class="token keyword">RUN</span> pip install <span class="token punctuation">-</span>r requirements.txt<span class="token keyword">CMD</span> <span class="token punctuation">[</span><span class="token string">"python"</span><span class="token punctuation">,</span> <span class="token string">"app.py"</span><span class="token punctuation">]</span> - requirements.txt123Flask<span class="token operator">==</span><span class="token number">1.1</span><span class="token number">.1</span>web3<span class="token operator">==</span><span class="token number">4.9</span><span class="token number">.1</span>
- docker-compose.yml12345678910111213141516171819<span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">'3.7'</span><span class="token key atrule">services</span><span class="token punctuation">:</span><span class="token key atrule">app</span><span class="token punctuation">:</span><span class="token key atrule">image</span><span class="token punctuation">:</span> dapp<span class="token punctuation">-</span>python<span class="token key atrule">build</span><span class="token punctuation">:</span><span class="token key atrule">context</span><span class="token punctuation">:</span> .<span class="token key atrule">dockerfile</span><span class="token punctuation">:</span> Dockerfile<span class="token key atrule">volumes</span><span class="token punctuation">:</span><span class="token punctuation">-</span> .<span class="token punctuation">:</span>/app<span class="token key atrule">ports</span><span class="token punctuation">:</span><span class="token punctuation">-</span> <span class="token string">'${PUBLIC_PORT}:${PORT}'</span><span class="token key atrule">restart</span><span class="token punctuation">:</span> unless<span class="token punctuation">-</span>stopped<span class="token key atrule">environment</span><span class="token punctuation">:</span><span class="token key atrule">PORT</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>PORT<span class="token punctuation">}</span><span class="token key atrule">PROJECT_ID</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>PROJECT_ID<span class="token punctuation">}</span><span class="token key atrule">ADDRESS</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>ADDRESS<span class="token punctuation">}</span><span class="token key atrule">PRIVATE_KEY</span><span class="token punctuation">:</span> $<span class="token punctuation">{</span>PRIVATE_KEY<span class="token punctuation">}</span>
- .env123456PORT=888PUBLIC_PORT=9999PROJECT_ID=<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>YOUR_INFURA_PROJECT_ID</span><span class="token punctuation">></span></span>ADDRESS=<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>YOUR_ACCOUNT</span><span class="token punctuation">></span></span>PRIVATE_KEY=<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>PRIVATE_KEY</span><span class="token punctuation">></span></span>
- app.py
Ta sẽ tạo một khung app flask với các thư viện như dưới và giả lập các biến như
address
haybalance
để show thử sang bên fileindex.html
xem có được không12345678910111213141516<span class="token keyword">from</span> flask <span class="token keyword">import</span> Flask<span class="token punctuation">,</span> render_template<span class="token punctuation">,</span> request<span class="token punctuation">,</span> url_for<span class="token keyword">from</span> web3 <span class="token keyword">import</span> Web3<span class="token keyword">import</span> osapp <span class="token operator">=</span> Flask<span class="token punctuation">(</span>__name__<span class="token punctuation">,</span> static_folder<span class="token operator">=</span><span class="token string">'static'</span><span class="token punctuation">)</span>address_server<span class="token operator">=</span><span class="token string">"address_server"</span>balance<span class="token operator">=</span><span class="token string">"balance_server"</span>@app<span class="token punctuation">.</span>route<span class="token punctuation">(</span><span class="token string">"/"</span><span class="token punctuation">)</span><span class="token keyword">def</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><span class="token keyword">return</span> render_template<span class="token punctuation">(</span><span class="token string">'index.html'</span><span class="token punctuation">,</span> title<span class="token operator">=</span><span class="token string">'Build Dapp By Python'</span><span class="token punctuation">,</span> address<span class="token operator">=</span>address_server<span class="token punctuation">,</span> balance<span class="token operator">=</span>balance<span class="token punctuation">)</span><span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">"__main__"</span><span class="token punctuation">:</span>app<span class="token punctuation">.</span>run<span class="token punctuation">(</span>host<span class="token operator">=</span><span class="token string">"0.0.0.0"</span><span class="token punctuation">,</span> port<span class="token operator">=</span>os<span class="token punctuation">.</span>environ<span class="token punctuation">[</span><span class="token string">'PORT'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>debug<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span> - templates/index.html
Minh có đã add tý css và ảnh cho nó đỡ xấu vào nên hơi dài tý. Sau đó đổ các biến đã truyền bên server sang cho file
index
như sau12345678910111213141516171819202122232425262728293031323334353637383940<span class="token doctype"><!DOCTYPE html></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>{{ title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://use.fontawesome.com/releases/v5.3.1/css/all.css<span class="token punctuation">"</span></span><span class="token attr-name">integrity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU<span class="token punctuation">"</span></span> <span class="token attr-name">crossorigin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>anonymous<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://fonts.googleapis.com/css?family=Roboto:300,400<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{{ url_for(<span class="token punctuation">'</span>static<span class="token punctuation">'</span>, filename=<span class="token punctuation">'</span>css/style.css<span class="token punctuation">'</span>) }}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form_wrapper<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form_left<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>/static/img/icon.png<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>computer icon<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Address Server:<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h3</span><span class="token punctuation">></span></span>{{ address }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h3</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Balance server:<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h3</span><span class="token punctuation">></span></span> {{ balance }} ETH<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h3</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>/send<span class="token punctuation">"</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>POST<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form_right<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span> Hello, this is a send coin website <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>input_container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>i</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>fas fa-address-book<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>i</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Address<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span> text<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>address<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>field_email<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>input_field<span class="token punctuation">'</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>input_container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>i</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>fas fa-gift<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>i</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Value<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>value<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>field_password<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>input_field<span class="token punctuation">'</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>send<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>input_submit<span class="token punctuation">'</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>input_field<span class="token punctuation">'</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span> - static/css/style.css
Do file này khá dài nên mình chỉ minh họa mấy dòng đầu tiên có gì mọi người vào repo trên github ở cuối bài nha
1234567891011121314151617<span class="token selector">body</span> <span class="token punctuation">{</span><span class="token property">text-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token selector">:root</span> <span class="token punctuation">{</span><span class="token property">--body_gradient_left</span><span class="token punctuation">:</span> #7200d0<span class="token punctuation">;</span><span class="token property">--body_gradient_right</span><span class="token punctuation">:</span> #c800c1<span class="token punctuation">;</span><span class="token property">--form_bg</span><span class="token punctuation">:</span> #ffffff<span class="token punctuation">;</span><span class="token property">--input_bg</span><span class="token punctuation">:</span> #e5e5e5<span class="token punctuation">;</span><span class="token property">--input_hover</span><span class="token punctuation">:</span> #eaeaea<span class="token punctuation">;</span><span class="token property">--submit_bg</span><span class="token punctuation">:</span> #1fcc44<span class="token punctuation">;</span><span class="token property">--submit_hover</span><span class="token punctuation">:</span> #40e263<span class="token punctuation">;</span><span class="token property">--icon_color</span><span class="token punctuation">:</span> #6b6b6b<span class="token punctuation">;</span><span class="token punctuation">}</span>...
Cấu trúc thư mục sẽ có dạng như sau:
Bây giờ chạy cmd docker-compose up --build
để docker tải images và build container cho chúng ta
Như vậy là đã build xong giờ chúng ta sẽ kiểm tra các thư viện install xem đã có chưa bằng cách chiu vào trong docker để xem nha:
- Đầu tiên là kiểm tra xem tên hoặc id của container đang chạy là gì:
docker ps
và ở đây tên nó làdapp_with_python_app_1
- Rồi giờ chiu vào kiểm tra nào :
docker exec dapp_with_python_app_1 pip freeze
có thể hiểu làdocker exec <name_container> <cmd_run>
thì ở đây ta đang kiểm tra xem thư viện thằng pip đã tải về và 2 thứ ta cần đã có
Test xem sao nào
Ngon nghẻ ngay đã có 2 biến là string
được gửi sang và hiển thi ra. Tiếp theo giờ mới là phần quan trọng này đó là thêm phần tương tác với blockchian vào cho application. Một điều cần để ý đó là ở phần kết quả docker-composer
là nó báo đang chạy trên cổng 8888
nhưng thực chất muốn vào web từ browser chúng ta phải vào cổng 9999
vì trong docker-composer mình đã cấu hình là mapping cổng 8888
của container với cổng 9999
của máy thật. Và nếu để ý kỹ mọi người nhìn lại ảnh kết quả của docker ps
ta sẽ thấy
Triển Khai Tương Tác Với Blockchain
Sử dụng web3 để get balance từ blockchian
- app.py12345678910111213141516171819202122232425<span class="token keyword">from</span> flask <span class="token keyword">import</span> Flask<span class="token punctuation">,</span> render_template<span class="token punctuation">,</span> request<span class="token punctuation">,</span> url_for<span class="token keyword">from</span> web3 <span class="token keyword">import</span> Web3<span class="token keyword">import</span> osapp <span class="token operator">=</span> Flask<span class="token punctuation">(</span>__name__<span class="token punctuation">,</span> static_folder<span class="token operator">=</span><span class="token string">'static'</span><span class="token punctuation">)</span><span class="token comment"># Ta sẽ cấu hình sử dụng mang ropsten với PROJECT_ID lấy từ trang infura </span><span class="token comment"># và mình đã đưa nó vào biến môi trường</span>infura_url <span class="token operator">=</span> <span class="token string">"https://ropsten.infura.io/v3/"</span> <span class="token operator">+</span> os<span class="token punctuation">.</span>environ<span class="token punctuation">[</span><span class="token string">'PROJECT_ID'</span><span class="token punctuation">]</span>web3 <span class="token operator">=</span> Web3<span class="token punctuation">(</span>Web3<span class="token punctuation">.</span>HTTPProvider<span class="token punctuation">(</span>infura_url<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token comment"># địa chỉ mình cũng đã đưa vào biến môi trường và get balance </span>address_server<span class="token operator">=</span>os<span class="token punctuation">.</span>environ<span class="token punctuation">[</span><span class="token string">'ADDRESS'</span><span class="token punctuation">]</span>balance <span class="token operator">=</span> web3<span class="token punctuation">.</span>fromWei<span class="token punctuation">(</span>web3<span class="token punctuation">.</span>eth<span class="token punctuation">.</span>getBalance<span class="token punctuation">(</span>address_server<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'ether'</span><span class="token punctuation">)</span>@app<span class="token punctuation">.</span>route<span class="token punctuation">(</span><span class="token string">"/"</span><span class="token punctuation">)</span><span class="token keyword">def</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><span class="token keyword">return</span> render_template<span class="token punctuation">(</span><span class="token string">'index.html'</span><span class="token punctuation">,</span> title<span class="token operator">=</span><span class="token string">'Build Dapp By Python'</span><span class="token punctuation">,</span>address<span class="token operator">=</span>address_server<span class="token punctuation">,</span> balance<span class="token operator">=</span>balance<span class="token punctuation">)</span><span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">"__main__"</span><span class="token punctuation">:</span>app<span class="token punctuation">.</span>run<span class="token punctuation">(</span>host<span class="token operator">=</span><span class="token string">"0.0.0.0"</span><span class="token punctuation">,</span> port<span class="token operator">=</span>os<span class="token punctuation">.</span>environ<span class="token punctuation">[</span><span class="token string">'PORT'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>debug<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span>
Chúng ta sẽ đi từng bước vừa thực hiện vừa test kết quả vậy là địa chỉ và balance đã có
Bây giờ sẽ viết hàm sendCoin
để chuyển tiền. Trước tiên ta cần set private_key
để ký các gia giao gửi và nhận, tham số tiếp theo là nonce
để set vào transaction khi gửi. Tiếp đến chúng ta cần get các params mà bên form gửi về bằng cách sử dụng request
. Sau khi đã có địa chỉ đích address_des
và giá trị cần send value
ta sẽ tạo transaction với các tham số như biến tx
bên dưới. signed_tx
chính là sử dụng private key để ký vào giao dịch. Cuối cùng là thực hiện giao dich với sendRawTransaction
, giá trị nó trả về là một mã hash ta có thể sử dụng mã này lên web blockchain để check transaction bằng mã hash này. Sau khi có được mã hash ta sẽ lên trang web để check transaction. Tất cả các thông số cần hiển thỉ mình sẽ gửi sang cho view send.index
- app.py12345678910111213141516171819202122232425<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>@app<span class="token punctuation">.</span>route<span class="token punctuation">(</span><span class="token string">"/send"</span><span class="token punctuation">,</span> methods<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">'POST'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token keyword">def</span> <span class="token function">sendCoin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>private_key<span class="token operator">=</span>os<span class="token punctuation">.</span>environ<span class="token punctuation">[</span><span class="token string">'PRIVATE_KEY'</span><span class="token punctuation">]</span>nonce <span class="token operator">=</span> web3<span class="token punctuation">.</span>eth<span class="token punctuation">.</span>getTransactionCount<span class="token punctuation">(</span>address_server<span class="token punctuation">)</span>address_des <span class="token operator">=</span> request<span class="token punctuation">.</span>form<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'address'</span><span class="token punctuation">)</span>value <span class="token operator">=</span> request<span class="token punctuation">.</span>form<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'value'</span><span class="token punctuation">)</span>tx <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">'nonce'</span><span class="token punctuation">:</span> nonce<span class="token punctuation">,</span><span class="token string">'to'</span><span class="token punctuation">:</span> address_des<span class="token punctuation">,</span><span class="token string">'value'</span><span class="token punctuation">:</span> web3<span class="token punctuation">.</span>toWei<span class="token punctuation">(</span>value<span class="token punctuation">,</span> <span class="token string">'ether'</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token string">'gas'</span><span class="token punctuation">:</span> <span class="token number">2000000</span><span class="token punctuation">,</span><span class="token string">'gasPrice'</span><span class="token punctuation">:</span> web3<span class="token punctuation">.</span>toWei<span class="token punctuation">(</span><span class="token string">'50'</span><span class="token punctuation">,</span> <span class="token string">'gwei'</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token punctuation">}</span>signed_tx <span class="token operator">=</span> web3<span class="token punctuation">.</span>eth<span class="token punctuation">.</span>account<span class="token punctuation">.</span>signTransaction<span class="token punctuation">(</span>tx<span class="token punctuation">,</span> private_key<span class="token punctuation">)</span>tx_hash <span class="token operator">=</span> web3<span class="token punctuation">.</span>toHex<span class="token punctuation">(</span>web3<span class="token punctuation">.</span>eth<span class="token punctuation">.</span>sendRawTransaction<span class="token punctuation">(</span>signed_tx<span class="token punctuation">.</span>rawTransaction<span class="token punctuation">)</span><span class="token punctuation">)</span>balance_server <span class="token operator">=</span> web3<span class="token punctuation">.</span>fromWei<span class="token punctuation">(</span>web3<span class="token punctuation">.</span>eth<span class="token punctuation">.</span>getBalance<span class="token punctuation">(</span>address_server<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'ether'</span><span class="token punctuation">)</span><span class="token keyword">return</span> render_template<span class="token punctuation">(</span><span class="token string">'send.html'</span><span class="token punctuation">,</span> title<span class="token operator">=</span><span class="token string">'Build Dapp By Python'</span><span class="token punctuation">,</span> tx_hash<span class="token operator">=</span>tx_hash<span class="token punctuation">,</span>address_des<span class="token operator">=</span>address_des<span class="token punctuation">,</span>value<span class="token operator">=</span>value<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
- templates/send.html1234567891011121314151617181920212223242526272829303132333435<span class="token doctype"><!DOCTYPE html></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>{{ title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://use.fontawesome.com/releases/v5.3.1/css/all.css<span class="token punctuation">"</span></span><span class="token attr-name">integrity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU<span class="token punctuation">"</span></span> <span class="token attr-name">crossorigin</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>anonymous<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://fonts.googleapis.com/css?family=Roboto:300,400<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{{ url_for(<span class="token punctuation">'</span>static<span class="token punctuation">'</span>, filename=<span class="token punctuation">'</span>css/style.css<span class="token punctuation">'</span>) }}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form_wrapper<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form_left<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>/static/img/icon.png<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>computer icon<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>tx_hash:<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h3</span><span class="token punctuation">></span></span> {{ tx_hash }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h3</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>form_right<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span> Page Send<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>input_container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>{{address_des}}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>input_container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Value: {{value}} ETH<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>input_submit<span class="token punctuation">'</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>input_field<span class="token punctuation">'</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Back Home<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span>
Xem kết quả nào
- Đầu tiên vào trang
index
nhập các thông tin
- Và kiểm tra cả trên metamark ảnh đầu tiên là địa chỉ server và balance, ảnh tiếp theo sẽ là địa chỉ gửi và balance
- Rồi vây giờ send xem 1 ETH này có được chuyển đến địa chỉ đích hay không
- Mã hash đã được trả về ta có thể lấy mã hash này lên ropsten để check. Nhưng do giao dịch cần phải được confirm nên cần phải sau một khoảng thời gian mới check được thông tin giao dịch. Cách đơn giản nhất là ta kiểm tra thấy balance trong tài khoản metamark đã thay đổi là ta có thể lên check giao dịch
Kết Luận
Vậy là ta đã có một bộ khung để build dapp blockchain với python, mong rằng bài viết này có thể giúp được các bạn trong việc build dapp blockchain với python
Do Python là ngôn ngữ ở phía server nên không giống như các ngôn ngữ client có thể sẽ tương tác trực tiếp với browser để có thể kết nối được với metamark. Nên mình đành dùng cách này để kết nối và ký giao dịch bằng private key trên chính server
Đây là mã nguồn hoàn chỉnh của bài này và mình cũng đã đưa một số hàm khác nữa để phù hợp cho việc phát triển : Repo Github