Exemple #1
0
    def test_have_two_proposals(self):
        bts = self.bts
        tx1 = bts.new_tx()

        # Proposal 1
        proposal1 = bts.new_proposal(tx1, proposer="init0")
        op = operations.Transfer(
            **{
                "fee": {
                    "amount": 0,
                    "asset_id": "1.3.0"
                },
                "from": "1.2.0",
                "to": "1.2.0",
                "amount": {
                    "amount": 0,
                    "asset_id": "1.3.0"
                },
                "prefix": "TEST"
            })
        for i in range(0, 3):
            proposal1.appendOps(op)

        # Proposal 1
        proposal2 = bts.new_proposal(tx1, proposer="init0")
        op = operations.Transfer(
            **{
                "fee": {
                    "amount": 0,
                    "asset_id": "1.3.0"
                },
                "from": "1.2.0",
                "to": "1.2.0",
                "amount": {
                    "amount": 5555555,
                    "asset_id": "1.3.0"
                },
                "prefix": "TEST"
            })
        for i in range(0, 2):
            proposal2.appendOps(op)
        tx = tx1.json()

        self.assertEqual(len(tx["operations"]), 2)  # 2 proposals

        # Test proposal 1
        prop = tx["operations"][0]
        self.assertEqual(prop[0], 22)
        ps = prop[1]
        self.assertEqual(len(ps["proposed_ops"]), 3)
        for i in range(0, 3):
            self.assertEqual(ps["proposed_ops"][i]["op"][0], 0)

        # Test proposal 2
        prop = tx["operations"][1]
        self.assertEqual(prop[0], 22)
        ps = prop[1]
        self.assertEqual(len(ps["proposed_ops"]), 2)
        for i in range(0, 2):
            self.assertEqual(ps["proposed_ops"][i]["op"][0], 0)
Exemple #2
0
def do_batch(dat):
    """
	Make a batch of transfers
	:param dat:
	:return:
	"""
    import config
    snap_info = pickle.loads(Redisdb.get("snapshot_info"))
    try:
        Bitshares = config.BitShares(node=config.WSS_NODE,
                                     wif=dat['form']['key'])
        oaccount = Bitshares.wallet.getAccounts()[0]
    except Exception as err:
        print(err.__repr__())
        Redisdb.rpush("messages", "*|launch_error|key not found")
        print(0)
        return False

    for job in dat['job']:
        try:
            wif = dat['key']
            pub = format(account.PrivateKey(wif).pubkey, config.PREFIX)
            to_account_id = job[0].decode('utf8')
            amount = 10
            asset_id = dat['asset']['id']
            message = "abcdefgABCDEFG0123456789"
            nonce = "5862723643998573708"

            fee = objects.Asset(amount=0, asset_id="1.3.0")
            amount = objects.Asset(amount=int(amount), asset_id=asset_id)
            encrypted_memo = memo.encode_memo(
                account.PrivateKey(wif),
                account.PublicKey(pub, prefix=config.PREFIX), nonce, message)
            memoStruct = {
                "from": pub,
                "to": pub,
                "nonce": nonce,
                "message": encrypted_memo,
            }
            memoObj = objects.Memo(**memoStruct)
            tmp = operations.Transfer(
                **{
                    "fee": fee,
                    "from": dat['from'],
                    "to": to_account_id,
                    "amount": amount,
                    "memo": memoObj,
                    "prefix": config.PREFIX
                })
            print()
            #test = Bitshares.transfer(job[0].decode('utf8'), float(job[1]), dat['asset'], "", dat['from'])
        except Exception as err:
            print(err.__repr__())
            print(0)

    Redisdb.decr("batch_jobs", int(1))
    Redisdb.rpush(
        "messages",
        datetime.datetime.now().isoformat() +
        " Jobs queue: {}".format(int(Redisdb.get("batch_jobs"))))
