Welcome to steempy’s documentation!

Steem is a blockchain-based autonomous company (i.e. a DAC) that offers decentralized exchanging as well as sophisticated financial instruments as products.

It is based on Graphene (tm), a blockchain technology stack (i.e. software) that allows for fast transactions and ascalable blockchain solution. In case of Steem, it comes with decentralized trading of assets as well as customized on-chain smart contracts.

About this Library

The purpose of steempy is to simplify development of products and services that use the Steem blockchain. It comes with

  • it’s own (bip32-encrypted) wallet
  • RPC interface for the Blockchain backend
  • JSON-based blockchain objects (accounts, blocks, prices, markets, etc)
  • a simple to use yet powerful API
  • transaction construction and signing
  • push notification API
  • and more

Quickstart

Note

All methods that construct and sign a transaction can be given

the account= parameter to identify the user that is going to affected by this transaction, e.g.:

  • the source account in a transfer
  • the accout that buys/sells an asset in the exchange
  • the account whos collateral will be modified

Important, If no account is given, then the default_account according to the settings in config is used instead.

from steempy import Steem
steem = Steem()
steem.wallet.unlock("wallet-passphrase")
steem.transfer("<to>", "<amount>", "<asset>", "<memo>", account="<from>")
from steempy.blockchain import Blockchain
blockchain = Blockchain()
for op in Blockchain.ops():
    print(op)
from steempy.block import Block
print(Block(1))
from steempy.account import Account
account = Account("test")
print(account.balances)
for h in account.history():
    print(h)
from steempy.market import Market
# Not working at the moment
# market = Market("STEEM:SBD")
# print(market.ticker())
# market.steem.wallet.unlock("wallet-passphrase")
# print(market.sell(300, 100)  # sell 100 STEEM for 300 STEEM/SBD
from steempy.dex import Dex
# not working at the moment
# dex = Dex()
# dex.steem.wallet.unlock("wallet-passphrase")

General

Installation

Installation

Install with pip3:

$ sudo apt-get install libffi-dev libssl-dev python-dev
$ pip3 install steempy

or the with pip:

$ pip install -U steempy

Manual installation:

$ git clone https://github.com/holgern/steempy/
$ cd steempy
$ python setup.py build
$ python setup.py install --user

Upgrade

$ pip install --user --upgrade

Quickstart

Tutorials

Bundle Many Operations

With Steem, you can bundle multiple operations into a single transactions. This can be used to do a multi-send (one sender, multiple receivers), but it also allows to use any other kind of operation. The advantage here is that the user can be sure that the operations are executed in the same order as they are added to the transaction.

from pprint import pprint
from steempy import Steem

testnet = Steem(
    "wss://testnet.steem.vc",
    nobroadcast=True,
    bundle=True,
)

testnet.wallet.unlock("supersecret")

testnet.transfer("test1", 1, "STEEM", account="test")
testnet.transfer("test1", 1, "STEEM", account="test")
testnet.transfer("test1", 1, "STEEM", account="test")
testnet.transfer("test1", 1, "STEEM", account="test")

pprint(testnet.broadcast())

Proposing a Transaction

In Steem, you can propose a transactions to any account. This is used to facilitate on-chain multisig transactions. With python-steem, you can do this simply by using the proposer attribute:

from pprint import pprint
from steempy import Steem

testnet = Steem(
    "wss://testnet.steem.vc",
    proposer="test"
)
testnet.wallet.unlock("supersecret")
pprint(testnet.transfer("tst1", 1, "STEEM", account="test"))

Simple Sell Script

from steempy import Steem
from steempy.market import Market
from steempy.price import Price
from steempy.amount import Amount

#
# Instanciate Steem (pick network via API node)
#
steem = Steem(
    "wss://node.testnet.steem.eu",
    nobroadcast=True   # <<--- set this to False when you want to fire!
)

#
# Unlock the Wallet
#
steem.wallet.unlock("<supersecret>")

#
# This defines the market we are looking at.
# The first asset in the first argument is the *quote*
# Sell and buy calls always refer to the *quote*
#
market = Market(
    "GOLD:USD",
    steem_instance=steem
)

#
# Sell an asset for a price with amount (quote)
#
print(market.sell(
    Price(100.0, "USD/GOLD"),
    Amount("0.01 GOLD")
))

Sell at a timely rate

import threading
from steempy import Steem
from steempy.market import Market
from steempy.price import Price
from steempy.amount import Amount


