Git Product home page Git Product logo

python-bitshares's Introduction

Python Library for BitShares

Stable

docs master Travis master codecov

Develop

docs develop Travis develop codecov develop


Documentation

Visit the pybitshares website for in depth documentation on this Python library.

Installation

Install with pip3:

$ sudo apt-get install libffi-dev libssl-dev python-dev python3-dev python3-pip
$ pip3 install bitshares

Manual installation:

$ git clone https://github.com/bitshares/python-bitshares/
$ cd python-bitshares
$ python3 setup.py install --user

Upgrade

$ pip3 install --user --upgrade bitshares

Contributing

python-bitshares welcomes contributions from anyone and everyone. Please see our guidelines for contributing and the code of conduct.

Discussion and Developers

Discussions around development and use of this library can be found in a dedicated Telegram Channel

License

A copy of the license is available in the repository's LICENSE file.

python-bitshares's People

Contributors

abitmore avatar actions-user avatar algruun avatar avral avatar bitphage avatar brickgao avatar broncotc avatar christophersanborn avatar emfrias avatar gades avatar grctest avatar harukama avatar henryw2019 avatar jhtitor avatar mikakoi avatar mironovdm avatar pyup-bot avatar runestone0 avatar smileychris avatar tianyekuo avatar tydus avatar xeroc avatar zapata avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-bitshares's Issues

Memo encryption doesn't work - shows ** on Bitshares and manual decryption throws error

I made a transfer using following code in python 3.6.4 / bitshares==0.1.11:

from bitshares import BitShares
bitshares = BitShares(keys={pub_key: priv_key})
bitshares.transfer('abc', 0.01, 'ABC', 'test-memo', 'def')

And it shows two asterisks as memo on BitShares dex no matter what I write as memo text:
image

When I try manually encrypting and decrypting memo, I got an error while decrypting:

from bitshares import BitShares
from bitshares.memo import Memo

bitshares = BitShares(keys={pub_key: priv_key})

memoObj = Memo(
    from_account=from_account,
    to_account=to_account,
    bitshares_instance=bitshares
)
enc = memoObj.encrypt('test')
memoObj.decrypt(enc)

Error:

Traceback (most recent call last):
  File "/Users/darklow/www/abc/env/lib/python3.6/site-packages/bitsharesbase/memo.py", line 116, in decode_memo
    return _unpad(message.decode('utf8'), 16)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd5 in position 4: invalid continuation byte

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/darklow/www/abc/env/lib/python3.6/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
    utility.execute()
  File "/Users/darklow/www/abc/env/lib/python3.6/site-packages/django/core/management/__init__.py", line 365, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/darklow/www/abc/env/lib/python3.6/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/darklow/www/abc/env/lib/python3.6/site-packages/django/core/management/base.py", line 335, in execute
    output = self.handle(*args, **options)
  File "/Users/darklow/www/abc/abc-swap/abcswap/management/commands/send_to_bitshares.py", line 13, in handle
    bitshares_sender.test(options['pub_key'], options['priv_key'])
  File "/Users/darklow/www/abc/abc-swap/abcswap/lib/bitshares_sender.py", line 36, in test
    memoObj.decrypt(enc)
  File "/Users/darklow/www/abc/env/lib/python3.6/site-packages/bitshares/memo.py", line 133, in decrypt
    memo.get("message")
  File "/Users/darklow/www/abc/env/lib/python3.6/site-packages/bitsharesbase/memo.py", line 118, in decode_memo
    raise ValueError(message)
ValueError: b'i\x1bf8\xd5A\xd2^X\xaf\xe0v'

Need a method to remove existing sqlite database state and file

There may be a way to accomplish this but if so it is missing from the documentation.

There is currently no way to "start fresh" or clear the self.created flag of the wallet class.

The idea is to code a robust, integrated solution so a PyBitShares program is standalone, without the need for uptick or some external program to initialize the wallet. This is no problem if no wallet has ever been created, however once a wallet has been created there is no way to get rid of it and recreate a new one.

A simple reset method to clear the "created" flag would probably do the trick. Of course it would be best if the method also removed the bitshares.sqlite DB file and cleaned up any other state associated with the old wallet. The method should result in a state identical to one in which no wallet was ever created.

Still reading storage config url when I specified the node url

I found some bugs in the code when I was using it.

Such as the Asset Class, you did not pass the bitshares_instance variable to the parent class.

I think this bug is also exist in other Class file, please check and fix it, thanks.

bitshares/asset.py line 43
super().__init__( asset, lazy=lazy, full=full, bitshares_instance=None )

bitshares/asset.py line 52
super(Asset, self).__init__(asset)

Change sqlite database to mysq

Hi @xeroc, We would like to know if there is a way to change the bitshares.sqlite to other database link mysql. We are planning to load balance our application, and we would like for all of our instances(servers) to have the same bitshares key storage. We would like to know if there are any other ways to load balance our application without having an issue with the bitshares.sqlite?

Attempts to get txId via Signed_Transaction.id for a transaction with operation expiration field set way in the past cause an exception

Example code:

from bitshares.block import Block
from bitsharesbase.signedtransactions import Signed_Transaction
from pprint import pprint
block = Block(25065606)
pprint( block['transactions'][8] )
Signed_Transaction(**block['transactions'][8]).id