def appendTransferOpToTx(builder, from_name, to_name, amount, symbol):

    ## TODO: Cleanup exception catching for better user feedback

    try:
        account = Account(from_name, blockchain_instance=blockchain)
        amountAsset = Amount(amount, symbol, blockchain_instance=blockchain)
        to = Account(to_name, blockchain_instance=blockchain)
    except NumRetriesReached:
        Logger.Write("ERROR: Can't reach API node: 'NumRetries' reached.  Check network connection.")
        raise
    except:
        Logger.Write("Problem locating source or destination account, or asset. Might not exist.")
        raise

    memoObj = Memo(from_account=account, to_account=to, blockchain_instance=blockchain)
    memo_text = "" #"Signed by BitShares App on Ledger Nano S!"

    op = operations.Transfer(
        **{
            "fee": {"amount": 0, "asset_id": "1.3.0"},
            "from": account["id"],
            "to": to["id"],
            "amount": {"amount": int(amountAsset), "asset_id": amountAsset.asset["id"]},
            "memo": memoObj.encrypt(memo_text),
        }
    )

    builder.appendOps(op)
    return builder
 def test_add_one_proposal_two_ops(self):
     tx1 = bitshares.new_tx()
     proposal1 = bitshares.new_proposal(tx1, proposer="init0")
     op = operations.Transfer(
         **{
             "fee": {
                 "amount": 0,
                 "asset_id": "1.3.0"
             },
             "from": "1.2.0",
             "to": "1.2.0",
             "amount": {
                 "amount": 0,
                 "asset_id": "1.3.0"
             },
             "prefix": "TEST",
         })
     proposal1.appendOps(op)
     proposal1.appendOps(op)
     tx = tx1.json()
     self.assertEqual(tx["operations"][0][0], 22)
     self.assertEqual(len(tx["operations"]), 1)
     ps = tx["operations"][0][1]
     self.assertEqual(len(ps["proposed_ops"]), 2)
     self.assertEqual(ps["proposed_ops"][0]["op"][0], 0)
     self.assertEqual(ps["proposed_ops"][1]["op"][0], 0)
Exemple #5
0
    def obtain_raw_tx():
#         if old_operation is None:
        _memo = memo.encrypt(memo_plain)
        _expiration = Config.get("bitshares", "transaction_expiration_in_sec", 60 * 60 * 24)  # 24 hours
#         else:
#             memo_encrypted = memo.encrypt(memo_plain)

        op = operations.Transfer(**{
            "fee": {
                "amount": 0,
                "asset_id": "1.3.0"
            },  # will be replaced
            "from": from_account["id"],
            "to": to_account["id"],
            "amount": amount.json(),
            "memo": _memo,
            "prefix": bitshares_instance.prefix
        })

        tx = TransactionBuilder(
            bitshares_instance=bitshares_instance
        )
        tx.appendOps(op)
        tx.set_expiration(_expiration)

        # Build the transaction, obtain fee to be paid
        tx.constructTx()
        return tx.json()
    def test_Transfer(self):
        pub = format(account.PrivateKey(wif).pubkey, prefix)
        from_account_id = "1.2.0"
        to_account_id = "1.2.1"
        amount = 1000000
        asset_id = "1.3.4"
        message = "abcdefgABCDEFG0123456789"
        nonce = "5862723643998573708"

        fee = objects.Asset(amount=0, asset_id="1.3.0")
        amount = objects.Asset(amount=int(amount), asset_id=asset_id)
        encrypted_memo = memo.encode_memo(
            account.PrivateKey(wif), account.PublicKey(pub, prefix=prefix),
            nonce, message)
        memoStruct = {
            "from": pub,
            "to": pub,
            "nonce": nonce,
            "message": encrypted_memo,
            "chain": prefix
        }
        memoObj = objects.Memo(**memoStruct)
        op = operations.Transfer(
            **{
                "fee": fee,
                "from": from_account_id,
                "to": to_account_id,
                "amount": amount,
                "memo": memoObj
            })
        ops = [Operation(op)]
        tx = Signed_Transaction(ref_block_num=ref_block_num,
                                ref_block_prefix=ref_block_prefix,
                                expiration=expiration,
                                operations=ops)
        tx = tx.sign([wif], chain=prefix)
        tx.verify([PrivateKey(wif).pubkey], "BTS")
        txWire = hexlify(bytes(tx)).decode("ascii")

        compare = ("f68585abf4dce7c804570100000000000000000000000140420"
                   "f0000000000040102c0ded2bc1f1305fb0faac5e6c03ee3a192"
                   "4234985427b6167ca569d13df435cf02c0ded2bc1f1305fb0fa"
                   "ac5e6c03ee3a1924234985427b6167ca569d13df435cf8c94d1"
                   "9817945c5120fa5b6e83079a878e499e2e52a76a7739e9de409"
                   "86a8e3bd8a68ce316cee50b210000011f39e3fa7071b795491e"
                   "3b6851d61e7c959be92cc7deb5d8491cf1c3c8c99a1eb44553c"
                   "348fb8f5001a78b18233ac66727e32fc776d48e92d9639d64f6"
                   "8e641948")
        self.assertEqual(compare[:-130], txWire[:-130])
