2020-11-17 19:23:57 +01:00
""" Deploys giftable token, and optionally gifts a set amount to all accounts in wallet
. . moduleauthor : : Louis Holbrook < dev @holbrook.no >
. . pgp : : 0826 EDA1702D1E87C6E2875121D2E7BB88C2A746
"""
# SPDX-License-Identifier: GPL-3.0-or-later
# standard imports
2021-01-09 01:24:03 +01:00
import sys
2020-12-01 23:54:17 +01:00
import os
2020-11-17 19:23:57 +01:00
import json
import argparse
import logging
2021-01-09 01:24:03 +01:00
import time
2020-11-17 19:23:57 +01:00
# third-party imports
import web3
2021-01-09 01:24:03 +01:00
from eth_keys import keys
2020-11-17 19:23:57 +01:00
logging . basicConfig ( level = logging . WARNING )
logg = logging . getLogger ( )
logging . getLogger ( ' web3 ' ) . setLevel ( logging . WARNING )
logging . getLogger ( ' urllib3 ' ) . setLevel ( logging . WARNING )
2020-12-11 16:45:01 +01:00
script_dir = os . path . dirname ( __file__ )
data_dir = os . path . join ( script_dir , ' .. ' , ' data ' )
2021-01-09 01:24:03 +01:00
2020-11-17 19:23:57 +01:00
argparser = argparse . ArgumentParser ( )
argparser . add_argument ( ' -p ' , ' --provider ' , dest = ' p ' , default = ' http://localhost:8545 ' , type = str , help = ' Web3 provider url (http only) ' )
2021-01-09 01:24:03 +01:00
argparser . add_argument ( ' -w ' , action = ' store_true ' , help = ' Wait for the last transaction to be confirmed ' )
argparser . add_argument ( ' -ww ' , action = ' store_true ' , help = ' Wait for every transaction to be confirmed ' )
argparser . add_argument ( ' -e ' , action = ' store_true ' , help = ' Treat all transactions as essential ' )
argparser . add_argument ( ' -i ' , ' --chain-spec ' , dest = ' i ' , type = str , default = ' Ethereum:1 ' , help = ' Chain specification string ' )
argparser . add_argument ( ' -y ' , ' --key-file ' , dest = ' y ' , type = str , help = ' Ethereum keystore file to use for signing ' )
argparser . add_argument ( ' --name ' , dest = ' n ' , default = ' Giftable Token ' , type = str , help = ' Token name ' )
argparser . add_argument ( ' --symbol ' , dest = ' s ' , default = ' GFT ' , type = str , help = ' Token symbol ' )
argparser . add_argument ( ' --decimals ' , dest = ' d ' , default = 18 , type = int , help = ' Token decimals ' )
argparser . add_argument ( ' --account ' , action = ' append ' , type = str , help = ' Account to fund ' )
argparser . add_argument ( ' --minter ' , action = ' append ' , type = str , help = ' Minter to add ' )
2020-12-11 16:45:01 +01:00
argparser . add_argument ( ' --abi-dir ' , dest = ' abi_dir ' , type = str , default = data_dir , help = ' Directory containing bytecode and abi (default: {} ) ' . format ( data_dir ) )
2020-11-17 19:23:57 +01:00
argparser . add_argument ( ' -v ' , action = ' store_true ' , help = ' Be verbose ' )
argparser . add_argument ( ' amount ' , type = int , help = ' Initial token supply (will be owned by contract creator) ' )
args = argparser . parse_args ( )
if args . v :
logg . setLevel ( logging . DEBUG )
2021-01-09 01:24:03 +01:00
block_mode = 0
if args . ww :
logg . debug ( ' set block after each tx ' )
block_mode = 2
elif args . w :
logg . debug ( ' set block until last tx ' )
block_mode = 1
w3 = web3 . Web3 ( web3 . Web3 . HTTPProvider ( args . p ) )
private_key = None
signer_address = None
if args . y != None :
logg . debug ( ' loading keystore file {} ' . format ( args . y ) )
f = open ( args . y , ' r ' )
encrypted_key = f . read ( )
f . close ( )
private_key = w3 . eth . account . decrypt ( encrypted_key , ' ' )
private_key_object = keys . PrivateKey ( private_key )
signer_address = private_key_object . public_key . to_checksum_address ( )
logg . debug ( ' now have key for signer address {} ' . format ( signer_address ) )
network_pair = args . i . split ( ' : ' )
network_id = int ( network_pair [ 1 ] )
def waitFor ( tx_hash ) :
i = 1
while True :
try :
return w3 . eth . getTransactionReceipt ( tx_hash )
except web3 . exceptions . TransactionNotFound :
logg . debug ( ' poll # {} for {} ' . format ( i , tx_hash . hex ( ) ) )
i + = 1
time . sleep ( 1 )
2020-12-01 23:54:17 +01:00
def main ( ) :
2020-11-17 19:23:57 +01:00
2020-12-18 10:34:45 +01:00
f = open ( os . path . join ( args . abi_dir , ' GiftableToken.json ' ) , ' r ' )
2020-11-17 19:23:57 +01:00
abi = json . load ( f )
f . close ( )
2020-12-11 16:42:47 +01:00
f = open ( os . path . join ( args . abi_dir , ' GiftableToken.bin ' ) , ' r ' )
2020-11-17 19:23:57 +01:00
bytecode = f . read ( )
f . close ( )
2021-01-09 01:24:03 +01:00
gas_price = w3 . eth . gasPrice
last_tx = None
nonce = w3 . eth . getTransactionCount ( signer_address , ' pending ' )
2020-11-17 19:23:57 +01:00
c = w3 . eth . contract ( abi = abi , bytecode = bytecode )
2021-01-09 01:24:03 +01:00
tx = c . constructor ( args . n , args . s , args . d ) . buildTransaction ( {
' chainId ' : network_id ,
' gas ' : 1500000 ,
' gasPrice ' : gas_price ,
' nonce ' : nonce ,
} ) #transact()
signed_tx = w3 . eth . account . sign_transaction ( tx , private_key )
tx_hash = w3 . eth . sendRawTransaction ( signed_tx . rawTransaction )
last_tx = tx_hash
rcpt = waitFor ( tx_hash )
if rcpt [ ' status ' ] == 0 :
logg . critial ( ' constructor transaction failed {} ' . format ( tx_hash ) )
sys . exit ( 1 )
else :
logg . info ( ' constructor succeeded. gas used: {} ' . format ( rcpt [ ' gasUsed ' ] ) )
2020-11-17 19:23:57 +01:00
address = rcpt . contractAddress
2021-01-09 01:24:03 +01:00
logg . debug ( ' token contract mined {} {} {} {} ' . format ( address , args . n , args . s , args . d ) )
2020-11-17 19:23:57 +01:00
c = w3 . eth . contract ( abi = abi , address = address )
2021-01-09 01:24:03 +01:00
balance = c . functions . balanceOf ( signer_address ) . call ( )
logg . info ( ' balance {} : {} {} ' . format ( signer_address , balance , tx_hash . hex ( ) ) )
2020-11-30 11:37:58 +01:00
2021-01-09 01:24:03 +01:00
if args . account != None :
for a in args . account :
if a == signer_address :
2020-11-17 19:23:57 +01:00
continue
2021-01-09 01:24:03 +01:00
nonce + = 1
tx = c . functions . mint ( args . amount ) . buildTransaction ( {
' chainId ' : network_id ,
' gas ' : 70000 ,
' gasPrice ' : gas_price ,
' nonce ' : nonce ,
} )
signed_tx = w3 . eth . account . sign_transaction ( tx , private_key )
tx_hash_mint = w3 . eth . sendRawTransaction ( signed_tx . rawTransaction )
last_tx = tx_hash_mint
logg . info ( ' mint to {} tx {} ' . format ( a , tx_hash_mint . hex ( ) ) )
if block_mode == 2 :
rcpt = waitFor ( tx_hash_mint )
if rcpt [ ' status ' ] == 0 :
logg . error ( ' mint failed: {} ' . format ( tx_hash_mint . hex ( ) ) )
if args . e :
sys . exit ( 1 )
else :
logg . info ( ' mint succeeded. gas used: {} ' . format ( rcpt [ ' gasUsed ' ] ) )
nonce + = 1
tx = c . functions . transfer ( a , args . amount ) . buildTransaction ( {
' chainId ' : network_id ,
' gas ' : 40000 ,
' gasPrice ' : gas_price ,
' nonce ' : nonce ,
} )
signed_tx = w3 . eth . account . sign_transaction ( tx , private_key )
tx_hash_transfer = w3 . eth . sendRawTransaction ( signed_tx . rawTransaction )
last_tx = tx_hash_transfer
logg . info ( ' trasnfer to {} tx {} ' . format ( a , tx_hash_mint . hex ( ) ) )
if block_mode == 2 :
rcpt = waitFor ( tx_hash_transfer )
balance = c . functions . balanceOf ( a ) . call ( )
logg . info ( ' balance {} : {} ' . format ( a , balance ) )
if rcpt [ ' status ' ] == 0 :
logg . error ( ' transfer failed: {} ' . format ( tx_hash_mint . hex ( ) ) )
if args . e :
sys . exit ( 1 )
else :
logg . info ( ' transfer succeeded. gas used: {} ' . format ( rcpt [ ' gasUsed ' ] ) )
if args . minter != None :
for a in args . minter :
if a == signer_address :
2020-12-06 14:12:49 +01:00
continue
2021-01-09 01:24:03 +01:00
nonce + = 1
tx = c . functions . addMinter ( a ) . buildTransaction ( {
' chainId ' : network_id ,
' gas ' : 50000 ,
' gasPrice ' : 1000000000000 ,
' nonce ' : nonce ,
} )
signed_tx = w3 . eth . account . sign_transaction ( tx , private_key )
tx_hash_minter = w3 . eth . sendRawTransaction ( signed_tx . rawTransaction )
last_tx = tx_hash_minter
logg . info ( ' minter add {} tx {} ' . format ( a , tx_hash_minter . hex ( ) ) )
if block_mode == 2 :
rcpt = waitFor ( tx_hash_minter )
balance = c . functions . balanceOf ( a ) . call ( )
if rcpt [ ' status ' ] == 0 :
logg . error ( ' minter add failed: {} ' . format ( tx_hash_minter ) )
if args . e :
sys . exit ( 1 )
else :
logg . info ( ' minter add succeeded. gas used: {} ' . format ( rcpt [ ' gasUsed ' ] ) )
if block_mode > 0 :
rcpt = waitFor ( last_tx )
if rcpt [ ' status ' ] == 0 :
logg . error ( ' failed: {} ' . format ( tx_hash_mint . hex ( ) ) )
if args . e :
sys . exit ( 1 )
2020-12-06 14:12:49 +01:00
2020-11-17 19:23:57 +01:00
print ( address )
2021-01-09 01:24:03 +01:00
sys . exit ( 0 )
2020-12-01 23:54:17 +01:00
if __name__ == ' __main__ ' :
main ( )