GithubHelp home page GithubHelp logo

0xomara / radixlib Goto Github PK

View Code? Open in Web Editor NEW
37.0 4.0 13.0 288 KB

A Python package written to make the interaction with the Radix ledger easier.

Home Page: https://pypi.org/project/radixlib

License: MIT License

Python 100.00%
radix blockchain python cryptocurrency python3

radixlib's Introduction

Note This library has reached its end-of-life and will become an open archive with the transition from Olympia to Babylon. This library has been replaced by the Python Radix Engine Toolkit. For issues and PRs, please open them against the Radix Engine Toolkit repo.

RadixLib

PyPI version License: MIT Python 3.7 Python 3.8 Python 3.9 Python 3.10

Table of Content

Introduction

RadixLib is an API wrapper for the Radix Gateway API which allows for a quick, easy, and pythonic way to interact with the Radix blockchain directly from python. The following are some of the features offered in this python package:

  • Connecting to the Radix blockchain through the Gateway API.
  • Connecting to custom Radix networks (i.e. stokenet, localnet, devnets or any custom network.)
  • Querying the Gateway API for information (example: account balances, transactions, etc...)
  • Building, signing, and submitting transactions to the blockchain.
  • Creating signers to hold the seed phrase and derive public and private keys.
  • Loading signers from the mnemonic phrase, seed phrase or the wallet.json from the Radix desktop wallet.
  • Creating signers from random mnemonic phrases.
  • A powerful derivations module for all kinds of derivations needed in Radix.

The features listed above are only a small subset of the features offered by this python package. This wrapper is fully compatible with the Gateway API which means that all of the operations that can be done through the Gateway API are supported by this package. This package offerers so much more and can in theory be used to build a python version of the Radix desktop wallet.

Installing the Package

The radixlib package is available on pypi which means that it can be installed through pip. Alternatively, the package may be installed and setup from the source code. The sections below outline how these two methods may be carried out.

Method 1: Setting up the package through pip and PyPI

The installation of this package through pip is as simple as running the following command

python3 -m pip3 install radixlib

After running the above command, you should find that the radixlib package is now installed to the python interpreter that you're currently using.

Method 2: Setting up the package from source

To setup this package from the source code you may begin by cloning this repository to your local machine and then running the setup script. You may do that through the following commands:

git clone -b master https://github.com/0xOmarA/RadixLib
cd RadixLib
python3 setup.py install

After installing the package through one of the methods outlined above, you can check if the package has been installed correctly or not by running pip freeze and checking if radixlib is listed there or not.

Getting Started

In this section of the document, a series of simple examples are given to help you get started using this package. More detailed and indepth examples are provided in the examples directory.

With the package installed, you are now ready to begin using this package and the functionality that it has. One thing to note is that the name that this package uses in python is the same as the name it uses on Github and on mypy; meaning, that if we were to import this package into our python script, we may do so using the following code:

import radixlib

However, throughout this code and in the examples, the name of the package import is changed to radix upon import to make the package somewhat easier to use a little bit less verbose. So, you will often see this package imported in the following manner:

import radixlib as radix

Loading Your Wallet

The very first example that we will be looking at here is how can you load your wallet using this packahe into your python code. There are three main methods which you may use to load your wallet:

  • Through the mnemonic phrase
  • Through the seed
  • Through the wallet.json file obtained from the Radix desktop wallet

The following three examples go through how loading your wallet may be done through all three of the above-mentioned methods:

Method 1: Loading your wallet through the mnemonic phrase

import radixlib as radix

def main() -> None:
    # The network that we will be connecting the wallet to
    network: radix.network.Network = radix.network.MAINNET

    # The mnemonic phrase we will be using to load the wallet
    mnemonic_phrase: str = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"

    # Loading the wallet from the mnemonic phrase
    wallet: radix.Wallet = radix.Wallet(
        provider = radix.Provider(network),
        signer = radix.Signer.from_mnemonic(mnemonic_phrase)
    )
    print("Wallet address:", wallet.address)

if __name__ == "__main__":
    main()

To load a wallet through the mnemonic phrase the first thing that we do is define the network that we will be connecting to (for the purpose of this example we connect to the radix mainnet) and then we define the mnemonic phrase that we will be using for the wallet. Finally, the radix.Wallet object is instantiated through the provider and the signer.

In this case, the network variable is used to inform the provider of the network and the url of the gateway API to communicate with, and the mnemonic phrase is used by the signer to derive the seed and eventually the public and private keys of the wallet.

Method 2: Loading your wallet through the seed

import radixlib as radix

