Bitshares Coin Handler

Module contents

Bitshares Coin Handler

This python module is a Coin Handler for Privex’s CryptoToken Converter, designed to handle all required functionality for both receiving and sending tokens on the Bitshares network.

It will automatically handle any payments.models.Coin which has its type set to bitshares

Copyright:

+===================================================+
|                 © 2019 Privex Inc.                |
|               https://www.privex.io               |
+===================================================+
|                                                   |
|        CryptoToken Converter                      |
|                                                   |
|        Core Developer(s):                         |
|                                                   |
|          (+)  Chris (@someguy123) [Privex]        |
|                                                   |
+===================================================+
payments.coin_handlers.Bitshares.reload()[source]

Reload’s the provides property for the loader and manager from the DB.

By default, since new tokens are constantly being created for Bitshares, our classes can provide for any models.Coin by scanning for coins with the type bitshares. This saves us from hard coding specific coin symbols.

Submodules

BitsharesLoader module

Copyright:

+===================================================+
|                 © 2019 Privex Inc.                |
|               https://www.privex.io               |
+===================================================+
|                                                   |
|        CryptoToken Converter                      |
|                                                   |
|        Core Developer(s):                         |
|                                                   |
|          (+)  Chris (@someguy123) [Privex]        |
|                                                   |
+===================================================+
class payments.coin_handlers.Bitshares.BitsharesLoader.BitsharesLoader(symbols)[source]

Bases: payments.coin_handlers.base.BaseLoader.BaseLoader, payments.coin_handlers.Bitshares.BitsharesMixin.BitsharesMixin

This class handles loading transactions for the Bitshares network, and can support any token on Bitshares.

Copyright:

+===================================================+
|                 © 2019 Privex Inc.                |
|               https://www.privex.io               |
+===================================================+
|                                                   |
|        CryptoToken Converter                      |
|                                                   |
|        Core Developer(s):                         |
|                                                   |
|          (+)  Chris (@someguy123) [Privex]        |
|                                                   |
+===================================================+
clean_txs(account: bitshares.account.Account, symbol: str, transactions: Iterable[dict]) → Generator[dict, None, None][source]

Filters a list of transactions by the receiving account, yields dict’s conforming with payments.models.Deposit

Parameters:
  • account (str) – The ‘to’ account to filter by
  • symbol (str) – The symbol of the token being filtered
  • transactions (list<dict>) – A list<dict> of transactions to filter
Returns:

A generator yielding dict s conforming to payments.models.Deposit

list_txs(batch=0) → Generator[dict, None, None][source]

Get transactions for all coins in self.coins where the ‘to’ field matches coin.our_account If load() hasn’t been ran already, it will automatically call self.load() :return: Generator yielding dicts that conform to models.Deposit

load(tx_count=1000)[source]

The load function should prepare your loader, by either importing all of the data required for filtering, or setting up a generator for the list_txs() method to load them paginated.

It does NOT return anything, it simply creates any connections required, sets up generator functions if required for paginating the data, and/or pre-loads the first batch of transaction data.

Parameters:tx_count – The total amount of transactions that should be loaded PER SYMBOL, most recent first.
Returns:None
provides

This attribute is automatically generated by scanning for models.Coin s with the type bitshares. This saves us from hard coding specific coin symbols. See __init__.py for populating code.

BitsharesManager module

Copyright:

+===================================================+
|                 © 2019 Privex Inc.                |
|               https://www.privex.io               |
+===================================================+
|                                                   |
|        CryptoToken Converter                      |
|                                                   |
|        Core Developer(s):                         |
|                                                   |
|          (+)  Chris (@someguy123) [Privex]        |
|                                                   |
+===================================================+
class payments.coin_handlers.Bitshares.BitsharesManager.BitsharesManager(symbol: str)[source]

Bases: payments.coin_handlers.base.BaseManager.BaseManager, payments.coin_handlers.Bitshares.BitsharesMixin.BitsharesMixin

This class handles various operations for the **Bitshares* network, and supports any token on Bitshares.