Output:

{'expiration': '2018-03-09T03:11:50',
 'extensions': [],
 'operation_results': [[1, '1.7.58254444']],
 'operations': [[1,
                 {'amount_to_sell': {'amount': 100000000,
                                     'asset_id': '1.3.113'},
                  'expiration': '1963-11-29T12:38:45',
                  'extensions': [],
                  'fee': {'amount': 92, 'asset_id': '1.3.0'},
                  'fill_or_kill': False,
                  'min_to_receive': {'amount': 15847860, 'asset_id': '1.3.121'},
                  'seller': '1.2.33015'}]],
 'ref_block_num': 30853,
 'ref_block_prefix': 594311437,
 'signatures': ['204fb2556eced197d849f87618683f4a3ab2c560b59bae6adecad3bd887adf959d45262d6d74123c933321898176ff7f062c96f88c94b16fac4358d694959b46fe']}
Traceback (most recent call last):
  File "bug.py", line 6, in <module>
    Signed_Transaction(**block['transactions'][8]).id
  File "/home/femtocat/.local/lib/python3.5/site-packages/graphenebase/signedtransactions.py", line 84, in id
    h = hashlib.sha256(bytes(self)).digest()
  File "/home/femtocat/.local/lib/python3.5/site-packages/graphenebase/objects.py", line 84, in __bytes__
    b += bytes(value)
  File "/home/femtocat/.local/lib/python3.5/site-packages/graphenebase/types.py", line 197, in __bytes__
    return bytes(self.length) + b"".join([bytes(a) for a in self.data])
  File "/home/femtocat/.local/lib/python3.5/site-packages/graphenebase/types.py", line 197, in <listcomp>
    return bytes(self.length) + b"".join([bytes(a) for a in self.data])
  File "/home/femtocat/.local/lib/python3.5/site-packages/graphenebase/objects.py", line 57, in __bytes__
    return bytes(Id(self.opId)) + bytes(self.op)
  File "/home/femtocat/.local/lib/python3.5/site-packages/graphenebase/objects.py", line 84, in __bytes__
    b += bytes(value)
  File "/home/femtocat/.local/lib/python3.5/site-packages/graphenebase/types.py", line 214, in __bytes__
    return struct.pack("<I", timegm(time.strptime((self.data + "UTC"), timeformat)))
struct.error: argument out of range

market.orderbook() bug?

I have installed pybitshares using via pip3. the following code generate the below error:
from bitshares import BitShares
from bitshares.market import Market
market = Market("BTS:BTC")
print(market.orderbook())
error:
print(market.orderbook())
File "/usr/local/lib/python3.5/site-packages/bitshares/market.py", line 209, in orderbook
), orders["asks"]))
File "/usr/local/lib/python3.5/site-packages/bitshares/market.py", line 208, in
bitshares_instance=self.bitshares
File "/usr/local/lib/python3.5/site-packages/bitshares/price.py", line 331, in init
self["id"] = order["id"]
UnboundLocalError: local variable 'order' referenced before assignment

Historic settlement prices?

Hey,

Would it be possible to request historical market data through python-bitshares in the future?

Like:

market = Market("USD:BTS", "2018-03-01T12:00:00+00:00")
historical_ticker_data = market.ticker()

Would this require changes to bitshares-core to achieve?

The second best solution for retrieving the feed price for an asset would be using elastic search to retrieve published price feeds (from a single user, rather than asset-summary data?) for the asset in question, probably the simpler solution?

Memo decode issue when both receiver and sender key are present

Assume an arbitrary memo

memo = {'from': 'TEST5LWr6Azqd5uRQkKhqdqDT8PAPnfwjSNSJUNbeUmrJquRqsFU7s', 'to': 'TEST8Usudm1jJBaM99YWMEiRNEc5yWyE9uT5zB3iw47FEpu6WHaowG', 'nonce': '18045968873016477071', 'message': '9ad92b7ca801d6dc5bae9dfbd0c23229', 'prefix': 'TEST'}

decoded_memo = Memo(
                bitshares_instance=self.bitshares
            ).decrypt(payload["memo"])

Said instance holds the memo key to one account (this account has active key != memo key) and the active key to the other (this account has active key == memo key).

In bitShares.memo we have the following:

def decrypt(self, memo):
        """ Decrypt a memo

            :param str memo: encrypted memo message
            :returns: encrypted memo
            :rtype: str
        """
        if not memo:
            return None

        # We first try to decode assuming we received the memo
        try:
            memo_wif = self.bitshares.wallet.getPrivateKeyForPublicKey(
                memo["to"]
            )
            pubkey = memo["from"]
        except KeyNotFound:
            try:
                # if that failed, we assume that we have sent the memo
                memo_wif = self.bitshares.wallet.getPrivateKeyForPublicKey(
                    memo["from"]
                )
                pubkey = memo["to"]
            except KeyNotFound:
                # if all fails, raise exception
                raise MissingKeyError(
                    "Non of the required memo keys are installed!"
                    "Need any of {}".format(
                    [memo["to"], memo["from"]]))

        return BtsMemo.decode_memo(
            PrivateKey(memo_wif),
            PublicKey(pubkey, prefix=self.bitshares.prefix),
            memo.get("nonce"),
            memo.get("message")
        )

