├── .gitignore ├── LICENSE ├── README.md ├── config.py ├── main.py ├── transfer.py └── value.csv /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | .idea 103 | test -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Primas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pst_transfer 2 | 批量向多个账户进行转账操作 3 | 4 | ## 查看tx 5 | ``` 6 | https://ropsten.etherscan.io/ 7 | ``` 8 | 9 | ## 配置 10 | ``` 11 | passwd #账户密码,用来解锁账户 12 | token_contract_address #token合约地址 13 | account_address #账户地址 14 | eth_rpc #以太坊rpc 15 | TOKEN_ABI #token abi 16 | csv_file #需要转账的数据文件 17 | ``` 18 | 19 | ## 执行 20 | ``` 21 | 配置好配置文件之后 22 | 执行python main.py 会显示转账过程以及tx 23 | ``` 24 | 25 | ## 具体显示结果 26 | ``` 27 | isConnected: True 28 | unlockAccount: True 29 | transfer: 0x04d8692cb9f998d3cff6ebd8fd0ec8531be9e5e0 10 0x234a5c4541f6bd09d15f9c0d64280712715de4d078a97a014f417f2b145dc564 30 | transfer: 0x05e995ec955a3d33bd47ef9b975c7965b52ffce7 10 0x5162e40f627e0224f644420665dcf2ad0cfbf712082de38a13239886724b3a20 31 | transfer: 0x0fc34436261e2d4d3e53765be7ab126f94d5c838 10 0xc1f39f21a3f34472dcc06441e5bcc3e91c0896805153aeedcc6852d6c3db3b95 32 | transfer: 0x10f1de67d86a8dbf9eb381845e630b8c89949f1e 10 0xe0398a23f1fbd2ecf589dc88a5524575730487f5c1b2a34bdf2b256806186544 33 | transfer: 0x13f3c1e0195ed7ca8b953f4494cc3e86d1c4e5a0 10 0x7eeba26dd1f5ca0ff04b18673858ad2fc1db5709cda05f2f43d1bed5682d1946 34 | transfer: 0x1a88503ea0cebfecf06e9f70f0db0c171ee3ddfd 10 0x87a33158884b50b0dc066f21b3c9809b666544b85a8d35cff83fa039fd45217a 35 | transfer: 0x1b8d70fee3df5b0c681c380f08da700c1f3f6b03 10 0x14650bfb667ac16d2abea11ad385398ab0912c4d93fdb9b1a921caa8898a04a6 36 | transfer: 0x200ff3f6a443ae5c730ce6d76ac421d8dabec081 10 0x49215a5c9d7b46ddec596ddc5a983eabb4cd1343682303bec231eb834fd9ce6b 37 | 38 | 39 | [ 40 | { 41 | "account_address": "0x04d8692cb9f998d3cff6ebd8fd0ec8531be9e5e0", 42 | "tx": "0x234a5c4541f6bd09d15f9c0d64280712715de4d078a97a014f417f2b145dc564" 43 | }, 44 | { 45 | "account_address": "0x05e995ec955a3d33bd47ef9b975c7965b52ffce7", 46 | "tx": "0x5162e40f627e0224f644420665dcf2ad0cfbf712082de38a13239886724b3a20" 47 | }, 48 | { 49 | "account_address": "0x0fc34436261e2d4d3e53765be7ab126f94d5c838", 50 | "tx": "0xc1f39f21a3f34472dcc06441e5bcc3e91c0896805153aeedcc6852d6c3db3b95" 51 | }, 52 | { 53 | "account_address": "0x10f1de67d86a8dbf9eb381845e630b8c89949f1e", 54 | "tx": "0xe0398a23f1fbd2ecf589dc88a5524575730487f5c1b2a34bdf2b256806186544" 55 | }, 56 | { 57 | "account_address": "0x13f3c1e0195ed7ca8b953f4494cc3e86d1c4e5a0", 58 | "tx": "0x7eeba26dd1f5ca0ff04b18673858ad2fc1db5709cda05f2f43d1bed5682d1946" 59 | }, 60 | { 61 | "account_address": "0x1a88503ea0cebfecf06e9f70f0db0c171ee3ddfd", 62 | "tx": "0x87a33158884b50b0dc066f21b3c9809b666544b85a8d35cff83fa039fd45217a" 63 | }, 64 | { 65 | "account_address": "0x1b8d70fee3df5b0c681c380f08da700c1f3f6b03", 66 | "tx": "0x14650bfb667ac16d2abea11ad385398ab0912c4d93fdb9b1a921caa8898a04a6" 67 | }, 68 | { 69 | "account_address": "0x200ff3f6a443ae5c730ce6d76ac421d8dabec081", 70 | "tx": "0x49215a5c9d7b46ddec596ddc5a983eabb4cd1343682303bec231eb834fd9ce6b" 71 | } 72 | ] 73 | ``` -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | csv_file = "value.csv" 4 | 5 | passwd = "12345678" 6 | token_contract_address = b"ox123456" 7 | account_address = b'0x123456' 8 | eth_rpc = "https://localhost:8545" 9 | 10 | TOKEN_ABI = json.loads( 11 | """ 12 | [{"constant":true,"inputs":[],"name":"supply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"creationBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initialOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_target","type":"address"},{"name":"_timestamp","type":"uint256"}],"name":"catchYou","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"transfersEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"creationTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_transfersEnabled","type":"bool"}],"name":"enableTransfers","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}] 13 | """ 14 | ) 15 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import json 3 | 4 | from test import config 5 | from transfer import transfer_pst 6 | 7 | if __name__ == '__main__': 8 | tx = [] 9 | with open(config.csv_file) as f: 10 | tx = list(transfer_pst([row for row in csv.DictReader(f)])) 11 | 12 | print("\n\n", json.dumps(tx, sort_keys=True, indent=2)) 13 | -------------------------------------------------------------------------------- /transfer.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from web3 import Web3, HTTPProvider 4 | 5 | from test import config 6 | 7 | web3 = Web3(HTTPProvider(config.eth_rpc)) 8 | web3.eth.defaultAccount = config.account_address 9 | 10 | from web3 import personal as wp 11 | 12 | p = wp.Personal(web3) 13 | print("isConnected:", web3.isConnected()) 14 | print("unlockAccount: ", p.unlockAccount(web3.eth.defaultAccount, config.passwd)) # ropsten 15 | 16 | token_Contract = web3.eth.contract( 17 | abi=config.TOKEN_ABI 18 | ) 19 | 20 | t_contract = token_Contract(address=config.token_contract_address) 21 | 22 | 23 | def transfer_pst(rows): 24 | for row in rows: 25 | p.unlockAccount(web3.eth.defaultAccount, config.passwd, duration=hex(100)) 26 | t = t_contract.transact().transfer(row["address"], int(row["value"]) * 10 ** 18) 27 | print("transfer:", row["address"], row["value"], t) 28 | yield { 29 | "account_address": row["address"], 30 | "tx": t 31 | } 32 | -------------------------------------------------------------------------------- /value.csv: -------------------------------------------------------------------------------- 1 | address,value 2 | 0x04d8692cb9f998d3cff6ebd8fd0ec8531be9e5e0,10 3 | 0x05e995ec955a3d33bd47ef9b975c7965b52ffce7,10 4 | 0x0fc34436261e2d4d3e53765be7ab126f94d5c838,10 5 | 0x10f1de67d86a8dbf9eb381845e630b8c89949f1e,10 6 | 0x13f3c1e0195ed7ca8b953f4494cc3e86d1c4e5a0,10 7 | 0x1a88503ea0cebfecf06e9f70f0db0c171ee3ddfd,10 8 | 0x1b8d70fee3df5b0c681c380f08da700c1f3f6b03,10 9 | 0x200ff3f6a443ae5c730ce6d76ac421d8dabec081,10 --------------------------------------------------------------------------------