Listing transactions and spending funds

From wallet perspective transactions can be generally grouped into incoming and outgoing. This is just a convenience, as almost every outgoing transaction has a change amount that goes back to the originating wallet.

Listing transactions

Retrieving the history of the wallet is pretty straightforward:

In [8]: txns = wal.transactions()

In [9]: txns[0].txid
Out[9]: '88633270f854eea5b2f35a863d748b294299deecf62ec9629ff08fca87fff45c'

In [10]: txns[0].amount_out
Out[10]: Decimal('1.000000')

In [11]: txns[0].fee
Out[11]: Decimal('0.168801')

In [12]: txns[1].txid
Out[12]: '0b048162778e29e98d833d948a3be7f18f9ce8693d7ee407c7d38b6ef2a5a264'

As you probably noticed, the amounts are given in ADA as Python Decimal type, which is perfect for monetary operations.

Narrowing down the query

In order to limit the number of results you may ask for transactions meeting special criteria.

The most important, perhaps, is the txid argument which accepts single IDs as well as sequences thereof. So, both

wal.transactions(txid="0b048162778e29e98d833d948a3be7f18f9ce8693d7ee407c7d38b6ef2a5a264")

as well as

wal.transactions(txid=[
    "0b048162778e29e98d833d948a3be7f18f9ce8693d7ee407c7d38b6ef2a5a264",
    "88633270f854eea5b2f35a863d748b294299deecf62ec9629ff08fca87fff45c"]
    )

are valid queries.

Blockchain position

The transaction filter accepts parameters filtering against the position in the ledger. min_epoch, max_epoch, min_slot, max_slot, min_absolute_slot, max_absolute_slot, min_height and max_height can be used and combined.

Ranges combining different criteria may be applied in the same call, e.g. to ask only for the first 10 slots of epoch 230 would be

wal.transactions(min_epoch=230, max_epoch=230, max_slot=10)

Because both epochs and slots are precisely defined periods of time, querying for them is like asking for quite precise timestamp of mining of the transaction’s block. In contrast, asking for height considers the actual number of blocks since the genesis, as not all slots have been used to generate a block.

Mempool

Even though the mempool life part of Cardano transactions is usually very short, it is possible to ask for transactions not in ledger, as well as to exclude them from the results.

To include mempool, use unconfirmed=True. To include mined transactions, use confirmed=True. False values exclude these types of transactions from the results.

By default, unconfirmed=False and confirmed=True which means the default settings ask only for transactions in the ledger.

Filtering by address

Arguments src_addr and dest_addr filter for source and destination addresses, respectively. They can be used to ask for single or multiple addresses, just like txid described above.

Note

Please be aware that this kind of query is not very reliable. cardano-wallet is known to return incomplete input/output data, missing the address info.

Spending funds

In order to spend funds, you need to specify the destination address, amount (as Decimal or int) and provide the passphrase if you haven’t done so when initializing the Wallet object.

In [17]: tx = wal.transfer(
    "addr_test1qqr585tvlc7ylnqvz8pyqwauzrdu0mxag3m7q56grgmgu7sxu2hyfhlkwuxupa9d5085eunq2qywy7hvmvej456flknswgndm3",
    7,
    passphrase="xxx")

In [18]: tx.txid
Out[18]: 'a7a16a0653a6a397eb822ff8a3f610b5dabc82c5da2425fcc267f983f0edec88'

In [19]: tx.amount_in
Out[19]: Decimal('0.000000')

In [20]: tx.amount_out
Out[20]: Decimal('7.000000')

In [21]: tx.fee
Out[21]: Decimal('0.168801')

Another useful function is Wallet.transfer_multiple which accepts more than one destination for a single transaction. It is useful for aggregating payouts and reducing fee costs. The difference from the previous method is that it accepts a sequence of (address, amount) pairs.

In [23]: tx = wallet.transfer_multiple(
        (
            (
                "addr_test1qqr585tvlc7ylnqvz8pyqwauzrdu0mxag3m7q56grgmgu7sxu2hyfhlkwuxupa9d5085eunq2qywy7hvmvej456flknswgndm3",
                Decimal("1.234567"),
            ),
            (
                "addr_test1qqd86dlwasc5kwe39m0qvu4v6krd24qek0g9pv9f2kq9x28d56vd3zqzthdaweyrktfm3h5cz4je9h5j6s0f24pryswqgepa9e",
                Decimal("2.345678"),
            ),
        ),
        passphrase="xxx",
    )

In [24]: tx.txid
Out[24]: 'a7a16a0653a6a397eb822ff8a3f610b5dabc82c5da2425fcc267f983f0edec88'

In [25]: tx.amount_in
Out[25]: Decimal('0.000000')

In [26]: tx.amount_out
Out[26]: Decimal('3.580245')

In [27]: tx.fee
Out[27]: Decimal('0.168801')

Of course the list of destinations can have a single element. In fact, the transfer() method is just a shortcut for transfer_multiple() to make single payments easier.

Estimating fees

The Wallet object also offers method which estimates fee for transaction. The signature is similar to transfer_multiple(). It accepts a list of payments to be made and optionally the metadata, and returns a tuple of estimated minimum and maximum fee for the eventual transaction.

In [23]: f = wal.estimate_fee(
        (
            ("addr_test1qqr585tvlc7ylnqvz8pyqwauzrdu0mxag3m7q56grgmgu7sxu2hyfhlkwuxupa9d5085eunq2qywy7hvmvej456flknswgndm3",
            Decimal("1.234567")),
            ("addr_test1qqd86dlwasc5kwe39m0qvu4v6krd24qek0g9pv9f2kq9x28d56vd3zqzthdaweyrktfm3h5cz4je9h5j6s0f24pryswqgepa9e",
            Decimal("2.345678")),
        ))