It handles:

  • Validating source/destination accounts
  • Checking the balance for a given account, as well as the total amount received with a certain memo
  • Issuing tokens to users
  • Sending tokens to users

Copyright:

+===================================================+
|                 © 2019 Privex Inc.                |
|               https://www.privex.io               |
+===================================================+
|                                                   |
|        CryptoToken Converter                      |
|                                                   |
|        Core Developer(s):                         |
|                                                   |
|          (+)  Chris (@someguy123) [Privex]        |
|                                                   |
+===================================================+
address_valid(address) → bool[source]

If an account ( address param) exists on Bitshares, will return True. Otherwise False.

balance(address: str = None, memo: str = None, memo_case: bool = False) → decimal.Decimal[source]

Get token balance for a given Bitshares account, if memo is given - get total symbol amt received with this memo.

Parameters:
  • address – Bitshares account to get balance for, if not set, uses self.coin.our_account
  • memo – If not None, get total self.symbol received with this memo.
  • memo_case – Case sensitive memo search
Raises:

AccountNotFound – The requested account/address doesn’t exist

Returns:

Decimal(balance)

get_deposit() → tuple[source]

Returns the deposit account for this symbol

Return tuple:A tuple containing (‘account’, receiving_account). The memo must be generated by the calling function.
health() → Tuple[str, tuple, tuple][source]

Return health data for the passed symbol.

Health data will include: symbol, status, API node, symbol issuer, symbol precision, our account for transacting with this symbol, and our account’s balance of this symbol

Return tuple health_data:
 (manager_name:str, headings:list/tuple, health_data:list/tuple,)
health_test() → bool[source]

Check if the Bitshares API and node connection works or not, by requesting basic information such as the token metadata, and checking if our sending/receiving account exists.

Return bool:True if Bitshares appears to be working, False if broken.
is_amount_above_minimum(amount: decimal.Decimal, precision: int) → bool[source]

Helper function to test if amount is at least equal to the minimum allowed fractional unit of our token. Returns True if so, otherwise False.

issue(amount: decimal.Decimal, address: str, memo: str = None, trigger_data=None) → dict[source]

Issue (create/print) tokens to a given address/account, optionally specifying a memo if desired. The network transaction fee for issuance will be paid by the issuing account in BTS.

Example - Issue 5.10 SGTK to @privex

>>> s = BitsharesManager('SGTK')
>>> s.issue(address='privex', amount=Decimal('5.10'))
Parameters:
  • amount (Decimal) – Amount of tokens to issue, as a Decimal
  • address – Account to issue the tokens to (which is also the issuer account)
  • memo – Optional memo for the issuance transaction
Raises:
  • IssuerKeyError – Cannot issue because we don’t have authority to (missing key etc.)
  • TokenNotFound – When the requested token symbol does not exist
  • AccountNotFound – The requested account doesn’t exist
  • ArithmeticError – When the amount is lower than the lowest amount allowed by the token’s precision
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 issued,
    fee:Decimal    - TX Fee that was taken from the amount (will be 0 if fee is in BTS rather than the issuing token),
    from:str       - The account/address the coins were issued from,
    send_type:str       - Should be statically set to "issue"
}
provides

This attribute is automatically generated by scanning for models.Coin s with the type bitshares. This saves us from hard coding specific coin symbols. See __init__.py for populating code.

send(amount, address, memo=None, from_address=None, trigger_data=None) → dict[source]

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 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')
Parameters:
  • amount (Decimal) – Amount of tokens to send, as a Decimal()
  • address – Account to send the tokens to
  • from_address – Account to send the tokens from
  • memo – Memo to send tokens with
Raises:
  • AttributeError – When both from_address and self.coin.our_account are blank.
  • ArithmeticError – When the amount is lower than the lowest amount allowed by the token’s precision (after subtracting the network transaction fee)
  • AuthorityMissing – Cannot send because we don’t have authority to (missing key etc.)
  • AccountNotFound – The requested account/address doesn’t exist
  • TokenNotFound – When the requested token symbol does not exist
  • 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"
}
send_or_issue(amount, address, memo=None, trigger_data=None) → dict[source]