Exemple #7
0
    def test_transfer(self):
        pub = format(account.PrivateKey(wif).pubkey, prefix)
        from_account_id = "1.2.0"
        to_account_id = "1.2.1"
        amount = 1000000
        asset_id = "1.3.4"
        message = "abcdefgABCDEFG0123456789"
        nonce = "5862723643998573708"

        fee = objects.Asset(amount=0, asset_id="1.3.0")
        amount = objects.Asset(amount=int(amount), asset_id=asset_id)
        self.op = operations.Transfer(
            **{
                "fee": fee,
                "from": from_account_id,
                "to": to_account_id,
                "amount": amount,
                "memo": {
                    "from":
                    pub,
                    "to":
                    pub,
                    "nonce":
                    nonce,
                    "message":
                    memo.encode_memo(
                        account.PrivateKey(wif),
                        account.PublicKey(pub, prefix=prefix),
                        nonce,
                        message,
                    ),
                },
                "prefix": prefix,
            })
        self.cm = ("f68585abf4dce7c804570100000000000000000000000140420"
                   "f0000000000040102c0ded2bc1f1305fb0faac5e6c03ee3a192"
                   "4234985427b6167ca569d13df435cf02c0ded2bc1f1305fb0fa"
                   "ac5e6c03ee3a1924234985427b6167ca569d13df435cf8c94d1"
                   "9817945c5120fa5b6e83079a878e499e2e52a76a7739e9de409"
                   "86a8e3bd8a68ce316cee50b210000011f39e3fa7071b795491e"
                   "3b6851d61e7c959be92cc7deb5d8491cf1c3c8c99a1eb44553c"
                   "348fb8f5001a78b18233ac66727e32fc776d48e92d9639d64f6"
                   "8e641948")
        self.doit()
def append_transfer_tx(append_to, dest_account_name):
    #
    #  `append_to` is a TransactionBuilder object. (E.g. from BitShares.new_tx())
    #  `dest_account_name` is a string account name.
    #
    account = Account(tip_sender, blockchain_instance=blockchain)
    amount = Amount(tip_amount,
                    tip_asset_symbol,
                    blockchain_instance=blockchain)
    try:
        to = Account(dest_account_name, blockchain_instance=blockchain)
    except NumRetriesReached:
        Logger.Write(
            "ERROR: Can't reach API node: 'NumRetries' reached.  Check network connection."
        )
        raise
    except:
        Logger.Write("Problem locating destination account. Might not exist.")
        raise
    memoObj = Memo(from_account=account,
                   to_account=to,
                   blockchain_instance=blockchain)
    memo_text = ""  #"Signed by BitShares App on Ledger Nano S!"

    op = operations.Transfer(
        **{
            "fee": {
                "amount": 0,
                "asset_id": "1.3.0"
            },
            "from": account["id"],
            "to": to["id"],
            "amount": {
                "amount": int(amount),
                "asset_id": amount.asset["id"]
            },
            "memo": memoObj.encrypt(memo_text),
        })

    append_to.appendOps(op)
    return append_to
Exemple #9
0
    def transfer(self, to, amount, asset, memo="", account=None):
        """ Transfer an asset to another account.

            :param str to: Recipient
            :param float amount: Amount to transfer
            :param str asset: Asset to transfer
            :param str memo: (optional) Memo, may begin with `#` for encrypted messaging
            :param str account: (optional) the source account for the transfer if not ``default_account``
        """
        from .memo import Memo
        if not account:
            if "default_account" in config:
                account = config["default_account"]
        if not account:
            raise ValueError("You need to provide an account")

        account = Account(account, bitshares_instance=self)
        amount = Amount(amount, asset, bitshares_instance=self)
        to = Account(to, bitshares_instance=self)

        memoObj = Memo(from_account=account,
                       to_account=to,
                       bitshares_instance=self)

        op = operations.Transfer(
            **{
                "fee": {
                    "amount": 0,
                    "asset_id": "1.3.0"
                },
                "from": account["id"],
                "to": to["id"],
                "amount": {
                    "amount": int(amount),
                    "asset_id": amount.asset["id"]
                },
                "memo": memoObj.encrypt(memo),
                "prefix": self.rpc.chain_params["prefix"]
            })
        return self.finalizeOp(op, account, "active")