When trying to decode with the memo_wif/pubkey from the "... we received the memo ..." section, the decoding errors with
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 1: invalid start byte
When decoding with memo_wif/pubkey from "... we have sent the memo ..." section, everything works.

python-bitshares websocket doesn't handle well failing ssl handshakes

For example node wss://eu.nodes.bitshares.works fails ssl handshake and the websocket keeps trying to connect to the node.
I think the connection should simply be killed and error raised in case of a ssl handshake failure.
Here's the traceback:

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)
Traceback (most recent call last):
  File "/home/mika/scripts/DEXBot/venv/lib/python3.5/site-packages/websocket_client-0.47.0-py3.5.egg/websocket/_app.py", line 234, in run_forever
    host=host, origin=origin)
  File "/home/mika/scripts/DEXBot/venv/lib/python3.5/site-packages/websocket_client-0.47.0-py3.5.egg/websocket/_core.py", line 217, in connect
    options.pop('socket', None))
  File "/home/mika/scripts/DEXBot/venv/lib/python3.5/site-packages/websocket_client-0.47.0-py3.5.egg/websocket/_http.py", line 76, in connect
    sock = _ssl_socket(sock, options.sslopt, hostname)
  File "/home/mika/scripts/DEXBot/venv/lib/python3.5/site-packages/websocket_client-0.47.0-py3.5.egg/websocket/_http.py", line 191, in _ssl_socket
    sock = _wrap_sni_socket(sock, sslopt, hostname, check_hostname)
  File "/home/mika/scripts/DEXBot/venv/lib/python3.5/site-packages/websocket_client-0.47.0-py3.5.egg/websocket/_http.py", line 168, in _wrap_sni_socket
    server_hostname=hostname,
  File "/usr/lib/python3.5/ssl.py", line 377, in wrap_socket
    _context=self)
  File "/usr/lib/python3.5/ssl.py", line 752, in __init__
    self.do_handshake()
  File "/usr/lib/python3.5/ssl.py", line 988, in do_handshake
    self._sslobj.do_handshake()
  File "/usr/lib/python3.5/ssl.py", line 633, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)

import backup file

This could be a silly question, I have a wallet backup file, how can I import that into the pybitshares wallet? I searched the code, but didn't find anything related to "restore" or something, could you help shed some light on this?

Failed to compare two Price

>>> bts_cny = Market("BTS:CNY",bitshares_instance=bit)
>>> p2 = bts_cny.ticker()['highestBid']
>>> p3 = bts_cny.ticker()['highestBid']
>>> p2 > p3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/dist-packages/bitshares/price.py", line 314, in __gt__
    assert other["quote"]["symbol"] == self["base"]["symbol"]
AssertionError

It doesn't make sense that two price with same base & quote can't compare with each other .
I thought that was a mistake with copy & paste .
the asserts in magic methods of Prince class should be fixed

Market().ticker() OverflowError

print(Market('USD:BTS').ticker()) File "/usr/local/lib/python3.5/dist-packages/bitshares/market.py", line 178, in ticker bitshares_instance=self.bitshares File "/usr/local/lib/python3.5/dist-packages/bitshares/price.py", line 117, in __init__ frac = Fraction(float(price)).limit_denominator(10 ** base["precision"]) File "/usr/lib/python3.5/fractions.py", line 130, in __new__ value = Fraction.from_float(numerator) File "/usr/lib/python3.5/fractions.py", line 216, in from_float raise OverflowError("Cannot convert %r to %s." % (f, cls.__name__)) OverflowError: Cannot convert inf to Fraction.
A trivial program triggered this OverflowError for awhile, then the problem corrected itself. I assume small values from the network overflowed whatever this is doing.

Can't use multithreading to buy

Traceback (most recent call last):
File "/home/daiz/.local/lib/python3.5/site-packages/bitshares-0.1.9-py3.5.egg/bitsharesapi/bitsharesnoderpc.py", line 42, in rpcexec
File "/home/daiz/.local/lib/python3.5/site-packages/graphenelib-0.5.5-py3.5.egg/grapheneapi/graphenewsrpc.py", line 160, in rpcexec
grapheneapi.graphenewsrpc.RPCError: Assert Exception: operations.size() > 0: A transaction must have at least one operation

What datetime format is needed for market.trade() ?

I'm trying to get market trade history using python-bitshares, and am using the following datetime format:

"2017-12-29T19:16:36Z"

It results in the following error:

"grapheneapi.graphenewsrpc.RPCError: Day of month value is out of range 1..31: Day of month value is out of range 1..31: unable to convert ISO-formatted string to fc::time_point_sec"

Am I not using the proper date format?

More details:

Traceback (most recent call last):
  File "/home/btsapi/python-bitshares/bitsharesapi/bitsharesnoderpc.py", line 42, in rpcexec
    return super(BitSharesNodeRPC, self).rpcexec(payload)
  File "/home/btsapi/.local/lib/python3.6/site-packages/grapheneapi/graphenewsrpc.py", line 160, in rpcexec
    raise RPCError(ret['error']['message'])