def sell():
    """ Sell an asset for a price with amount (quote)
    """
    print(market.sell(
        Price(100.0, "USD/GOLD"),
        Amount("0.01 GOLD")
    ))

    threading.Timer(60, sell).start()


if __name__ == "__main__":
    #
    # Instanciate Steem (pick network via API node)
    #
    steem = Steem(
        "wss://node.testnet.steem.eu",
        nobroadcast=True   # <<--- set this to False when you want to fire!
    )

    #
    # Unlock the Wallet
    #
    steem.wallet.unlock("<supersecret>")

    #
    # This defines the market we are looking at.
    # The first asset in the first argument is the *quote*
    # Sell and buy calls always refer to the *quote*
    #
    market = Market(
        "GOLD:USD",
        steem_instance=steem
    )

    sell()

Configuration

The pysteem library comes with its own local configuration database that stores information like

  • API node URL
  • default account name
  • the encrypted master password

and potentially more.

You can access those variables like a regular dictionary by using

from steempy import Steem
steem = Steem()
print(steem.config.items())

Keys can be added and changed like they are for regular dictionaries.

If you don’t want to load the steem.Steem class, you can load the configuration directly by using:

from steempy.storage import configStorage as config

API

Contributing to python-steem

We welcome your contributions to our project.

Repository

The main repository of python-steem is currently located at:

Flow

This project makes heavy use of git flow. If you are not familiar with it, then the most important thing for your to understand is that:

pull requests need to be made against the develop branch

How to Contribute

  1. Familiarize yourself with contributing on github <https://guides.github.com/activities/contributing-to-open-source/>
  2. Fork or branch from the master.
  3. Create commits following the commit style
  4. Start a pull request to the master branch
  5. Wait for a @holger80 or another member to review

Issues

Feel free to submit issues and enhancement requests.

Contributing

Please refer to each project’s style guidelines and guidelines for submitting patches and additions. In general, we follow the “fork-and-pull” Git workflow.

  1. Fork the repo on GitHub
  2. Clone the project to your own machine
  3. Commit changes to your own branch
  4. Push your work back up to your fork
  5. Submit a Pull request so that we can review your changes

NOTE: Be sure to merge the latest from “upstream” before making a pull request!

Support and Questions

We have currently not setup a distinct channel for development around pysteemi. However, many of the contributors are frequently reading through these channels:

steempy Libraries

Steem

The Steem library has been designed to allow developers to easily access its routines and make use of the network without dealing with all the related blockchain technology and cryptography. This library can be used to do anything that is allowed according to the Steem blockchain protocol.

Instances

Default instance to be used when no steem_instance is given to the Objects!

from steempy.instance import shared_steem_instance

account = Account("test")
# is equivalent with
account = Account("test", steem_instance=shared_steem_instance())

Account

Obtaining data of an account.

from steempy.account import Account
account = Account("test")
print(account)
print(account.balances)

Amount

For the sake of easier handling of Assets on the blockchain

from steempy.amount import Amount
from steempy.asset import Asset
a = Amount("1 USD")
b = Amount(1, "USD")
c = Amount("20", Asset("USD"))
a + b
a * 2
a += b
a /= 2.0

Asset

Block

Easily read data in a Block

from steempy.block import Block
from pprint import pprint
pprint(Block(1))

Blockchain

Read blockchain related data-

from steempy.blockchain import Blockchain
chain = Blockchain()

Read current block and blockchain info

print(chain.get_current_block())
print(chain.info())

Monitor for new blocks ..

for block in chain.blocks():
    print(block)

… or each operation individually:

for operations in chain.ops():
    print(operations)

Exceptions

Market

Notify

This modules allows yout to be notified of events taking place on the blockchain.

Price

Witness

Read data about a witness

from steempy.witness import Witness
Witness("gtg")

Low Level Classes

Storage

These classes are very low level and are not well documented.

API

Utilities

Transaction Builder

To build your own transactions and sign them

from steempy.transactionbuilder import TransactionBuilder
from steempybase.operations import Transfer
tx = TransactionBuilder()
tx.appendOps(Transfer(**{
         "from": "test",
         "to": "test1",
         "amount": "1 STEEM",
         "memo": ""
     }))
tx.appendSigner("test", "active")
tx.sign()
tx.broadcast()

Wallet

Create a new wallet

A new wallet can be created by using:

from steempy import Steem
steem = Steem()
steem.wallet.create("supersecret-passphrase")

This will raise an exception if you already have a wallet installed.

Unlocking the wallet for signing

The wallet can be unlocked for signing using

from steempy import Steem
steem = Steem()
steem.wallet.unlock("supersecret-passphrase")