Send tokens to a given account, optionally specifying a memo. If the balance of the sending account is too low, try to issue new tokens to ourself first. See documentation for the BitsharesManager.BitsharesManager.send() and BitsharesManager.BitsharesManager.issue() functions for more details.

send_type in the returned dict will be either ‘send’ or ‘issue’ depending on the operation performed

BitsharesMixin module

Copyright:

+===================================================+
|                 © 2019 Privex Inc.                |
|               https://www.privex.io               |
+===================================================+
|                                                   |
|        CryptoToken Converter                      |
|                                                   |
|        Core Developer(s):                         |
|                                                   |
|          (+)  Chris (@someguy123) [Privex]        |
|                                                   |
+===================================================+
class payments.coin_handlers.Bitshares.BitsharesMixin.BitsharesMixin[source]

Bases: object

BitsharesMixin - A class that provides shared functionality used by both BitsharesLoader and BitsharesManager.

Main features:

- Access the BitShares shared instance via :py:attr:`.bitshares`
- Access the Blockchain shared instance via :py:attr:`.blockchain`
- Safely get Bitshares network data (account data, asset data, and block timestamps)

Copyright:

+===================================================+
|                 © 2019 Privex Inc.                |
|               https://www.privex.io               |
+===================================================+
|                                                   |
|        CryptoToken Converter                      |
|                                                   |
|        Core Developer(s):                         |
|                                                   |
|          (+)  Chris (@someguy123) [Privex]        |
|                                                   |
+===================================================+
bitshares

Returns an instance of BitShares and caches it in the attribute _bitshares after creation

blockchain

Returns an instance of Blockchain and caches it in the attribute _blockchain after creation

get_account_obj(account_name) → bitshares.account.Account[source]

If an account exists on Bitshares, will return a bitshares.account.Account object. Otherwise None.

Parameters:account_name – Bitshares account to get data for

:return Account or None

get_asset_obj(symbol) → bitshares.asset.Asset[source]

If a token symbol exists on Bitshares, will return a bitshares.asset.Asset object. Otherwise None.

Parameters:symbol – Bitshares token to get data for (can be symbol name or id)

:return Asset or None

get_block_timestamp(block_number) → int[source]

Given a block number, returns the timestamp of that block. If block number is invalid or an error happens, returns 0.

Parameters:block_number – block number to get data for

:return int

get_decimal_from_amount(amount_obj: bitshares.amount.Amount) → decimal.Decimal[source]

Helper function to convert a Bitshares Amount object into a Decimal

get_private_key(account_name, key_type) → str[source]

Find the Bitshares models.CryptoKeyPair in the database for a given account account_name and key type ‘key_type’ (e.g. ‘active’ or ‘memo’), decrypt the private key, then return the plaintext key.

If no matching key could be found, will raise an AuthorityMissing exception.

Parameters:
  • account_name (str) – The Bitshares account to find a private key for
  • key_type (str) – Key type to search for. Can be ‘active’, ‘memo’, or ‘owner’
Raises:
  • AuthorityMissing – No key could be found for the given account_name
  • EncryptKeyMissing – CTC admin did not set ENCRYPT_KEY in their .env, or it is invalid
  • EncryptionError – Something went wrong while decrypting the private key (maybe ENCRYPT_KEY is invalid)
Return str key:

the plaintext key

set_wallet_keys(account_name, key_types: List[str])[source]

Retrieves a models.CryptoKeyPair for a given account account_name and each key type specified in the key_types list (e.g. ‘active’ or ‘memo’). Each private key is then decrypted and added to the underlying Bitshares wallet for use in transactions.

If no matching key could be found, will raise an AuthorityMissing exception.

Parameters:
  • account_name (str) – The Bitshares account to set keys for
  • key_types (List) – Key types to search for. Can include ‘active’, ‘memo’, or ‘owner’
Raises:
  • AuthorityMissing – A key could be found for the given account_name
  • EncryptKeyMissing – CTC admin did not set ENCRYPT_KEY in their .env, or it is invalid
  • EncryptionError – Something went wrong while decrypting the private key (maybe ENCRYPT_KEY is invalid)