grapheneapi.graphenewsrpc.RPCError: Day of month value is out of range 1..31: Day of month value is out of range 1..31: unable to convert ISO-formatted string to fc::time_point_sec

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 74, in <module>
    temp_market_history = list(target_market.trades(start="2017-12-20T20:02:08+00:00", stop="2017-12-21T20:02:08+00:00", limit=100))
  File "/home/btsapi/python-bitshares/bitshares/market.py", line 269, in trades
    limit)
  File "/home/btsapi/.local/lib/python3.6/site-packages/grapheneapi/graphenewsrpc.py", line 195, in method
    r = self.rpcexec(query)
  File "/home/btsapi/python-bitshares/bitsharesapi/bitsharesnoderpc.py", line 50, in rpcexec
    raise exceptions.UnhandledRPCError(msg)
bitsharesapi.exceptions.UnhandledRPCError: Day of month value is out of range 1..31: Day of month value is out of range 1..31: unable to convert ISO-formatted string to fc::time_point_sec

Dex.returnFees() returns invalid JSON?

Hey,

Stumbled across an issue with the 'Dex.returnFees()' today using the following snippet:

from bitshares.dex import Dex
test = Dex()
print(test.returnFees())

The output JSON is not correctly formatted - when you run it through a JSON 'prettifier' you get the following error messages:

Error: Parse error on line 1:
{	'transfer': {		'fee
--^
Expecting 'STRING', '}', got 'undefined'
JSON Pretty: SyntaxError: Bad string at character 2 near "{'transfer': {'fee': 0.21851, 'price_per_kbyte': 0.12139}, 'limit_order_create': {'fee': 0.01213}, 'limit_order_cancel': {'fee': 0.00121}, 'call_order_update': {'fee': 0.01213}, 'fill_order': {}, 'account_create': {'basic_fee': 1.21396, 'premium_fee': 60.69837, 'price_per_kbyte': 0.08497}, 'account_update': {'fee': 0.01213, 'price_per_kbyte': 0.08497}, 'account_whitelist': {'fee': 1.21396}, 'account_upgrade': {'membership_annual_fee': 121396752.70075, 'membership_lifetime_fee': 1456.76103}, 'account_transfer': {'fee': 60.69837}, 'asset_create': {'symbol3': 97117.40216, 'symbol4': 24279.35054, 'long_symbol': 606.98376, 'price_per_kbyte': 0.12139}, 'asset_update': {'fee': 24.27935, 'price_per_kbyte': 0.08497}, 'asset_update_bitasset': {'fee': 60.69837}, 'asset_update_feed_producers': {'fee': 60.69837}, 'asset_issue': {'fee': 0.21851, 'price_per_kbyte': 0.12139}, 'asset_reserve': {'fee': 0.01213}, 'asset_fund_fee_pool': {'fee': 6.06983}, 'asset_settle': {'fee': 0.60698}, 'asset_global_settle': {'fee': 60.69837}, 'asset_publish_feed': {'fee': 0.00121}, 'witness_create': {'fee': 606.98376}, 'witness_update': {'fee': 0.12139}, 'proposal_create': {'fee': 1.82095, 'price_per_kbyte': 0.60698}, 'proposal_update': {'fee': 0.06069, 'price_per_kbyte': 0.08497}, 'proposal_delete': {'fee': 0.0}, 'withdraw_permission_create': {'fee': 1.82095}, 'withdraw_permission_update': {'fee': 0.12139}, 'withdraw_permission_claim': {'fee': 0.17481, 'price_per_kbyte': 0.08497}, 'withdraw_permission_delete': {'fee': 0.0}, 'committee_member_create': {'fee': 60.69837}, 'committee_member_update': {'fee': 121.39675}, 'committee_member_update_global_parameters': {'fee': 0.0}, 'vesting_balance_create': {'fee': 60.69837}, 'vesting_balance_withdraw': {'fee': 24.27935}, 'worker_create': {'fee': 606.98376}, 'custom': {'fee': 0.12139, 'price_per_kbyte': 0.60698}, 'assert': {'fee': 6.06983}, 'balance_claim': {}, 'override_transfer': {'fee': 12.13967, 'price_per_kbyte': 0.08497}, 'transfer_to_blind': {'fee': 2.54933, 'price_per_output': 0.84977}, 'transfer_from_blind': {'fee': 2.54933}, 'asset_claim_fees': {'fee': 12.13967}} "

Relevant JSON output:

{
	'transfer': {
		'fee': 0.21851,
		'price_per_kbyte': 0.12139
	},
	'limit_order_create': {
		'fee': 0.01213
	},
	'limit_order_cancel': {
		'fee': 0.00121
	},
	'call_order_update': {
		'fee': 0.01213
	},
	'fill_order': {},
	'account_create': {
		'basic_fee': 1.21396,
		'premium_fee': 60.69837,
		'price_per_kbyte': 0.08497
	},
	'account_update': {
		'fee': 0.01213,
		'price_per_kbyte': 0.08497
	},
	'account_whitelist': {
		'fee': 1.21396
	},
	'account_upgrade': {
		'membership_annual_fee': 121396752.70075,
		'membership_lifetime_fee': 1456.76103
	},
	'account_transfer': {
		'fee': 60.69837
	},
	'asset_create': {
		'symbol3': 97117.40216,
		'symbol4': 24279.35054,
		'long_symbol': 606.98376,
		'price_per_kbyte': 0.12139
	},
	'asset_update': {
		'fee': 24.27935,
		'price_per_kbyte': 0.08497
	},
	'asset_update_bitasset': {
		'fee': 60.69837
	},
	'asset_update_feed_producers': {
		'fee': 60.69837
	},
	'asset_issue': {
		'fee': 0.21851,
		'price_per_kbyte': 0.12139
	},
	'asset_reserve': {
		'fee': 0.01213
	},
	'asset_fund_fee_pool': {
		'fee': 6.06983
	},
	'asset_settle': {
		'fee': 0.60698
	},
	'asset_global_settle': {
		'fee': 60.69837
	},
	'asset_publish_feed': {
		'fee': 0.00121
	},
	'witness_create': {
		'fee': 606.98376
	},
	'witness_update': {
		'fee': 0.12139
	},
	'proposal_create': {
		'fee': 1.82095,
		'price_per_kbyte': 0.60698
	},
	'proposal_update': {
		'fee': 0.06069,
		'price_per_kbyte': 0.08497
	},
	'proposal_delete': {
		'fee': 0.0
	},
	'withdraw_permission_create': {
		'fee': 1.82095
	},
	'withdraw_permission_update': {
		'fee': 0.12139
	},
	'withdraw_permission_claim': {
		'fee': 0.17481,
		'price_per_kbyte': 0.08497
	},
	'withdraw_permission_delete': {
		'fee': 0.0
	},
	'committee_member_create': {
		'fee': 60.69837
	},
	'committee_member_update': {
		'fee': 121.39675
	},
	'committee_member_update_global_parameters': {
		'fee': 0.0
	},
	'vesting_balance_create': {
		'fee': 60.69837
	},
	'vesting_balance_withdraw': {
		'fee': 24.27935
	},
	'worker_create': {
		'fee': 606.98376
	},
	'custom': {
		'fee': 0.12139,
		'price_per_kbyte': 0.60698
	},
	'assert': {
		'fee': 6.06983
	},
	'balance_claim': {},
	'override_transfer': {
		'fee': 12.13967,
		'price_per_kbyte': 0.08497
	},
	'transfer_to_blind': {
		'fee': 2.54933,
		'price_per_output': 0.84977
	},
	'transfer_from_blind': {
		'fee': 2.54933
	},
	'asset_claim_fees': {
		'fee': 12.13967
	}
}

Would it not be better to place the fee details within an array and each encapsulated by {} ? Like the following: (... = concatenation)

{
	'transfer': [
		{'fee': 0.21851},
		{'price_per_kbyte': 0.12139}
	],
        ........
        'balance_claim': [],
        ........
	'asset_claim_fees': [
		{'fee': 12.13967}
	]
}

Cheers πŸ‘

Sign memo with varying keys

With an offline signing service, a feature in the bitshares object to dynamically add and remove wifs from in ram storage would be convenient!

Inconsistent limit handling

Hey,

I'm working on a REST API for this python-bitshares library, and stumbled across inconsistent handling of limits.

For the account tx history, you can set the limit to -1 to get all data (heck, you can set it to -100000000 and get the same result as -1).

When you input a limit of -1 when retrieving a market's orderbook it produces the following error:

File "/home/btsapi/python-bitshares/bitshares/market.py", line 235, in orderbook limit
File "/home/btsapi/HUG/lib/python3.6/site-packages/grapheneapi/graphenewsrpc.py", line 195, in method r = self.rpcexec(query)
File "/home/btsapi/python-bitshares/bitsharesapi/bitsharesnoderpc.py", line 50, in rpcexec raise exceptions.UnhandledRPCError(msg)
bitsharesapi.exceptions.UnhandledRPCError: Assert Exception: limit <= 50:

Speaking of which, when you set the limit to 0 for the orderbook it shows no results, but for account tx history, 0 returns a single result.

I'll set a minimum of 0 for the API limit parameter, however I felt it was worth raising the above.

Cheers πŸ‘

Account.openorders does not propagate bitshares_instance

Account(bitshares_instance=some_bitshares_instance).openorders returns Orders objects with a different bitshares_instance: shared_bitshares_instance in particular and not some_bitshares_instance.

One is forced to use set_shared_bitshares_instance instead of being able to pass bitshares_instance= to everything.

The offending code, line 157 of account.py:
return [Order(o) for o in self["limit_orders"]]

Wrong price returned by market order book

In market.py, orderbook function:

        asks = list(map(lambda x: Order(
            Amount(x["quote"], self["quote"], bitshares_instance=self.bitshares),
            Amount(x["base"], self["base"], bitshares_instance=self.bitshares),
            bitshares_instance=self.bitshares
        ), orders["asks"]))
        bids = list(map(lambda x: Order(
            Amount(x["quote"], self["quote"], bitshares_instance=self.bitshares),
            Amount(x["base"], self["base"], bitshares_instance=self.bitshares),
            bitshares_instance=self.bitshares
        ), orders["bids"]))

Orders are constructed with base amount and quote amount only. This leads to wrong price when the order was partially filled.

For example, with this data:

Mon Mar 19 22:19:22 UTC 2018
{"id":1037,"jsonrpc":"2.0","result":{"base":"USD","quote":"BTS","bids":[{"price":"0.127431355173731879","quote":"2.88782","base":"0.3680"}],"asks":[{"price":"0.12743137102808178","quote":"431.10656","base":"54.9365"}]}}

The bid price returned by market.orderbook is 0.3680/2.88782 = 0.12743177, which is far from the real price returned by the API server which is 0.127431355.

The operations has not been added after 10 blocks

It's reported that, when checking if a transaction is included in a block, the lib compares the full transaction json with result of get_block API. But there are issues when producing the json, e.g. converting big numbers from/to json, so sometimes even if a transaction is included in a block, the lib still reports "The operations has not been added after 10 blocks". The correct way is to compare transaction_id's.

Not sure if it's still an issue.

Selecting asset for paying fee's

I've tried building a transaction where i set the asset fee for transfer but it's still using 1.3.0(BTS) for the fee. Can someone help me with this. Here's the code i'm using.

from bitshares.transactionbuilder import TransactionBuilder
from bitsharesbase.operations import Transfer
tx = TransactionBuilder()
tx.appendOps(Transfer(**{
    "fee": {"amount": 0, "asset_id": "1.3.121"},
    "from": "1.2.124",
    "to": "1.2.1241",
    "amount": {"amount": 500, "asset_id": "1.3.121"},
}))
tx.appendSigner("xeroc", "active")
tx.sign()
tx.broadcast()

Am i doing it wrong? If so please show me how to set asset fee thank you.

Signed_Transaction usage for Testnet not straightforward

When signing a transaction to be published on the Testnet that contains transfers (in this case exactly one) with memo one needs to do the following:

transaction = build_your_transaction_with_one_transfer()
transaction["operations"][0][1].update({"prefix": "TEST"})
tx = Signed_Transaction(**transaction)
stx = tx.sign(wifs, chain="TEST").json()

Not sure if this could be optimized for easy use. Right now I need to know the internal structure of the transaction to update the prefix.

documentation issues

  1. There is no link to this github repo in the documentation. I suggest it at least needs to be on this page: http://docs.pybitshares.com/en/latest/contribute.html
  2. There is no help or support page. The support info is bundled into the contribute page. I suggest a new help page with suggestions to use community channels for general assistance and the github repo issue function for reporting bugs. help page menu link should always be visible on the left
  3. The wallet and storage object documentation needs to be enhanced as this area is confusing for newbies. need explicit examples on how to add a new pub/wif. a description about how it works would help, is the account name is not stored locally? also a description where this key info could be sourced would be helpful, a bit like the btsbots explanation of where the keys are found in the online exchange (screenshots would be great here too.
    Great effort so far, keep up the good work!

Transfer Error in TestNet

When I use "wss://node.bitshares.eu" (live node)

from bitshares import BitShares
bitshares = BitShares()
bitshares.wallet.unlock("secret word")
bitshares.transfer("red-head", "1", "BTS","memo details here",None)  --> **This is working**

When I use "wss://node.testnet.bitshares.eu" (testnet node)

from bitshares import BitShares
bitshares = BitShares()
bitshares.wallet.unlock("secret word")
bitshares.transfer("red-head", "1", "TEST","memo details here",None)  --> **This is NOT WORKING**

Here is the error details ;

Traceback (most recent call last):
File "/home/serdar/bitshares-deneme.py", line 46, in
print(bitshares.transfer("testt1", "1", "MYBTC","deneme",None))
File "/home/serdar/.local/lib/python3.5/site-packages/bitshares/bitshares.py", line 429, in transfer
"prefix": self.rpc.chain_params["prefix"]
File "/home/serdar/.local/lib/python3.5/site-packages/bitsharesbase/operations.py", line 46, in init
memo = Optional(Memo(kwargs["memo"]))
File "/home/serdar/.local/lib/python3.5/site-packages/bitsharesbase/objects.py", line 98, in init
('from', PublicKey(kwargs["from"], prefix=prefix)),
File "/home/serdar/.local/lib/python3.5/site-packages/bitsharesbase/account.py", line 84, in init
super(PublicKey, self).init(*args, **kwargs)
File "/home/serdar/.local/lib/python3.5/site-packages/graphenebase/account.py", line 216, in init
self._pk = Base58(pk, prefix=prefix)
File "/home/serdar/.local/lib/python3.5/site-packages/graphenebase/base58.py", line 60, in init
raise ValueError("Error loading Base58 object")
ValueError: Error loading Base58 object

Transfer Error

When I try to use transfer function if I set memo parameter as None it is sending successfully
But If set memo parameter as a string I am getting this error output ;

from bitshares import BitShares
bitshares = BitShares()
bitshares.wallet.unlock("xxxxxxxx")
bitshares.transfer("red-head2", "0.000001", "OPEN.BTC", None,"red-head") --> this is working good
bitshares.transfer("red-head2", "0.000001", "OPEN.BTC", "sometextmessage","red-head") --> this is NOT working

Error Details
Traceback (most recent call last):
File "/home/serdar/bitshares-deneme.py", line 39, in
bitshares.transfer("red-head2", "0.000001", "OPEN.BTC", "[]","red-head")
File "/home/serdar/.local/lib/python3.5/site-packages/bitshares/bitshares.py", line 422, in transfer
"memo": memoObj.encrypt(memo)
File "/home/serdar/.local/lib/python3.5/site-packages/bitsharesbase/operations.py", line 45, in init
memo = Optional(Memo(kwargs["memo"]))
File "/home/serdar/.local/lib/python3.5/site-packages/bitsharesbase/objects.py", line 98, in init
('from', PublicKey(kwargs["from"], prefix=prefix)),
KeyError: 'from'

Purpose of 'proposal' function?

I've been trying to use the 'proposal' function to retrieve a list of the worker proposals, however I've noticed that worker proposals use 1.14.x and the proposal is checking for 1.10.x - is the proposal function for proposed transactions as opposed to worker proposals?

Memo encoding/decoding bug

Memo encoding/decoding often raises UnicodeDecodeError, when i try decode memo message. Look on my example:

from bitsharesbase.memo import encode_memo, decode_memo
from bitsharesbase.account import PrivateKey, PublicKey

sender_private_key = '5H***********************************************'
sender_memo_key = 'BTS7***********************************************'

receiver_private_key = '5K**********************************************'
receiver_memo_key = 'BTS6***********************************************'

nonce = 389577592240607
message = 'test'

encoded_memo = encode_memo(
    priv=PrivateKey(sender_private_key, prefix='BTS'),
    pub=PublicKey(receiver_memo_key, prefix='BTS'),
    nonce=nonce,
    message='my secret message 1!'
)

result = decode_memo(
    priv=PrivateKey(receiver_private_key, prefix='BTS'),
    pub=PublicKey(sender_memo_key, prefix='BTS'),
    nonce=nonce,
    message=encoded_memo
)

assert message == result

this code raises exception:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8d in position 0: invalid start byte

in function bitsharesbase.memo.decode_memo at line 116

        return _unpad(message.decode('utf8'), 16)

Private keys and memo keys definitely correct for sender and receiver accounts, because i successfully signed and sent transactions, using this keys and your library.

Also i tried send memo transaction using cli_wallet and web wallet, and all works fine.

I need implement transaction processing for some exchange, and memo decoding very important for me, so i will use cli_wallet instead this useless library.

If memo module not works, it must be removed or marked as deprecated, because many developers may spend many days in bug search like me.

Unhandled RPC error w/ dacplay ws server

I was recently investigating the cause of an internal server error in the hug-rest api: BTS-CM/Bitshares-HUG-REST-API#2

The script would occasionally fail at this point:

 price = market.ticker()["quoteSettlement_price"] # Get Settlement price of USD

It appears to only trigger against the following server:

Server: wss://bitshares.dacplay.org/ws
Traceback (most recent call last):
  File "/home/btsapi/python-bitshares/bitsharesapi/bitsharesnoderpc.py", line 42, in rpcexec
    return super(BitSharesNodeRPC, self).rpcexec(payload)
  File "/home/btsapi/HUG/lib/python3.6/site-packages/grapheneapi/graphenewsrpc.py", line 160, in rpcexec
    raise RPCError(ret['error']['message'])
grapheneapi.graphenewsrpc.RPCError: Assert Exception: _index[space_id].size() > type_id:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "a.py", line 44, in <module>
    print(market.ticker())
  File "/home/btsapi/python-bitshares/bitshares/market.py", line 154, in ticker
    self["quote"]["id"],
  File "/home/btsapi/HUG/lib/python3.6/site-packages/grapheneapi/graphenewsrpc.py", line 195, in method
    r = self.rpcexec(query)
  File "/home/btsapi/python-bitshares/bitsharesapi/bitsharesnoderpc.py", line 50, in rpcexec
    raise exceptions.UnhandledRPCError(msg)
bitsharesapi.exceptions.UnhandledRPCError: Assert Exception: _index[space_id].size() > type_id:

It's not caused due to the server being unreachable, as the following works:

Lost connection to node during wsconnect(): wss://bitshares.crypto.fans/ws (2/-1

Is this caused by the dacplay server not having required extensions enabled? To deter this from happening again, would it be wise to add try/except handling to all RPC attempts in the code?

In the mean time, I've removed the dacplay server from my API.

Cheers πŸ‘

the exchange rate calculation is wrong

Today I'm using this library to get back the order book of BTS:CNY (BTS is the base, CNY is the quote)

Part of the result is as follows:

'bids': 
[758.09461 BTS 732.0726 CNY @ 0.965674456 CNY/BTS, 
16,996.94113 BTS 16,402.0482 CNY @ 0.965000001 CNY/BTS, 
666.72547 BTS 642.7797 CNY @ 0.964084513 CNY/BTS, 
0.00010 BTS 0.0001 CNY @ 1.000000000 CNY/BTS, 
381.03624 BTS 367.1020 CNY @ 0.963430670 CNY/BTS]}

All bids should be in decreasing order, but you can look at "0.00010 BTS 0.0001 CNY @ 1.000000000 CNY/BTS", it's not correct, and if I'm reading this from openledger wallet, it shows at this moment, the rate for this order is 0.963493

What do we miss here?

account open order rate doesn't go below 0

Hey,

I've been working on a HUG REST API using this library, and found the following when using account 'openorder':

12,500 WHALESHARE 500 BEYONDBIT @ 0 BEYONDBIT/WHALESHARE

It should be showing 0.04 BEYONDBIT/WHALESHARE, but it's showing 0?

Cheers πŸ‘

Why can not I cancel the order?

This is my code:
market = Market("BTS:CNY")
account = Account("bitshares.bot")

market.bitshares.wallet.unlock("xxxxxx")
s = account.openorders.getitem(0).get("id")
print(s.split('.')[2])

print(market.cancel(s.split('.')[2]))
This is the logs:
30995418
Traceback (most recent call last):
File "/home/hiquanta/PycharmProjects/btsbots/Trans.py", line 37, in
print(market.cancel(s))
File "/home/hiquanta/.pyenv/versions/3.6.2/lib/python3.6/site-packages/bitshares/market.py", line 545, in cancel
return self.bitshares.cancel(orderNumber, account=account)
File "/home/hiquanta/.pyenv/versions/3.6.2/lib/python3.6/site-packages/bitshares/bitshares.py", line 862, in cancel
"prefix": self.rpc.chain_params["prefix"]}))
File "/home/hiquanta/.pyenv/versions/3.6.2/lib/python3.6/site-packages/bitsharesbase/operations.py", line 196, in init
('order', ObjectId(kwargs["order"], "limit_order")),
File "/home/hiquanta/.pyenv/versions/3.6.2/lib/python3.6/site-packages/bitsharesbase/objects.py", line 36, in init
raise Exception("Object id is invalid")
Exception: Object id is invalid