Adding a Private Key

A private key can be added by using the steem.wallet.Wallet.addPrivateKey() method that is available after unlocking the wallet with the correct passphrase:

from steempy import Steem
steem = Steem()
steem.wallet.unlock("supersecret-passphrase")
steem.wallet.addPrivateKey("5xxxxxxxxxxxxxxxxxxxx")

Note

The private key has to be either in hexadecimal or in wallet import format (wif) (starting with a 5).

API

SteemWebsocket

This class allows subscribe to push notifications from the Steem node.

from pprint import pprint
from steempyapi.websocket import SteemWebsocket

ws = SteemWebsocket(
    "wss://gtg.steem.house:8090",
    accounts=["test"],
    # on_market=pprint,
    # on_block=print,
    on_account=print,
)

ws.run_forever()

Defintion

SteemNodeRPC

This class allows to call API methods exposed by the witness node via websockets.

Defintion

Manual Constructing and Signing of Transactions

Warning

This is a low level class. Do not use this class unless you know what you are doing!

Note

This class is under development and meant for people that are looking into the low level construction and signing of various transactions.

Loading Transactions Class

We load the class for manual transaction construction via:

from steempybase import transactions, operations

Construction

Now we can use the predefined transaction formats, e.g. Transfer or limit_order_create as follows:

  1. define the expiration time
  2. define a JSON object that contains all data for that transaction
  3. load that data into the corresponding operations class
  4. collect multiple operations
  5. get some blockchain parameters to prevent replay attack
  6. Construct the actual transaction from the list of operations
  7. sign the transaction with the corresponding private key(s)

Example A: Transfer

expiration = transactions.formatTimeFromNow(60)
op = operations.Transfer(**{
    "from": "test",
    "to": "test1",
    "amount": "1.000 SBD",
    "memo": ""
})
ops    = [transactions.Operation(op)]
ref_block_num, ref_block_prefix = transactions.getBlockParams(rpc)
tx     = transactions.Signed_Transaction(ref_block_num=ref_block_num,
                                         ref_block_prefix=ref_block_prefix,
                                         expiration=expiration,
                                         operations=ops)
tx = tx.sign([wif])

Broadcasting

For broadcasting, we first need to convert the transactions class into a JSON object. After that, we can broadcast this to the network:

# Broadcast JSON to network
rpc.broadcast_transaction(tx.json(), api="network_broadcast"):

Memo

Memo Keys

In BitShares, memos are AES-256 encrypted with a shared secret between sender and receiver. It is derived from the memo private key of the sender and the memo publick key of the receiver.

In order for the receiver to decode the memo, the shared secret has to be derived from the receiver’s private key and the senders public key.

The memo public key is part of the account and can be retreived with the get_account call:

get_account <accountname>
{
  [...]
  "options": {
    "memo_key": "GPH5TPTziKkLexhVKsQKtSpo4bAv5RnB8oXcG4sMHEwCcTf3r7dqE",
    [...]
  },
  [...]
}

while the memo private key can be dumped with dump_private_keys

Memo Message

The take the following form:

{
  "from": "GPH5mgup8evDqMnT86L7scVebRYDC2fwAWmygPEUL43LjstQegYCC",
  "to": "GPH5Ar4j53kFWuEZQ9XhxbAja4YXMPJ2EnUg5QcrdeMFYUNMMNJbe",
  "nonce": "13043867485137706821",
  "message": "d55524c37320920844ca83bb20c8d008"
}

The fields from and to contain the memo public key of sender and receiver. The nonce is a random integer that is used for the seed of the AES encryption of the message.

Example

Encrypting a memo

The high level memo class makes use of the pysteem wallet to obtain keys for the corresponding accounts.

from steempy.memo import Memo
from steempy.account import Account

memoObj = Memo(
    from_account=Account(from_account),
    to_account=Account(to_account)
)
encrypted_memo = memoObj.encrypt(memo)
Decoding of a received memo
from getpass import getpass
from steempy.block import Block
from steempy.memo import Memo

# Obtain a transfer from the blockchain
block = Block(23755086)                   # block
transaction = block["transactions"][3]    # transactions
op = transaction["operations"][0]         # operation
op_id = op[0]                             # operation type
op_data = op[1]                           # operation payload

# Instantiate Memo for decoding
memo = Memo()

# Unlock wallet
memo.unlock_wallet(getpass())

# Decode memo
# Raises exception if required keys not available in the wallet
print(memo.decrypt(op_data["memo"]))

API

Glossary

Indices and tables