Exemple #10
0
    async def __on_send_asset(self, to, asset_id, amount, memo=''):
        """ 发送资产
        """
        # 加密备注
        to_id = None
        memo_data = None
        if memo != '':
            to_id, memo_data = await self.__encrypt_memo(to, memo)
        else:
            to_account = await self.node_api.get_account_by_name(to)
            to_id = to_account['id']

        # 计算转账数量
        asset = await self.get_asset_info(asset_id)
        amount = amount * 10 ** asset['precision']

        # 生成转账操作
        prefix = self.node_api.chain_params['prefix']
        op = operations.Transfer(**{
            'to': to_id,
            'from': self.account['id'],
            'amount': {
                'amount': amount,
                'asset_id': asset_id
            },
            'prefix': prefix,
            'memo': memo_data,
            'fee': {'amount': 0, 'asset_id': asset_id}
        })

        # 执行转账操作
        txbuffer = builder.Builder(self.node_api)
        txbuffer.append_ops(op)
        await txbuffer.append_signer(self.account, self.wifkey, prefix, 'active')
        await txbuffer.sign(asset_id, expiration=600)
        res = await txbuffer.broadcast()
        return res.json()
Exemple #11
0
    async def send_to(self, to, asset, amount, memo=''):
        ''' 发送资产
        '''
        # 加密备注
        to_id = None
        memo_data = None
        if memo != '':
            to_id, memo_data = await self._encrypt_memo(to, memo)
        else:
            to_account = await self.client.get_account_by_name(to)
            to_id = to_account['id']

        # 计算转账数量
        amount = amount * 10 ** asset['precision']

        # 生成转账操作
        prefix = self.client.chain_params['prefix']
        op = operations.Transfer(**{
            'to': to_id,
            'from': self.account['id'],
            'amount': {
                'amount': amount,
                'asset_id': asset['id']
            },
            'prefix': prefix,
            'memo': memo_data,
            'fee': {'amount': 0, 'asset_id': asset['id']}
        })

        # 执行转账操作
        txbuffer = Builder(self.client)
        txbuffer.append_ops(op)
        await txbuffer.append_signer(self.account, SysConfig().active_key, prefix, 'active')
        signedtx = await txbuffer.sign(asset['id'], expiration=600)
        await txbuffer.broadcast()
        return signedtx.id
    def send(self, amount, address, memo=None, from_address=None) -> dict:
        """
        Send tokens to a given address/account, optionally specifying a memo. The Bitshares network transaction fee
        will be subtracted from the amount before sending.

        There must be a valid :py:class:`models.CryptoKeyPair` in the database for both 'active' and 'memo' keys for the
        from_address account, or an AuthorityMissing exception will be thrown.

        Example - send 1.23 BUILDTEAM from @someguy123 to @privex with memo 'hello'

            >>> s = BitsharesManager('BUILDTEAM')
            >>> s.send(from_address='someguy123', address='privex', amount=Decimal('1.23'), memo='hello')

        :param Decimal amount:      Amount of tokens to send, as a Decimal()
        :param address:             Account to send the tokens to
        :param from_address:        Account to send the tokens from
        :param memo:                Memo to send tokens with
        :raises AttributeError:     When both `from_address` and `self.coin.our_account` are blank.
        :raises ArithmeticError:    When the amount is lower than the lowest amount allowed by the token's precision
                                    (after subtracting the network transaction fee)
        :raises AuthorityMissing:   Cannot send because we don't have authority to (missing key etc.)
        :raises AccountNotFound:    The requested account/address doesn't exist
        :raises TokenNotFound:      When the requested token `symbol` does not exist
        :raises NotEnoughBalance:   The account `from_address` does not have enough balance to send this amount.
        :return dict: Result Information

        Format::

          {
              txid:str - Transaction ID - None if not known,
              coin:str - Symbol that was sent,
              amount:Decimal - The amount that was sent (after fees),
              fee:Decimal    - TX Fee that was taken from the amount,
              from:str       - The account/address the coins were sent from,
              send_type:str       - Should be statically set to "send"
          }

        """
        # Try from_address first. If that's empty, try using self.coin.our_account. If both are empty, abort.
        if empty(from_address):
            if empty(self.coin.our_account):
                raise AttributeError(
                    "Both 'from_address' and 'coin.our_account' are empty. Cannot send."
                )
            from_address = self.coin.our_account

        # make sure we have the necessary private keys loaded (memo key for encrypting memo, active key for sending coins)
        self.set_wallet_keys(from_address, ['memo', 'active'])

        asset_obj = self.get_asset_obj(self.symbol)
        if asset_obj is None:
            raise exceptions.TokenNotFound(
                f'Failed to send because {self.symbol} is an invalid token symbol.'
            )

        # trim input amount to the token's precision just to be safe
        str_amount = ('{0:.' + str(asset_obj['precision']) +
                      'f}').format(amount)
        amount = Decimal(str_amount)

        if not self.is_amount_above_minimum(amount, asset_obj['precision']):
            raise ArithmeticError(
                f'Failed to send because {amount} is less than the minimum amount allowed for {self.symbol} tokens.'
            )

        from_account = self.get_account_obj(from_address)
        if from_account is None:
            raise exceptions.AccountNotFound(
                f'Failed to send because source account {from_address} could not be found.'
            )
        to_account = self.get_account_obj(address)
        if to_account is None:
            raise exceptions.AccountNotFound(
                f'Failed to send because destination account {address} could not be found.'
            )

        # verify from_account balance is sufficient for the transaction
        from_account_balance = self.get_decimal_from_amount(
            from_account.balance(self.symbol))
        if from_account_balance < amount:
            raise exceptions.NotEnoughBalance(
                f'Failed to send because source account {from_address} balance {from_account_balance} {self.symbol} is less than amount to send ({amount} {self.symbol}).'
            )

        amount_obj = Amount(str_amount,
                            self.symbol,
                            blockchain_instance=self.bitshares)

        try:
            if memo is None:
                memo = ''
            memo_obj = Memo(from_account=from_account,
                            to_account=to_account,
                            blockchain_instance=self.bitshares)
            encrypted_memo = memo_obj.encrypt(memo)

            # build preliminary transaction object, without network transaction fee
            op = operations.Transfer(
                **{
                    'fee': {
                        'amount': 0,
                        'asset_id': amount_obj.asset['id']
                    },
                    'from': from_account['id'],
                    'to': to_account['id'],
                    'amount': {
                        'amount': int(amount_obj),
                        'asset_id': amount_obj.asset['id']
                    },
                    'memo': encrypted_memo,
                    'prefix': self.bitshares.prefix,
                })

            # calculate how much the transaction fee is - rather clunky method here but it works
            ops = [self.bitshares.txbuffer.operation_class(op)]
            ops_with_fees = self.bitshares.txbuffer.add_required_fees(
                ops, asset_id=amount_obj.asset['id'])
            raw_fee_amount = Decimal(
                str(ops_with_fees[0][1].data['fee']['amount']))
            fee_amount_str = '{0:f}'.format(
                raw_fee_amount / (10**amount_obj.asset['precision']))
            fee_amount = Amount(fee_amount_str,
                                self.symbol,
                                blockchain_instance=self.bitshares)
            amount_obj = amount_obj - fee_amount

            # verify the amount still makes sense after subtracting the transaction fee
            if int(amount_obj) < 1:
                raise ArithmeticError(
                    f'Failed to send because {amount} is less than the network transaction fee of {fee_amount_str} {self.symbol} tokens.'
                )

            # correct the transaction object to take into account the transaction fee
            adj_op = operations.Transfer(
                **{
                    'fee': {
                        'amount': int(fee_amount),
                        'asset_id': amount_obj.asset['id']
                    },
                    'from': from_account['id'],
                    'to': to_account['id'],
                    'amount': {
                        'amount': int(amount_obj),
                        'asset_id': amount_obj.asset['id']
                    },
                    'memo': encrypted_memo,
                    'prefix': self.bitshares.prefix,
                })

            log.debug(
                'doing Bitshares transaction - from_address[%s], address[%s], amount[%s %s], fee_amount[%s], amount_obj[%s], memo[%s]',
                from_address, address, str_amount, self.symbol, fee_amount,
                amount_obj, memo)

            # and finally, do the op!
            self.bitshares.finalizeOp(adj_op,
                                      from_address,
                                      "active",
                                      fee_asset=amount_obj.asset['id'])
            result = self.bitshares.broadcast()
        except KeyNotFound as e:
            raise exceptions.AuthorityMissing(str(e))

        return {
            'txid':
            None,  # transaction ID is not readily available from the Bitshares API
            'coin': self.orig_symbol,
            'amount': self.get_decimal_from_amount(amount_obj),
            'fee': self.get_decimal_from_amount(fee_amount),
            'from': from_address,
            'send_type': 'send'
        }