Calling account.openorders gives the original order

Calling account.openorders gives orders that have the original details.
For example if I make a sell order with amount of 20, and somebody buys half of that, account.openorders still returns the original 20 as amount.

Is there another method to get the updated amount?

How to limit node reconnect attempts?

I'm trying to provide redundent node connections when publishing price feeds for long periods of time.

When I try the following it gets stuck in a reconnect loop for the fist invalid server. Is there a way of providing a timeout of a max connect attempts, so that I can loop through a list of API servers?

full_node_list = ["wss://bitshfares.openledger.info/ws",
                         "wss://bitshares.crypto.fans/ws",
                         "wss://openledger.hk/ws"]

for server in full_node_list:
  try:
    bitshares_api_node = BitShares(server)
    break
  except:
    print(server + " is offline!")

Output:

Lost connection to node during wsconnect(): wss://nodfe.bitshares.eu/ws (2/-1) Retrying in 2 seconds
Lost connection to node during wsconnect(): wss://nodfe.bitshares.eu/ws (3/-1) Retrying in 4 seconds
Lost connection to node during wsconnect(): wss://nodfe.bitshares.eu/ws (4/-1) Retrying in 6 seconds
......

Should I instead try to connect using a 3rd party websocket client to ping the API servers before moving ahead with creating a Bitshares instance?