def main() -> None:
    # The network that we will be connecting the wallet to
    network: radix.network.Network = radix.network.MAINNET

    # The seed phrase that the signer will be using for the wallet
    # Don't worry, this is the seed phrase of the abandon wallet so I'm not exposing any sensitive 
    # info ;)
    seed: str = "94cfb81f135f8d85d787a84173cf1e9fc51792f3723e2b93a162fa57a03370fd80971d026eed300544116dfee4d5b375c77ea86b65dfd44e2ecda58044684fe0"

    # Loading the wallet from the mnemonic phrase
    wallet: radix.Wallet = radix.Wallet(
        provider = radix.Provider(network),
        signer = radix.Signer(seed)
    )
    print("Wallet address:", wallet.address)

if __name__ == "__main__":
    main()

As you might notice, the code used for this second method is almost identical to that used in the first method. However, there are two main differences here:

  • We're now using the seed to create our Signer object instead of using the mnemonic.
  • We're instantiating the Signer through the class constructor and not through a class function.

Aside from the above-mentioned differences, the code for the previous method and this method is identical.

Method 3: Loading your wallet through the wallet.json

You might be wondering "what exactly is a wallet.json file?" and you would be right to ask that question. In short, wallet.json is a file that the Radix desktop wallet produces where your mnemonic phrase is encrypted using your wallet passphrase. You may find more information about the wallet.json file and it's format in this amazing article written by Stuart from RadixPool.com.

To load up a Radix.Wallet object from the wallet.json file, you may use the following code:

import radixlib as radix

def main() -> None:
    # The network that we will be connecting the wallet to
    network: radix.network.Network = radix.network.MAINNET

    # The path to your wallet.json file and the passphrase used by the Radix desktop wallet
    wallet_json_path: str = "./wallet.json"
    passphrase: str = "MyUltraSuperSecurePassword1234"

    # Loading the wallet from the mnemonic phrase
    wallet: radix.Wallet = radix.Wallet(
        provider = radix.Provider(network),
        signer = radix.Signer.from_wallet_json(wallet_json_path, passphrase),
    )
    print("Wallet address:", wallet.address)

if __name__ == "__main__":
    main()

In this case, we are using the path to the wallet.json file as well as the passphrase which the Radix wallet uses to encrypt the contents of the file as arguments to the radix.Signer.from_wallet_json method to create the signer that we will be using for the wallet object.

Query for Account Balance

Now that we have discussed how a radix.Wallet object may be instantiated, we may now begin to dive deeper into what the radix.Wallet object offers and what it gives us. One of the things that the radix.Wallet object allows for is an easy way to query the gateway API for the balance of the currently loaded account.

To demonstrate querying for the account balance may be done, we will take the code from Method 1: Loading your wallet through the mnemonic phrase and extend it to allow for the added functionality. The modified code is as follows:

from typing import Dict
import radixlib as radix

def main() -> None:
    # The network that we will be connecting the wallet to
    network: radix.network.Network = radix.network.MAINNET

    # The mnemonic phrase we will be using to load the wallet
    mnemonic_phrase: str = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"

    # Loading the wallet from the mnemonic phrase
    wallet: radix.Wallet = radix.Wallet(
        provider = radix.Provider(network),
        signer = radix.Signer.from_mnemonic(mnemonic_phrase)
    )
    print("Wallet address:", wallet.address)

    # Getting the balance for the currently loaded account
    balances: Dict[str, Dict[str, int]] = wallet.get_account_balances()
    print("Wallet balances:", balances)

if __name__ == "__main__":
    main()

The only section that was added in this code is a call to the wallet.get_account_balances method which gets the balances of all of the tokens that the account currently holds.

Query for Account Transactions

Another typical thing which you might want to do is to query for the transaction history for your account. This is very simple to do using the radixlib package.

Extending upon the code from the previous example, we may get the last 30 transactions involving our account through the code below:

from typing import Tuple, List, Dict, Any
import radixlib as radix

def main() -> None:
    # The network that we will be connecting the wallet to
    network: radix.network.Network = radix.network.MAINNET

    # The mnemonic phrase we will be using to load the wallet
    mnemonic_phrase: str = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"

    # Loading the wallet from the mnemonic phrase
    wallet: radix.Wallet = radix.Wallet(
        provider = radix.Provider(network),
        signer = radix.Signer.from_mnemonic(mnemonic_phrase)
    )
    print("Wallet address:", wallet.address)

    # Getting the balance for the currently loaded account
    balances: Dict[str, Dict[str, int]] = wallet.get_account_balances()
    print("Wallet balances:", balances)

    # Getting the last 30 transactions on the currently loaded account
    _, transactions = wallet.get_account_transactions(limit=30)
    print("Transactions:", transactions)

if __name__ == "__main__":
    main()

Getting the last 30 transactions that our account was involved in was as simple as calling the wallet.get_account_transactions method with the argument limit set to 30.

Additional More Detailed Examples

