diff --git a/bitshares/aio/bitshares.py b/bitshares/aio/bitshares.py index c8864b6e..3a42bc97 100644 --- a/bitshares/aio/bitshares.py +++ b/bitshares/aio/bitshares.py @@ -240,7 +240,8 @@ async def create_account( active_accounts_authority = [[active_account["id"], 1]] else: raise ValueError( - "Call incomplete! Provide either a password, owner/active public keys or owner/active accounts + memo key!" + "Call incomplete! Provide either a password, owner/active public keys " + "or owner/active accounts + memo key!" ) # additional authorities @@ -1561,34 +1562,39 @@ async def htlc_redeem(self, htlc_id, preimage, account=None, **kwargs): ) return await self.finalizeOp(op, account, "active", **kwargs) - async def subscribe_to_blocks(self): + async def subscribe_to_blocks(self, event_id=2): """ Activate subscription to block. Each time block is applied an event will occur in self.notifications. + + :param int event_id: id of this subscription in upcoming notifications """ - await self.rpc.set_block_applied_callback(2) + await self.rpc.set_block_applied_callback(event_id) - async def subscribe_to_pending_transactions(self): + async def subscribe_to_pending_transactions(self, event_id=0): """ Activate subscription to pending transactions. Each time transaction is pushed to database an event will occur in self.notifications. + + :param int event_id: id of this subscription in upcoming notifications """ - await self.rpc.set_pending_transaction_callback(0) + await self.rpc.set_pending_transaction_callback(event_id) - async def subscribe_to_accounts(self, accounts): + async def subscribe_to_accounts(self, accounts, event_id=1): """ Activate subscription to account-related events. :param list accounts: account names or ids to subscribe + :param int event_id: id of this subscription in upcoming notifications """ if isinstance(accounts, str): accounts = [accounts] # Set subscription, False means we're don't need ALL create/delete events - await self.rpc.set_subscribe_callback(1, False) + await self.rpc.set_subscribe_callback(event_id, False) # True means we're activating subscription on account await self.rpc.get_full_accounts(accounts, True) @@ -1598,6 +1604,7 @@ async def subscribe_to_market(self, market, event_id=4): :param str,bitshares.aio.Market market: market to set subscription on + :param int event_id: id of this subscription in upcoming notifications """ if isinstance(market, str): market = await Market(market, blockchain_instance=self) diff --git a/bitshares/aio/price.py b/bitshares/aio/price.py index bad3daf6..59d9000d 100644 --- a/bitshares/aio/price.py +++ b/bitshares/aio/price.py @@ -325,8 +325,14 @@ async def __init__(self, feed, **kwargs): "maximum_short_squeeze_ratio": feed[1][1][ "maximum_short_squeeze_ratio" ], - "settlement_price": await Price(feed[1][1]["settlement_price"]), - "core_exchange_rate": await Price(feed[1][1]["core_exchange_rate"]), + "settlement_price": await Price( + feed[1][1]["settlement_price"], + blockchain_instance=self.blockchain, + ), + "core_exchange_rate": await Price( + feed[1][1]["core_exchange_rate"], + blockchain_instance=self.blockchain, + ), }, ) else: @@ -337,7 +343,11 @@ async def __init__(self, feed, **kwargs): "maintenance_collateral_ratio" ], "maximum_short_squeeze_ratio": feed["maximum_short_squeeze_ratio"], - "settlement_price": await Price(feed["settlement_price"]), - "core_exchange_rate": await Price(feed["core_exchange_rate"]), + "settlement_price": await Price( + feed["settlement_price"], blockchain_instance=self.blockchain + ), + "core_exchange_rate": await Price( + feed["core_exchange_rate"], blockchain_instance=self.blockchain + ), }, ) diff --git a/bitshares/bitshares.py b/bitshares/bitshares.py index 951a5333..b28cc1f0 100644 --- a/bitshares/bitshares.py +++ b/bitshares/bitshares.py @@ -179,7 +179,7 @@ def create_account( self, account_name, registrar=None, - referrer="1.2.35641", + referrer="temp-account", referrer_percent=50, owner_key=None, active_key=None, @@ -307,7 +307,8 @@ def create_account( active_accounts_authority = [[active_account["id"], 1]] else: raise ValueError( - "Call incomplete! Provide either a password, owner/active public keys or owner/active accounts + memo key!" + "Call incomplete! Provide either a password, owner/active public keys " + "or owner/active accounts + memo key!" ) # additional authorities @@ -350,7 +351,6 @@ def create_account( "options": { "memo_key": memo, "voting_account": voting_account["id"], - "num_witness": 0, "num_committee": 0, "votes": [], "extensions": [], @@ -606,14 +606,14 @@ def approvewitness(self, witnesses, account=None, **kwargs): if not isinstance(witnesses, (list, set, tuple)): witnesses = {witnesses} + total_num = len([x for x in options["votes"] if x[0].startswith("1:")]) + # averages out over all voted witnesses for witness in witnesses: witness = Witness(witness, blockchain_instance=self) - options["votes"].append(witness["vote_id"]) + options["votes"].append( + [witness["vote_id"], 100 / (len(witnesses) + total_num)] + ) - options["votes"] = list(set(options["votes"])) - options["num_witness"] = len( - list(filter(lambda x: float(x.split(":")[0]) == 1, options["votes"])) - ) options["voting_account"] = "1.2.5" # Account("proxy-to-self")["id"] op = operations.Account_update( @@ -648,13 +648,10 @@ def disapprovewitness(self, witnesses, account=None, **kwargs): for witness in witnesses: witness = Witness(witness, blockchain_instance=self) - if witness["vote_id"] in options["votes"]: - options["votes"].remove(witness["vote_id"]) + options["votes"] = [ + [a, w] for a, w in options["votes"] if a != witness["vote_id"] + ] - options["votes"] = list(set(options["votes"])) - options["num_witness"] = len( - list(filter(lambda x: float(x.split(":")[0]) == 1, options["votes"])) - ) options["voting_account"] = "1.2.5" # Account("proxy-to-self")["id"] op = operations.Account_update( diff --git a/bitshares/price.py b/bitshares/price.py index 5ec78528..3d24209f 100644 --- a/bitshares/price.py +++ b/bitshares/price.py @@ -373,8 +373,14 @@ def __init__(self, feed, **kwargs): "maximum_short_squeeze_ratio": feed[1][1][ "maximum_short_squeeze_ratio" ], - "settlement_price": Price(feed[1][1]["settlement_price"]), - "core_exchange_rate": Price(feed[1][1]["core_exchange_rate"]), + "settlement_price": Price( + feed[1][1]["settlement_price"], + blockchain_instance=self.blockchain, + ), + "core_exchange_rate": Price( + feed[1][1]["core_exchange_rate"], + blockchain_instance=self.blockchain, + ), }, ) else: @@ -385,7 +391,11 @@ def __init__(self, feed, **kwargs): "maintenance_collateral_ratio" ], "maximum_short_squeeze_ratio": feed["maximum_short_squeeze_ratio"], - "settlement_price": Price(feed["settlement_price"]), - "core_exchange_rate": Price(feed["core_exchange_rate"]), + "settlement_price": Price( + feed["settlement_price"], blockchain_instance=self.blockchain + ), + "core_exchange_rate": Price( + feed["core_exchange_rate"], blockchain_instance=self.blockchain + ), }, ) diff --git a/bitsharesbase/chains.py b/bitsharesbase/chains.py index 4c8d136a..26e6ade5 100644 --- a/bitsharesbase/chains.py +++ b/bitsharesbase/chains.py @@ -15,4 +15,19 @@ "core_symbol": "TEST", "prefix": "TEST", }, + "DNATESTNET": { + "chain_id": "93b266081a68bea383ef613753a9cafaa01b3b7b04ed00a01e5dec5de8cb4983", + "core_symbol": "DNA", + "prefix": "DNA", + }, + "UDRUR": { + "chain_id": "8278e1c46cffb419eca1f7032210be9ecc5eccebb30bed66b8aafaf431b04ce7", + "core_symbol": "DNA", + "prefix": "DNA", + }, + "developdna": { + "chain_id": "ab4a1353e1ed2eab06673ec55eeffb011b331cd6c45dc957176271ed36794541", + "core_symbol": "DNA", + "prefix": "DNA", + }, } diff --git a/bitsharesbase/objects.py b/bitsharesbase/objects.py index 9d1c1613..3ea2b128 100644 --- a/bitsharesbase/objects.py +++ b/bitsharesbase/objects.py @@ -167,10 +167,9 @@ def __init__(self, *args, **kwargs): if len(args) == 1 and len(kwargs) == 0: kwargs = args[0] # remove dublicates - kwargs["votes"] = list(set(kwargs["votes"])) # Sort votes kwargs["votes"] = sorted( - kwargs["votes"], key=lambda x: float(x.split(":")[1]) + kwargs["votes"], key=lambda x: float(x[0].split(":")[1]) ) super().__init__( OrderedDict( @@ -180,9 +179,13 @@ def __init__(self, *args, **kwargs): "voting_account", ObjectId(kwargs["voting_account"], "account"), ), - ("num_witness", Uint16(kwargs["num_witness"])), ("num_committee", Uint16(kwargs["num_committee"])), - ("votes", Array([VoteId(o) for o in kwargs["votes"]])), + ( + "votes", + Map( + [[VoteId(o[0]), Uint16(o[1])] for o in kwargs["votes"]] + ), + ), ("extensions", Set([])), ] ) @@ -456,3 +459,62 @@ def __init__(self, *args, **kwargs): else: raise ValueError("Unknown {}".format(self.__class__.name)) super().__init__(data, id) + + +class VestingPolicyInitializer(Static_variant): + def __init__(self, o): + class linear_vesting_policy_initializer(GrapheneObject): + def __init__(self, *args, **kwargs): + kwargs.update(args[0]) + super().__init__( + OrderedDict( + [ + ("begin_timestamp", PointInTime(kwargs["begin_timestamp"])), + ( + "vesting_cliff_seconds", + Uint32(kwargs["vesting_cliff_seconds"]), + ), + ( + "vesting_duration_seconds", + Uint32(kwargs["vesting_duration_seconds"]), + ), + ] + ) + ) + + class cdd_vesting_policy_initializer(GrapheneObject): + def __init__(self, *args, **kwargs): + kwargs.update(args[0]) + super().__init__( + OrderedDict( + [ + ("start_claim", PointInTime(kwargs["start_claim"])), + ("vesting_seconds", Uint32(kwargs["vesting_seconds"])), + ] + ) + ) + + class instant_vesting_policy_initializer(GrapheneObject): + def __init__(self, *args, **kwargs): + kwargs.update(args[0]) + super().__init__(OrderedDict([])) + + class cliff_vesting_policy_initializer(GrapheneObject): + def __init__(self, *args, **kwargs): + kwargs.update(args[0]) + super().__init__( + OrderedDict([("duration", Uint32(kwargs["duration"]))]) + ) + + variants = [ + linear_vesting_policy_initializer, + cdd_vesting_policy_initializer, + instant_vesting_policy_initializer, + cliff_vesting_policy_initializer, + ] + id = o[0] + try: + data = variants[id](o[1]) + except Exception: + raise ValueError("Unknown {}".format(self.__class__.name)) + super().__init__(data, id) diff --git a/bitsharesbase/objecttypes.py b/bitsharesbase/objecttypes.py index 040b04f8..a6c35d38 100644 --- a/bitsharesbase/objecttypes.py +++ b/bitsharesbase/objecttypes.py @@ -18,4 +18,6 @@ object_type["worker"] = 14 object_type["balance"] = 15 object_type["htlc"] = 16 -object_type["OBJECT_TYPE_COUNT"] = 16 +object_type["custom_authority"] = 17 +object_type["ticket"] = 18 +object_type["OBJECT_TYPE_COUNT"] = 18 diff --git a/bitsharesbase/operationids.py b/bitsharesbase/operationids.py index d5b94ce7..ee035cc1 100644 --- a/bitsharesbase/operationids.py +++ b/bitsharesbase/operationids.py @@ -55,6 +55,11 @@ "htlc_redeemed", "htlc_extend", "htlc_refund", + "custom_authority_create_operation", + "custom_authority_update_operation", + "custom_authority_delete_operation", + "ticket_create_operation", + "ticket_update_operation", ] operations = {o: ops.index(o) for o in ops} diff --git a/bitsharesbase/operations.py b/bitsharesbase/operations.py index c5f141b0..ded3c5f2 100644 --- a/bitsharesbase/operations.py +++ b/bitsharesbase/operations.py @@ -29,6 +29,7 @@ from .account import PublicKey from .objects import ( AccountCreateExtensions, + VestingPolicyInitializer, AccountOptions, Asset, AssetOptions, @@ -686,6 +687,16 @@ def __init__(self, *args, **kwargs): else: new_signing_key = Optional(None) + if ( + "block_producer_reward_pct" in kwargs + and kwargs["block_producer_reward_pct"] + ): + block_producer_reward_pct = Optional( + Uint32(kwargs["block_producer_reward_pct"]) + ) + else: + block_producer_reward_pct = Optional(None) + super().__init__( OrderedDict( [ @@ -697,6 +708,7 @@ def __init__(self, *args, **kwargs): ), ("new_url", new_url), ("new_signing_key", new_signing_key), + ("block_producer_reward_pct", block_producer_reward_pct), ] ) ) @@ -1043,4 +1055,89 @@ def __init__(self, *args, **kwargs): ) +ticket_type_strings = [ + "liquid", + "lock_180_days", + "lock_360_days", + "lock_720_days", + "lock_forever", +] + + +class Ticket_create_operation(GrapheneObject): + def __init__(self, *args, **kwargs): + if isArgsThisClass(self, args): + self.data = args[0].data + else: + if len(args) == 1 and len(kwargs) == 0: + kwargs = args[0] + + if isinstance(kwargs["target_type"], int): + target_type = Varint32(kwargs["target_type"]) + else: + target_type = Varint32(ticket_type_strings.index(kwargs["target_type"])) + + super().__init__( + OrderedDict( + [ + ("fee", Asset(kwargs["fee"])), + ("account", ObjectId(kwargs["account"], "account")), + ("target_type", target_type), + ("amount", Asset(kwargs["amount"])), + ("extensions", Set([])), + ] + ) + ) + + +class Ticket_update_operation(GrapheneObject): + def __init__(self, *args, **kwargs): + if isArgsThisClass(self, args): + self.data = args[0].data + else: + if len(args) == 1 and len(kwargs) == 0: + kwargs = args[0] + + if isinstance(kwargs["target_type"], int): + target_type = Varint32(kwargs["target_type"]) + else: + target_type = Varint32(ticket_type_strings.index(kwargs["target_type"])) + + if kwargs.get("amount_for_new_target"): + amount_for_new_target = Optional(Asset(kwargs["amount_for_new_target"])) + else: + amount_for_new_target = Optional(None) + + super().__init__( + OrderedDict( + [ + ("fee", Asset(kwargs["fee"])), + ("ticket", ObjectId(kwargs["ticket"], "ticket")), + ("account", ObjectId(kwargs["account"], "account")), + ("target_type", target_type), + ("amount_for_new_target", amount_for_new_target), + ("extensions", Set([])), + ] + ) + ) + + +class Vesting_balance_create(GrapheneObject): + def __init__(self, *args, **kwargs): + if isArgsThisClass(self, args): + self.data = args[0].data + else: + super().__init__( + OrderedDict( + [ + ("fee", Asset(kwargs["fee"])), + ("creator", ObjectId(kwargs["creator"], "account")), + ("owner", ObjectId(kwargs["owner"], "account")), + ("amount", Asset(kwargs["amount"])), + ("policy", VestingPolicyInitializer(kwargs["policy"])), + ] + ) + ) + + fill_classmaps() diff --git a/confchain.py b/confchain.py new file mode 100644 index 00000000..9a1b3336 --- /dev/null +++ b/confchain.py @@ -0,0 +1,284 @@ +# -*- coding: utf-8 -*- +import sys +import click +import time +import json + +from grapheneapi.grapheneapi import GrapheneAPI + +from bitshares.utils import formatTimeFromNow +from bitshares.genesisbalance import GenesisBalances +from bitshares.account import Account +from bitshares.amount import Amount +from bitshares.asset import Asset +from bitshares.proposal import Proposals +from bitshares.witness import Witness +from bitshares.blockchain import Blockchain + +from bitshares import BitShares + +from getpass import getpass + +from pprint import pprint +from bitshares.instance import set_shared_blockchain_instance +from bitsharesbase.account import PasswordKey +from bitsharesbase import operations + + +connection = { + "blocking": True, + "nobroadcast": False, + "num_retries": 1, + #"node": ["wss://node.mvsdna.com"], + "node": ["ws://localhost:8090"], + "keys": [ + # udrur + "5JEVg45P9ySbo4ZVuqfCBjydEi11C7n7z9PhqZAwwL8effcfEvU", # initial balance + "5JBtkKThCStcYZwBJhQEys1nc7e44F4giZCdLj3FyQWWAxESteB", # foundation active + "5JxNuvALBwigV29bnGd969sCsTwiuExs6pgdrnvvzs6PTvCiB9n", # foundation owner + "5JyhVvLVBo7ujoce5wHpCEWsnjVsmrmBHP8UK4Qy8pEYqXK6ptD", # faucet + "5KWNLXftSvmUaxmtfHPrwpD39654H3TwwaUkenpBNoLJsSvHPtW", # init0 owner + ] +} + +blockchain = BitShares( + **connection +) + +set_shared_blockchain_instance(blockchain) + + +def sleep(t: int) -> None: + click.echo(" - Going to sleep for {}s".format(t)) + time.sleep(int(t)) + + +@click.group() +def main(): + pass + + +@main.command() +def info(): + click.echo(dict(Account("1.2.6"))) + + +@main.command() +def listaccounts(): + click.echo(blockchain.wallet.getAccounts()) + + +@main.command() +@click.argument("ids", required=False, nargs=-1) +def claim(ids): + """ 2 - Claim genesis stake + """ + _claim(ids) + + +def _claim(ids): + # Claim genesis stake + click.echo(" - Claiming Genesis Stake") + p = GenesisBalances() + if not ids: + [click.echo(x) for x in p] + return + try: + for x in p: + if x["id"] in ids: + click.echo(x.claim(account="foundation")) + click.echo("Claimed!") + except Exception as e: + click.echo(click.style(str(e), fg="red")) + + +@main.command() +def keys(): + password = "RYzJFo7uXPPoRtew" # P5JNdP5NtnuaispDGX4gUdx6WkEXYLCrkvKYm6dH7mbXgX76VzLz + keys = dict( + active_key=str(PasswordKey("faucet", password, role="active").get_private_key()), + owner_key=str(PasswordKey("faucet", password, role="owner").get_private_key()), + memo_key=str(PasswordKey("faucet", password, role="memo").get_private_key()) + ) + click.echo(keys) + + +@main.command() +@click.argument("accounts", nargs=-1) +def accounts(accounts): + """ 3 - create accounts + """ + _accounts = [ + { + "name": "faucet", + "password": "RYzJFo7uXPPoRtew", + "registrar": "foundation" + }, + { + "name": "debug", + "password": "P5JNdP5NtnuaispDGX4gUdx6WkEXYLCrkvKYm6dH7mbXgX76VzLz" + } + ] + for account in _accounts: + if accounts is not None and account["name"] not in accounts: + continue + click.echo(" - Creating account {}".format(account["name"])) + try: + click.echo( + blockchain.create_account( + account["name"], registrar=account.get("registrar", "faucet"), password=account["password"] + ) + ) + except Exception as e: + click.echo(click.style(str(e), fg="red")) + + +@main.command() +def upgrade(): + """ Upgrade accounts + """ + accounts = ["faucet"] + for account in accounts: + click.echo(" - Upgrading account {}".format(account)) + try: + click.echo(Account(account).upgrade()) + except Exception as e: + click.echo(click.style(str(e), fg="red")) + + +@main.command() +@click.argument("account") +@click.argument("reward_percent") +def createwitness( + account, + reward_percent +): + """ Upgrade accounts + """ + click.echo(" - Creating witness for {}".format(account)) + try: + click.echo("") + except Exception as e: + click.echo(click.style(str(e), fg="red")) + + +@main.command() +@click.argument("account") +@click.argument("reward_percent") +def updatewitness( + account, + reward_percent +): + GRAPHENE_1_PERCENT = 100 + + witness = Witness(account) + account = witness.account + op = operations.Witness_update( + **{ + "fee": {"amount": 0, "asset_id": "1.3.0"}, + "prefix": blockchain.prefix, + "witness": witness["id"], + "witness_account": account["id"], + "block_producer_reward_pct": int(reward_percent) * GRAPHENE_1_PERCENT + } + ) + return blockchain.finalizeOp(op, account["name"], "active") + + +@main.command() +def fund(): + """ Fund accounts + """ + accounts = [ + "init0", + "init1", + "init2", + "init3", + "init4", + "init5", + "init6", + "init7", + "init8", + "init9", + "init10", + "witness-account", + "faucet" + ] + for account in accounts: + click.echo(" - Transferring core token to account {}".format(account)) + try: + click.echo(blockchain.transfer(account, 1000000, "DNA", account="foundation")) + except Exception as e: + click.echo(click.style(str(e), fg="red")) + + +@main.command() +@click.argument("accounts", nargs=-1) +def vote(accounts): + """ 6 - Vote + """ + _vote(accounts) + + +def _vote(accounts=None): + if not accounts: + accounts = [ + "init0", + "init1", + "init2", + "init3", + "init4", + "init5", + "init6", + "init7", + "init8", + "init9", + "init10", + ] + try: + click.echo(blockchain.approvewitness(accounts, account="foundation")) + click.echo("Voted!") + except Exception as e: + click.echo(click.style(str(e), fg="red")) + + +@main.command() +def setupvesting(): + _setupvesting() + + +def _setupvesting(): + creator = Account("foundation") + owner = Account("init0") + amount = Amount("10000000 DNA") + + op = operations.Vesting_balance_create( + **{ + "fee": {"amount": 0, "asset_id": "1.3.0"}, + "creator": creator["id"], + "owner": owner["id"], + "amount": amount.json(), + "policy": [3, {"duration": 60 * 60 * 24 * 365}], + "extensions": [], + } + ) + + try: + click.echo(blockchain.finalizeOp(op, creator, "active")) + click.echo("Vested!") + except Exception as e: + click.echo(click.style(str(e), fg="red")) + + +@main.command() +def fixer(): + # claim + _claim("1.15.0") + + _setupvesting() + + _vote() + + +if __name__ == "__main__": + main() diff --git a/docs/requirements.txt b/docs/requirements.txt index fa668fb7..ae33b51d 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ -graphenelib==1.2.0 -bitshares==0.4.0 +graphenelib>=1.3.1,<2.0.0 +bitshares autobahn>=0.14 pycryptodome==3.9.7 appdirs==1.4.3 diff --git a/requirements.txt b/requirements.txt index aaec613c..38c6a34c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -graphenelib>=1.1.16 +graphenelib>=1.3.1,<2.0.0 Events==0.3 websockets +click diff --git a/tests/fixtures.py b/tests/fixtures.py index b8a21daa..a90beb40 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -22,7 +22,7 @@ # bitshares instance bitshares = BitShares( - "wss://node.bitshares.eu", keys=wifs, nobroadcast=True, num_retries=1 + "wss://node.mvsdna.com", keys=wifs, nobroadcast=True, num_retries=1 ) config = bitshares.config diff --git a/tests/test_transactions.py b/tests/test_transactions.py index 36986c4a..1836d866 100644 --- a/tests/test_transactions.py +++ b/tests/test_transactions.py @@ -46,14 +46,17 @@ def doit(self, printWire=False): # Test against Bitshares backened live = bitshares.rpc.get_transaction_hex(tx.json()) - # Compare expected result with test unit - self.assertEqual(self.cm[:-130], txWire[:-130]) + # Compare expected result with online backend + self.assertEqual(live[:-130], self.cm[:-130]) # Compare expected result with online result self.assertEqual(live[:-130], txWire[:-130]) - # Compare expected result with online backend - self.assertEqual(live[:-130], self.cm[:-130]) + # Compare expected result with test unit + self.assertEqual(self.cm[:-130], txWire[:-130]) + + # Compare expected result with test unit + self.assertEqual(self.cm[:-130], txWire[:-130]) def test_call_update(self): self.op = operations.Call_order_update( @@ -241,9 +244,86 @@ def test_override_transfer(self): ) self.doit() + def test_create_account(self): + self.maxDiff = None + self.op = operations.Account_create( + **{ + "fee": {"amount": 1467634, "asset_id": "1.3.0"}, + "registrar": "1.2.33", + "referrer": "1.2.27", + "referrer_percent": 3, + "name": "foobar-f124", + "owner": { + "weight_threshold": 1, + "account_auths": [], + "key_auths": [ + [ + prefix + + "6pbVDAjRFiw6fkiKYCrkz7PFeL7XNAfefrsREwg8MKpJ9VYV9x", + 1, + ], + [ + prefix + + "6zLNtyFVToBsBZDsgMhgjpwysYVbsQD6YhP3kRkQhANUB4w7Qp", + 1, + ], + ], + "address_auths": [], + }, + "active": { + "weight_threshold": 1, + "account_auths": [], + "key_auths": [ + [ + prefix + + "6pbVDAjRFiw6fkiKYCrkz7PFeL7XNAfefrsREwg8MKpJ9VYV9x", + 1, + ], + [ + prefix + + "6zLNtyFVToBsBZDsgMhgjpwysYVbsQD6YhP3kRkQhANUB4w7Qp", + 1, + ], + [ + prefix + + "8CemMDjdUWSV5wKotEimhK6c4dY7p2PdzC2qM1HpAP8aLtZfE7", + 1, + ], + ], + "address_auths": [], + }, + "options": { + "memo_key": prefix + + "5TPTziKkLexhVKsQKtSpo4bAv5RnB8oXcG4sMHEwCcTf3r7dqE", + "voting_account": "1.2.5", + "num_witness": 0, + "num_committee": 0, + "votes": [], + "extensions": [], + }, + "extensions": {}, + "prefix": prefix, + } + ) + self.cm = ( + "f68585abf4dce7c804570105f26416000000000000211b03000b666f" + "6f6261722d6631323401000000000202fe8cc11cc8251de6977636b5" + "5c1ab8a9d12b0b26154ac78e56e7c4257d8bcf6901000314aa202c91" + "58990b3ec51a1aa49b2ab5d300c97b391df3beb34bb74f3c62699e01" + "000001000000000303b453f46013fdbccb90b09ba169c388c34d8445" + "4a3b9fbec68d5a7819a734fca0010002fe8cc11cc8251de6977636b5" + "5c1ab8a9d12b0b26154ac78e56e7c4257d8bcf6901000314aa202c91" + "58990b3ec51a1aa49b2ab5d300c97b391df3beb34bb74f3c62699e01" + "0000024ab336b4b14ba6d881675d1c782912783c43dbbe31693aa710" + "ac1896bd7c3d61050000000000000000011f024373610743cab92abc" + "197cc69aa04c45e20a8c1c495629ca5765d8e458a18f0920bfaf9d0a" + "909c01819cf887a66d06903af71fb07f0aac34600c733590984e" + ) + self.doit(1) + """ # TODO FIX THIS UNIT TEST - def test_create_account(self): + def test_create_account2(self): self.op = operations.Account_create(**{ "fee": {"amount": 1467634, "asset_id": "1.3.0" @@ -968,6 +1048,27 @@ def test_assert_b(self): ) self.doit(0) + def test_create_vesting_balance(self): + self.op = operations.Vesting_balance_create( + **{ + "fee": {"amount": 0, "asset_id": "1.3.0"}, + "creator": "1.2.6", + "owner": "1.2.10", + "amount": {"amount": 1000000000, "asset_id": "1.3.0"}, + "policy": [3, {"duration": 60 * 60 * 24 * 365}], + "extensions": [], + } + ) + + self.cm = ( + "f68585abf4dce7c804570120000000000000000000060a00ca" + "9a3b0000000000038033e10100011f4250927ce868f9d5cbf3" + "c6b465555fbede833151be85a0dd882728534574e8e27ce57f" + "f7c6e293eb475aead195618d2f3f28a1d94d95d10c07c81f98" + "0b338256" + ) + self.doit(0) + def compareConstructedTX(self): self.maxDiff = None self.op = operations.Call_order_update( diff --git a/tests/testnet/aio/test_bitshares.py b/tests/testnet/aio/test_bitshares.py index 69f63650..8b3f3454 100644 --- a/tests/testnet/aio/test_bitshares.py +++ b/tests/testnet/aio/test_bitshares.py @@ -117,9 +117,9 @@ async def test_approve_disapprove_committee(bitshares, default_account): @pytest.mark.asyncio async def test_approve_proposal(bitshares, default_account): + # Set blocking to get "operation_results" bitshares.blocking = "head" - parent = bitshares.new_tx() - proposal = bitshares.new_proposal(parent=parent) + proposal = bitshares.new_proposal() await bitshares.transfer( "init1", 1, "TEST", append_to=proposal, account=default_account ) @@ -143,8 +143,7 @@ async def test_disapprove_proposal(bitshares, default_account, unused_account): # Create proposal bitshares.blocking = "head" - parent = bitshares.new_tx() - proposal = bitshares.new_proposal(parent=parent) + proposal = bitshares.new_proposal() await bitshares.transfer( "init1", 1, "TEST", append_to=proposal, account=default_account ) @@ -339,3 +338,14 @@ async def test_subscribe_to_market(bitshares, assets, default_account): event_correct = True break assert event_correct + + +@pytest.mark.asyncio +async def test_double_connect(bitshares_testnet): + from bitshares.aio import BitShares + + bitshares = BitShares( + node="ws://127.0.0.1:{}".format(bitshares_testnet.service_port), num_retries=-1 + ) + await bitshares.connect() + await bitshares.connect() diff --git a/tests/testnet/aio/test_price.py b/tests/testnet/aio/test_price.py index ff36726d..d9825eeb 100644 --- a/tests/testnet/aio/test_price.py +++ b/tests/testnet/aio/test_price.py @@ -6,7 +6,7 @@ from bitshares.aio.asset import Asset from bitshares.aio.amount import Amount from bitshares.aio.account import Account -from bitshares.aio.price import Price, Order, FilledOrder +from bitshares.aio.price import Price, PriceFeed, Order, FilledOrder from bitshares.aio.market import Market log = logging.getLogger("grapheneapi") @@ -111,3 +111,23 @@ async def test_filled_order(default_account, do_trade): log.info("Order from history: {}".format(order)) # Test copy() await order.copy() + + +@pytest.mark.asyncio +async def test_pricefeed_init_no_shared_instance(not_shared_instance, bitasset): + bitshares = not_shared_instance + asset = await Asset(bitasset, blockchain_instance=bitshares) + await asset.ensure_full() + + # Prevent using instantiated objects loaded to cache + Asset.clear_cache() + feed = await PriceFeed( + asset["bitasset_data"]["feeds"][0], blockchain_instance=bitshares + ) + assert feed["settlement_price"] > 0 + + Asset.clear_cache() + feed = await PriceFeed( + asset["bitasset_data"]["current_feed"], blockchain_instance=bitshares + ) + assert feed["settlement_price"] > 0