Exemple #13
0
def test_proposal_delete_operation(INSTANCE, cleartxpool):

    instance = INSTANCE
    reset_wallet(instance)

    # create two accounts
    logging.info('create new accounts')
    accounts = create_accounts(instance, num=2)
    if accounts == False:
        logging.info('create account error')
        assert 0

    # get accounts information
    accountName1 = accounts[0]['account']
    accountName2 = accounts[1]['account']
    activeKey1 = accounts[0]['active']['wif_priv_key']
    activeKey2 = accounts[1]['active']['wif_priv_key']
    account1 = cybex.Account(accountName1, cybex_instance=instance)
    account2 = cybex.Account(accountName2, cybex_instance=instance)

    # add active key
    instance.wallet.addPrivateKey(activeKey1)
    instance.wallet.addPrivateKey(activeKey2)

    # transfer 3 CYB to account1 and account2 from nathan
    acc = instance.const['master_account'] 
    valu = 3
    instance.transfer(accountName1, valu, 'CYB', '', acc)
    instance.transfer(accountName2, valu, 'CYB', '', acc)
    logging.info('transfer %s CYB from %s to %s and %s' % (valu, acc, account1, account2))
    account1.refresh()
    account2.refresh()
    assert int(account1.balances[0]) == valu * 10 ** account1.balances[0].asset.precision
    assert int(account2.balances[0]) == valu * 10 ** account2.balances[0].asset.precision
    
    # proposal with two transaction
    instance.proposer = accountName1
    instance.proposal_expiration = int(60*60*24)

    fee = instance.fee[0]['fee']['fee']/100000
    logging.info('fee: %s' % fee)
    amount1 = 100000
    amount2 = 200000
    transfer1 = btsops.Transfer(**{
        "fee": {"amount": fee, "asset_id":"1.3.0"},
        "from": dict(account1)["id"],
        "to": dict(account2)["id"],
        "amount": {"amount": amount1, "asset_id": "1.3.0"},
        "extensions": [],
    })

    transfer2 = btsops.Transfer(**{
        "fee": {"amount": fee, "asset_id":"1.3.0"},
        "from": dict(account2)["id"],
        "to": dict(account1)["id"],
        "amount": {"amount": amount2, "asset_id": "1.3.0"},
        "extensions": [],
    })

    instance.finalizeOp([transfer1, transfer2], account1, "active")
    logging.info('%s create a proposal' % account1)
    account1.refresh()
    p_id = dict(account1.proposals[0])['id']