In [24]: f
Out[24]: (Decimal('0.174785'), Decimal('0.180989'))

Note

Don’t forget to include metadata when estimating fees. They are based on the transaction size and additional data changes that significantly.

Metadata

Since the Shelley era, Cardano allows for adding metadata to transactions. Metadata is a mapping where keys are integers and values belong to a short list of supported data types. Description of the structure is beyond the scope of this documentation, however you may read this description or another one which includes a good test example.

Lists and dicts as map keys

While Cardano supports map objects that use another map or list as key element, this feature cannot be supported by the Python module directly. The reason is that data on blockchain is immutable (cannot be modified) while the corresponding Python objects (dict and list) are mutable, which disqualifies them as dict keys due to unstable hash value.

For that reason, substitutions have been introduced when following types of variables are used as keys:

  • list: the key on Python side is tuple,

  • dict: will be converted to ImmutableDict

Storing and retrieving metadata

Metadata can be passed to Wallet.transfer() and Wallet.transfer_multiple() methods as dict or Metadata instance. It will be instantly available in the .metadata attribute of the resulting Transaction object.

In [23]: tx = wal.transfer(
    "addr_test1qqr585tvlc7ylnqvz8pyqwauzrdu0mxag3m7q56grgmgu7sxu2hyfhlkwuxupa9d5085eunq2qywy7hvmvej456flknswgndm3",
    7,
    metadata={1: "first value", 23: "next value"},
    passphrase="xxx")

In [24]: tx.metadata
Out[24]: {1: 'first value', 23: 'next value'}

Metadata can be initialized separately by passing a list of (key, value) pairs.

In [25]: m = Metadata(((1, "first value"), (23, "next value")))

In [26]: m
Out[26]: {1: 'first value', 23: 'next value'}

Such instance can be also passed as metadata parameter to the transfer methods.

API reference

Transactions

class cardano.transaction.Input(iid=None, address=None, amount=None, assets=None)

Represents a Transaction input.

Parameters
  • iid (str hex) – the input ID

  • address (cardano.address.Address) – the origin address

  • amount (Decimal) – the amount in ADA

  • assets (list) – a sequence of AssetID quantity pairs

class cardano.transaction.Output(address=None, amount=None, assets=None)

Represents a Transaction output.

Parameters
  • address (cardano.address.Address) – the destination address

  • amount (Decimal) – the amount in ADA

  • assets (list) – a sequence of AssetID quantity pairs

class cardano.transaction.Transaction(txid=None, **kwargs)

Represents a Cardano transaction.

Parameters
  • txid – the ID of the transaction

  • fee – fee amount in ADA

  • inputs – a sequence of Input objects

  • outputs – a sequence of Output objects

  • local_inputs – a sequence of Input objects that originate from local wallet

  • local_outputs – a sequence of Output objects that are destined to local wallet

  • withdrawals – a sequence of (Decimal, str) pairs of amounts and stake addresses

  • metadata – an instance of Metadata

Numbers

A submodule with helpers useful for unit conversion. The idea is to represent amounts in ADA as Decimal type with 6 places of precision. For low-level backends, however, it’s easier to use int of Lovelaces.

Also, float arguments are accepted but will issue a RuntimeWarning as it is a very bad idea to use floating-point numbers for monetary data.

cardano.numbers.as_ada(amount)

Return the amount rounded to maximal ADA precision.

Parameters

amount (Decimal,int) – the amount to be sanitized

Return type

Decimal with 6 decimal places precision

cardano.numbers.from_lovelaces(amount)

Convert Lovelaces to ADA.

Parameters

amount (int) – the amount of Lovelaces

Return type

Decimal

cardano.numbers.to_lovelaces(amount)

Convert ADA to Lovelaces.

Parameters

amount (Decimal,int) – the amount of ADA

Return type

int

Metadata

A class representing Cardano transaction metadata. Inherits from dict and offers both validation and serialization of the data.

class cardano.metadata.ImmutableDict

A flavor of dict with all mutating methods blocked and hash generation added. It can be used as mapping keys.

clear() None.  Remove all items from D.
pop(k[, d]) v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised

popitem() (k, v), remove and return some (key, value) pair as a

2-tuple; but raise KeyError if D is empty.

update([E, ]**F) None.  Update D from dict/iterable E and F.

If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

class cardano.metadata.Metadata(*args, **kwargs)

Represents Cardano transaction metadata. Inherits from dict but passes all keys and values through validity check.

Parameters

mapping – a sequence of (key, value) pairs

static deserialize(txdata)

Deserializes transaction metadata dict and returns Metadata instance.

Parameters

txdata – the transaction data

serialize()

Returns serialized form of the metadata, which can be passed to the transaction.

static serialize_value(val)

Serializes Python value to an object that can be passed to transaction as a metadata value. The returned object is a mapping which contains both the type name and the value.

Raises RuntimeError when a value of unrecognized type has been passed.

static validate_key(key)

Checks if the key is allowed, i.e. is an int and within the allowed range.

Raises KeyError otherwise.

static validate_value(val)

Checks if the value is allowed, i.e. is one of int, str, bytes, bytearray, list or dict.

Raises TypeError otherwise. Also raises ValueError if the value is of proper type but exceeds range limit for Cardano metadata.