1 b" a5 z! X; c
- pip install web3.py
2、注册 Infura 获得节点服务
使用邮箱注册 Infura 账户后,创建一个项目,即可获得以太坊节点服务,进入设置即可看到链接的URL' N: j+ W$ }# c$ f6 X$ K H; u
) ?+ Q+ H% r, h0 k# y( v7 N. B
可以选择主网测试网等,会有两个链接,一个是使用HTTPS的一个是使用WebSocket,按你的需求选择一个就行了,注意:Infura 个人免费请求次数,是每天有十万个请求。
3、代码示例 . X1 C( a% [9 i2 @% V% B
- from web3 import Web3
- import json
- import time" |* ~4 u0 F5 c& d
- import os
- import logging
- from django.conf import settings) S2 q% C; A4 K+ r7 Z
- from decimal import Decimal7 r- X% ~% L, j0 }4 V; I! u
- 0 h! C# \/ o F1 u2 L! x1 @
- class PayEthOrToken(object):- \& `% m7 g/ n% w- ]/ Z
-
- def __init__(self):
- # 设置web3
- self.web3 = Web3(Web3.HTTPProvider('your infura http url'))% S# e. i* X. r
- # token合约地址
- self.contract_address = 'your contract address'( i: g; S- H0 b+ h8 c- K& F
- # 主钱包地址
- self.wallet = 'your wallet address'4 Q2 ?* ^' |! c0 u) T! ]* M
- # 钱包的私钥
- self.wallet_key = 'your wallet key'
- # 合约的abi test.json 是eth的abi json文件,可以在eth区块链浏览器上获得
- with open('test.json', 'r') as f:" m- C. W; D: f" v: S5 m
- self.abi = json.loads(f.read())6 i/ ]: |- }7 p3 L0 a/ i
- # 生成合约
- self.contract = self.web3.eth.contract(address=self.contract_address, abi=self.abi)" `4 [; c- V6 Z7 [9 p$ ^ W0 u R3 d
- # 代币简写
- self.token_name = 'USDT'1 O' p Y* P% \
- 3 p a1 K+ ]* l2 X* ?7 K* z0 |
- def transfer_usdt(self, to, value):
- '''进行代币转账" S( [& H9 j* G9 Q& t% j
- args:& O# |2 J8 s. e: Z8 g
- to str:接收代币的地址
- value str/int:代币数量,以ether为单位,可以是字符串和int类型1 O* A. A* @2 L. E" k& Y+ ?+ R
- returns:8 }: P: R. \ P. K( j
- (str, str):返回交易哈希,以及异常信息
- '''
- try:- Q# _4 ?9 M$ q: p1 @& l
- token_balance = self.web3.fromWei(self.contract.functions.balanceOf(self.wallet).call(), 'ether') G! d. v& @3 P! \: ^) O; r
- # 如果代币不足返回异常9 p* I" j1 Q4 j9 v7 y1 f* |' T/ D
- if Decimal(token_balance) < Decimal(value):( `; B% g5 Q0 ~( E( c& Y) O
- return None, 'Platform USDT token is insufficient, please try again later'
- # 进行转账代币2 B5 A' n$ M, Q
- nonce = self.web3.eth.get_transaction_count(self.wallet)
- tx = {
- 'from': self.wallet,
- 'nonce': nonce,
- 'gas': 100000,
- 'gasPrice': self.web3.toWei('50', 'gwei'),/ e; `4 p9 a1 x( B3 h
- 'chainId': 16 m7 u, |& r- Z3 q7 s }) E
- }
- to = Web3.toChecksumAddress(to)
- txn = self.contract.functions.transfer(to, self.web3.toWei(value, 'ether')).buildTransaction(tx)
- signed_txn = self.web3.eth.account.sign_transaction(txn, private_key=self.wallet_key)/ n. D5 v9 V- }
- tx_hash = self.web3.eth.send_raw_transaction(signed_txn.rawTransaction)3 f; J. e4 M5 A( }
- return self.web3.toHex(tx_hash), 'pay success'1 B* n" m/ Z/ X5 j" b: c
- except Exception as e:+ Y( _3 J) l2 C3 n: x
- logging.error(f'转账{self.token_name}代币时发生异常:{e}')1 u- v% l$ r, I6 O% `- }3 R2 j
- logging.exception(e)1 [' @8 \. g2 k+ h* k
- return None, str(e)
- - i- ~. i7 R& [
- def transfer_eth(self, to, value):2 i* e' g' B+ f
- '''进行eth转账
- args:. c3 _' D/ t6 k, Y( L
- to str:接收以太坊的地址8 W% C. _# q: \4 `
- value str/int:数量,以ether为单位,可以是字符串和int类型; n9 ~# p2 j% i4 w
- returns:
- str:返回交易哈希7 e3 h' N& v+ L: q/ C9 z. G+ @
- '''
- try:
- token_balance = self.web3.fromWei(self.web3.eth.get_balance(self.wallet), 'ether')/ X9 f1 ?& c( A- t5 B" u
- # 如果代币不足返回异常( W0 Y4 Z( a. j: P6 l% |
- if Decimal(token_balance) < Decimal(value):: @6 `( M" d" L
- return None, 'Platform ETH token is insufficient, please try again later'# x) B7 W1 k% U" Y
- # 获取 nonce,这个是交易计数
- to = Web3.toChecksumAddress(to)8 @) e$ v. X& `( ~9 ~0 U/ g* L
- nonce = self.web3.eth.get_transaction_count(self.wallet), a$ X8 U/ O" F9 _2 b) h
- tx = {
- 'nonce': nonce,
- 'to': to,) ]% {& W- C* E8 l) L# z
- 'gas': 100000,
- 'gasPrice': self.web3.toWei('50', 'gwei'),
- 'value': self.web3.toWei(value, 'ether'),2 b. k, O2 D+ j! e+ Z5 C. T* S
- 'chainId': 1
- }& V1 l+ ~2 W* H. f# c
- # 签名交易. t9 m! @2 L& G( [; ]4 {; h
- signed_tx = self.web3.eth.account.sign_transaction(tx, self.wallet_key)" Z$ w8 D$ V. J
- 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}')
- logging.exception(e)% ?* Y( `) u0 H) F2 E6 P
- return None, str(e)4 ?& C t7 ?4 Q" K! t