#    logging.info(dict(account1.proposals[0]))
    logging.info('proposal id: %s' % p_id)
    logging.info('proposal: %s transfer %s CYB to %s, %s transfer %s CYB to %s' % (account1, amount1/100000, account2, account2, amount2/100000, account1))
    
    instance.proposer = None 
    logging.info('after %s proposal, %s balance cyb: %s' % (account1, account1, account1.balance('CYB')))
    logging.info('after %s proposal, %s balance cyb: %s' % (account1, account2, account2.balance('CYB')))

    # check proposal
    assert len(dict(account1.proposals[0])['required_active_approvals']) == 2
    assert len(dict(account1.proposals[0])['available_active_approvals']) == 0 
    assert account1.balance('CYB') == valu - fee
    assert account2.balance('CYB') == valu
    logging.info('this proposal has not been executed')

    # add account1 sign
    logging.info('%s accept the proposal' % (account1))
    instance.approveproposal([p_id], account=accountName1, approver=accountName1)
    account1.refresh()
    account2.refresh()
    assert len(dict(account1.proposals[0])['required_active_approvals']) == 2
    assert len(dict(account1.proposals[0])['available_active_approvals']) == 1 
    assert account1.balance('CYB') == valu - 2*fee
    assert account2.balance('CYB') == valu
    logging.info('after %s sign, %s balance cyb: %s' % (account1, account1, account1.balance('CYB')))
    logging.info('after %s sign, %s balance cyb: %s' % (account1, account2, account2.balance('CYB')))
    logging.info('this proposal is not executed yet')
    
    logging.info('%s dissapprove proposal' % (account1))
    instance.disapproveproposal([p_id], account=accountName1, approver=accountName1)
    account1.refresh()
    account2.refresh()
    logging.info('after %s disapprove proposal, %s balance: %s' % (account1, account1, account1.balance('CYB')))
    logging.info('after %s disapprove proposal, %s balance: %s' % (account1, account2, account2.balance('CYB')))
    
    logging.info('%s delete this proposal' % (account1))
    instance.proposal_delete(proposal_id=p_id, account=accountName1)

    # check account1 balance
    account1.refresh()
    account2.refresh()
    logging.info('%s balance: %s' % (account1, account1.balance('CYB')))
    logging.info('%s balance: %s' % (account2, account2.balance('CYB')))
    assert account2.balance('CYB') == valu 
    assert account1.balance('CYB') == valu -3*fee - 0.001