The examples that you've seen here are some simple examples which might be helpful for you to get started using this package. You might want to checkout the examples in the examples directory of the repo for more detailed examples where more interesting concepts such as sending transactions is showcased and explained.

Acknowledgement

Thank you to everybody who has helped make this package possible from the Radix team and from the community. Special thanks to Stuart from RadixPool.com for his amazing efforts and write ups on the technical side of Radix.

Licence: MIT

Copyright (c) 2022 0xOmarA

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

radixlib's People

Contributors

0xomara avatar kevinforrestconnors 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

Watchers

 avatar  avatar  avatar  avatar

radixlib's Issues

How do you build a large multi action transaction?

On examples/6- multi-action transactions/main.py you show sending XRD to 3 addresses, but the action was built manually 1-2-3. Is it possible to loop through hundreds of addresses and built this action without writing them all out? Thanks!

unknown error

Hi Omar, any idea what this error might be caused from? From my side, it's possible there were simultaneous token sends, and not enough pause in between them (that old issue that caused us to use 4 second delay between any sends). But wasn't sure if this was the same error ..

query_response: Dict[str, Any] = provider.get_account_transactions( File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/provider.py", line 261, in get_account_transactions return self.__dispatch( File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/provider.py", line 95, in __dispatch response: requests.Response = requests.request( File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/api.py", line 61, in request return session.request(method=method, url=url, **kwargs) File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/sessions.py", line 529, in request resp = self.send(prep, **send_kwargs) File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/sessions.py", line 645, in send r = adapter.send(request, **kwargs) File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/adapters.py", line 501, in send raise ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))

Token definition error during parsing

Just parsing transaction history, and it's throwing this error.

  File "/home/ubuntu/NattyRadishesReservationTracker/main.py", line 499, in getTransactionHistory
    parsed_transaction_list: List[Dict[str, Any]] = radix.parsers.DefaultParser.parse(
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/parsers/default_parser.py", line 40, in parse
    parsed_data: Any = parsing_function(data) # type: ignore
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/parsers/default_parser.py", line 258, in parse_get_account_transactions
    return list(map(
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/parsers/default_parser.py", line 259, in <lambda>
    lambda x: cls.parse({'transaction': x}, 'transaction_status'),
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/parsers/default_parser.py", line 40, in parse
    parsed_data: Any = parsing_function(data) # type: ignore
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/parsers/default_parser.py", line 621, in parse_transaction_status
    "actions": list(map(
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/parsers/default_parser.py", line 622, in <lambda>
    lambda x: getattr(radix.actions, x['type']).from_dict(x), 
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/actions/create_token_definition.py", line 146, in from_dict
    return cls(
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/actions/create_token_definition.py", line 70, in __init__
    raise ValueError(
ValueError: You must specify 'token_supply' and the 'to_account' arguments when creating a fixed supply token and remove the specification for the token owner.

My code is:

while True:
            query_response: Dict[str, Any] = provider.get_account_transactions(
                account_address = wallet_address,
                cursor = cursor
            )
            parsed_transaction_list: List[Dict[str, Any]] = radix.parsers.DefaultParser.parse(
                data = query_response,
                data_type = "get_account_transactions"
            )
            transactions_list.extend(parsed_transaction_list)
            cursor = query_response.get('next_cursor')
            if cursor is None:
                break

Duplicate code in Signer.from_mnemonic

It looks like the code referenced in the link below does the same thing twice just in different ways.

# If the supplied mnemonic phrase is a list then convert it to a string
if isinstance(mnemonic_phrase, (list, tuple)):
mnemonic_string: str = " ".join(mnemonic_phrase)
else:
mnemonic_string: str = mnemonic_phrase
mnemonic_string: str = " ".join(mnemonic_phrase) if isinstance(mnemonic_phrase,
(list, tuple)) else mnemonic_phrase

trying to figure out this bug coming from provider.py

Any ideas? I've updated to the latest.

transactions_list = getTransactionHistory(wallet_addresses)
  File "/home/ubuntu/NattyRadishesReservationTracker/main.py", line 495, in getTransactionHistory
    query_response: Dict[str, Any] = provider.get_account_transactions(
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/provider.py", line 261, in get_account_transactions
    return self.__dispatch(
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/radixlib/provider.py", line 95, in __dispatch
    response: requests.Response = requests.request(
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/sessions.py", line 529, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/sessions.py", line 687, in send
    r.content
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/models.py", line 838, in content
    self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b''
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/requests/models.py", line 763, in generate
    raise ChunkedEncodingError(e)
requests.exceptions.ChunkedEncodingError: ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))
Traceback (most recent call last):
  File "/home/ubuntu/NattyRadishesReservationTracker/env/lib/python3.9/site-packages/urllib3/response.py", line 697, in _update_chunk_length
    self.chunk_left = int(line, 16)
ValueError: invalid literal for int() with base 16: b''

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.