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 istuple
,
dict
: will be converted toImmutableDict
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 IDaddress (
cardano.address.Address
) – the origin addressamount (
Decimal
) – the amount in ADAassets (
list
) – a sequence ofAssetID
quantity pairs
- class cardano.transaction.Output(address=None, amount=None, assets=None)¶
Represents a
Transaction
output.- Parameters
address (
cardano.address.Address
) – the destination addressamount (
Decimal
) – the amount in ADAassets (
list
) – a sequence ofAssetID
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
objectsoutputs – a sequence of
Output
objectslocal_inputs – a sequence of
Input
objects that originate from local walletlocal_outputs – a sequence of
Output
objects that are destined to local walletwithdrawals – a sequence of (
Decimal
,str
) pairs of amounts and stake addressesmetadata – 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 returnsMetadata
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
ordict
.Raises
TypeError
otherwise. Also raisesValueError
if the value is of proper type but exceeds range limit for Cardano metadata.