Exemple #14
0
def test_proposal_one_operation_with_multisign(INSTANCE, cleartxpool):

    instance = INSTANCE
    reset_wallet(instance)

    # create two accounts
    logging.info('create new accounts')
    accounts = create_accounts(instance, num=4)
    if accounts == False:
        logging.info('create account error')
        assert 0

    # get accounts information
    accountName1 = accounts[0]['account']
    accountName2 = accounts[1]['account']
    accountName3 = accounts[2]['account']
    accountName4 = accounts[3]['account']
    activeKey1 = accounts[0]['active']['wif_priv_key']
    activeKey2 = accounts[1]['active']['wif_priv_key']
    activeKey3 = accounts[2]['active']['wif_priv_key']
    activeKey4 = accounts[3]['active']['wif_priv_key']
    activePub1 = accounts[0]['active']['pub_key']
    activePub2 = accounts[1]['active']['pub_key']
    activePub3 = accounts[2]['active']['pub_key']
    account1 = cybex.Account(accountName1, cybex_instance=instance)
    account3 = cybex.Account(accountName3, cybex_instance=instance)
    account4 = cybex.Account(accountName4, cybex_instance=instance)

    # add active key
    instance.wallet.addPrivateKey(activeKey1)
    instance.wallet.addPrivateKey(activeKey2)

    # transfer 3 CYB to account1 and account2 from nathan
    acc = instance.const['master_account'] 
    valu = 3
    instance.transfer(accountName1, valu, 'CYB', '', acc)
    instance.transfer(accountName2, valu, 'CYB', '', acc)
    instance.transfer(accountName3, valu, 'CYB', '', acc)
    instance.transfer(accountName4, valu, 'CYB', '', acc)
    logging.info('transfer %s CYB from %s to %s, %s, %s and %s' % (valu, acc, account1, cybex.Account(accountName2, cybex_instance=instance), account3, account4))
    account1.refresh()
    account3.refresh()
    account4.refresh()
    assert int(account1.balances[0]) == valu * 10 ** account1.balances[0].asset.precision
    assert int(account3.balances[0]) == valu * 10 ** account3.balances[0].asset.precision
    assert int(account4.balances[0]) == valu * 10 ** account4.balances[0].asset.precision
   
    # make account2 a multisign account, controled by account3 and account4
    obj = {'weight_threshold':2, 'account_auths':[[account3['id'], 1], [account4['id'], 1]], 'key_auths':[[activePub2, 1]], 'address_auths':[]}
    update_active_keys(instance, obj,  account=accountName2)
    account2 = cybex.Account(accountName2, cybex_instance=instance)
    account2.refresh()
    assert account2['active']['weight_threshold'] == 2

    # proposal with one transaction
    instance.proposer = accountName1
    instance.proposal_expiration = int(60*60*24)

    fee = instance.fee[0]['fee']['fee']/100000
    logging.info('fee: %s' % fee)
    amount = 200000

    transfer = btsops.Transfer(**{
        "fee": {"amount": fee, "asset_id":"1.3.0"},
        "from": dict(account2)["id"],
        "to": dict(account1)["id"],
        "amount": {"amount": amount, "asset_id": "1.3.0"},
        "extensions": [],
    })

    instance.finalizeOp([transfer], account1, "active")
    logging.info('%s create a proposal' % account1)
    account2.refresh()
