def login(username, password): st = steem.Steem(['https://ws.testnet3.golos.io']) if not st.steemd.login(username, password): return None private_key = PasswordKey(username, password, 'posting') st.commit.wallet.setKeys(str(private_key.get_private())) return User(username, password, st)
def __init__(self): self._steem = steem.Steem(['https://ws.testnet3.golos.io']) self._username = '******' self._password = '******' if not self._steem.steemd.login(self._username, self._password): raise RuntimeError('ChainMaster login failed!') key = PasswordKey(self._username, self._password, 'posting') self._steem.commit.wallet.setKeys(str(key.get_private()))
def wallet(): import_wifForm = forms.ImportWifKey() import_accountpwd = forms.ImportAccountPassword() if request.method == 'POST' and steem.wallet.locked(): flash("Wallet is locked!") elif request.method == 'POST' and "import_wif" in request.form: if import_wifForm.validate(): steem.wallet.addPrivateKey(import_wifForm.wif.data) elif request.method == 'POST' and "import_accountpwd" in request.form: if import_accountpwd.validate(): from steembase.account import PasswordKey keyImported = False for role in ["active", "posting", "memo"]: # do not add owner key! priv = PasswordKey(import_accountpwd.accountname.data, import_accountpwd.password.data, role).get_private_key() pub = format(priv.pubkey, "STM") importName = steem.wallet.getAccountFromPublicKey(pub) if importName: configStore["web:user"] = importName try: steem.wallet.addPrivateKey(str(priv)) except: flash("Key seems to be installed already!", "error") keyImported = True if not keyImported: flash( "The account could not be imported. " "Verify your password!", "error") return render_template('wallet.html', **locals())
def test_PasswordKey(self): a = [ "Aang7foN3oz1Ungai2qua5toh3map8ladei1eem2ohsh2shuo8aeji9Thoseo7ah", "iep1Mees9eghiifahwei5iidi0Sazae9aigaeT7itho3quoo2dah5zuvobaelau5", "ohBeuyoothae5aer9odaegh5Eeloh1fi7obei9ahSh0haeYuas1sheehaiv5LaiX", "geiQuoo9NeeLoaZee0ain3Ku1biedohsesien4uHo1eib1ahzaesh5shae3iena7", "jahzeice6Ix8ohBo3eik9pohjahgeegoh9sahthai1aeMahs8ki7Iub1oojeeSuo", "eiVahHoh2hi4fazah9Tha8loxeeNgequaquuYee6Shoopo3EiWoosheeX6yohg2o", "PheeCh3ar8xoofoiphoo4aisahjiiPah4vah0eeceiJ2iyeem9wahyupeithah9T", "IuyiibahNgieshei2eeFu8aic1IeMae9ooXi9jaiwaht4Wiengieghahnguang0U", "Ipee1quee7sheughemae4eir8pheix3quac3ei0Aquo9ohieLaeseeh8AhGeM2ew", "Tech5iir0aP6waiMeiHoph3iwoch4iijoogh0zoh9aSh6Ueb2Dee5dang1aa8IiP" ] b = [ "STM5NyCrrXHmdikC6QPRAPoDjSHVQJe3WC5bMZuF6YhqhSsfYfjhN", "STM8gyvJtYyv5ZbT2ZxbAtgufQ5ovV2bq6EQp4YDTzQuSwyg7Ckry", "STM7yE71iVPSpaq8Ae2AmsKfyFxA8pwYv5zgQtCnX7xMwRUQMVoGf", "STM5jRgWA2kswPaXsQNtD2MMjs92XfJ1TYob6tjHtsECg2AusF5Wo", "STM6XHwVxcP6zP5NV1jUbG6Kso9m8ZG9g2CjDiPcZpAxHngx6ATPB", "STM59X1S4ofTAeHd1iNHDGxim5GkLo2AdcznksUsSYGU687ywB5WV", "STM6BPPL4iSRbFVVN8v3BEEEyDsC1STRK7Ba9ewQ4Lqvszn5J8VAe", "STM7cdK927wj95ptUrCk6HKWVeF74LG5cTjDTV22Z3yJ4Xw8xc9qp", "STM7VNFRjrE1hs1CKpEAP9NAabdFpwvzYXRKvkrVBBv2kTQCbNHz7", "STM7ZZFhEBjujcKjkmY31i1spPMx6xDSRhkursZLigi2HKLuALe5t", ] for i, pwd in enumerate(a): p = format( PasswordKey("xeroc", pwd, "posting").get_public(), "STM") self.assertEqual(p, b[i])
import steem import steembase from steembase.account import PasswordKey from steembase.account import PrivateKey from steembase import operations account = input('Account: ') old_password = input('Current password: '******'New password: '******'https://testnet.steem.vc'], keys=[wif]) new_public_keys = {} for role in ["owner", "active", "posting", "memo"]: private_key = PasswordKey(account, new_password, role).get_private_key() new_public_keys[role] = str(private_key.pubkey) new_data = { "account": account, "json_metadata": {}, "owner": { "key_auths": [ [new_public_keys["owner"], 1] ],
def legacy(): """ Piston like cli application. This will be re-written as a @click app in the future. """ global args parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="Command line tool to interact with the Steem network" ) """ Default settings for all tools """ parser.add_argument( '--node', type=str, default=configStorage["node"], help='URL for public Steem API (default: "https://api.steemit.com")' ) parser.add_argument( '--no-broadcast', '-d', action='store_true', help='Do not broadcast anything' ) parser.add_argument( '--no-wallet', '-p', action='store_true', help='Do not load the wallet' ) parser.add_argument( '--unsigned', '-x', action='store_true', help='Do not try to sign the transaction' ) parser.add_argument( '--expires', '-e', default=60, help='Expiration time in seconds (defaults to 30)' ) parser.add_argument( '--verbose', '-v', type=int, default=3, help='Verbosity' ) parser.add_argument( '--version', action='version', version='%(prog)s {version}'.format( version=pkg_resources.require("steem")[0].version ) ) subparsers = parser.add_subparsers(help='sub-command help') """ Command "set" """ setconfig = subparsers.add_parser('set', help='Set configuration') setconfig.add_argument( 'key', type=str, choices=availableConfigurationKeys, help='Configuration key' ) setconfig.add_argument( 'value', type=str, help='Configuration value' ) setconfig.set_defaults(command="set") """ Command "config" """ configconfig = subparsers.add_parser('config', help='Show local configuration') configconfig.set_defaults(command="config") """ Command "info" """ parser_info = subparsers.add_parser('info', help='Show basic STEEM blockchain info') parser_info.set_defaults(command="info") parser_info.add_argument( 'objects', nargs='*', type=str, help='General information about the blockchain, a block, an account name, a post, a public key, ...' ) """ Command "changewalletpassphrase" """ changepasswordconfig = subparsers.add_parser('changewalletpassphrase', help='Change wallet password') changepasswordconfig.set_defaults(command="changewalletpassphrase") """ Command "addkey" """ addkey = subparsers.add_parser('addkey', help='Add a new key to the wallet') addkey.add_argument( '--unsafe-import-key', nargs='*', type=str, help='private key to import into the wallet (unsafe, unless you delete your bash history)' ) addkey.set_defaults(command="addkey") """ Command "delkey" """ delkey = subparsers.add_parser('delkey', help='Delete keys from the wallet') delkey.add_argument( 'pub', nargs='*', type=str, help='the public key to delete from the wallet' ) delkey.set_defaults(command="delkey") """ Command "getkey" """ getkey = subparsers.add_parser('getkey', help='Dump the privatekey of a pubkey from the wallet') getkey.add_argument( 'pub', type=str, help='the public key for which to show the private key' ) getkey.set_defaults(command="getkey") """ Command "listkeys" """ listkeys = subparsers.add_parser('listkeys', help='List available keys in your wallet') listkeys.set_defaults(command="listkeys") """ Command "listaccounts" """ listaccounts = subparsers.add_parser('listaccounts', help='List available accounts in your wallet') listaccounts.set_defaults(command="listaccounts") """ Command "upvote" """ parser_upvote = subparsers.add_parser('upvote', help='Upvote a post') parser_upvote.set_defaults(command="upvote") parser_upvote.add_argument( 'post', type=str, help='@author/permlink-identifier of the post to upvote to (e.g. @xeroc/python-steem-0-1)' ) parser_upvote.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='The voter account name' ) parser_upvote.add_argument( '--weight', type=float, default=configStorage["default_vote_weight"], required=False, help='Actual weight (from 0.1 to 100.0)' ) """ Command "downvote" """ parser_downvote = subparsers.add_parser('downvote', help='Downvote a post') parser_downvote.set_defaults(command="downvote") parser_downvote.add_argument( '--account', type=str, default=configStorage["default_account"], help='The voter account name' ) parser_downvote.add_argument( 'post', type=str, help='@author/permlink-identifier of the post to downvote to (e.g. @xeroc/python-steem-0-1)' ) parser_downvote.add_argument( '--weight', type=float, default=configStorage["default_vote_weight"], required=False, help='Actual weight (from 0.1 to 100.0)' ) """ Command "transfer" """ parser_transfer = subparsers.add_parser('transfer', help='Transfer STEEM') parser_transfer.set_defaults(command="transfer") parser_transfer.add_argument( 'to', type=str, help='Recipient' ) parser_transfer.add_argument( 'amount', type=float, help='Amount to transfer' ) parser_transfer.add_argument( 'asset', type=str, choices=["STEEM", "SBD"], help='Asset to transfer (i.e. STEEM or SDB)' ) parser_transfer.add_argument( 'memo', type=str, nargs="?", default="", help='Optional memo' ) parser_transfer.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Transfer from this account' ) """ Command "powerup" """ parser_powerup = subparsers.add_parser('powerup', help='Power up (vest STEEM as STEEM POWER)') parser_powerup.set_defaults(command="powerup") parser_powerup.add_argument( 'amount', type=str, help='Amount of VESTS to powerup' ) parser_powerup.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Powerup from this account' ) parser_powerup.add_argument( '--to', type=str, required=False, default=None, help='Powerup this account' ) """ Command "powerdown" """ parser_powerdown = subparsers.add_parser('powerdown', help='Power down (start withdrawing STEEM from steem POWER)') parser_powerdown.set_defaults(command="powerdown") parser_powerdown.add_argument( 'amount', type=str, help='Amount of VESTS to powerdown' ) parser_powerdown.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='powerdown from this account' ) """ Command "powerdownroute" """ parser_powerdownroute = subparsers.add_parser('powerdownroute', help='Setup a powerdown route') parser_powerdownroute.set_defaults(command="powerdownroute") parser_powerdownroute.add_argument( 'to', type=str, default=configStorage["default_account"], help='The account receiving either VESTS/SteemPower or STEEM.' ) parser_powerdownroute.add_argument( '--percentage', type=float, default=100, help='The percent of the withdraw to go to the "to" account' ) parser_powerdownroute.add_argument( '--account', type=str, default=configStorage["default_account"], help='The account which is powering down' ) parser_powerdownroute.add_argument( '--auto_vest', action='store_true', help=('Set to true if the from account should receive the VESTS as' 'VESTS, or false if it should receive them as STEEM.') ) """ Command "convert" """ parser_convert = subparsers.add_parser('convert', help='Convert STEEMDollars to Steem (takes a week to settle)') parser_convert.set_defaults(command="convert") parser_convert.add_argument( 'amount', type=float, help='Amount of SBD to convert' ) parser_convert.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Convert from this account' ) """ Command "balance" """ parser_balance = subparsers.add_parser('balance', help='Show the balance of one more more accounts') parser_balance.set_defaults(command="balance") parser_balance.add_argument( 'account', type=str, nargs="*", default=configStorage["default_account"], help='balance of these account (multiple accounts allowed)' ) """ Command "interest" """ interest = subparsers.add_parser('interest', help='Get information about interest payment') interest.set_defaults(command="interest") interest.add_argument( 'account', type=str, nargs="*", default=configStorage["default_account"], help='Inspect these accounts' ) """ Command "permissions" """ parser_permissions = subparsers.add_parser('permissions', help='Show permissions of an account') parser_permissions.set_defaults(command="permissions") parser_permissions.add_argument( 'account', type=str, nargs="?", default=configStorage["default_account"], help='Account to show permissions for' ) """ Command "allow" """ parser_allow = subparsers.add_parser('allow', help='Allow an account/key to interact with your account') parser_allow.set_defaults(command="allow") parser_allow.add_argument( '--account', type=str, nargs="?", default=configStorage["default_account"], help='The account to allow action for' ) parser_allow.add_argument( 'foreign_account', type=str, nargs="?", help='The account or key that will be allowed to interact as your account' ) parser_allow.add_argument( '--permission', type=str, default="posting", choices=["owner", "posting", "active"], help='The permission to grant (defaults to "posting")' ) parser_allow.add_argument( '--weight', type=int, default=None, help=('The weight to use instead of the (full) threshold. ' 'If the weight is smaller than the threshold, ' 'additional signatures are required') ) parser_allow.add_argument( '--threshold', type=int, default=None, help=('The permission\'s threshold that needs to be reached ' 'by signatures to be able to interact') ) """ Command "disallow" """ parser_disallow = subparsers.add_parser('disallow', help='Remove allowance an account/key to interact with your account') parser_disallow.set_defaults(command="disallow") parser_disallow.add_argument( '--account', type=str, nargs="?", default=configStorage["default_account"], help='The account to disallow action for' ) parser_disallow.add_argument( 'foreign_account', type=str, help='The account or key whose allowance to interact as your account will be removed' ) parser_disallow.add_argument( '--permission', type=str, default="posting", choices=["owner", "posting", "active"], help='The permission to remove (defaults to "posting")' ) parser_disallow.add_argument( '--threshold', type=int, default=None, help=('The permission\'s threshold that needs to be reached ' 'by signatures to be able to interact') ) """ Command "newaccount" """ parser_newaccount = subparsers.add_parser('newaccount', help='Create a new account') parser_newaccount.set_defaults(command="newaccount") parser_newaccount.add_argument( 'accountname', type=str, help='New account name' ) parser_newaccount.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Account that pays the fee' ) parser_newaccount.add_argument( '--fee', type=str, required=False, default='0 STEEM', help='Base Fee to pay. Delegate the rest.' ) """ Command "importaccount" """ parser_importaccount = subparsers.add_parser('importaccount', help='Import an account using a passphrase') parser_importaccount.set_defaults(command="importaccount") parser_importaccount.add_argument( 'account', type=str, help='Account name' ) parser_importaccount.add_argument( '--roles', type=str, nargs="*", default=["active", "posting", "memo"], # no owner help='Import specified keys (owner, active, posting, memo)' ) """ Command "updateMemoKey" """ parser_updateMemoKey = subparsers.add_parser('updatememokey', help='Update an account\'s memo key') parser_updateMemoKey.set_defaults(command="updatememokey") parser_updateMemoKey.add_argument( '--account', type=str, nargs="?", default=configStorage["default_account"], help='The account to updateMemoKey action for' ) parser_updateMemoKey.add_argument( '--key', type=str, default=None, help='The new memo key' ) """ Command "approvewitness" """ parser_approvewitness = subparsers.add_parser('approvewitness', help='Approve a witnesses') parser_approvewitness.set_defaults(command="approvewitness") parser_approvewitness.add_argument( 'witness', type=str, help='Witness to approve' ) parser_approvewitness.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Your account' ) """ Command "disapprovewitness" """ parser_disapprovewitness = subparsers.add_parser('disapprovewitness', help='Disapprove a witnesses') parser_disapprovewitness.set_defaults(command="disapprovewitness") parser_disapprovewitness.add_argument( 'witness', type=str, help='Witness to disapprove' ) parser_disapprovewitness.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Your account' ) """ Command "sign" """ parser_sign = subparsers.add_parser('sign', help='Sign a provided transaction with available and required keys') parser_sign.set_defaults(command="sign") parser_sign.add_argument( '--file', type=str, required=False, help='Load transaction from file. If "-", read from stdin (defaults to "-")' ) """ Command "broadcast" """ parser_broadcast = subparsers.add_parser('broadcast', help='broadcast a signed transaction') parser_broadcast.set_defaults(command="broadcast") parser_broadcast.add_argument( '--file', type=str, required=False, help='Load transaction from file. If "-", read from stdin (defaults to "-")' ) """ Command "orderbook" """ orderbook = subparsers.add_parser('orderbook', help='Obtain orderbook of the internal market') orderbook.set_defaults(command="orderbook") orderbook.add_argument( '--chart', action='store_true', help="Enable charting (requires matplotlib)" ) """ Command "buy" """ parser_buy = subparsers.add_parser('buy', help='Buy STEEM or SBD from the internal market') parser_buy.set_defaults(command="buy") parser_buy.add_argument( 'amount', type=float, help='Amount to buy' ) parser_buy.add_argument( 'asset', type=str, choices=["STEEM", "SBD"], help='Asset to buy (i.e. STEEM or SDB)' ) parser_buy.add_argument( 'price', type=float, help='Limit buy price denoted in (SBD per STEEM)' ) parser_buy.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Buy with this account (defaults to "default_account")' ) """ Command "sell" """ parser_sell = subparsers.add_parser('sell', help='Sell STEEM or SBD from the internal market') parser_sell.set_defaults(command="sell") parser_sell.add_argument( 'amount', type=float, help='Amount to sell' ) parser_sell.add_argument( 'asset', type=str, choices=["STEEM", "SBD"], help='Asset to sell (i.e. STEEM or SDB)' ) parser_sell.add_argument( 'price', type=float, help='Limit sell price denoted in (SBD per STEEM)' ) parser_sell.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Sell from this account (defaults to "default_account")' ) """ Command "cancel" """ parser_cancel = subparsers.add_parser('cancel', help='Cancel order in the internal market') parser_cancel.set_defaults(command="cancel") parser_cancel.add_argument( 'orderid', type=int, help='Orderid' ) parser_cancel.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Cancel from this account (defaults to "default_account")' ) """ Command "resteem" """ parser_resteem = subparsers.add_parser('resteem', help='Resteem an existing post') parser_resteem.set_defaults(command="resteem") parser_resteem.add_argument( 'identifier', type=str, help='@author/permlink-identifier of the post to resteem' ) parser_resteem.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Resteem as this user (requires to have the key installed in the wallet)' ) """ Command "follow" """ parser_follow = subparsers.add_parser('follow', help='Follow another account') parser_follow.set_defaults(command="follow") parser_follow.add_argument( 'follow', type=str, help='Account to follow' ) parser_follow.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Follow from this account' ) parser_follow.add_argument( '--what', type=str, required=False, nargs="*", default=["blog"], help='Follow these objects (defaults to "blog")' ) """ Command "unfollow" """ parser_unfollow = subparsers.add_parser('unfollow', help='unfollow another account') parser_unfollow.set_defaults(command="unfollow") parser_unfollow.add_argument( 'unfollow', type=str, help='Account to unfollow' ) parser_unfollow.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Unfollow from this account' ) parser_unfollow.add_argument( '--what', type=str, required=False, nargs="*", default=[], help='Unfollow these objects (defaults to "blog")' ) """ Command "setprofile" """ parser_setprofile = subparsers.add_parser('setprofile', help='Set a variable in an account\'s profile') parser_setprofile.set_defaults(command="setprofile") parser_setprofile.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='setprofile as this user (requires to have the key installed in the wallet)' ) parser_setprofile_a = parser_setprofile.add_argument_group('Multiple keys at once') parser_setprofile_a.add_argument( '--pair', type=str, nargs='*', help='"Key=Value" pairs' ) parser_setprofile_b = parser_setprofile.add_argument_group('Just a single key') parser_setprofile_b.add_argument( 'variable', type=str, nargs='?', help='Variable to set' ) parser_setprofile_b.add_argument( 'value', type=str, nargs='?', help='Value to set' ) """ Command "delprofile" """ parser_delprofile = subparsers.add_parser('delprofile', help='Set a variable in an account\'s profile') parser_delprofile.set_defaults(command="delprofile") parser_delprofile.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='delprofile as this user (requires to have the key installed in the wallet)' ) parser_delprofile.add_argument( 'variable', type=str, nargs='*', help='Variable to set' ) """ Command "witnessupdate" """ parser_witnessprops = subparsers.add_parser('witnessupdate', help='Change witness properties') parser_witnessprops.set_defaults(command="witnessupdate") parser_witnessprops.add_argument( '--witness', type=str, default=configStorage["default_account"], help='Witness name' ) parser_witnessprops.add_argument( '--maximum_block_size', type=float, required=False, help='Max block size' ) parser_witnessprops.add_argument( '--account_creation_fee', type=float, required=False, help='Account creation fee' ) parser_witnessprops.add_argument( '--sbd_interest_rate', type=float, required=False, help='SBD interest rate in percent' ) parser_witnessprops.add_argument( '--url', type=str, required=False, help='Witness URL' ) parser_witnessprops.add_argument( '--signing_key', type=str, required=False, help='Signing Key' ) """ Command "witnesscreate" """ parser_witnesscreate = subparsers.add_parser('witnesscreate', help='Create a witness') parser_witnesscreate.set_defaults(command="witnesscreate") parser_witnesscreate.add_argument( 'witness', type=str, help='Witness name' ) parser_witnesscreate.add_argument( 'signing_key', type=str, help='Signing Key' ) parser_witnesscreate.add_argument( '--maximum_block_size', type=float, default="65536", help='Max block size' ) parser_witnesscreate.add_argument( '--account_creation_fee', type=float, default=30, help='Account creation fee' ) parser_witnesscreate.add_argument( '--sbd_interest_rate', type=float, default=0.0, help='SBD interest rate in percent' ) parser_witnesscreate.add_argument( '--url', type=str, default="", help='Witness URL' ) """ Parse Arguments """ args = parser.parse_args() # Logging log = logging.getLogger(__name__) verbosity = ["critical", "error", "warn", "info", "debug"][int(min(args.verbose, 4))] log.setLevel(getattr(logging, verbosity.upper())) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch = logging.StreamHandler() ch.setLevel(getattr(logging, verbosity.upper())) ch.setFormatter(formatter) log.addHandler(ch) # GrapheneAPI logging if args.verbose > 4: verbosity = ["critical", "error", "warn", "info", "debug"][int(min((args.verbose - 4), 4))] gphlog = logging.getLogger("graphenebase") gphlog.setLevel(getattr(logging, verbosity.upper())) gphlog.addHandler(ch) if args.verbose > 8: verbosity = ["critical", "error", "warn", "info", "debug"][int(min((args.verbose - 8), 4))] gphlog = logging.getLogger("grapheneapi") gphlog.setLevel(getattr(logging, verbosity.upper())) gphlog.addHandler(ch) if not hasattr(args, "command"): parser.print_help() sys.exit(2) # initialize STEEM instance options = { "node": args.node, "unsigned": args.unsigned, "expires": args.expires } if args.command == "sign": options.update({"offline": True}) if args.no_wallet: options.update({"wif": []}) steem = stm.Steem(no_broadcast=args.no_broadcast, **options) if args.command == "set": if (args.key in ["default_account"] and args.value[0] == "@"): args.value = args.value[1:] configStorage[args.key] = args.value elif args.command == "config": t = PrettyTable(["Key", "Value"]) t.align = "l" for key in configStorage: if key in availableConfigurationKeys: # hide internal config data t.add_row([key, configStorage[key]]) print(t) elif args.command == "info": if not args.objects: t = PrettyTable(["Key", "Value"]) t.align = "l" blockchain = Blockchain(mode="head") info = blockchain.info() median_price = steem.get_current_median_history_price() steem_per_mvest = ( Amount(info["total_vesting_fund_steem"]).amount / (Amount(info["total_vesting_shares"]).amount / 1e6) ) price = ( Amount(median_price["base"]).amount / Amount(median_price["quote"]).amount ) for key in info: t.add_row([key, info[key]]) t.add_row(["steem per mvest", steem_per_mvest]) t.add_row(["internal price", price]) print(t.get_string(sortby="Key")) for obj in args.objects: # Block if re.match("^[0-9]*$", obj): block = Block(obj) if block: t = PrettyTable(["Key", "Value"]) t.align = "l" for key in sorted(block): value = block[key] if key == "transactions": value = json.dumps(value, indent=4) t.add_row([key, value]) print(t) else: print("Block number %s unknown" % obj) # Account name elif re.match("^[a-zA-Z0-9\-\._]{2,16}$", obj): from math import log10 account = Account(obj) t = PrettyTable(["Key", "Value"]) t.align = "l" for key in sorted(account): value = account[key] if key == "json_metadata": value = json.dumps( json.loads(value or "{}"), indent=4 ) if key in ["posting", "witness_votes", "active", "owner"]: value = json.dumps(value, indent=4) if key == "reputation" and int(value) > 0: value = int(value) rep = (max(log10(value) - 9, 0) * 9 + 25 if value > 0 else max(log10(-value) - 9, 0) * -9 + 25) value = "{:.2f} ({:d})".format( rep, value ) t.add_row([key, value]) print(t) # witness available? try: witness = Witness(obj) t = PrettyTable(["Key", "Value"]) t.align = "l" for key in sorted(witness): value = witness[key] if key in ["props", "sbd_exchange_rate"]: value = json.dumps(value, indent=4) t.add_row([key, value]) print(t) except: pass # Public Key elif re.match("^STM.{48,55}$", obj): account = steem.commit.wallet.getAccountFromPublicKey(obj) if account: t = PrettyTable(["Account"]) t.align = "l" t.add_row([account]) print(t) else: print("Public Key not known" % obj) # Post identifier elif re.match(".*@.{3,16}/.*$", obj): post = Post(obj) if post: t = PrettyTable(["Key", "Value"]) t.align = "l" for key in sorted(post): value = post[key] if (key in ["tags", "json_metadata", "active_votes" ]): value = json.dumps(value, indent=4) t.add_row([key, value]) print(t) else: print("Post now known" % obj) else: print("Couldn't identify object to read") elif args.command == "changewalletpassphrase": steem.commit.wallet.changePassphrase() elif args.command == "addkey": if args.unsafe_import_key: for key in args.unsafe_import_key: try: steem.commit.wallet.addPrivateKey(key) except Exception as e: print(str(e)) else: import getpass while True: wifkey = getpass.getpass('Private Key (wif) [Enter to quit]:') if not wifkey: break try: steem.commit.wallet.addPrivateKey(wifkey) except Exception as e: print(str(e)) continue installed_keys = steem.commit.wallet.getPublicKeys() if len(installed_keys) == 1: name = steem.commit.wallet.getAccountFromPublicKey(installed_keys[0]) print("=" * 30) print("Would you like to make %s a default user?" % name) print() print("You can set it with with:") print(" steempy set default_account <account>") print("=" * 30) elif args.command == "delkey": if confirm( "Are you sure you want to delete keys from your wallet?\n" "This step is IRREVERSIBLE! If you don't have a backup, " "You may lose access to your account!" ): for pub in args.pub: steem.commit.wallet.removePrivateKeyFromPublicKey(pub) elif args.command == "getkey": print(steem.commit.wallet.getPrivateKeyForPublicKey(args.pub)) elif args.command == "listkeys": t = PrettyTable(["Available Key"]) t.align = "l" for key in steem.commit.wallet.getPublicKeys(): t.add_row([key]) print(t) elif args.command == "listaccounts": t = PrettyTable(["Name", "Type", "Available Key"]) t.align = "l" for account in steem.commit.wallet.getAccounts(): t.add_row([ account["name"] or "n/a", account["type"] or "n/a", account["pubkey"] ]) print(t) elif args.command == "upvote" or args.command == "downvote": post = Post(args.post) if args.command == "downvote": weight = -float(args.weight) else: weight = +float(args.weight) if not args.account: print("Not voter provided!") return print_json(post.vote(weight, voter=args.account)) elif args.command == "transfer": print_json(steem.commit.transfer( args.to, args.amount, args.asset, memo=args.memo, account=args.account )) elif args.command == "powerup": print_json(steem.commit.transfer_to_vesting( args.amount, account=args.account, to=args.to )) elif args.command == "powerdown": print_json(steem.commit.withdraw_vesting( args.amount, account=args.account, )) elif args.command == "convert": print_json(steem.commit.convert( args.amount, account=args.account, )) elif args.command == "powerdownroute": print_json(steem.commit.set_withdraw_vesting_route( args.to, percentage=args.percentage, account=args.account, auto_vest=args.auto_vest )) elif args.command == "balance": if args.account and isinstance(args.account, list): for account in args.account: a = Account(account) print("\n@%s" % a.name) t = PrettyTable(["Account", "STEEM", "SBD", "VESTS"]) t.align = "r" t.add_row([ 'Available', a.balances['available']['STEEM'], a.balances['available']['SBD'], a.balances['available']['VESTS'], ]) t.add_row([ 'Rewards', a.balances['rewards']['STEEM'], a.balances['rewards']['SBD'], a.balances['rewards']['VESTS'], ]) t.add_row([ 'Savings', a.balances['savings']['STEEM'], a.balances['savings']['SBD'], 'N/A', ]) t.add_row([ 'TOTAL', a.balances['total']['STEEM'], a.balances['total']['SBD'], a.balances['total']['VESTS'], ]) print(t) else: print("Please specify an account: steempy balance <account>") elif args.command == "interest": t = PrettyTable(["Account", "Last Interest Payment", "Next Payment", "Interest rate", "Interest"]) t.align = "r" if isinstance(args.account, str): args.account = [args.account] for a in args.account: i = steem.commit.interest(a) t.add_row([ a, i["last_payment"], "in %s" % strfage(i["next_payment_duration"]), "%.1f%%" % i["interest_rate"], "%.3f %s" % (i["interest"], "SBD"), ]) print(t) elif args.command == "permissions": account = Account(args.account) print_permissions(account) elif args.command == "allow": if not args.foreign_account: from steembase.account import PasswordKey pwd = get_terminal(text="Password for Key Derivation: ", confirm=True) args.foreign_account = format(PasswordKey(args.account, pwd, args.permission).get_public(), "STM") print_json(steem.commit.allow( args.foreign_account, weight=args.weight, account=args.account, permission=args.permission, threshold=args.threshold )) elif args.command == "disallow": print_json(steem.commit.disallow( args.foreign_account, account=args.account, permission=args.permission, threshold=args.threshold )) elif args.command == "updatememokey": if not args.key: # Loop until both match from steembase.account import PasswordKey pw = get_terminal(text="Password for Memo Key: ", confirm=True, allowedempty=False) memo_key = PasswordKey(args.account, pw, "memo") args.key = format(memo_key.get_public_key(), "STM") memo_privkey = memo_key.get_private_key() # Add the key to the wallet if not args.no_broadcast: steem.commit.wallet.addPrivateKey(memo_privkey) print_json(steem.commit.update_memo_key( args.key, account=args.account )) elif args.command == "newaccount": import getpass while True: pw = getpass.getpass("New Account Passphrase: ") if not pw: print("You cannot chosen an empty password!") continue else: pwck = getpass.getpass( "Confirm New Account Passphrase: " ) if pw == pwck: break else: print("Given Passphrases do not match!") print_json(steem.commit.create_account( args.accountname, creator=args.account, password=pw, delegation_fee_steem=args.fee, )) elif args.command == "importaccount": from steembase.account import PasswordKey import getpass password = getpass.getpass("Account Passphrase: ") account = Account(args.account) imported = False if "owner" in args.roles: owner_key = PasswordKey(args.account, password, role="owner") owner_pubkey = format(owner_key.get_public_key(), "STM") if owner_pubkey in [x[0] for x in account["owner"]["key_auths"]]: print("Importing owner key!") owner_privkey = owner_key.get_private_key() steem.commit.wallet.addPrivateKey(owner_privkey) imported = True if "active" in args.roles: active_key = PasswordKey(args.account, password, role="active") active_pubkey = format(active_key.get_public_key(), "STM") if active_pubkey in [x[0] for x in account["active"]["key_auths"]]: print("Importing active key!") active_privkey = active_key.get_private_key() steem.commit.wallet.addPrivateKey(active_privkey) imported = True if "posting" in args.roles: posting_key = PasswordKey(args.account, password, role="posting") posting_pubkey = format(posting_key.get_public_key(), "STM") if posting_pubkey in [x[0] for x in account["posting"]["key_auths"]]: print("Importing posting key!") posting_privkey = posting_key.get_private_key() steem.commit.wallet.addPrivateKey(posting_privkey) imported = True if "memo" in args.roles: memo_key = PasswordKey(args.account, password, role="memo") memo_pubkey = format(memo_key.get_public_key(), "STM") if memo_pubkey == account["memo_key"]: print("Importing memo key!") memo_privkey = memo_key.get_private_key() steem.commit.wallet.addPrivateKey(memo_privkey) imported = True if not imported: print("No matching key(s) found. Password correct?") elif args.command == "sign": if args.file and args.file != "-": if not os.path.isfile(args.file): raise Exception("File %s does not exist!" % args.file) with open(args.file) as fp: tx = fp.read() else: tx = sys.stdin.read() tx = eval(tx) print_json(steem.commit.sign(tx)) elif args.command == "broadcast": if args.file and args.file != "-": if not os.path.isfile(args.file): raise Exception("File %s does not exist!" % args.file) with open(args.file) as fp: tx = fp.read() else: tx = sys.stdin.read() tx = eval(tx) steem.commit.broadcast(tx) elif args.command == "buy": if args.asset == "SBD": price = 1.0 / args.price else: price = args.price dex = Dex(steem) print_json(dex.buy( args.amount, args.asset, price, account=args.account )) elif args.command == "sell": if args.asset == "SBD": price = 1.0 / args.price else: price = args.price dex = Dex(steem) print_json(dex.sell( args.amount, args.asset, price, account=args.account )) elif args.command == "cancel": dex = Dex(steem) print_json( dex.cancel(args.orderid) ) elif args.command == "approvewitness": print_json(steem.commit.approve_witness( args.witness, account=args.account )) elif args.command == "disapprovewitness": print_json(steem.commit.disapprove_witness( args.witness, account=args.account )) elif args.command == "resteem": print_json(steem.commit.resteem( args.identifier, account=args.account )) elif args.command == "follow": print_json(steem.commit.follow( args.follow, what=args.what, account=args.account )) elif args.command == "unfollow": print_json(steem.commit.unfollow( args.unfollow, what=args.what, account=args.account )) elif args.command == "setprofile": from .profile import Profile keys = [] values = [] if args.pair: for pair in args.pair: key, value = pair.split("=") keys.append(key) values.append(value) if args.variable and args.value: keys.append(args.variable) values.append(args.value) profile = Profile(keys, values) account = Account(args.account) account["json_metadata"] = Profile( account["json_metadata"] if account["json_metadata"] else {} ) account["json_metadata"].update(profile) print_json(steem.commit.update_account_profile( account["json_metadata"], account=args.account )) elif args.command == "delprofile": from .profile import Profile account = Account(args.account) account["json_metadata"] = Profile(account["json_metadata"]) for var in args.variable: account["json_metadata"].remove(var) print_json(steem.commit.update_account_profile( account["json_metadata"], account=args.account )) elif args.command == "witnessupdate": witness = Witness(args.witness) props = witness["props"] if args.account_creation_fee: props["account_creation_fee"] = str(Amount("%f STEEM" % args.account_creation_fee)) if args.maximum_block_size: props["maximum_block_size"] = args.maximum_block_size if args.sbd_interest_rate: props["sbd_interest_rate"] = int(args.sbd_interest_rate * 100) print_json(steem.commit.witness_update( args.signing_key or witness["signing_key"], args.url or witness["url"], props, account=args.witness )) elif args.command == "witnesscreate": props = { "account_creation_fee": str(Amount("%f STEEM" % args.account_creation_fee)), "maximum_block_size": args.maximum_block_size, "sbd_interest_rate": int(args.sbd_interest_rate * 100) } print_json(steem.commit.witness_update( args.signing_key, args.url, props, account=args.witness )) else: print("No valid command given")
from steembase.account import PasswordKey account = 'initminer' password = '******' key_types = ['posting', 'active', 'owner', 'memo'] for key_type in key_types: private_key = PasswordKey(account, password, key_type).get_private_key() public_key = private_key.pubkey print('Private ' + key_type + ' key: ' + str(private_key)) print('Public ' + key_type + ' key: ' + str(public_key) + '\n')
def create_account( self, account_name, json_meta={}, creator=None, owner_key=None, active_key=None, posting_key=None, memo_key=None, password=None, additional_owner_keys=[], additional_active_keys=[], additional_posting_keys=[], additional_owner_accounts=[], additional_active_accounts=[], additional_posting_accounts=[], storekeys=True, ): """ Create new account in Steem The brainkey/password can be used to recover all generated keys (see `steembase.account` for more details. By default, this call will use ``default_author`` to register a new name ``account_name`` with all keys being derived from a new brain key that will be returned. The corresponding keys will automatically be installed in the wallet. .. note:: Account creations cost a fee that is defined by the network. If you create an account, you will need to pay for that fee! .. warning:: Don't call this method unless you know what you are doing! Be sure to understand what this method does and where to find the private keys for your account. .. note:: Please note that this imports private keys (if password is present) into the wallet by default. However, it **does not import the owner key** for security reasons. Do NOT expect to be able to recover it from piston if you lose your password! :param str account_name: (**required**) new account name :param str json_meta: Optional meta data for the account :param str creator: which account should pay the registration fee (defaults to ``default_author``) :param str owner_key: Main owner key :param str active_key: Main active key :param str posting_key: Main posting key :param str memo_key: Main memo_key :param str password: Alternatively to providing keys, one can provide a password from which the keys will be derived :param array additional_owner_keys: Additional owner public keys :param array additional_active_keys: Additional active public keys :param array additional_posting_keys: Additional posting public keys :param array additional_owner_accounts: Additional owner account names :param array additional_active_accounts: Additional acctive account names :param array additional_posting_accounts: Additional posting account names :param bool storekeys: Store new keys in the wallet (default: ``True``) :raises AccountExistsException: if the account already exists on the blockchain """ if not creator and config["default_author"]: creator = config["default_author"] if not creator: raise ValueError("Not creator account given. Define it with " + "creator=x, or set the default_author in piston") if password and (owner_key or posting_key or active_key or memo_key): raise ValueError("You cannot use 'password' AND provide keys!") account = None try: account = self.rpc.get_account(account_name) except: pass if account: raise AccountExistsException " Generate new keys from password" from steembase.account import PasswordKey, PublicKey if password: posting_key = PasswordKey(account_name, password, role="posting") active_key = PasswordKey(account_name, password, role="active") owner_key = PasswordKey(account_name, password, role="owner") memo_key = PasswordKey(account_name, password, role="memo") posting_pubkey = posting_key.get_public_key() active_pubkey = active_key.get_public_key() owner_pubkey = owner_key.get_public_key() memo_pubkey = memo_key.get_public_key() posting_privkey = posting_key.get_private_key() active_privkey = active_key.get_private_key() # owner_privkey = owner_key.get_private_key() memo_privkey = memo_key.get_private_key() # store private keys if storekeys: # self.wallet.addPrivateKey(owner_privkey) self.wallet.addPrivateKey(active_privkey) self.wallet.addPrivateKey(posting_privkey) self.wallet.addPrivateKey(memo_privkey) elif (owner_key and posting_key and active_key and memo_key): posting_pubkey = PublicKey(posting_key, prefix=prefix) active_pubkey = PublicKey(active_key, prefix=prefix) owner_pubkey = PublicKey(owner_key, prefix=prefix) memo_pubkey = PublicKey(memo_key, prefix=prefix) else: raise ValueError( "Call incomplete! Provide either a password or public keys!") owner = format(posting_pubkey, prefix) active = format(active_pubkey, prefix) posting = format(owner_pubkey, prefix) memo = format(memo_pubkey, prefix) owner_key_authority = [[owner, 1]] active_key_authority = [[active, 1]] posting_key_authority = [[posting, 1]] owner_accounts_authority = [] active_accounts_authority = [] posting_accounts_authority = [] # additional authorities for k in additional_owner_keys: owner_key_authority.append([k, 1]) for k in additional_active_keys: active_key_authority.append([k, 1]) for k in additional_posting_keys: posting_key_authority.append([k, 1]) for k in additional_owner_accounts: owner_accounts_authority.append([k, 1]) for k in additional_active_accounts: active_accounts_authority.append([k, 1]) for k in additional_posting_accounts: posting_accounts_authority.append([k, 1]) props = self.rpc.get_chain_properties() fee = props["account_creation_fee"] s = { 'creator': creator, 'fee': fee, 'json_metadata': json_meta, 'memo_key': memo, 'new_account_name': account_name, 'owner': { 'account_auths': owner_accounts_authority, 'key_auths': owner_key_authority, 'weight_threshold': 1 }, 'active': { 'account_auths': active_accounts_authority, 'key_auths': active_key_authority, 'weight_threshold': 1 }, 'posting': { 'account_auths': posting_accounts_authority, 'key_auths': posting_key_authority, 'weight_threshold': 1 } } op = transactions.Account_create(**s) wif = self.wallet.getActiveKeyForAccount(creator) return self.executeOp(op, wif)
def legacyentry(): """ Piston like cli application. This will be re-written as a @click app in the future. """ global args parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="Command line tool to interact with the Steem network") """ Default settings for all tools """ parser.add_argument( '--node', type=str, default=configStorage["node"], help='URL for public Steem API (default: "https://api.steemit.com")' ) parser.add_argument( '--no-broadcast', '-d', action='store_true', help='Do not broadcast anything') parser.add_argument( '--no-wallet', '-p', action='store_true', help='Do not load the wallet') parser.add_argument( '--unsigned', '-x', action='store_true', help='Do not try to sign the transaction') parser.add_argument( '--expires', '-e', default=60, help='Expiration time in seconds (defaults to 30)') parser.add_argument( '--verbose', '-v', type=int, default=3, help='Verbosity') parser.add_argument( '--version', action='version', version='%(prog)s {version}'.format( version=pkg_resources.require("steem")[0].version)) subparsers = parser.add_subparsers(help='sub-command help') """ Command "set" """ setconfig = subparsers.add_parser('set', help='Set configuration') setconfig.add_argument( 'key', type=str, choices=availableConfigurationKeys, help='Configuration key') setconfig.add_argument('value', type=str, help='Configuration value') setconfig.set_defaults(command="set") """ Command "config" """ configconfig = subparsers.add_parser( 'config', help='Show local configuration') configconfig.set_defaults(command="config") """ Command "info" """ parser_info = subparsers.add_parser( 'info', help='Show basic STEEM blockchain info') parser_info.set_defaults(command="info") parser_info.add_argument( 'objects', nargs='*', type=str, help='General information about the blockchain, a block, an account' ' name, a post, a public key, ...') """ Command "changewalletpassphrase" """ changepasswordconfig = subparsers.add_parser( 'changewalletpassphrase', help='Change wallet password') changepasswordconfig.set_defaults(command="changewalletpassphrase") """ Command "addkey" """ addkey = subparsers.add_parser( 'addkey', help='Add a new key to the wallet') addkey.add_argument( '--unsafe-import-key', nargs='*', type=str, help='private key to import into the wallet (unsafe, unless you ' + 'delete your shell history)') addkey.set_defaults(command="addkey") parsewif = subparsers.add_parser( 'parsewif', help='Parse a WIF private key without importing') parsewif.add_argument( '--unsafe-import-key', nargs='*', type=str, help='WIF key to parse (unsafe, delete your bash history)') parsewif.set_defaults(command='parsewif') """ Command "delkey" """ delkey = subparsers.add_parser( 'delkey', help='Delete keys from the wallet') delkey.add_argument( 'pub', nargs='*', type=str, help='the public key to delete from the wallet') delkey.set_defaults(command="delkey") """ Command "getkey" """ getkey = subparsers.add_parser( 'getkey', help='Dump the privatekey of a pubkey from the wallet') getkey.add_argument( 'pub', type=str, help='the public key for which to show the private key') getkey.set_defaults(command="getkey") """ Command "listkeys" """ listkeys = subparsers.add_parser( 'listkeys', help='List available keys in your wallet') listkeys.set_defaults(command="listkeys") """ Command "listaccounts" """ listaccounts = subparsers.add_parser( 'listaccounts', help='List available accounts in your wallet') listaccounts.set_defaults(command="listaccounts") """ Command "upvote" """ parser_upvote = subparsers.add_parser('upvote', help='Upvote a post') parser_upvote.set_defaults(command="upvote") parser_upvote.add_argument( 'post', type=str, help='author/permlink-identifier of the post to upvote ' + 'to (e.g. xeroc/python-steem-0-1)') parser_upvote.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='The voter account name') parser_upvote.add_argument( '--weight', type=float, default=configStorage["default_vote_weight"], required=False, help='Actual weight (from 0.1 to 100.0)') """ Command "downvote" """ parser_downvote = subparsers.add_parser('downvote', help='Downvote a post') parser_downvote.set_defaults(command="downvote") parser_downvote.add_argument( '--account', type=str, default=configStorage["default_account"], help='The voter account name') parser_downvote.add_argument( 'post', type=str, help='author/permlink-identifier of the post to downvote ' + 'to (e.g. xeroc/python-steem-0-1)') parser_downvote.add_argument( '--weight', type=float, default=configStorage["default_vote_weight"], required=False, help='Actual weight (from 0.1 to 100.0)') """ Command "transfer" """ parser_transfer = subparsers.add_parser('transfer', help='Transfer STEEM') parser_transfer.set_defaults(command="transfer") parser_transfer.add_argument('to', type=str, help='Recipient') parser_transfer.add_argument( 'amount', type=float, help='Amount to transfer') parser_transfer.add_argument( 'asset', type=str, choices=["STEEM", "SBD"], help='Asset to transfer (i.e. STEEM or SDB)') parser_transfer.add_argument( 'memo', type=str, nargs="?", default="", help='Optional memo') parser_transfer.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Transfer from this account') """ Command "powerup" """ parser_powerup = subparsers.add_parser( 'powerup', help='Power up (vest STEEM as STEEM POWER)') parser_powerup.set_defaults(command="powerup") parser_powerup.add_argument( 'amount', type=str, help='Amount of VESTS to powerup') parser_powerup.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Powerup from this account') parser_powerup.add_argument( '--to', type=str, required=False, default=None, help='Powerup this account') """ Command "powerdown" """ parser_powerdown = subparsers.add_parser( 'powerdown', help='Power down (start withdrawing STEEM from steem POWER)') parser_powerdown.set_defaults(command="powerdown") parser_powerdown.add_argument( 'amount', type=str, help='Amount of VESTS to powerdown') parser_powerdown.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='powerdown from this account') """ Command "powerdownroute" """ parser_powerdownroute = subparsers.add_parser( 'powerdownroute', help='Setup a powerdown route') parser_powerdownroute.set_defaults(command="powerdownroute") parser_powerdownroute.add_argument( 'to', type=str, default=configStorage["default_account"], help='The account receiving either VESTS/SteemPower or STEEM.') parser_powerdownroute.add_argument( '--percentage', type=float, default=100, help='The percent of the withdraw to go to the "to" account') parser_powerdownroute.add_argument( '--account', type=str, default=configStorage["default_account"], help='The account which is powering down') parser_powerdownroute.add_argument( '--auto_vest', action='store_true', help=('Set to true if the from account should receive the VESTS as' 'VESTS, or false if it should receive them as STEEM.')) """ Command "convert" """ parser_convert = subparsers.add_parser( 'convert', help='Convert STEEMDollars to Steem (takes a week to settle)') parser_convert.set_defaults(command="convert") parser_convert.add_argument( 'amount', type=float, help='Amount of SBD to convert') parser_convert.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Convert from this account') """ Command "balance" """ parser_balance = subparsers.add_parser( 'balance', help='Show the balance of one more more accounts') parser_balance.set_defaults(command="balance") parser_balance.add_argument( 'account', type=str, nargs="*", default=configStorage["default_account"], help='balance of these account (multiple accounts allowed)') """ Command "interest" """ interest = subparsers.add_parser( 'interest', help='Get information about interest payment') interest.set_defaults(command="interest") interest.add_argument( 'account', type=str, nargs="*", default=configStorage["default_account"], help='Inspect these accounts') """ Command "permissions" """ parser_permissions = subparsers.add_parser( 'permissions', help='Show permissions of an account') parser_permissions.set_defaults(command="permissions") parser_permissions.add_argument( 'account', type=str, nargs="?", default=configStorage["default_account"], help='Account to show permissions for') """ Command "allow" """ parser_allow = subparsers.add_parser( 'allow', help='Allow an account/key to interact with your account') parser_allow.set_defaults(command="allow") parser_allow.add_argument( '--account', type=str, nargs="?", default=configStorage["default_account"], help='The account to allow action for') parser_allow.add_argument( 'foreign_account', type=str, nargs="?", help='The account or key that will be allowed to interact with ' + 'your account') parser_allow.add_argument( '--permission', type=str, default="posting", choices=["owner", "posting", "active"], help='The permission to grant (defaults to "posting")') parser_allow.add_argument( '--weight', type=int, default=None, help=('The weight to use instead of the (full) threshold. ' 'If the weight is smaller than the threshold, ' 'additional signatures are required')) parser_allow.add_argument( '--threshold', type=int, default=None, help=('The permission\'s threshold that needs to be reached ' 'by signatures to be able to interact')) """ Command "disallow" """ parser_disallow = subparsers.add_parser( 'disallow', help='Remove allowance an account/key to interact with your account') parser_disallow.set_defaults(command="disallow") parser_disallow.add_argument( '--account', type=str, nargs="?", default=configStorage["default_account"], help='The account to disallow action for') parser_disallow.add_argument( 'foreign_account', type=str, help='The account or key whose allowance to interact as your ' + 'account will be removed') parser_disallow.add_argument( '--permission', type=str, default="posting", choices=["owner", "posting", "active"], help='The permission to remove (defaults to "posting")') parser_disallow.add_argument( '--threshold', type=int, default=None, help=('The permission\'s threshold that needs to be reached ' 'by signatures to be able to interact')) """ Command "newaccount" """ parser_newaccount = subparsers.add_parser( 'newaccount', help='Create a new account') parser_newaccount.set_defaults(command="newaccount") parser_newaccount.add_argument( 'accountname', type=str, help='New account name') parser_newaccount.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Account that pays the fee') parser_newaccount.add_argument( '--fee', type=str, required=False, default='0 STEEM', help='Base Fee to pay. Delegate the rest.') """ Command "importaccount" """ parser_importaccount = subparsers.add_parser( 'importaccount', help='Import an account using a passphrase') parser_importaccount.set_defaults(command="importaccount") parser_importaccount.add_argument('account', type=str, help='Account name') parser_importaccount.add_argument( '--roles', type=str, nargs="*", default=["active", "posting", "memo"], # no owner help='Import specified keys (owner, active, posting, memo)') """ Command "updateMemoKey" """ parser_updateMemoKey = subparsers.add_parser( 'updatememokey', help='Update an account\'s memo key') parser_updateMemoKey.set_defaults(command="updatememokey") parser_updateMemoKey.add_argument( '--account', type=str, nargs="?", default=configStorage["default_account"], help='The account to updateMemoKey action for') parser_updateMemoKey.add_argument( '--key', type=str, default=None, help='The new memo key') """ Command "approvewitness" """ parser_approvewitness = subparsers.add_parser( 'approvewitness', help='Approve a witnesses') parser_approvewitness.set_defaults(command="approvewitness") parser_approvewitness.add_argument( 'witness', type=str, help='Witness to approve') parser_approvewitness.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Your account') """ Command "disapprovewitness" """ parser_disapprovewitness = subparsers.add_parser( 'disapprovewitness', help='Disapprove a witnesses') parser_disapprovewitness.set_defaults(command="disapprovewitness") parser_disapprovewitness.add_argument( 'witness', type=str, help='Witness to disapprove') parser_disapprovewitness.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Your account') """ Command "sign" """ parser_sign = subparsers.add_parser( 'sign', help='Sign a provided transaction with available and required keys') parser_sign.set_defaults(command="sign") parser_sign.add_argument( '--file', type=str, required=False, help='Load transaction from file. If "-", read from ' + 'stdin (defaults to "-")') """ Command "broadcast" """ parser_broadcast = subparsers.add_parser( 'broadcast', help='broadcast a signed transaction') parser_broadcast.set_defaults(command="broadcast") parser_broadcast.add_argument( '--file', type=str, required=False, help='Load transaction from file. If "-", read from ' + 'stdin (defaults to "-")') """ Command "orderbook" """ orderbook = subparsers.add_parser( 'orderbook', help='Obtain orderbook of the internal market') orderbook.set_defaults(command="orderbook") orderbook.add_argument( '--chart', action='store_true', help="Enable charting (requires matplotlib)") """ Command "buy" """ parser_buy = subparsers.add_parser( 'buy', help='Buy STEEM or SBD from the internal market') parser_buy.set_defaults(command="buy") parser_buy.add_argument('amount', type=float, help='Amount to buy') parser_buy.add_argument( 'asset', type=str, choices=["STEEM", "SBD"], help='Asset to buy (i.e. STEEM or SDB)') parser_buy.add_argument( 'price', type=float, help='Limit buy price denoted in (SBD per STEEM)') parser_buy.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Buy with this account (defaults to "default_account")') """ Command "sell" """ parser_sell = subparsers.add_parser( 'sell', help='Sell STEEM or SBD from the internal market') parser_sell.set_defaults(command="sell") parser_sell.add_argument('amount', type=float, help='Amount to sell') parser_sell.add_argument( 'asset', type=str, choices=["STEEM", "SBD"], help='Asset to sell (i.e. STEEM or SDB)') parser_sell.add_argument( 'price', type=float, help='Limit sell price denoted in (SBD per STEEM)') parser_sell.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Sell from this account (defaults to "default_account")') """ Command "cancel" """ parser_cancel = subparsers.add_parser( 'cancel', help='Cancel order in the internal market') parser_cancel.set_defaults(command="cancel") parser_cancel.add_argument('orderid', type=int, help='Orderid') parser_cancel.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Cancel from this account (defaults to "default_account")') """ Command "resteem" """ parser_resteem = subparsers.add_parser( 'resteem', help='Resteem an existing post') parser_resteem.set_defaults(command="resteem") parser_resteem.add_argument( 'identifier', type=str, help='author/permlink-identifier of the post to resteem') parser_resteem.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Resteem as this user (requires to have the ' + 'key installed in the wallet)') """ Command "follow" """ parser_follow = subparsers.add_parser( 'follow', help='Follow another account') parser_follow.set_defaults(command="follow") parser_follow.add_argument('follow', type=str, help='Account to follow') parser_follow.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Follow from this account') parser_follow.add_argument( '--what', type=str, required=False, nargs="*", default=["blog"], help='Follow these objects (defaults to "blog")') """ Command "unfollow" """ parser_unfollow = subparsers.add_parser( 'unfollow', help='unfollow another account') parser_unfollow.set_defaults(command="unfollow") parser_unfollow.add_argument( 'unfollow', type=str, help='Account to unfollow') parser_unfollow.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='Unfollow from this account') parser_unfollow.add_argument( '--what', type=str, required=False, nargs="*", default=[], help='Unfollow these objects (defaults to "blog")') """ Command "setprofile" """ parser_setprofile = subparsers.add_parser( 'setprofile', help='Set a variable in an account\'s profile') parser_setprofile.set_defaults(command="setprofile") parser_setprofile.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='setprofile as this user (requires to have the key ' + 'installed in the wallet)') parser_setprofile_a = parser_setprofile.add_argument_group( 'Multiple keys at once') parser_setprofile_a.add_argument( '--pair', type=str, nargs='*', help='"Key=Value" pairs') parser_setprofile_b = parser_setprofile.add_argument_group( 'Just a single key') parser_setprofile_b.add_argument( 'variable', type=str, nargs='?', help='Variable to set') parser_setprofile_b.add_argument( 'value', type=str, nargs='?', help='Value to set') """ Command "delprofile" """ parser_delprofile = subparsers.add_parser( 'delprofile', help='Set a variable in an account\'s profile') parser_delprofile.set_defaults(command="delprofile") parser_delprofile.add_argument( '--account', type=str, required=False, default=configStorage["default_account"], help='delprofile as this user (requires to have the ' + 'key installed in the wallet)') parser_delprofile.add_argument( 'variable', type=str, nargs='*', help='Variable to set') """ Command "witnessupdate" """ parser_witnessprops = subparsers.add_parser( 'witnessupdate', help='Change witness properties') parser_witnessprops.set_defaults(command="witnessupdate") parser_witnessprops.add_argument( '--witness', type=str, default=configStorage["default_account"], help='Witness name') parser_witnessprops.add_argument( '--maximum_block_size', type=float, required=False, help='Max block size') parser_witnessprops.add_argument( '--account_creation_fee', type=float, required=False, help='Account creation fee') parser_witnessprops.add_argument( '--sbd_interest_rate', type=float, required=False, help='SBD interest rate in percent') parser_witnessprops.add_argument( '--url', type=str, required=False, help='Witness URL') parser_witnessprops.add_argument( '--signing_key', type=str, required=False, help='Signing Key') """ Command "witnesscreate" """ parser_witnesscreate = subparsers.add_parser( 'witnesscreate', help='Create a witness') parser_witnesscreate.set_defaults(command="witnesscreate") parser_witnesscreate.add_argument('witness', type=str, help='Witness name') parser_witnesscreate.add_argument( 'signing_key', type=str, help='Signing Key') parser_witnesscreate.add_argument( '--maximum_block_size', type=float, default="65536", help='Max block size') parser_witnesscreate.add_argument( '--account_creation_fee', type=float, default=30, help='Account creation fee') parser_witnesscreate.add_argument( '--sbd_interest_rate', type=float, default=0.0, help='SBD interest rate in percent') parser_witnesscreate.add_argument( '--url', type=str, default="", help='Witness URL') """ Parse Arguments """ args = parser.parse_args() # Logging log = logging.getLogger(__name__) verbosity = ["critical", "error", "warn", "info", "debug"][int( min(args.verbose, 4))] log.setLevel(getattr(logging, verbosity.upper())) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch = logging.StreamHandler() ch.setLevel(getattr(logging, verbosity.upper())) ch.setFormatter(formatter) log.addHandler(ch) # GrapheneAPI logging if args.verbose > 4: verbosity = ["critical", "error", "warn", "info", "debug"][int( min((args.verbose - 4), 4))] gphlog = logging.getLogger("graphenebase") gphlog.setLevel(getattr(logging, verbosity.upper())) gphlog.addHandler(ch) if args.verbose > 8: verbosity = ["critical", "error", "warn", "info", "debug"][int( min((args.verbose - 8), 4))] gphlog = logging.getLogger("grapheneapi") gphlog.setLevel(getattr(logging, verbosity.upper())) gphlog.addHandler(ch) if not hasattr(args, "command"): parser.print_help() sys.exit(2) # initialize STEEM instance options = { "node": args.node, "unsigned": args.unsigned, "expires": args.expires } if args.command == "sign": options.update({"offline": True}) if args.no_wallet: options.update({"wif": []}) steem = stm.Steem(no_broadcast=args.no_broadcast, **options) if args.command == "set": # TODO: Evaluate this line with cli refactor. if (args.key in ["default_account"] and args.value[0] == "@"): args.value = args.value[1:] configStorage[args.key] = args.value elif args.command == "config": t = PrettyTable(["Key", "Value"]) t.align = "l" for key in configStorage: # hide internal config data if key in availableConfigurationKeys: t.add_row([key, configStorage[key]]) print(t) elif args.command == "info": if not args.objects: t = PrettyTable(["Key", "Value"]) t.align = "l" blockchain = Blockchain(mode="head") info = blockchain.info() median_price = steem.get_current_median_history_price() steem_per_mvest = ( Amount(info["total_vesting_fund_steem"]).amount / (Amount(info["total_vesting_shares"]).amount / 1e6)) price = (Amount(median_price["base"]).amount / Amount( median_price["quote"]).amount) for key in info: t.add_row([key, info[key]]) t.add_row(["steem per mvest", steem_per_mvest]) t.add_row(["internal price", price]) print(t.get_string(sortby="Key")) for obj in args.objects: # Block if re.match("^[0-9]*$", obj): block = Block(obj) if block: t = PrettyTable(["Key", "Value"]) t.align = "l" for key in sorted(block): value = block[key] if key == "transactions": value = json.dumps(value, indent=4) t.add_row([key, value]) print(t) else: print("Block number %s unknown" % obj) # Account name elif re.match("^[a-zA-Z0-9\-\._]{2,16}$", obj): from math import log10 account = Account(obj) t = PrettyTable(["Key", "Value"]) t.align = "l" for key in sorted(account): value = account[key] if key == "json_metadata": value = json.dumps(json.loads(value or "{}"), indent=4) if key in ["posting", "witness_votes", "active", "owner"]: value = json.dumps(value, indent=4) if key == "reputation" and int(value) > 0: value = int(value) rep = (max(log10(value) - 9, 0) * 9 + 25 if value > 0 else max(log10(-value) - 9, 0) * -9 + 25) value = "{:.2f} ({:d})".format(rep, value) t.add_row([key, value]) print(t) # witness available? try: witness = Witness(obj) t = PrettyTable(["Key", "Value"]) t.align = "l" for key in sorted(witness): value = witness[key] if key in ["props", "sbd_exchange_rate"]: value = json.dumps(value, indent=4) t.add_row([key, value]) print(t) except: # noqa FIXME(sneak) pass # Public Key elif re.match("^STM.{48,55}$", obj): account = steem.commit.wallet.getAccountFromPublicKey(obj) if account: t = PrettyTable(["Account"]) t.align = "l" t.add_row([account]) print(t) else: print("Public Key not known" % obj) # Post identifier elif re.match(".*@.{3,16}/.*$", obj): post = Post(obj) if post: t = PrettyTable(["Key", "Value"]) t.align = "l" for key in sorted(post): value = post[key] if (key in ["tags", "json_metadata", "active_votes"]): value = json.dumps(value, indent=4) t.add_row([key, value]) print(t) else: print("Post now known" % obj) else: print("Couldn't identify object to read") elif args.command == "changewalletpassphrase": steem.commit.wallet.changePassphrase() elif args.command == "addkey": if args.unsafe_import_key: for key in args.unsafe_import_key: try: steem.commit.wallet.addPrivateKey(key) except Exception as e: print(str(e)) else: import getpass while True: wifkey = getpass.getpass('Private Key (wif) [Enter to quit]:') if not wifkey: break try: steem.commit.wallet.addPrivateKey(wifkey) except Exception as e: print(str(e)) continue installed_keys = steem.commit.wallet.getPublicKeys() if len(installed_keys) == 1: name = steem.commit.wallet.getAccountFromPublicKey( installed_keys[0]) print("=" * 30) print("Would you like to make %s a default user?" % name) print() print("You can set it with with:") print(" steempy set default_account <account>") print("=" * 30) elif args.command == "delkey": if confirm("Are you sure you want to delete keys from your wallet?\n" "This step is IRREVERSIBLE! If you don't have a backup, " "You may lose access to your account!"): for pub in args.pub: steem.commit.wallet.removePrivateKeyFromPublicKey(pub) elif args.command == "parsewif": if args.unsafe_import_key: for key in args.unsafe_import_key: try: print(PrivateKey(key).pubkey) except Exception as e: print(str(e)) else: import getpass while True: wifkey = getpass.getpass('Private Key (wif) [Enter to quit:') if not wifkey: break try: print(PrivateKey(wifkey).pubkey) except Exception as e: print(str(e)) continue elif args.command == "getkey": print(steem.commit.wallet.getPrivateKeyForPublicKey(args.pub)) elif args.command == "listkeys": t = PrettyTable(["Available Key"]) t.align = "l" for key in steem.commit.wallet.getPublicKeys(): t.add_row([key]) print(t) elif args.command == "listaccounts": t = PrettyTable(["Name", "Type", "Available Key"]) t.align = "l" for account in steem.commit.wallet.getAccounts(): t.add_row([ account["name"] or "n/a", account["type"] or "n/a", account["pubkey"] ]) print(t) elif args.command == "upvote" or args.command == "downvote": post = Post(args.post) if args.command == "downvote": weight = -float(args.weight) else: weight = +float(args.weight) if not args.account: print("Not voter provided!") return print_json(post.vote(weight, voter=args.account)) elif args.command == "transfer": print_json( steem.commit.transfer( args.to, args.amount, args.asset, memo=args.memo, account=args.account)) elif args.command == "powerup": print_json( steem.commit.transfer_to_vesting( args.amount, account=args.account, to=args.to)) elif args.command == "powerdown": print_json( steem.commit.withdraw_vesting( args.amount, account=args.account, )) elif args.command == "convert": print_json(steem.commit.convert( args.amount, account=args.account, )) elif args.command == "powerdownroute": print_json( steem.commit.set_withdraw_vesting_route( args.to, percentage=args.percentage, account=args.account, auto_vest=args.auto_vest)) elif args.command == "balance": if args.account and isinstance(args.account, list): for account in args.account: a = Account(account) print("\n%s" % a.name) t = PrettyTable(["Account", "STEEM", "SBD", "VESTS"]) t.align = "r" t.add_row([ 'Available', a.balances['available']['STEEM'], a.balances['available']['SBD'], a.balances['available']['VESTS'], ]) t.add_row([ 'Rewards', a.balances['rewards']['STEEM'], a.balances['rewards']['SBD'], a.balances['rewards']['VESTS'], ]) t.add_row([ 'Savings', a.balances['savings']['STEEM'], a.balances['savings']['SBD'], 'N/A', ]) t.add_row([ 'TOTAL', a.balances['total']['STEEM'], a.balances['total']['SBD'], a.balances['total']['VESTS'], ]) print(t) else: print("Please specify an account: steempy balance <account>") elif args.command == "interest": t = PrettyTable([ "Account", "Last Interest Payment", "Next Payment", "Interest rate", "Interest" ]) t.align = "r" if isinstance(args.account, str): args.account = [args.account] for a in args.account: i = steem.commit.interest(a) t.add_row([ a, i["last_payment"], "in %s" % strfage(i["next_payment_duration"]), "%.1f%%" % i["interest_rate"], "%.3f %s" % (i["interest"], "SBD"), ]) print(t) elif args.command == "permissions": account = Account(args.account) print_permissions(account) elif args.command == "allow": if not args.foreign_account: from steembase.account import PasswordKey pwd = get_terminal( text="Password for Key Derivation: ", confirm=True) args.foreign_account = format( PasswordKey(args.account, pwd, args.permission).get_public(), "STM") print_json( steem.commit.allow( args.foreign_account, weight=args.weight, account=args.account, permission=args.permission, threshold=args.threshold)) elif args.command == "disallow": print_json( steem.commit.disallow( args.foreign_account, account=args.account, permission=args.permission, threshold=args.threshold)) elif args.command == "updatememokey": if not args.key: # Loop until both match from steembase.account import PasswordKey pw = get_terminal( text="Password for Memo Key: ", confirm=True, allowedempty=False) memo_key = PasswordKey(args.account, pw, "memo") args.key = format(memo_key.get_public_key(), "STM") memo_privkey = memo_key.get_private_key() # Add the key to the wallet if not args.no_broadcast: steem.commit.wallet.addPrivateKey(memo_privkey) print_json( steem.commit.update_memo_key(args.key, account=args.account)) elif args.command == "newaccount": import getpass while True: pw = getpass.getpass("New Account Passphrase: ") if not pw: print("You cannot chosen an empty password!") continue else: pwck = getpass.getpass("Confirm New Account Passphrase: ") if pw == pwck: break else: print("Given Passphrases do not match!") print_json( steem.commit.create_account( args.accountname, creator=args.account, password=pw, delegation_fee_steem=args.fee, )) elif args.command == "importaccount": from steembase.account import PasswordKey import getpass password = getpass.getpass("Account Passphrase: ") account = Account(args.account) imported = False if "owner" in args.roles: owner_key = PasswordKey(args.account, password, role="owner") owner_pubkey = format(owner_key.get_public_key(), "STM") if owner_pubkey in [x[0] for x in account["owner"]["key_auths"]]: print("Importing owner key!") owner_privkey = owner_key.get_private_key() steem.commit.wallet.addPrivateKey(owner_privkey) imported = True if "active" in args.roles: active_key = PasswordKey(args.account, password, role="active") active_pubkey = format(active_key.get_public_key(), "STM") if active_pubkey in [x[0] for x in account["active"]["key_auths"]]: print("Importing active key!") active_privkey = active_key.get_private_key() steem.commit.wallet.addPrivateKey(active_privkey) imported = True if "posting" in args.roles: posting_key = PasswordKey(args.account, password, role="posting") posting_pubkey = format(posting_key.get_public_key(), "STM") if posting_pubkey in [ x[0] for x in account["posting"]["key_auths"] ]: print("Importing posting key!") posting_privkey = posting_key.get_private_key() steem.commit.wallet.addPrivateKey(posting_privkey) imported = True if "memo" in args.roles: memo_key = PasswordKey(args.account, password, role="memo") memo_pubkey = format(memo_key.get_public_key(), "STM") if memo_pubkey == account["memo_key"]: print("Importing memo key!") memo_privkey = memo_key.get_private_key() steem.commit.wallet.addPrivateKey(memo_privkey) imported = True if not imported: print("No matching key(s) found. Password correct?") elif args.command == "sign": if args.file and args.file != "-": if not os.path.isfile(args.file): raise Exception("File %s does not exist!" % args.file) with open(args.file) as fp: tx = fp.read() else: tx = sys.stdin.read() tx = eval(tx) print_json(steem.commit.sign(tx)) elif args.command == "broadcast": if args.file and args.file != "-": if not os.path.isfile(args.file): raise Exception("File %s does not exist!" % args.file) with open(args.file) as fp: tx = fp.read() else: tx = sys.stdin.read() tx = eval(tx) steem.commit.broadcast(tx) elif args.command == "buy": if args.asset == "SBD": price = 1.0 / args.price else: price = args.price dex = Dex(steem) print_json( dex.buy(args.amount, args.asset, price, account=args.account)) elif args.command == "sell": if args.asset == "SBD": price = 1.0 / args.price else: price = args.price dex = Dex(steem) print_json( dex.sell(args.amount, args.asset, price, account=args.account)) elif args.command == "cancel": dex = Dex(steem) print_json(dex.cancel(args.orderid)) elif args.command == "approvewitness": print_json( steem.commit.approve_witness(args.witness, account=args.account)) elif args.command == "disapprovewitness": print_json( steem.commit.disapprove_witness( args.witness, account=args.account)) elif args.command == "resteem": print_json(steem.commit.resteem(args.identifier, account=args.account)) elif args.command == "follow": print_json( steem.commit.follow( args.follow, what=args.what, account=args.account)) elif args.command == "unfollow": print_json( steem.commit.unfollow( args.unfollow, what=args.what, account=args.account)) elif args.command == "setprofile": from .profile import Profile keys = [] values = [] if args.pair: for pair in args.pair: key, value = pair.split("=") keys.append(key) values.append(value) if args.variable and args.value: keys.append(args.variable) values.append(args.value) profile = Profile(keys, values) account = Account(args.account) account["json_metadata"] = Profile(account["json_metadata"] if account["json_metadata"] else {}) account["json_metadata"].update(profile) print_json( steem.commit.update_account_profile( account["json_metadata"], account=args.account)) elif args.command == "delprofile": from .profile import Profile account = Account(args.account) account["json_metadata"] = Profile(account["json_metadata"]) for var in args.variable: account["json_metadata"].remove(var) print_json( steem.commit.update_account_profile( account["json_metadata"], account=args.account)) elif args.command == "witnessupdate": witness = Witness(args.witness) props = witness["props"] if args.account_creation_fee: props["account_creation_fee"] = str( Amount("%f STEEM" % args.account_creation_fee)) if args.maximum_block_size: props["maximum_block_size"] = args.maximum_block_size if args.sbd_interest_rate: props["sbd_interest_rate"] = int(args.sbd_interest_rate * 100) print_json( steem.commit.witness_update( args.signing_key or witness["signing_key"], args.url or witness["url"], props, account=args.witness)) elif args.command == "witnesscreate": props = { "account_creation_fee": str(Amount("%f STEEM" % args.account_creation_fee)), "maximum_block_size": args.maximum_block_size, "sbd_interest_rate": int(args.sbd_interest_rate * 100) } print_json( steem.commit.witness_update( args.signing_key, args.url, props, account=args.witness)) else: print("No valid command given")
def main(): global args parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="Command line tool to interact with the Steem network") """ Default settings for all tools """ parser.add_argument( '--node', type=str, default=config["node"], help= 'Websocket URL for public Steem API (default: "wss://this.piston.rocks/")' ) parser.add_argument('--rpcuser', type=str, default=config["rpcuser"], help='Websocket user if authentication is required') parser.add_argument( '--rpcpassword', type=str, default=config["rpcpassword"], help='Websocket password if authentication is required') parser.add_argument('--nobroadcast', '-d', action='store_true', help='Do not broadcast anything') parser.add_argument('--nowallet', '-p', action='store_true', help='Do not load the wallet') parser.add_argument('--unsigned', '-x', action='store_true', help='Do not try to sign the transaction') parser.add_argument('--expires', '-e', default=30, help='Expiration time in seconds (defaults to 30)') parser.add_argument('--verbose', '-v', type=int, default=3, help='Verbosity') parser.add_argument( '--version', action='version', version='%(prog)s {version}'.format(version=__VERSION__)) subparsers = parser.add_subparsers(help='sub-command help') """ Command "set" """ setconfig = subparsers.add_parser('set', help='Set configuration') setconfig.add_argument('key', type=str, choices=availableConfigurationKeys, help='Configuration key') setconfig.add_argument('value', type=str, help='Configuration value') setconfig.set_defaults(command="set") """ Command "config" """ configconfig = subparsers.add_parser('config', help='Show local configuration') configconfig.set_defaults(command="config") """ Command "info" """ parser_info = subparsers.add_parser( 'info', help='Show infos about piston and Steem') parser_info.set_defaults(command="info") """ Command "changewalletpassphrase" """ changepasswordconfig = subparsers.add_parser('changewalletpassphrase', help='Change wallet password') changepasswordconfig.set_defaults(command="changewalletpassphrase") """ Command "addkey" """ addkey = subparsers.add_parser('addkey', help='Add a new key to the wallet') addkey.add_argument('wifkeys', nargs='*', type=str, help='the private key in wallet import format (wif)') addkey.set_defaults(command="addkey") """ Command "delkey" """ delkey = subparsers.add_parser('delkey', help='Delete keys from the wallet') delkey.add_argument('pub', nargs='*', type=str, help='the public key to delete from the wallet') delkey.set_defaults(command="delkey") """ Command "getkey" """ getkey = subparsers.add_parser( 'getkey', help='Dump the privatekey of a pubkey from the wallet') getkey.add_argument( 'pub', type=str, help='the public key for which to show the private key') getkey.set_defaults(command="getkey") """ Command "listkeys" """ listkeys = subparsers.add_parser('listkeys', help='List available keys in your wallet') listkeys.set_defaults(command="listkeys") """ Command "listaccounts" """ listaccounts = subparsers.add_parser( 'listaccounts', help='List available accounts in your wallet') listaccounts.set_defaults(command="listaccounts") """ Command "list" """ parser_list = subparsers.add_parser('list', help='List posts on Steem') parser_list.set_defaults(command="list") parser_list.add_argument( '--start', type=str, help='Start list from this identifier (pagination)') parser_list.add_argument('--category', type=str, help='Only posts with in this category') parser_list.add_argument('--sort', type=str, default=config["list_sorting"], choices=[ "trending", "created", "active", "cashout", "payout", "votes", "children", "hot" ], help='Sort posts') parser_list.add_argument('--limit', type=int, default=config["limit"], help='Limit posts by number') parser_list.add_argument('--columns', type=str, nargs="+", help='Display custom columns') """ Command "categories" """ parser_categories = subparsers.add_parser('categories', help='Show categories') parser_categories.set_defaults(command="categories") parser_categories.add_argument( '--sort', type=str, default=config["categories_sorting"], choices=["trending", "best", "active", "recent"], help='Sort categories') parser_categories.add_argument('category', nargs="?", type=str, help='Only categories used by this author') parser_categories.add_argument('--limit', type=int, default=config["limit"], help='Limit categories by number') """ Command "read" """ parser_read = subparsers.add_parser('read', help='Read a post on Steem') parser_read.set_defaults(command="read") parser_read.add_argument( 'post', type=str, help= '@author/permlink-identifier of the post to read (e.g. @xeroc/python-steem-0-1)' ) parser_read.add_argument( '--full', action='store_true', help='Show full header information (YAML formated)') parser_read.add_argument('--comments', action='store_true', help='Also show all comments') parser_read.add_argument('--parents', type=int, default=0, help='Show x parents for the reply') parser_read.add_argument( '--format', type=str, default=config["format"], help='Format post', choices=["markdown", "raw"], ) """ Command "post" """ parser_post = subparsers.add_parser('post', help='Post something new') parser_post.set_defaults(command="post") parser_post.add_argument( '--author', type=str, required=False, default=config["default_author"], help= 'Publish post as this user (requires to have the key installed in the wallet)' ) parser_post.add_argument( '--permlink', type=str, required=False, help= 'The permlink (together with the author identifies the post uniquely)') parser_post.add_argument('--category', default=config["post_category"], type=str, help='Specify category') parser_post.add_argument( '--tags', default=[], help='Specify tags', nargs='*', ) parser_post.add_argument('--title', type=str, required=False, help='Title of the post') parser_post.add_argument( '--file', type=str, default=None, help='Filename to open. If not present, or "-", stdin will be used') """ Command "reply" """ reply = subparsers.add_parser('reply', help='Reply to an existing post') reply.set_defaults(command="reply") reply.add_argument( 'replyto', type=str, help= '@author/permlink-identifier of the post to reply to (e.g. @xeroc/python-steem-0-1)' ) reply.add_argument( '--author', type=str, required=False, default=config["default_author"], help= 'Publish post as this user (requires to have the key installed in the wallet)' ) reply.add_argument( '--permlink', type=str, required=False, help= 'The permlink (together with the author identifies the post uniquely)') reply.add_argument('--title', type=str, required=False, help='Title of the post') reply.add_argument('--file', type=str, required=False, help='Send file as responds. If "-", read from stdin') """ Command "edit" """ parser_edit = subparsers.add_parser('edit', help='Edit to an existing post') parser_edit.set_defaults(command="edit") parser_edit.add_argument( 'post', type=str, help= '@author/permlink-identifier of the post to edit to (e.g. @xeroc/python-steem-0-1)' ) parser_edit.add_argument('--author', type=str, required=False, default=config["default_author"], help='Post an edit as another author') parser_edit.add_argument('--file', type=str, required=False, help='Patch with content of this file') parser_edit.add_argument( '--replace', action='store_true', help="Don't patch but replace original post (will make you lose votes)" ) """ Command "upvote" """ parser_upvote = subparsers.add_parser('upvote', help='Upvote a post') parser_upvote.set_defaults(command="upvote") parser_upvote.add_argument( 'post', type=str, help= '@author/permlink-identifier of the post to upvote to (e.g. @xeroc/python-steem-0-1)' ) parser_upvote.add_argument('--voter', type=str, required=False, default=config["default_voter"], help='The voter account name') parser_upvote.add_argument('--weight', type=float, default=config["default_vote_weight"], required=False, help='Actual weight (from 0.1 to 100.0)') """ Command "downvote" """ parser_downvote = subparsers.add_parser('downvote', help='Downvote a post') parser_downvote.set_defaults(command="downvote") parser_downvote.add_argument('--voter', type=str, default=config["default_voter"], help='The voter account name') parser_downvote.add_argument( 'post', type=str, help= '@author/permlink-identifier of the post to downvote to (e.g. @xeroc/python-steem-0-1)' ) parser_downvote.add_argument('--weight', type=float, default=config["default_vote_weight"], required=False, help='Actual weight (from 0.1 to 100.0)') """ Command "replies" """ replies = subparsers.add_parser('replies', help='Show recent replies to your posts') replies.set_defaults(command="replies") replies.add_argument('--author', type=str, required=False, default=config["default_author"], help='Show replies to this author') replies.add_argument('--limit', type=int, default=config["limit"], help='Limit posts by number') """ Command "transfer" """ parser_transfer = subparsers.add_parser('transfer', help='Transfer STEEM') parser_transfer.set_defaults(command="transfer") parser_transfer.add_argument('to', type=str, help='Recepient') parser_transfer.add_argument('amount', type=float, help='Amount to transfer') parser_transfer.add_argument('asset', type=str, choices=["GOLOS", "GBG"], help='Asset to (i.e. STEEM or SDB)') parser_transfer.add_argument('memo', type=str, nargs="?", default="", help='Optional memo') parser_transfer.add_argument('--account', type=str, required=False, default=config["default_author"], help='Transfer from this account') """ Command "powerup" """ parser_powerup = subparsers.add_parser( 'powerup', help='Power up (vest STEEM as STEEM POWER)') parser_powerup.set_defaults(command="powerup") parser_powerup.add_argument('amount', type=str, help='Amount of VESTS to powerup') parser_powerup.add_argument('--account', type=str, required=False, default=config["default_author"], help='Powerup from this account') parser_powerup.add_argument('--to', type=str, required=False, default=config["default_author"], help='Powerup this account') """ Command "powerdown" """ parser_powerdown = subparsers.add_parser( 'powerdown', help='Power down (start withdrawing STEEM from STEEM POWER)') parser_powerdown.set_defaults(command="powerdown") parser_powerdown.add_argument('amount', type=str, help='Amount of VESTS to powerdown') parser_powerdown.add_argument('--account', type=str, required=False, default=config["default_author"], help='powerdown from this account') """ Command "powerdownroute" """ parser_powerdownroute = subparsers.add_parser( 'powerdownroute', help='Setup a powerdown route') parser_powerdownroute.set_defaults(command="powerdownroute") parser_powerdownroute.add_argument( 'to', type=str, default=config["default_author"], help='The account receiving either VESTS/SteemPower or STEEM.') parser_powerdownroute.add_argument( '--percentage', type=float, default=100, help='The percent of the withdraw to go to the "to" account') parser_powerdownroute.add_argument( '--account', type=str, default=config["default_author"], help='The account which is powering down') parser_powerdownroute.add_argument( '--auto_vest', action='store_true', help=('Set to true if the from account should receive the VESTS as' 'VESTS, or false if it should receive them as STEEM.')) """ Command "convert" """ parser_convert = subparsers.add_parser( 'convert', help='Convert STEEMDollars to Steem (takes a week to settle)') parser_convert.set_defaults(command="convert") parser_convert.add_argument('amount', type=float, help='Amount of SBD to convert') parser_convert.add_argument('--account', type=str, required=False, default=config["default_author"], help='Convert from this account') """ Command "balance" """ parser_balance = subparsers.add_parser( 'balance', help='Show the balance of one more more accounts') parser_balance.set_defaults(command="balance") parser_balance.add_argument( 'account', type=str, nargs="*", default=config["default_author"], help='balance of these account (multiple accounts allowed)') """ Command "history" """ parser_history = subparsers.add_parser( 'history', help='Show the history of an account') parser_history.set_defaults(command="history") parser_history.add_argument('account', type=str, nargs="?", default=config["default_author"], help='History of this account') parser_history.add_argument('--limit', type=int, default=config["limit"], help='Limit number of entries') parser_history.add_argument('--memos', action='store_true', help='Show (decode) memos') parser_history.add_argument( '--first', type=int, default=99999999999999, help='Transactioon numer (#) of the last transaction to show.') parser_history.add_argument('--types', type=str, nargs="*", default=[], help='Show only these operation types') """ Command "interest" """ interest = subparsers.add_parser( 'interest', help='Get information about interest payment') interest.set_defaults(command="interest") interest.add_argument('account', type=str, nargs="*", default=config["default_author"], help='Inspect these accounts') """ Command "permissions" """ parser_permissions = subparsers.add_parser( 'permissions', help='Show permissions of an account') parser_permissions.set_defaults(command="permissions") parser_permissions.add_argument('account', type=str, nargs="?", default=config["default_author"], help='Account to show permissions for') """ Command "allow" """ parser_allow = subparsers.add_parser( 'allow', help='Allow an account/key to interact with your account') parser_allow.set_defaults(command="allow") parser_allow.add_argument('--account', type=str, nargs="?", default=config["default_author"], help='The account to allow action for') parser_allow.add_argument( 'foreign_account', type=str, nargs="?", help= 'The account or key that will be allowed to interact as your account') parser_allow.add_argument( '--permission', type=str, default="posting", choices=["owner", "posting", "active"], help=('The permission to grant (defaults to "posting")')) parser_allow.add_argument( '--weight', type=int, default=None, help=('The weight to use instead of the (full) threshold. ' 'If the weight is smaller than the threshold, ' 'additional signatures are required')) parser_allow.add_argument( '--threshold', type=int, default=None, help=('The permission\'s threshold that needs to be reached ' 'by signatures to be able to interact')) """ Command "disallow" """ parser_disallow = subparsers.add_parser( 'disallow', help='Remove allowance an account/key to interact with your account') parser_disallow.set_defaults(command="disallow") parser_disallow.add_argument('--account', type=str, nargs="?", default=config["default_author"], help='The account to disallow action for') parser_disallow.add_argument( 'foreign_account', type=str, help= 'The account or key whose allowance to interact as your account will be removed' ) parser_disallow.add_argument( '--permission', type=str, default="posting", choices=["owner", "posting", "active"], help=('The permission to remove (defaults to "posting")')) parser_disallow.add_argument( '--threshold', type=int, default=None, help=('The permission\'s threshold that needs to be reached ' 'by signatures to be able to interact')) """ Command "newaccount" """ parser_newaccount = subparsers.add_parser('newaccount', help='Create a new account') parser_newaccount.set_defaults(command="newaccount") parser_newaccount.add_argument('accountname', type=str, help='New account name') parser_newaccount.add_argument('--account', type=str, required=False, default=config["default_author"], help='Account that pays the fee') """ Command "importaccount" """ parser_importaccount = subparsers.add_parser( 'importaccount', help='Import an account using a passphrase') parser_importaccount.set_defaults(command="importaccount") parser_importaccount.add_argument('account', type=str, help='Account name') """ Command "updateMemoKey" """ parser_updateMemoKey = subparsers.add_parser( 'updatememokey', help='Update an account\'s memo key') parser_updateMemoKey.set_defaults(command="updatememokey") parser_updateMemoKey.add_argument( '--account', type=str, nargs="?", default=config["default_author"], help='The account to updateMemoKey action for') parser_updateMemoKey.add_argument('--key', type=str, default=None, help='The new memo key') """ Command "sign" """ parser_sign = subparsers.add_parser( 'sign', help='Sign a provided transaction with available and required keys') parser_sign.set_defaults(command="sign") parser_sign.add_argument( '--file', type=str, required=False, help= 'Load transaction from file. If "-", read from stdin (defaults to "-")' ) """ Command "broadcast" """ parser_broadcast = subparsers.add_parser( 'broadcast', help='broadcast a signed transaction') parser_broadcast.set_defaults(command="broadcast") parser_broadcast.add_argument( '--file', type=str, required=False, help= 'Load transaction from file. If "-", read from stdin (defaults to "-")' ) """ Command "web" """ webconfig = subparsers.add_parser('web', help='Launch web version of piston') webconfig.set_defaults(command="web") webconfig.add_argument('--port', type=int, default=config["web:port"], help='Port to open for internal web requests') webconfig.add_argument('--host', type=str, default=config["web:host"], help='Host address to listen to') """ Command "orderbook" """ orderbook = subparsers.add_parser( 'orderbook', help='Obtain orderbook of the internal market') orderbook.set_defaults(command="orderbook") orderbook.add_argument('--chart', action='store_true', help="Enable charting (requires matplotlib)") """ Command "buy" """ parser_buy = subparsers.add_parser( 'buy', help='Buy GOLOS or GBG from the internal market') parser_buy.set_defaults(command="buy") parser_buy.add_argument('amount', type=float, help='Amount to buy') parser_buy.add_argument('asset', type=str, choices=["GOLOS", "GBG"], help='Asset to buy (i.e. GOLOS or GBG)') parser_buy.add_argument('price', type=float, help='Limit buy price denoted in (GBG per GOLOS)') parser_buy.add_argument( '--account', type=str, required=False, default=config["default_account"], help='Buy with this account (defaults to "default_account")') """ Command "sell" """ parser_sell = subparsers.add_parser( 'sell', help='Sell GOLOS or GBG from the internal market') parser_sell.set_defaults(command="sell") parser_sell.add_argument('amount', type=float, help='Amount to sell') parser_sell.add_argument('asset', type=str, choices=["GOLOS", "GBG"], help='Asset to sell (i.e. GOLOS or GBG)') parser_sell.add_argument( 'price', type=float, help='Limit sell price denoted in (GBG per GOLOS)') parser_sell.add_argument( '--account', type=str, required=False, default=config["default_account"], help='Sell from this account (defaults to "default_account")') """ Parse Arguments """ args = parser.parse_args() # Logging log = logging.getLogger(__name__) verbosity = ["critical", "error", "warn", "info", "debug"][int(min(args.verbose, 4))] log.setLevel(getattr(logging, verbosity.upper())) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch = logging.StreamHandler() ch.setLevel(getattr(logging, verbosity.upper())) ch.setFormatter(formatter) log.addHandler(ch) # GrapheneAPI logging if args.verbose > 4: verbosity = ["critical", "error", "warn", "info", "debug"][int(min((args.verbose - 4), 4))] gphlog = logging.getLogger("graphenebase") gphlog.setLevel(getattr(logging, verbosity.upper())) gphlog.addHandler(ch) if args.verbose > 8: verbosity = ["critical", "error", "warn", "info", "debug"][int(min((args.verbose - 8), 4))] gphlog = logging.getLogger("grapheneapi") gphlog.setLevel(getattr(logging, verbosity.upper())) gphlog.addHandler(ch) if not hasattr(args, "command"): parser.print_help() sys.exit(2) # We don't require RPC for these commands rpc_not_required = ["set", "config", "web", ""] if args.command not in rpc_not_required and args.command: options = { "node": args.node, "rpcuser": args.rpcuser, "rpcpassword": args.rpcpassword, "nobroadcast": args.nobroadcast, "unsigned": args.unsigned, "expires": args.expires } # preload wallet with empty keys if args.nowallet: options.update({"wif": []}) # Signing only requires the wallet, no connection # essential for offline/coldstorage signing if args.command == "sign": options.update({"offline": True}) steem = SteemConnector(**options).getSteem() if args.command == "set": if (args.key in ["default_author", "default_voter", "default_account"] and args.value[0] == "@"): args.value = args.value[1:] config[args.key] = args.value elif args.command == "config": t = PrettyTable(["Key", "Value"]) t.align = "l" for key in config: if key in availableConfigurationKeys: # hide internal config data t.add_row([key, config[key]]) print(t) elif args.command == "info": t = PrettyTable(["Key", "Value"]) t.align = "l" info = steem.rpc.get_dynamic_global_properties() median_price = steem.rpc.get_current_median_history_price() steem_per_mvest = ( float(info["total_vesting_fund_steem"].split(" ")[0]) / (float(info["total_vesting_shares"].split(" ")[0]) / 1e6)) price = (float(median_price["base"].split(" ")[0]) / float(median_price["quote"].split(" ")[0])) for key in info: t.add_row([key, info[key]]) t.add_row(["steem per mvest", steem_per_mvest]) t.add_row(["internal price", price]) print(t) elif args.command == "changewalletpassphrase": steem.wallet.changePassphrase() elif args.command == "addkey": pub = None if len(args.wifkeys): for wifkey in args.wifkeys: pub = (steem.wallet.addPrivateKey(wifkey)) if pub: print(pub) else: import getpass wifkey = "" while True: wifkey = getpass.getpass('Private Key (wif) [Enter to quit]:') if not wifkey: break pub = (steem.wallet.addPrivateKey(wifkey)) if pub: print(pub) if pub: name = steem.wallet.getAccountFromPublicKey(pub) print("Setting new default user: %s" % name) print("You can change these settings with:") print(" piston set default_author x") print(" piston set default_voter x") config["default_author"] = name config["default_voter"] = name elif args.command == "delkey": if confirm("Are you sure you want to delete keys from your wallet?\n" "This step is IRREVERSIBLE! If you don't have a backup, " "You may lose access to your account!"): for pub in args.pub: steem.wallet.removePrivateKeyFromPublicKey(pub) elif args.command == "getkey": print(steem.wallet.getPrivateKeyForPublicKey(args.pub)) elif args.command == "listkeys": t = PrettyTable(["Available Key"]) t.align = "l" for key in steem.wallet.getPublicKeys(): t.add_row([key]) print(t) elif args.command == "listaccounts": t = PrettyTable(["Name", "Type", "Available Key"]) t.align = "l" for account in steem.wallet.getAccounts(): t.add_row([ account["name"] or "n/a", account["type"] or "n/a", account["pubkey"] ]) print(t) elif args.command == "reply": from textwrap import indent parent = steem.get_content(args.replyto) if parent["id"] == "0.0.0": print("Can't find post %s" % args.replyto) return reply_message = indent(parent["body"], "> ") post = frontmatter.Post( reply_message, **{ "title": args.title if args.title else "Re: " + parent["title"], "author": args.author if args.author else "required", "replyto": args.replyto, }) meta, json_meta, message = yaml_parse_file(args, initial_content=post) for required in ["author", "title"]: if (required not in meta or not meta[required] or meta[required] == "required"): print("'%s' required!" % required) # TODO, instead of terminating here, send the user back # to the EDITOR return pprint( steem.reply( meta["replyto"], message, title=meta["title"], author=meta["author"], meta=json_meta, )) elif args.command == "post" or args.command == "yaml": initmeta = { "title": args.title if args.title else "required", "author": args.author if args.author else "required", "category": args.category if args.category else "required", } if args.tags: initmeta["tags"] = args.tags post = frontmatter.Post("", **initmeta) meta, json_meta, body = yaml_parse_file(args, initial_content=post) if not body: print("Empty body! Not posting!") return for required in ["author", "title", "category"]: if (required not in meta or not meta[required] or meta[required] == "required"): print("'%s' required!" % required) # TODO, instead of terminating here, send the user back # to the EDITOR return pprint( steem.post( meta["title"], body, author=meta["author"], category=meta["category"], meta=json_meta, )) elif args.command == "edit": original_post = steem.get_content(args.post) edited_message = None if original_post["id"] == "0.0.0": print("Can't find post %s" % args.post) return post = frontmatter.Post( original_post["body"], **{ "title": original_post["title"] + " (immutable)", "author": original_post["author"] + " (immutable)", "tags": original_post["_tags"] }) meta, json_meta, edited_message = yaml_parse_file(args, initial_content=post) pprint( steem.edit( args.post, edited_message, replace=args.replace, meta=json_meta, )) elif args.command == "upvote" or args.command == "downvote": post = Post(steem, args.post) if args.command == "downvote": weight = -float(args.weight) else: weight = +float(args.weight) if not args.voter: print("Not voter provided!") return pprint(post.vote(weight, voter=args.voter)) elif args.command == "read": post_author, post_permlink = resolveIdentifier(args.post) if args.parents: # FIXME inconsistency, use @author/permlink instead! dump_recursive_parents(steem.rpc, post_author, post_permlink, args.parents, format=args.format) if not args.comments and not args.parents: post = steem.get_content(args.post) if post["id"] == "0.0.0": print("Can't find post %s" % args.post) return if args.format == "markdown": body = markdownify(post["body"]) else: body = post["body"] if args.full: meta = {} for key in post: if key in ["steem", "body"]: continue meta[key] = post[key] yaml = frontmatter.Post(body, **meta) print(frontmatter.dumps(yaml)) else: print(body) if args.comments: dump_recursive_comments(steem.rpc, post_author, post_permlink, format=args.format) elif args.command == "categories": categories = steem.get_categories(sort=args.sort, begin=args.category, limit=args.limit) t = PrettyTable(["name", "discussions", "payouts"]) t.align = "l" for category in categories: t.add_row([ category["name"], category["discussions"], category["total_payouts"], ]) print(t) elif args.command == "list": list_posts( steem.get_posts(limit=args.limit, sort=args.sort, category=args.category, start=args.start), args.columns) elif args.command == "replies": if not args.author: print("Please specify an author via --author\n " "or define your default author with:\n" " piston set default_author x") else: discussions = steem.get_replies(args.author) list_posts(discussions[0:args.limit]) elif args.command == "transfer": pprint( steem.transfer(args.to, args.amount, args.asset, memo=args.memo, account=args.account)) elif args.command == "powerup": pprint( steem.transfer_to_vesting(args.amount, account=args.account, to=args.to)) elif args.command == "powerdown": pprint(steem.withdraw_vesting( args.amount, account=args.account, )) elif args.command == "convert": pprint(steem.convert( args.amount, account=args.account, )) elif args.command == "powerdownroute": pprint( steem.set_withdraw_vesting_route(args.to, percentage=args.percentage, account=args.account, auto_vest=args.auto_vest)) elif args.command == "balance": t = PrettyTable( ["Account", "GOLOS", "GBG", "GESTS", "VESTS (in STEEM)"]) t.align = "r" if isinstance(args.account, str): args.account = [args.account] for a in args.account: b = steem.get_balances(a) t.add_row([ a, b["balance"], b["sbd_balance"], b["vesting_shares"], b["vesting_shares_steem"] ]) print(t) elif args.command == "history": t = PrettyTable(["#", "time/block", "Operation", "Details"]) t.align = "r" if isinstance(args.account, str): args.account = [args.account] if isinstance(args.types, str): args.types = [args.types] for a in args.account: for b in steem.rpc.account_history(a, args.first, limit=args.limit, only_ops=args.types): t.add_row([ b[0], "%s (%s)" % (b[1]["timestamp"], b[1]["block"]), b[1]["op"][0], format_operation_details(b[1]["op"], memos=args.memos), ]) print(t) elif args.command == "interest": t = PrettyTable([ "Account", "Last Interest Payment", "Next Payment", "Interest rate", "Interest" ]) t.align = "r" if isinstance(args.account, str): args.account = [args.account] for a in args.account: i = steem.interest(a) t.add_row([ a, i["last_payment"], "in %s" % strfage(i["next_payment_duration"]), "%.1f%%" % i["interest_rate"], "%.3f GBG" % i["interest"], ]) print(t) elif args.command == "permissions": account = steem.rpc.get_account(args.account) print_permissions(account) elif args.command == "allow": if not args.foreign_account: from steembase.account import PasswordKey pwd = get_terminal(text="Password for Key Derivation: ", confirm=True) args.foreign_account = format( PasswordKey(args.account, pwd, args.permission).get_public(), "GLS") pprint( steem.allow(args.foreign_account, weight=args.weight, account=args.account, permission=args.permission, threshold=args.threshold)) elif args.command == "disallow": pprint( steem.disallow(args.foreign_account, account=args.account, permission=args.permission, threshold=args.threshold)) elif args.command == "updatememokey": if not args.key: # Loop until both match from steembase.account import PasswordKey pw = get_terminal(text="Password for Memo Key: ", confirm=True, allowedempty=False) memo_key = PasswordKey(args.account, pw, "memo") args.key = format(memo_key.get_public_key(), "GLS") memo_privkey = memo_key.get_private_key() # Add the key to the wallet if not args.nobroadcast: steem.wallet.addPrivateKey(memo_privkey) pprint(steem.update_memo_key(args.key, account=args.account)) elif args.command == "newaccount": import getpass while True: pw = getpass.getpass("New Account Passphrase: ") if not pw: print("You cannot chosen an empty password!") continue else: pwck = getpass.getpass("Confirm New Account Passphrase: ") if (pw == pwck): break else: print("Given Passphrases do not match!") pprint( steem.create_account( args.accountname, creator=args.account, password=pw, )) elif args.command == "importaccount": from steembase.account import PasswordKey import getpass password = getpass.getpass("Account Passphrase: ") posting_key = PasswordKey(args.account, password, role="posting") active_key = PasswordKey(args.account, password, role="active") memo_key = PasswordKey(args.account, password, role="memo") posting_pubkey = format(posting_key.get_public_key(), "GLS") active_pubkey = format(active_key.get_public_key(), "GLS") memo_pubkey = format(memo_key.get_public_key(), "GLS") account = steem.rpc.get_account(args.account) imported = False if active_pubkey in [x[0] for x in account["active"]["key_auths"]]: active_privkey = active_key.get_private_key() steem.wallet.addPrivateKey(active_privkey) imported = True if posting_pubkey in [x[0] for x in account["posting"]["key_auths"]]: posting_privkey = posting_key.get_private_key() steem.wallet.addPrivateKey(posting_privkey) imported = True if memo_pubkey == account["memo_key"]: memo_privkey = memo_key.get_private_key() steem.wallet.addPrivateKey(memo_privkey) imported = True if not imported: print("No keys matched! Invalid password?") elif args.command == "sign": if args.file and args.file != "-": if not os.path.isfile(args.file): raise Exception("File %s does not exist!" % args.file) with open(args.file) as fp: tx = fp.read() else: tx = sys.stdin.read() tx = eval(tx) pprint(steem.sign(tx)) elif args.command == "broadcast": if args.file and args.file != "-": if not os.path.isfile(args.file): raise Exception("File %s does not exist!" % args.file) with open(args.file) as fp: tx = fp.read() else: tx = sys.stdin.read() tx = eval(tx) steem.broadcast(tx) elif args.command == "web": SteemConnector(node=args.node, rpcuser=args.rpcuser, rpcpassword=args.rpcpassword, nobroadcast=args.nobroadcast, num_retries=1) from . import web web.run(port=args.port, host=args.host) elif args.command == "orderbook": if args.chart: try: import numpy import Gnuplot from itertools import accumulate except: print( "To use --chart, you need gnuplot and gnuplot-py installed" ) sys.exit(1) orderbook = steem.dex().returnOrderBook() if args.chart: g = Gnuplot.Gnuplot() g.title("Steem internal market - GBG:GOLOS") g.xlabel("price") g.ylabel("volume") g(""" set style data line set term xterm set border 15 """) xbids = [x["price"] for x in orderbook["bids"]] ybids = list(accumulate([x["gbg"] for x in orderbook["bids"]])) dbids = Gnuplot.Data(xbids, ybids, with_="lines") xasks = [x["price"] for x in orderbook["asks"]] yasks = list(accumulate([x["gbg"] for x in orderbook["asks"]])) dasks = Gnuplot.Data(xasks, yasks, with_="lines") g("set terminal dumb") g.plot(dbids, dasks) # write SVG data directly to stdout ... t = PrettyTable([ "bid GBG", "sum bids GBG", "bid GOLOS", "sum bids GOLOS", "bid price", "+", "ask price", "ask GOLOS", "sum asks steem", "ask GBG", "sum asks GBG" ]) t.align = "r" bidssteem = 0 bidssbd = 0 askssteem = 0 askssbd = 0 for i, o in enumerate(orderbook["asks"]): bidssbd += orderbook["bids"][i]["gbg"] bidssteem += orderbook["bids"][i]["golos"] askssbd += orderbook["asks"][i]["gbg"] askssteem += orderbook["asks"][i]["golos"] t.add_row([ "%.3f Ṩ" % orderbook["bids"][i]["gbg"], "%.3f ∑" % bidssbd, "%.3f ȿ" % orderbook["bids"][i]["golos"], "%.3f ∑" % bidssteem, "%.3f Ṩ/ȿ" % orderbook["bids"][i]["price"], "|", "%.3f Ṩ/ȿ" % orderbook["asks"][i]["price"], "%.3f ȿ" % orderbook["asks"][i]["golos"], "%.3f ∑" % askssteem, "%.3f Ṩ" % orderbook["asks"][i]["gbg"], "%.3f ∑" % askssbd ]) print(t) elif args.command == "buy": if args.asset == "GBG": price = 1.0 / args.price else: price = args.price pprint(steem.buy(args.amount, args.asset, price, account=args.account)) elif args.command == "sell": if args.asset == "GBG": price = 1.0 / args.price else: price = args.price pprint(steem.sell(args.amount, args.asset, price, account=args.account)) else: print("No valid command given")
def create_account( self, account_name, json_meta=None, password=None, owner_key=None, active_key=None, posting_key=None, memo_key=None, additional_owner_keys=[], additional_active_keys=[], additional_posting_keys=[], additional_owner_accounts=[], additional_active_accounts=[], additional_posting_accounts=[], store_keys=True, store_owner_key=False, delegation_fee_steem='0 STEEM', creator=None, ): """ Create new account in Steem The brainkey/password can be used to recover all generated keys (see `steembase.account` for more details. By default, this call will use ``default_account`` to register a new name ``account_name`` with all keys being derived from a new brain key that will be returned. The corresponding keys will automatically be installed in the wallet. .. note:: Account creations cost a fee that is defined by the network. If you create an account, you will need to pay for that fee! **You can partially pay that fee by delegating VESTS.** To pay the fee in full in STEEM, leave ``delegation_fee_steem`` set to ``0 STEEM`` (Default). To pay the fee partially in STEEM, partially with delegated VESTS, set ``delegation_fee_steem`` to a value greater than ``1 STEEM``. `Required VESTS will be calculated automatically.` To pay the fee with maximum amount of delegation, set ``delegation_fee_steem`` to ``1 STEEM``. `Required VESTS will be calculated automatically.` .. warning:: Don't call this method unless you know what you are doing! Be sure to understand what this method does and where to find the private keys for your account. .. note:: Please note that this imports private keys (if password is present) into the wallet by default. However, it **does not import the owner key** unless `store_owner_key` is set to True (default False). Do NOT expect to be able to recover it from the wallet if you lose your password! :param str account_name: (**required**) new account name :param str json_meta: Optional meta data for the account :param str owner_key: Main owner key :param str active_key: Main active key :param str posting_key: Main posting key :param str memo_key: Main memo_key :param str password: Alternatively to providing keys, one can provide a password from which the keys will be derived :param list additional_owner_keys: Additional owner public keys :param list additional_active_keys: Additional active public keys :param list additional_posting_keys: Additional posting public keys :param list additional_owner_accounts: Additional owner account names :param list additional_active_accounts: Additional active account names :param list additional_posting_accounts: Additional posting account names :param bool store_keys: Store new keys in the wallet (default: ``True``) :param bool store_owner_key: Store owner key in the wallet (default: ``False``) :param str delegation_fee_steem: (Optional) If set, `creator` pay a fee of this amount, and delegate the rest with VESTS (calculated automatically). Minimum: 1 STEEM. If left to 0 (Default), full fee is paid without VESTS delegation. :param str creator: which account should pay the registration fee (defaults to ``default_account``) :raises AccountExistsException: if the account already exists on the blockchain """ assert len( account_name) <= 16, "Account name must be at most 16 chars long" if not creator: creator = configStorage.get("default_account") if not creator: raise ValueError( "Not creator account given. Define it with " + "creator=x, or set the default_account using steempy") if password and (owner_key or posting_key or active_key or memo_key): raise ValueError("You cannot use 'password' AND provide keys!") # check if account already exists try: Account(account_name, steemd_instance=self.steemd) except: # noqa FIXME(sneak) pass else: raise AccountExistsException " Generate new keys from password" from steembase.account import PasswordKey, PublicKey if password: posting_key = PasswordKey(account_name, password, role="posting") active_key = PasswordKey(account_name, password, role="active") owner_key = PasswordKey(account_name, password, role="owner") memo_key = PasswordKey(account_name, password, role="memo") posting_pubkey = posting_key.get_public_key() active_pubkey = active_key.get_public_key() owner_pubkey = owner_key.get_public_key() memo_pubkey = memo_key.get_public_key() posting_privkey = posting_key.get_private_key() active_privkey = active_key.get_private_key() owner_privkey = owner_key.get_private_key() memo_privkey = memo_key.get_private_key() # store private keys if store_keys: if store_owner_key: self.wallet.addPrivateKey(owner_privkey) self.wallet.addPrivateKey(active_privkey) self.wallet.addPrivateKey(posting_privkey) self.wallet.addPrivateKey(memo_privkey) elif owner_key and posting_key and active_key and memo_key: posting_pubkey = PublicKey( posting_key, prefix=self.steemd.chain_params["prefix"]) active_pubkey = PublicKey( active_key, prefix=self.steemd.chain_params["prefix"]) owner_pubkey = PublicKey(owner_key, prefix=self.steemd.chain_params["prefix"]) memo_pubkey = PublicKey(memo_key, prefix=self.steemd.chain_params["prefix"]) else: raise ValueError( "Call incomplete! Provide either a password or public keys!") owner = format(owner_pubkey, self.steemd.chain_params["prefix"]) active = format(active_pubkey, self.steemd.chain_params["prefix"]) posting = format(posting_pubkey, self.steemd.chain_params["prefix"]) memo = format(memo_pubkey, self.steemd.chain_params["prefix"]) owner_key_authority = [[owner, 1]] active_key_authority = [[active, 1]] posting_key_authority = [[posting, 1]] owner_accounts_authority = [] active_accounts_authority = [] posting_accounts_authority = [] # additional authorities for k in additional_owner_keys: owner_key_authority.append([k, 1]) for k in additional_active_keys: active_key_authority.append([k, 1]) for k in additional_posting_keys: posting_key_authority.append([k, 1]) for k in additional_owner_accounts: owner_accounts_authority.append([k, 1]) for k in additional_active_accounts: active_accounts_authority.append([k, 1]) for k in additional_posting_accounts: posting_accounts_authority.append([k, 1]) props = self.steemd.get_chain_properties() required_fee_steem = Amount(props["account_creation_fee"]).amount * 30 required_fee_vests = 0 delegation_fee_steem = Amount(delegation_fee_steem).amount if delegation_fee_steem: # creating accounts without delegation requires 30x # account_creation_fee creating account with delegation allows one # to use VESTS to pay the fee where the ratio must satisfy 1 STEEM # in fee == 5 STEEM in delegated VESTS delegated_sp_fee_mult = 5 if delegation_fee_steem < 1: raise ValueError( "When creating account with delegation, at least " + "1 STEEM in fee must be paid.") # calculate required remaining fee in vests remaining_fee = required_fee_steem - delegation_fee_steem if remaining_fee > 0: required_sp = remaining_fee * delegated_sp_fee_mult required_fee_vests = Converter().sp_to_vests(required_sp) + 1 s = { 'creator': creator, 'fee': '%s STEEM' % (delegation_fee_steem or required_fee_steem), 'delegation': '%s VESTS' % required_fee_vests, 'json_metadata': json_meta or {}, 'memo_key': memo, 'new_account_name': account_name, 'owner': { 'account_auths': owner_accounts_authority, 'key_auths': owner_key_authority, 'weight_threshold': 1 }, 'active': { 'account_auths': active_accounts_authority, 'key_auths': active_key_authority, 'weight_threshold': 1 }, 'posting': { 'account_auths': posting_accounts_authority, 'key_auths': posting_key_authority, 'weight_threshold': 1 }, 'prefix': self.steemd.chain_params["prefix"] } op = operations.AccountCreateWithDelegation(**s) return self.finalizeOp(op, creator, "active")
def create_account(self, account_name, json_meta={}, creator=None, owner_key=None, active_key=None, posting_key=None, memo_key=None, password=None, additional_owner_keys=[], additional_active_keys=[], additional_posting_keys=[], additional_owner_accounts=[], additional_active_accounts=[], additional_posting_accounts=[], storekeys=True, ): """ Create new account in Steem The brainkey/password can be used to recover all generated keys (see `steembase.account` for more details. By default, this call will use ``default_author`` to register a new name ``account_name`` with all keys being derived from a new brain key that will be returned. The corresponding keys will automatically be installed in the wallet. .. note:: Account creations cost a fee that is defined by the network. If you create an account, you will need to pay for that fee! .. warning:: Don't call this method unless you know what you are doing! Be sure to understand what this method does and where to find the private keys for your account. .. note:: Please note that this imports private keys (if password is present) into the wallet by default. However, it **does not import the owner key** for security reasons. Do NOT expect to be able to recover it from piston if you lose your password! :param str account_name: (**required**) new account name :param str json_meta: Optional meta data for the account :param str creator: which account should pay the registration fee (defaults to ``default_author``) :param str owner_key: Main owner key :param str active_key: Main active key :param str posting_key: Main posting key :param str memo_key: Main memo_key :param str password: Alternatively to providing keys, one can provide a password from which the keys will be derived :param array additional_owner_keys: Additional owner public keys :param array additional_active_keys: Additional active public keys :param array additional_posting_keys: Additional posting public keys :param array additional_owner_accounts: Additional owner account names :param array additional_active_accounts: Additional acctive account names :param array additional_posting_accounts: Additional posting account names :param bool storekeys: Store new keys in the wallet (default: ``True``) :raises AccountExistsException: if the account already exists on the blockchain """ if not creator and config["default_author"]: creator = config["default_author"] if not creator: raise ValueError( "Not creator account given. Define it with " + "creator=x, or set the default_author in piston") if password and (owner_key or posting_key or active_key or memo_key): raise ValueError( "You cannot use 'password' AND provide keys!" ) account = None try: account = self.rpc.get_account(account_name) except: pass if account: raise AccountExistsException " Generate new keys from password" from steembase.account import PasswordKey, PublicKey if password: posting_key = PasswordKey(account_name, password, role="posting") active_key = PasswordKey(account_name, password, role="active") owner_key = PasswordKey(account_name, password, role="owner") memo_key = PasswordKey(account_name, password, role="memo") posting_pubkey = posting_key.get_public_key() active_pubkey = active_key.get_public_key() owner_pubkey = owner_key.get_public_key() memo_pubkey = memo_key.get_public_key() posting_privkey = posting_key.get_private_key() active_privkey = active_key.get_private_key() # owner_privkey = owner_key.get_private_key() memo_privkey = memo_key.get_private_key() # store private keys if storekeys: # self.wallet.addPrivateKey(owner_privkey) self.wallet.addPrivateKey(active_privkey) self.wallet.addPrivateKey(posting_privkey) self.wallet.addPrivateKey(memo_privkey) elif (owner_key and posting_key and active_key and memo_key): posting_pubkey = PublicKey(posting_key, prefix=prefix) active_pubkey = PublicKey(active_key, prefix=prefix) owner_pubkey = PublicKey(owner_key, prefix=prefix) memo_pubkey = PublicKey(memo_key, prefix=prefix) else: raise ValueError( "Call incomplete! Provide either a password or public keys!" ) owner = format(posting_pubkey, prefix) active = format(active_pubkey, prefix) posting = format(owner_pubkey, prefix) memo = format(memo_pubkey, prefix) owner_key_authority = [[owner, 1]] active_key_authority = [[active, 1]] posting_key_authority = [[posting, 1]] owner_accounts_authority = [] active_accounts_authority = [] posting_accounts_authority = [] # additional authorities for k in additional_owner_keys: owner_key_authority.append([k, 1]) for k in additional_active_keys: active_key_authority.append([k, 1]) for k in additional_posting_keys: posting_key_authority.append([k, 1]) for k in additional_owner_accounts: owner_accounts_authority.append([k, 1]) for k in additional_active_accounts: active_accounts_authority.append([k, 1]) for k in additional_posting_accounts: posting_accounts_authority.append([k, 1]) props = self.rpc.get_chain_properties() fee = props["account_creation_fee"] s = {'creator': creator, 'fee': fee, 'json_metadata': json_meta, 'memo_key': memo, 'new_account_name': account_name, 'owner': {'account_auths': owner_accounts_authority, 'key_auths': owner_key_authority, 'weight_threshold': 1}, 'active': {'account_auths': active_accounts_authority, 'key_auths': active_key_authority, 'weight_threshold': 1}, 'posting': {'account_auths': posting_accounts_authority, 'key_auths': posting_key_authority, 'weight_threshold': 1}} op = transactions.Account_create(**s) wif = self.wallet.getActiveKeyForAccount(creator) return self.executeOp(op, wif)
def get_public_key_from_password(shared_dict, account_name, password): if account_name + password not in shared_dict: shared_dict[account_name + password] = str( PasswordKey(account_name, password, 'owner').get_private_key().pubkey) return shared_dict[account_name + password]