Cheers

Market.sell returns None

Market.buy returns a rich dict with the order_id, Market.sell just returns None
very simple fix

diff --git a/bitshares/market.py b/bitshares/market.py
index 37aa827..cb385c6 100644
--- a/bitshares/market.py
+++ b/bitshares/market.py
@@ -518,6 +518,8 @@ class Market(dict):
             tx["orderid"] = tx["operation_results"][0][1]
             self.bitshares.blocking = prevblocking
 
+        return tx
+
     def cancel(self, orderNumber, account=None):
         """ Cancels an order you have placed in a given market. Requires
             only the "orderNumber". An order number takes the form

  

Memo: decode_memo function

Hi @xeroc,

I have an issue regarding the decode_memo function most of the time this works but there are instances that the return of the decode_memo function is ValueError, I understand that the message cannot be decoded as a valid UTF-8 string but the thing is that when I looked at the wallet.bitshares.org the memo is readable I am just wondering why this happens on the decode_memo.

Is there any other way to get fixed the issue? please see the example error below:
ValueError : b'r\x16\xd4\xd3\xd3\xaa(/\x04\xf0\xfa\xc0\xaah\xe7*#\x02\x1aN\x93q\x0e\xc8\x87\xb2v\xf2'

Or am I missing something here?

Thanks in advance

Happy New Year!!!

Henry

dependency on scrypt

This is more of a question/request than a bug as such.
python-bitshares has a hard dependency in scrypt, but doesn't import it itself: it's only imported over in python-graphenelib AFAICT,
python-graphenelib doesn't depend on scrypt: it depends ion pylibscrypt, and the relevant code uses whichever one is installed.
The scrypt dependency is causing us major pain: Linux users need to install libssl-dev and gcc: slow but at least reasonably automatic, on Windows it would need Visual C++ to compile the C extensions.
All for a speedup on decrypting private keys that I doubt we could measure let alone notice.
However because it's listed in setup.py here we are stuck: setuptools isn't smart enough to say "install this package but not one of its dependencies"
Would you consider removing the scrypt dependency? Users who want that microsecond speedup and have easy access to a C compiler can add it in easily through pip.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.