#    logging.info(dict(account2.proposals[0]))
    p_id = dict(account2.proposals[0])['id']
    logging.info('proposal id: %s' % p_id)
    logging.info('proposal: %s transfer %s CYB to %s' % (account2, amount/100000, account1))
    
    instance.proposer = None 
    logging.info('after %s proposal, %s balance cyb: %s' % (account1, account1, account1.balance('CYB')))
    logging.info('after %s proposal, %s balance cyb: %s' % (account1, account2, account2.balance('CYB')))
    logging.info('after %s proposal, %s balance cyb: %s' % (account3, account3, account3.balance('CYB')))
    logging.info('after %s proposal, %s balance cyb: %s' % (account3, account4, account4.balance('CYB')))

    # check proposal
    assert len(dict(account2.proposals[0])['required_active_approvals']) == 1 
    assert len(dict(account2.proposals[0])['available_active_approvals']) == 0 
    assert account1.balance('CYB') == valu - fee
    assert account2.balance('CYB') == valu
    logging.info('this proposal has not been executed')
#    time.sleep(60)
    # add account3 sign
#    instance.wallet.removePrivateKeyFromPublicKey(activePub1)
#    instance.wallet.removePrivateKeyFromPublicKey(activePub2)
    instance.wallet.addPrivateKey(activeKey3)
    logging.info('%s accept the proposal' % (account3))
    instance.approveproposal(p_id, account=accountName3, approver=accountName3)
    account1.refresh()
    account2.refresh()
    account3.refresh()
    account4.refresh()
    logging.info('after %s sign, %s balance cyb: %s' % (account3, account1, account1.balance('CYB')))
    logging.info('after %s sign, %s balance cyb: %s' % (account3, account2, account2.balance('CYB')))
    logging.info('after %s sign, %s balance cyb: %s' % (account3, account3, account3.balance('CYB')))
    logging.info('after %s sign, %s balance cyb: %s' % (account3, account4, account4.balance('CYB')))
    assert len(dict(account2.proposals[0])['required_active_approvals']) == 1 
    assert len(dict(account2.proposals[0])['available_active_approvals']) == 1 
    assert account1.balance('CYB') == valu - fee
    assert account2.balance('CYB') == valu 
    assert account3.balance('CYB') == valu - fee
    assert account4.balance('CYB') == valu 
    logging.info('this proposal has not been executed')
    
#    time.sleep(60)
    # add account4 sign
#    instance.wallet.removePrivateKeyFromPublicKey(activePub3)
    instance.wallet.addPrivateKey(activeKey4)
    logging.info('%s accept the proposal' % (account4))
    instance.approveproposal(p_id, account=accountName4, approver=accountName4)
    account1.refresh()
    account2.refresh()
    account3.refresh()
    account4.refresh()
    logging.info('after %s sign, %s balance cyb: %s' % (account4, account1, account1.balance('CYB')))
    logging.info('after %s sign, %s balance cyb: %s' % (account4, account2, account2.balance('CYB')))
    logging.info('after %s sign, %s balance cyb: %s' % (account4, account3, account3.balance('CYB')))
    logging.info('after %s sign, %s balance cyb: %s' % (account4, account4, account4.balance('CYB')))
    assert account1.balance('CYB') == valu - fee + amount/100000
    assert account2.balance('CYB') == valu - fee - amount/100000
    assert account3.balance('CYB') == valu - fee
    assert account4.balance('CYB') == valu - fee 
    logging.info('this proposal has been executed successfully')