% \* r1 Z8 l4 Q& E4 Y5 Z
- pip install web3.py
+ V o+ a6 D. P: w) q
2、注册 Infura 获得节点服务( E) ~5 ^4 M/ J8 d6 g/ W
使用邮箱注册 Infura 账户后,创建一个项目,即可获得以太坊节点服务,进入设置即可看到链接的URL9 b( {# G' p; u# |8 x6 _

可以选择主网测试网等,会有两个链接,一个是使用HTTPS的一个是使用WebSocket,按你的需求选择一个就行了,注意:Infura 个人免费请求次数,是每天有十万个请求。
3、代码示例 % \3 m! S9 o" }
- from web3 import Web3
- import json
- import time
- import os0 {2 L6 f* z8 H/ l
- import logging
- from django.conf import settings
- from decimal import Decimal
- ' U3 V# E! s( P3 g' e& n7 }
- class PayEthOrToken(object):
-
- def __init__(self):7 I" q w' @; [; z
- # 设置web3- a- r; l3 d5 {# I# D1 A3 I" U
- self.web3 = Web3(Web3.HTTPProvider('your infura http url'))
- # token合约地址
- self.contract_address = 'your contract address'0 c5 W6 c& p6 O* L/ d/ d% p
- # 主钱包地址: A' T$ y1 P$ _* p2 g" E& M
- self.wallet = 'your wallet address'
- # 钱包的私钥# V4 I6 a$ N" m8 |
- self.wallet_key = 'your wallet key'
- # 合约的abi test.json 是eth的abi json文件,可以在eth区块链浏览器上获得 u- ~) b1 y3 Q$ P8 m8 D
- with open('test.json', 'r') as f:% |1 l/ }) z! O, {" o7 o! o
- self.abi = json.loads(f.read()), ]7 f4 p8 ]. f: F. m
- # 生成合约
- self.contract = self.web3.eth.contract(address=self.contract_address, abi=self.abi)
- # 代币简写2 v4 ^$ g; |0 p4 r7 E B8 M! y
- self.token_name = 'USDT'
- - T) ^) ~5 X2 z" {- M: |
- def transfer_usdt(self, to, value):
- '''进行代币转账
- args:
- to str:接收代币的地址2 }7 j' I! D- Z2 |/ D2 ~. l
- value str/int:代币数量,以ether为单位,可以是字符串和int类型
- returns:. J- S1 J- Y2 P" K' ?. J% f4 S
- (str, str):返回交易哈希,以及异常信息
- ''', T* v3 h# M( l* ^+ X3 f3 H+ y
- try:- }) y- A0 ^( \( J1 \
- token_balance = self.web3.fromWei(self.contract.functions.balanceOf(self.wallet).call(), 'ether')( v9 u3 \; H. h. |. j, H
- # 如果代币不足返回异常. K- I4 ^, B7 Q0 @, {' [9 P& Q6 h" E
- if Decimal(token_balance) < Decimal(value):( d' d+ G5 i) D" P1 B
- return None, 'Platform USDT token is insufficient, please try again later'% K8 M( g+ q& V7 z0 c
- # 进行转账代币- z; s/ s0 M# R" \4 C
- nonce = self.web3.eth.get_transaction_count(self.wallet); U$ I' G7 W+ J& A5 d/ |* V# X ]7 `
- tx = {; l; J3 ]) ]' _1 {- _
- 'from': self.wallet,8 l; I9 D+ @( o' l# \
- 'nonce': nonce,: i$ q( L1 e( B! X
- 'gas': 100000,) t' P: ?' r/ Z- t! ]
- 'gasPrice': self.web3.toWei('50', 'gwei'),' e0 |4 G' x2 l
- 'chainId': 15 [, e, r) |4 ^ z4 N0 z/ B- g
- }7 }, n. ]: o Y1 t( X% J1 i
- to = Web3.toChecksumAddress(to)& W8 V+ n9 a! _
- txn = self.contract.functions.transfer(to, self.web3.toWei(value, 'ether')).buildTransaction(tx)$ g4 N5 ]- l+ Y4 J9 l( D3 E. c. z$ s
- 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)
- return self.web3.toHex(tx_hash), 'pay success'5 N& m ^! a' X2 G- Y$ ]6 Q S2 T* }$ T
- except Exception as e:* }& p9 Q) B8 f8 W
- logging.error(f'转账{self.token_name}代币时发生异常:{e}')
- logging.exception(e)
- return None, str(e)
-
- def transfer_eth(self, to, value):
- '''进行eth转账
- args:
- to str:接收以太坊的地址
- value str/int:数量,以ether为单位,可以是字符串和int类型
- returns:
- str:返回交易哈希
- '''( R, [4 i& u( R' n4 a E
- try:* d: W+ P9 c9 V+ _: H+ |
- token_balance = self.web3.fromWei(self.web3.eth.get_balance(self.wallet), 'ether')
- # 如果代币不足返回异常3 _& o8 v# A }: Z4 f- ^ G
- if Decimal(token_balance) < Decimal(value):
- return None, 'Platform ETH token is insufficient, please try again later'
- # 获取 nonce,这个是交易计数- Y: [$ L K6 e/ W7 v- ?7 P; M
- to = Web3.toChecksumAddress(to)
- nonce = self.web3.eth.get_transaction_count(self.wallet)
- tx = {
- 'nonce': nonce,8 c) t! o; `+ {0 o; T2 r
- 'to': to,7 F; ^4 }% I0 B0 i# `* \
- 'gas': 100000," n+ \) i' X! K% g& e7 ~$ q
- 'gasPrice': self.web3.toWei('50', 'gwei'),/ v7 A+ a1 b& x7 B: a
- 'value': self.web3.toWei(value, 'ether'),
- 'chainId': 1
- }
- # 签名交易' y2 l/ ?, j0 J# }3 @
- 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:% d) K( o9 V$ d( T( D6 ?9 j0 p
- logging.error(f'转账eth时发生异常:{e}')
- logging.exception(e)
- return None, str(e)