initial upload

This commit is contained in:
Luxferre
2024-02-14 23:56:51 +02:00
commit ce7ad5189c
3 changed files with 662 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
kisstron: KISS-friendly Tron CLI wallet
---------------------------------------
This is a simple, no-nonsense Tron cryptocurrency wallet written in Python 3
on top of the open-source tronpy library. The kisstron project aims to enable
CLI users to easily use Tron cryptocurrency, including stablecoins like USDT
or USDC, without all the hassle of "native" (Java-based) Tron's wallet-cli or
similar third-party projects.
== Features ==
* Support for mainnet Tron as well as Nile and Shasta testnets
* Small codebase size that can be easily audited
* Full BIP-39 support for mnemonic wallet generation and import (English only)
* Account info display: TRX/USDT/USDC balances, frozen assets, remaining
energy and bandwidth
* Sending TRX/USDT/USDC on all supported networks
* Freezing (for energy) and unfreezing TRX on all supported networks
* Ability to connect to custom nodes or TronGrid API (with your own API key)
* No filesystem interaction (that's a feature, not a bug: see the FAQ section)
* Full scriptability: send/freeze/unfreeze transactions require manual approval
but it actually can be turned off with a special commandline parameter for the
kisstron wallet to be used in various automation tasks
* The kisstron.py file can be used as a library itself for different projects
== Dependency setup ==
First, install Python 3, pip and the required dependencies (from this dir):
pip install -r requirements.txt
In some distributions, you may need to run pip3 instead of pip. Also, your
distribution might not contain the required development packages. For instance,
in Alpine Linux, you might have to run the following command first (as root):
apk add python3-dev libtool autoconf automake musl-dev libffi-dev
Optionally, make the kisstron.py file executable:
chmod +x kisstron.py
After everything is set up, you should be able to run the help screen:
./kisstron.py -h
== Usage ==
Now, let's cover typical kisstron wallet usage scenarios.
-- Generate a new wallet --
./kisstron.py new trx [-pp "passphrase"] [-wc word_count] [-dp derivation_path]
This will generate a new Tron wallet and display all its information. You must
then store this information in a secure place.
If -pp option is specified, your custom passphrase will be used to encrypt the
mnemonic phrase. If -wc option is specified, you can set to generate 15, 18, 21
or 24 words of mnemonic instead of 12. If -dp option is specified, you can set
a non-standard BIP-39 derivation path. It is generally NOT recommended to ever
use this option unless you are an expert.
-- Import an existing wallet from a mnemonic --
./kisstron.py import trx [-pp "passphrase"] [-dp derivation_path]
This will ask you to enter your BIP-39 mnemonic and import your Tron wallet by
recovering and displaying all information about it. You must then store this
information in a secure place.
If -pp option is specified, your custom passphrase will be used to decrypt the
mnemonic phrase. The -dp option is the same as for the "new trx" subcommand, so
the same precautions apply.
Note that entering a wrong passphrase won't generate an error: kisstron will
just restore a different wallet from the same mnemonic, so be careful.
-- Network options --
For any of the further operations in this section, the following options can
be added and are quite important:
* -net selects the network: mainnet (default), nile, shasta
* -node allows to specify custom Tron node URL (must be HTTP URL, not RPC)
* -tgkey allows to specify custom TronGrid API key (overrides -node)
These options will be marked as [netopts] in the further reference.
Note that -tgkey is only relevant for mainnet and has no effect on testnets.
-- Displaying account information --
Display account information based on any Tron address:
./kisstron.py info trx -addr tron_address [netopts]
Display your account information based on your private key (in hex):
./kisstron.py info trx -pk private_key [netopts]
Either of these commands will display the following information:
* Tron address (in Base58check format)
* Balances in TRX, USDT and USDC
* Frozen TRX assets (if any)
* Remaining bandwidth amount
* Remaining energy amount
If you supply both -pk and -addr to "info trx" subcommand, -pk will take
precedence.
-- Sending funds --
Send TRX:
./kisstron.py send trx -addr dest_addr -amt amount -pk private_key [netopts]
Send USDT:
./kisstron.py send usdt -addr dest_addr -amt amount -pk private_key [netopts]
Send USDC:
./kisstron.py send usdc -addr dest_addr -amt amount -pk private_key [netopts]
Any of these commands will ask you for confirmation by entering "yes" and
pressing Enter to send the transaction. If you don't want to do this or use
the send subcommands in some kind of automation, append -nc flag to them.
The amount is entered in floating point TRX/USDT/USDC values respectively,
not in minimal units.
When transfering USDT/USDC, you may get error messages related to lack of
energy to conduct the transaction. Please refer to the next section of TRX
freezing to get energy.
-- Freezing and unfreezing TRX funds --
Freeze TRX for energy:
./kisstron.py fre trx -amt amount -pk private_key [netopts]
Unfreeze TRX:
./kisstron.py unf trx -amt amount -pk private_key [netopts]
Any of these commands will ask you for confirmation by entering "yes" and
pressing Enter to send the transaction. If you don't want to do this or use
the subcommands in some kind of automation, append -nc flag to them.
Again, the amount of TRX is entered as a floating point value.
Keep in mind that it takes up to 72 hours to unfreeze your TRX assets.
== FAQ ==
- Can I trust it?
The author trusts it. In fact, kisstron was created because of lack of decent
FOSS Tron wallets for Linux/BSD desktop operating systems. However, it cannot
be considered production-ready as it hasn't undergone rigorous testing and
independent audit. The kisstron codebase is small and well-commented though,
so you can trust it exactly to the same extent as you trust the underlying
tronpy library and its dependencies.
You can study tronpy source code here: https://github.com/andelf/tronpy
- Why are TRC-20 tokens hardcoded?
To simplify the logic and avoid any user mistakes when manually pasting token
contract addresses. If you need to add custom token support, you can always
modify the KT_TRC20_TOKENS dictionary in the source code directly.
- Why doesn't kisstron do anything to keep private keys and passphrases secure?
Because it only cares about interacting with Tron network and creating or
restoring your wallets. For key/password management, there are dedicated tools
like pass (https://www.passwordstore.org/) that do their job extremely well.
For example, instead of -pk private_key, you could write -pk $(pass kt/pkey) or
something like that if you stored your wallet key under kt/pkey path in pass.
This way, your keys can stay secure without adding any filesystem interaction
to kisstron itself, reducing the overall attack surface.
- Does kisstron use any remote API to sign transactions?
No. The underlying tronpy library signs all transactions offline, so the
private key never leaves your machine. It uses libsecp256k1 via coincurve
library binding for transaction signing.
Ability to implement offline mode (transactions are created and signed on one
kisstron instance without Internet connectivity, then broadcast from another)
in the future versions is being studied.
- Why doesn't kisstron support TRC-10, multisig, witnesses, history etc?
Support for some of these things may come in the future. But kisstron was
created as a minimum viable wallet to operate on TRX and select stablecoins. It
adheres to the KISS principle ("keep it simple, stupid"), hence the name.
== Credits ==
Created by Luxferre in 2024, released into public domain with no warranties.
Made in Ukraine.
Executable
+459
View File
@@ -0,0 +1,459 @@
#!/usr/bin/env python3
# kisstron: a simple to use TRON CLI wallet based on tronpy
#
# Supports:
# * BIP39 mnemonic wallet generation/restoration
# * converting private keys to BIP39 mnemonics and vice versa
# * basic TRX parameters display (balance, energy, bandwidth)
# * basic TRX operations (transfer, freeze for energy, unfreeze)
# * basic TRC20 token operations (balance display, transfer) for select tokens
# (contract addresses are hardcoded, see KT_TRC20_TOKENS dictionary)
# * ability to select testnets (nile, shasta) if necessary
# * ability to connect to custom mainnet nodes if necessary
# * switching to TronGrid API by providing your own API key
#
# As of now, the main goal is to be able to operate on TRX and stablecoins.
# For mnemonic phrase generation, only English is currently supported.
#
# See README for more information, run with -h flag for usage instructions
#
# Created by Luxferre in 2024, released into public domain
import sys
from tronpy import Tron
from tronpy.keys import PrivateKey
from tronpy.providers import HTTPProvider
from tronpy.exceptions import BadAddress, AddressNotFound, BadKey, ValidationError
import mnemonic, eth_utils
# some global parameters (hardcoded)
KT_TIMEOUT = 20.0 # network operation timeout
KT_FEE_LIMIT = 10000000 # transaction fee limit for mainnet (in Sun)
KT_TEST_FEE_LIMIT = 1000000000 # transaction fee limit for testnets (in Sun)
TRX_SCALE = 1000000.0 # TRX scale (million Suns in 1 TRX)
TG_API_KEY = None # TronGrid API Key (unused by default)
NODE_ADDR = 'http://18.196.99.16:8090' # public Tron node (Germany)
# TRC20 token definitions (also hardcoded)
# Make sure the mainnet tokens match the contract addresses
# specified on these pages:
# USDT: https://tron.network/usdt
# USDC: https://tron.network/usdc
KT_TRC20_TOKENS = {
'mainnet': {
'usdt': {
'contract': 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
'ticker': 'USDT',
'show_balance': True
},
'usdc': {
'contract': 'TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8',
'ticker': 'USDC',
'show_balance': True
}
},
'nile': {
'usdt': {
'contract': 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',
'ticker': 'USDT',
'show_balance': True
},
'usdc': {
'contract': 'TEMVynQpntMqkPxP6wXTW2K7e4sM3cRmWz',
'ticker': 'USDC',
'show_balance': True
}
},
'shasta': {
'usdt': {
'contract': 'TG3XXyExBkPp9nzdajDZsozEu4BkaSJozs',
'ticker': 'USDT',
'show_balance': True
},
'usdc': {
'contract': 'TSdZwNqpHofzP6BsBKGQUWdBeJphLmF6id',
'ticker': 'USDC',
'show_balance': True
}
}
}
# helper functions
# print operation result according to the below convention
def presult(resdict: dict):
if 'success' not in resdict:
resdict['success'] = False
if 'message' not in resdict:
resdict['message'] = ''
if resdict['success'] == True:
print ('Success:\n%s\n' % resdict['message'])
else:
print ('Error:\n%s\n' % resdict['message'])
# confirm transactions
def trconfirm(promptstr: str):
choice = input(promptstr).lower()
if choice != 'yes':
print('Transaction not confirmed, aborting!')
sys.exit(0)
# instantiate tronpy client
def tronclient(network='mainnet'):
network = network.lower() # lowercase network name
if network == 'mainnet': # use a public node or TronGrid API for mainnet
if TG_API_KEY is not None: # TG_API_KEY must be set
client = Tron(network=network, conf={'fee_limit': KT_FEE_LIMIT},
provider=HTTPProvider(api_key=TG_API_KEY, timeout=KT_TIMEOUT))
else: # NODE_ADDR must be set
client = Tron(network=network, conf={'fee_limit': KT_FEE_LIMIT},
provider=HTTPProvider(NODE_ADDR, timeout=KT_TIMEOUT))
else: # any default API is fine for a testnet
client = Tron(network=network,
conf={'fee_limit': KT_TEST_FEE_LIMIT, 'timeout': KT_TIMEOUT})
return client
# get TRC20 token balance of an address (in float)
def trc20balance(client: Tron, contractaddr: str, targetaddr: str):
cntr = client.get_contract(contractaddr)
precision = cntr.functions.decimals()
return cntr.functions['balanceOf'](targetaddr) / (10 ** precision)
# operation definitions
# all operations return a dictionary with the following fields:
# success: True/False
# message: string
# (optional) result: dictionary
# create a new wallet
# input: network, passphrase, word count (12, 15, 18, 21, 24), derivation path
# output: private key, address, mnemonic
def newwallet(network: str, passphrase: str, wordcount: int, dpath: str):
res = {'success': False, 'message': '', 'result': {}}
if wordcount not in [12, 15, 18, 21, 24]:
res['message'] = 'Invalid word count for mnemonic generation'
return res
client = tronclient(network)
wallet, mnemo = client.generate_address_with_mnemonic(passphrase = passphrase,
num_words = wordcount, language = 'english', account_path = dpath)
wallet['mnemonic'] = mnemo
res['success'] = True
res['result'] = wallet
res['message'] = 'Wallet created, save this info in a secure place!\n\n'
res['message'] += 'Address: %s\n' % wallet['base58check_address']
res['message'] += 'Address (hex): %s\n' % wallet['hex_address']
res['message'] += 'Private key (hex): %s\n' % wallet['private_key']
res['message'] += 'Public key (hex): %s\n' % wallet['public_key']
res['message'] += 'Mnemonic: %s' % wallet['mnemonic']
return res
# import a wallet
# input: network, mnemonic, passphrase, derivation path
# output: private key, address
def importwallet(network: str, mnemo: str, passphrase: str, dpath: str):
res = {'success': False, 'message': '', 'result': {}}
client = tronclient(network)
try:
wallet = client.generate_address_from_mnemonic(mnemonic = mnemo,
passphrase = passphrase, account_path = dpath)
except (mnemonic.mnemonic.ConfigurationError,
eth_utils.exceptions.ValidationError):
res['message'] = 'Invalid mnemonic phrase!'
return res
wallet['mnemonic'] = mnemo
res['success'] = True
res['result'] = wallet
res['message'] = 'Wallet imported, save this info in a secure place!\n\n'
res['message'] += 'Address: %s\n' % wallet['base58check_address']
res['message'] += 'Address (hex): %s\n' % wallet['hex_address']
res['message'] += 'Private key (hex): %s\n' % wallet['private_key']
res['message'] += 'Public key (hex): %s\n' % wallet['public_key']
res['message'] += 'Mnemonic: %s' % wallet['mnemonic']
return res
# get account information by Tron address
# input: network, address
# output: info(dictionary)
def infobyaddr(network: str, address: str):
res = {'success': False, 'message': '', 'result': {}}
client = tronclient(network)
try:
rawinfo = client.get_account(address)
except BadAddress:
res['message'] = 'Invalid address! Set the correct one with -addr flag'
return res
except AddressNotFound:
res['message'] = 'Address not found on the blockchain! Set the correct one with -addr flag'
return res
# get bandwidth and energy information
rawresinfo = client.get_account_resource(address)
# some values used in bandwidth calculation
freenetlimit = 0
freenetused = 0
netlimit = 0
netused = 0
if 'freeNetLimit' in rawresinfo:
freenetlimit = rawresinfo['freeNetLimit']
if 'freeNetUsed' in rawresinfo:
freenetlimit = rawresinfo['freeNetUsed']
if 'NetLimit' in rawresinfo:
netlimit = rawresinfo['NetLimit']
if 'NetUsed' in rawresinfo:
netused = rawresinfo['NetUsed']
bandwidth = freenetlimit - freenetused + netlimit - netused
# some values used in energy calculation
energylimit = 0
energyused = 0
if 'EnergyLimit' in rawresinfo:
energylimit = rawresinfo['EnergyLimit']
if 'EnergyUsed' in rawresinfo:
energyused = rawresinfo['EnergyUsed']
# info dictionary received, parse it
info = {
'address': rawinfo['address'], # wallet address
'trxbalance': rawinfo['balance'], # TRX wallet balance (in Sun)
'frozen': [], # hold frozen TRX info here
'trc20balance': {}, # hold TRC20 token balances here
'bandwidth': bandwidth, # bandwidth
'energy': energylimit - energyused # energy
}
# iterate over TRX freeze records
for el in rawinfo['frozenV2']:
if 'type' in el and 'amount' in el and el['amount'] > 0:
info['frozen'].append({'type': el['type'], 'amount': el['amount']})
# iterate over hardcoded TRC20 tokens
for tkn in KT_TRC20_TOKENS[network]:
tknobj = KT_TRC20_TOKENS[network][tkn]
if tknobj['show_balance'] == True:
info['trc20balance'][tknobj['ticker']] = trc20balance(client,
tknobj['contract'], address)
res['success'] = True
res['result'] = info
res['message'] = 'Address: %s\nBalance:\n' % info['address']
res['message'] += '%f TRX\n' % (info['trxbalance'] / TRX_SCALE)
for ticker in info['trc20balance']:
res['message'] += '%f %s\n' % (info['trc20balance'][ticker], ticker)
res['message'] += 'Frozen assets:\n'
for el in info['frozen']:
res['message'] += '%s\t%f TRX\n' % (el['type'], el['amount'] / TRX_SCALE)
res['message'] += 'Remaining bandwidth: %s\n' % str(info['bandwidth'])
res['message'] += 'Remaining energy: %s' % str(info['energy'])
return res
# get own account information by private key
# input: network, private key
# output: info(dictionary)
def infobypk(network: str, pk: str):
res = {'success': False, 'message': '', 'result': {}}
try:
rpk = PrivateKey(bytes.fromhex(pk))
except (BadKey, ValueError):
res['message'] = 'Invalid private key!'
return res
client = tronclient(network)
addr = client.generate_address(rpk)['base58check_address']
return infobyaddr(network, addr)
# send TRX transaction (and wait for its completion)
# input: network, private key, target address, amount (in TRX)
# output: transaction receipt object
def sendtrx(network: str, pk: str, toaddr: str, amt: float):
res = {'success': False, 'message': '', 'result': {}}
if amt < 1:
res['message'] = 'Nothing to transfer!'
return res
try:
rpk = PrivateKey(bytes.fromhex(pk))
except (BadKey, ValueError):
res['message'] = 'Invalid private key!'
return res
client = tronclient(network)
fromaddr = client.generate_address(rpk)['base58check_address']
# build and sign the transaction
txn = client.trx.transfer(fromaddr, toaddr,
int(amt * TRX_SCALE)).build().sign(rpk)
# send the transaction
try:
receipt = txn.broadcast().wait()
except ValidationError:
res['message'] = 'Insufficient balance or other validation error!'
return res
res['success'] = True
res['message'] = 'Sent %f TRX to %s\nTransaction ID %s' % (amt,
toaddr, receipt['id'])
res['result'] = receipt
return res
# send TRC20 token transaction (and wait for its completion)
# input: network, private key, token ticker, target address, amount (in tokens)
# output: transaction receipt object
def sendtrc20(network: str, pk: str, ticker: str, toaddr: str, amt: float):
res = {'success': False, 'message': '', 'result': {}}
ticker = ticker.lower()
if ticker not in KT_TRC20_TOKENS[network]:
res['message'] = 'Token not supported by kisstron for %s!' % network
return res
if amt < 1:
res['message'] = 'Nothing to transfer!'
return res
try:
rpk = PrivateKey(bytes.fromhex(pk))
except (BadKey, ValueError):
res['message'] = 'Invalid private key!'
return res
client = tronclient(network)
fromaddr = client.generate_address(rpk)['base58check_address']
# instantiate the contract
contractaddr = KT_TRC20_TOKENS[network][ticker]['contract']
cntr = client.get_contract(contractaddr)
precision = cntr.functions.decimals()
scaler = 10 ** precision
# build and sign the transaction
txn = cntr.functions.transfer(toaddr,
int(amt * scaler)).with_owner(fromaddr).build().sign(rpk)
# send the transaction
try:
receipt = txn.broadcast().wait()
except ValidationError:
res['message'] = 'Insufficient balance or other validation error!'
return res
res['result'] = receipt
if receipt['receipt']['result'] == 'OUT_OF_ENERGY':
res['message'] = 'Not enough energy for transaction!'
return res
res['success'] = True
res['message'] = 'Sent %f %s to %s\nTransaction ID %s' % (amt,
KT_TRC20_TOKENS[network][ticker]['ticker'],
toaddr, receipt['id'])
return res
# freeze TRX for energy (and wait for its completion)
# input: network, private key, amount
# output: transaction receipt object
def freezetrx(network: str, pk: str, amt: float):
res = {'success': False, 'message': '', 'result': {}}
if amt < 1:
res['message'] = 'Nothing to freeze!'
return res
try:
rpk = PrivateKey(bytes.fromhex(pk))
except (BadKey, ValueError):
res['message'] = 'Invalid private key!'
return res
client = tronclient(network)
myaddr = client.generate_address(rpk)['base58check_address']
# build and sign the transaction
txn = client.trx.freeze_balance(myaddr, int(amt * TRX_SCALE),
"ENERGY").build().sign(rpk)
# send the transaction
try:
receipt = txn.broadcast().wait()
except ValidationError:
res['message'] = 'Insufficient balance or other validation error!'
return res
res['success'] = True
res['message'] = 'Frozen %f TRX at %s\nTransaction ID %s' % (amt,
myaddr, receipt['id'])
res['result'] = receipt
return res
# unfreeze TRX for energy (and wait for its completion)
# input: network, private key, amount
# output: transaction receipt object
def unfreezetrx(network: str, pk: str, amt: float):
res = {'success': False, 'message': '', 'result': {}}
if amt < 1:
res['message'] = 'Nothing to unfreeze!'
return res
try:
rpk = PrivateKey(bytes.fromhex(pk))
except (BadKey, ValueError):
res['message'] = 'Invalid private key!'
return res
client = tronclient(network)
myaddr = client.generate_address(rpk)['base58check_address']
# build and sign the transaction
txn = client.trx.unfreeze_balance(owner = myaddr,
unfreeze_balance = int(amt * TRX_SCALE),
resource = "ENERGY").build().sign(rpk)
# send the transaction
try:
receipt = txn.broadcast().wait()
except ValidationError:
res['message'] = 'Insufficient balance or other validation error!'
return res
res['success'] = True
res['message'] = 'Unfrozen %f TRX at %s\nTransaction ID %s' % (amt,
myaddr, receipt['id'])
res['result'] = receipt
return res
if __name__ == '__main__': # main app start
from argparse import ArgumentParser
parser = ArgumentParser(description='kisstron: a simple CLI wallet for Tron blockchain', epilog='(c) Luxferre 2024 --- No rights reserved <https://unlicense.org>')
parser.add_argument('op', help='Operation: new, import, info, send, fre[eze], unf[reeze]')
parser.add_argument('coin', help='Coin to operate on: trx (default), usdt, usdc', default='trx')
parser.add_argument('-net', '--network', default='mainnet', help='(op: all) Network: mainnet (default), nile, shasta')
parser.add_argument('-node', '--tron-node', default=NODE_ADDR, help='(op: all) Custom Tron node HTTP address (default %s)' % NODE_ADDR)
parser.add_argument('-tgkey', '--trongrid-api-key', default=None, help='(op: all) TronGrid API key (default None)')
parser.add_argument('-addr', '--address', default=None, help='(op: info, send) Tron address to send to or display information about (-pk overrides this to display own info)')
parser.add_argument('-amt', '--amount', type=float, default=0, help='(op: send, fre, unf) Amount to send/freeze/unfreeze')
parser.add_argument('-pk', '--private-key', default=None, help='(op: info, send, fre, unf) Private key for transactions or own information, in hex')
parser.add_argument('-pp', '--passphrase', default='', help='(op: new, import) Mnemonic encryption passphrase (default empty)')
parser.add_argument('-wc', '--words-count', type=int, default=12, help='(op: new) Word count in the mnemonic: 12 (default), 15, 18, 21, 24')
parser.add_argument('-dp', '--derivation-path', default="m/44'/195'/0'/0/0", help="(op: new, import) BIP-39 derivation path for mnemonic (default is m/44'/195'/0'/0/0)")
parser.add_argument('-nc', '--no-confirm', action='store_true', help='(op: send, fre, unf) Do not ask to type "yes" for transaction confirmation (dangerous)')
args = parser.parse_args()
# fix all relevant parameters (and lowercase where applicable)
op = args.op.lower() # operation
coin = args.coin.lower() # coin/token
tronnet = args.network.lower() # Tron network (mainnet, nile, shasta)
targetaddr = args.address # address parameter
amount = float(args.amount) # amount to send/freeze/unfreeze
pk = args.private_key # private key (in hex)
passphrase = args.passphrase # mnemonic encryption passphrase
wcount = int(args.words_count) # mnemonic word count (for new operation)
dpath = args.derivation_path # mnemonic derivation path (for new/import)
trans_confirm = True # ask for transaction confirmation ("yes")
NODE_ADDR = args.tron_node # custom Tron node HTTP address
TG_API_KEY = args.trongrid_api_key # optional TronGrid API key
if args.no_confirm == True:
trans_confirm = False
# check the constraints for every action and call appropriate functions
opres = {} # operation result placeholder
if op == 'new': # new wallet
opres = newwallet(tronnet, passphrase, wcount, dpath)
elif op == 'import': # import wallet
mnemo = input('Your mnemonic phrase: ')
opres = importwallet(tronnet, mnemo, passphrase, dpath)
elif op == 'info': # info on own or foreign address
if pk == None: # public info, address must be set
opres = infobyaddr(tronnet, targetaddr)
else: # own info, private key must be set
opres = infobypk(tronnet, pk)
elif op == 'send': # send transaction
if trans_confirm == True:
trconfirm('Enter "yes" to confirm sending funds: ')
if coin == 'trx': # send TRX
opres = sendtrx(tronnet, pk, targetaddr, amount)
else: # send one of the predefined TRC20 tokens
opres = sendtrc20(tronnet, pk, coin, targetaddr, amount)
elif op == 'fre' or op == 'freeze': # freeze TRX for energy
if trans_confirm == True:
trconfirm('Enter "yes" to confirm freezing funds: ')
opres = freezetrx(tronnet, pk, amount)
elif op == 'unf' or op == 'unfreeze': # unfreeze TRX
if trans_confirm == True:
trconfirm('Enter "yes" to confirm unfreezing funds: ')
opres = unfreezetrx(tronnet, pk, amount)
else: # unknown operation
print('Unknown operation!')
print('Run the script with -h parameter to see available options')
sys.exit(1)
presult(opres) # print out the result
+7
View File
@@ -0,0 +1,7 @@
cffi>=1.16.0
coincurve>=18.0.0
cytoolz>=0.12.3
mnemonic>=0.20
pycryptodome>=3.18.0
pycryptodomex>=3.18.0
tronpy>=0.4.0