4 F: C& i+ o" ?
- pip install web3.py
: G* q" H2 r6 c
2、注册 Infura 获得节点服务 @! ], y9 x, Q7 K: [1 y# ?
使用邮箱注册 Infura 账户后,创建一个项目,即可获得以太坊节点服务,进入设置即可看到链接的URL
- b6 S) f* Q$ U+ w
可以选择主网测试网等,会有两个链接,一个是使用HTTPS的一个是使用WebSocket,按你的需求选择一个就行了,注意:Infura 个人免费请求次数,是每天有十万个请求。) L0 I5 x/ p6 t& L" X; X3 @% `
3、代码示例 + u. I, a& j3 Q4 ]9 e: K% K
- ; F2 L; a; N8 g" ?# |; c
- from web3 import Web3$ f9 t' Q9 m6 `" J7 p ]: p5 k( A$ J
- import json
- import time
- import os4 c1 I( A. C$ E5 [3 N9 R- L
- import logging
- from django.conf import settings
- from decimal import Decimal
- : U/ S' @* S l6 C# j8 h: Z
- class PayEthOrToken(object):
- 6 A* i9 E: E0 I
- def __init__(self):% b* {4 }2 R: z3 S
- # 设置web33 V# z9 D5 ]$ ~% j
- self.web3 = Web3(Web3.HTTPProvider('your infura http url'))
- # token合约地址4 U" z; H" N1 L8 h0 b
- self.contract_address = 'your contract address'
- # 主钱包地址
- self.wallet = 'your wallet address'+ ?5 y. E7 {, e' J" c* C4 O
- # 钱包的私钥
- self.wallet_key = 'your wallet key'
- # 合约的abi test.json 是eth的abi json文件,可以在eth区块链浏览器上获得
- with open('test.json', 'r') as f:
- self.abi = json.loads(f.read())
- # 生成合约/ J7 h5 ?. x2 S0 i- g/ k, n
- self.contract = self.web3.eth.contract(address=self.contract_address, abi=self.abi)* p* y3 l k; d
- # 代币简写
- self.token_name = 'USDT'
- 2 j* i$ k, v+ [2 g7 Y4 O
- def transfer_usdt(self, to, value):" n4 o& U9 X' |- A: j: {) |- p$ f
- '''进行代币转账
- args:
- to str:接收代币的地址8 E i8 ]1 A9 R+ A& I: s
- value str/int:代币数量,以ether为单位,可以是字符串和int类型4 ~4 u, S/ _: H* e) V+ w3 o1 Y
- returns:2 y/ e' l: X" W" s$ T4 R3 ?7 e1 p! a
- (str, str):返回交易哈希,以及异常信息% |% z# w5 l5 @
- '''
- try:4 L5 W2 R+ n2 E% t0 K
- token_balance = self.web3.fromWei(self.contract.functions.balanceOf(self.wallet).call(), 'ether')
- # 如果代币不足返回异常* H9 ^" x5 }- Q( V# s5 L/ P; M4 w
- if Decimal(token_balance) < Decimal(value):
- return None, 'Platform USDT token is insufficient, please try again later'& K4 R' v6 A; t: Q% N, ]
- # 进行转账代币* t( j* {: z9 z6 J T. g
- nonce = self.web3.eth.get_transaction_count(self.wallet)$ z5 M" m; v9 j( i( e1 d* j) Y
- tx = {
- 'from': self.wallet,5 ?/ l- `: A+ R& V; v1 Q
- 'nonce': nonce,7 b6 K4 H$ g; y. `4 ]0 [- `- u
- 'gas': 100000,( F* [5 }- w# h! D l& Z+ Z* I+ I4 N' V
- 'gasPrice': self.web3.toWei('50', 'gwei'),& W9 L0 S% ], W, K
- 'chainId': 1
- }
- to = Web3.toChecksumAddress(to)
- txn = self.contract.functions.transfer(to, self.web3.toWei(value, 'ether')).buildTransaction(tx)/ {: _+ A; C8 ]& k' R& A
- signed_txn = self.web3.eth.account.sign_transaction(txn, private_key=self.wallet_key)
- tx_hash = self.web3.eth.send_raw_transaction(signed_txn.rawTransaction)4 w! M5 |" F' I9 }% V( A; B
- return self.web3.toHex(tx_hash), 'pay success'2 U9 B( C; w- O' @* C( w8 M
- except Exception as e:5 I# R# p3 k) }% _& k, Z
- logging.error(f'转账{self.token_name}代币时发生异常:{e}')8 j4 h, J* c; _- O4 t: W
- logging.exception(e) {9 U; j* f5 K1 I
- return None, str(e)
- ( M+ t- j: R: B1 i; U
- def transfer_eth(self, to, value):% P5 F v; H* K3 P
- '''进行eth转账+ G4 U0 m7 c' b! D
- args:
- to str:接收以太坊的地址
- value str/int:数量,以ether为单位,可以是字符串和int类型
- returns:
- str:返回交易哈希
- ''': Y% U+ i4 s# U/ N0 Q! N
- try:
- token_balance = self.web3.fromWei(self.web3.eth.get_balance(self.wallet), 'ether'); @& N3 k. i1 }7 Q& j2 C& X1 O2 R
- # 如果代币不足返回异常, `; z* F. \: S% y
- if Decimal(token_balance) < Decimal(value):# D# B9 d% y3 u# a* p1 _/ q
- return None, 'Platform ETH token is insufficient, please try again later'1 [$ [ z9 r0 n) }* M
- # 获取 nonce,这个是交易计数; a6 X0 |; y. w" h' S
- to = Web3.toChecksumAddress(to)
- nonce = self.web3.eth.get_transaction_count(self.wallet)/ Z/ ^) n( E$ q% _
- tx = {" M+ a9 A! ?2 \2 A; I& L
- 'nonce': nonce,
- 'to': to,/ ]1 M6 l& d. K8 k5 R8 l, F# F- ~# B
- 'gas': 100000,
- 'gasPrice': self.web3.toWei('50', 'gwei'),
- 'value': self.web3.toWei(value, 'ether'),4 q5 l( J/ G+ k" g; J' z
- 'chainId': 1
- }$ y' R7 T' X/ x0 m$ Q# v
- # 签名交易6 Z( C& |8 m, A. S$ \" p
- signed_tx = self.web3.eth.account.sign_transaction(tx, self.wallet_key)
- tx_hash = self.web3.eth.send_raw_transaction(signed_tx.rawTransaction)
- return self.web3.toHex(tx_hash), 'pay success'
- except Exception as e:
- logging.error(f'转账eth时发生异常:{e}')% D7 E4 y% J' l7 m
- logging.exception(e)# G; _8 N6 t; e
- return None, str(e)/ g! Q' e0 ~) N



