You interact with the Cardano blockchain through transactions. Your wallet
software takes care of the common user tasks, yet for advanced endeavors you
need the cardano-cli
. Which gets really cumbersome as transactions grow in
complexity. Bash scripts tame the problem only for a while, because their
limitation is the very thing they offer: Bash scripts automate repetitive tasks
at the cost of flexibility.
The command line is a great tool, yet if I ever write more than 4 words on the command line I go crazy. The command line is, for me, a tool for quick queries not a work environment. Bash scripts are good to automate simple things and keep dependencies low. However, I go crazy when maintaining large bash scripts. Bash scripts enslave you to the one dimensionality of the command line, because even when editing those scripts on an editor you must mark line breaks, and keep track of quoting your variables and input.
I want a tool that lets me craft my transactions, a powerful tool to interact
with the cardano-node
, which has all the features, does not get cumbersome as
you increase the complexity of your tasks, and empowers you as a user.
I couldn’t find such a tool, thus I started building it myself. A text editable interface to create my transactions for the Cardano network. A tool that embraces the power of my text editor instead of the limitations of the command line.
I host a YouTube Channel called Ars magna for my Cardano related projects. If you doubt whether this project is for you, have a look at how it can change your workflow:
Content | Link | Length |
---|---|---|
Spending transactions | https://www.youtube.com/watch?v=Sgvc3WaZlPY | 6:13 |
Token minting | https://www.youtube.com/watch?v=1hAv63NeJ-U | 9:22 |
Stake delegation | https://www.youtube.com/watch?v=0A30HIS-BEw | 9:46 |
Key files & address management | https://www.youtube.com/watch?v=8ZIT9Uq_9A0 | 14:25 |
Cardano Wallet Interface & scripts | https://youtu.be/Ma9nbhbz3wY | 14:59 |
Hardware wallet integration | https://www.youtube.com/watch?v=RbVH1YE1WW4 | 17:18 |
The videos are a show case of this project, yet as this project develops further, they naturally become obsolete. The documentation bellow is an up to date reference.
This project is a running experiment and in Alpha stage. Don’t rely on any of its functions or interfaces to be stable, because I’m still testing its user interface. Feedback is highly welcomed.
Warning aside, myself and other Cardano users believe this is an awesome way to interact with the Cardano blockchain, it frees you from the cumbersome CLI by offering you a declarative way to specify your transactions, without loosing fine grain control.
This project has received support from the Cardano community, it is a Catalyst Fund 7 & 9 funded projects and is a Plutus Pioneer Capstone 2021 challenge prize winner.
You need a running Cardano node post Vasil Hard-Fork you can connect to.
For Mainnet follow the standard guide https://docs.cardano.org/getting-started/installing-the-cardano-node
It manages the key generation for HD wallets
This package is the backend for Daedalus. It is another service that needs to run in the background, with it you have access to rich wallet functionalities.
To work with hardware wallets you need a patched version of the cardano-hw-cli from vacuumlabs. This patch allows the editor to directly push information to that utility and avoids managing so many files. The patched binary is in this repository https://github.com/arsmagna-xyz/cardano-hw-cli/tree/witness-request
Make sure to build the witness-request branch.
This is the latest release. Install it and also the following packages.
This package is on MELPA. If you use use-package
, get it directly with all
its Emacs dependencies with.
(use-package cardano-tx
:commands (cardano-tx-new cardano-tx-cli-tip))
The file guix.scm
provides a specification on all the package dependencies.
Binaries from IOHK as well as the Emacs dependencies.
You can install this package with:
guix package -f guix.scm
Or you can enter a developer container with all necessary dependencies using:
guix shell -D -f guix.scm -C
There are some variables you need to configure.
;; Path to cli tool
(setq cardano-tx-cli-command "/full/path/to/the/cardano-cli")
;; Path to cardano-address binary
(setq cardano-tx-address-command (executable-find "cardano-address"))
;; Path to the running node socket
(setq cardano-tx-cli-node-socket "/full/path/to/the/testnet/socket")
;; These are the network arguments for the Preview testnet
(setq cardano-tx-cli-network-args '("--testnet-magic" "2"))
;; When connecting to mainnet use
;; (setq cardano-tx-cli-network-args '("--mainnet"))
;; This directory stores all your key pairs (verification & signing), it is your
;; wallet. It also holds your staking key. Make sure this folder exists, as this
;; tool will not create it. For wallet hygiene use separate directories for
;; mainnet and testnets. It also holds an SQLite database to administer known data.
;; WARNING: Keys stored here are not encrypted
(setq cardano-tx-db-keyring-dir (expand-file-name "~/cardano-wallet-keys/"))
;; In case you want to log the CLI commands used
(setq cardano-tx-log-level 'debug)
This package focuses on the low-level, high power interfaces for the
cardano-cli
and cardano-addresses
. Yet, most of the time you just need a
simple wallet to spend your ADA and keep track of that transaction history. To
achieve that goal, this tool also integrates with cardano-wallet the middle-ware
server that sits between your cardano-node
and the Daedalus
front-end.
cardano-wallet
needs its own configuration to run the server that connects to
your node and provides a local REST API to manage your wallet. Once you have
configured it as specified on the official documentation, you only need to
load the package and specify the API endpoint. Using use-package
for example:
(use-package cardano-wallet
:commands (cardano-wallet-balances cardano-wallet-helm-pick)
:config
(setq cardano-wallet-url "http://localhost:8090"))
Start by interactively querying the tip of the Blockchain. Use: M-x
cardano-tx-cli-tip
, you should see at the bottom of the screen on the mini-buffer
the information about the tip.
At the time of writing it showed this:
block: 190408
epoch: 45
era: Babbage
hash: 4e422ef1108925a9b5a2d97b20a9938f1afc09297ae8d6522534dbc432bb1366
slot: 3971838
syncProgress: "100.00"
To create new keys and their corresponding addresses use: M-x
cardano-tx-address-new-key-files
. It will prompt you how to name your new
keys. Type one name or more separating them by spaces. This will populate the
directory you defined in cardano-tx-db-keyring-dir
, with the keys.
This means:
M-x cardano-tx-address-new-key-files RET first second third RET
will generated the following folder structure:
~/cardano-wallet-keys/
├── cardano.db
├── first.skey
├── first.vkey
├── second.skey
├── second.vkey
├── stake.skey
├── stake.vkey
├── third.skey
└── third.vkey
In the background it will create you default reward(staking) key and
interactively ask you whether to create addresses with your new key files using
that reward key or not. The addresses information and the keys are stored in the
SQLite database cardano.db
.
⚠ WARNING: Please keep in mind, that all keys are plain text files on your system. Thus, when working with “mainnet” ADA, make sure you take the necessary precautions to secure your files, work on an air gapped machine.
To create a staking key (under the name stake2
) use the ELisp command:
(cardano-tx-address-new-key "stake2" t)
The name stake
is the default name for the reward key, and created
automatically. After creating additional reward keys, you can generate new
addresses that use those keys by calling cardano-tx-address-load
. Select the
spending key type, confirm whether to watch the new address and which reward key
you want to use. All key file and addresses are stored in the SQLite database in
the cardano.db
file.
You can also install cardano-addresses and let this tool help you manage your keys following the CIP-3 specification, and CIP-11.
The function cardano-tx-address-gen-recovery-phrase
will assist you creating a
mnemonic seed recovery phrase and save it on your cardano-tx-db-keyring-dir
.
⚠ WARNING: Please keep in mind, that all keys and recovery phrases are plain text files on your system. Thus when working with “mainnet” ADA, make sure you take the necessary precautions to secure your files, work on air gapped machine.
The function cardano-tx-address-new-hd-key-files
prompts for a derivation path
for your key, you can still call this with many space separated paths. Following
CIP-11 the path 1852H/1815H/0H/2/0
will generate the staking key.
As in the previous section you can create the corresponding addresses calling
interactively cardano-tx-address-load
.
Installing the patched version from cardano-hw-cli from arsmagna-xyz on the
witness-request
branch. Register the location of the binary, for example.
(setq cardano-tx-hw-command (executable-find "cardano-hw-cli"))
You can request the hardware wallet public keys by calling M-x
cardano-tx-hw-request-extended-pubkeys
. The intention is to only request the
public keys following BIP32 until the account index, that is the path depth
of 3. E.g.
1852H/1815H/0H
The editor stores this extended public key on the database and manages the key
derivations, on demand in the database. You can access the stored keys by
calling M-x cardano-tx-db-master-keys
, which open a table view of the
registered extended public keys. Likewise to the HD wallets, to derive and
register the payment and staking verification keys you must first call M-x
cardano-tx-address-hw-derive-key-files
. There select which extended account key
do you want to derive from and define the paths along which to derive these
keys. In this case you can use the expansion syntax for paths with ..
marking
an inclusive range. For example
1852H/1815H/0H/0..1/0..3
Expands to
1852H/1815H/0H/0/0 1852H/1815H/0H/0/1 1852H/1815H/0H/0/2 1852H/1815H/0H/0/3 1852H/1815H/0H/1/0 1852H/1815H/0H/1/1 1852H/1815H/0H/1/2 1852H/1815H/0H/1/3
Don’t forget to derive the staking path which terminates in 2/0
.
Once you have your verification keys registered it is time to create the
corresponding addresses. In this case there is a special function that is
account preserving for each of the extended public keys from the hardware
device. Call M-x cardano-tx-address-hw-load
and select an extended public key
account. It will generate addresses for all registered keys in the database that
belong to that account.
If you generated some key files previous to using cardano.el or from previous
versions of it, before its use of a SQLite database you need to register those
keys to the database. The easiest way is using dired
to mark the files you
want to register and then interactively calling
cardano-tx-db-dired-load-files
. You can also register Cardano native simple
scripts (multisigs/timelocks) and Plutus script files.
To visualize the files registered in the database call the interactive function
cardano-tx-db-typed-files
. This opens a table view of all registered files.
You may add annotations to each file. Annotations help you identify in the
future their content more than the filename does. The available functions for
this view are:
Shortcut | Function | Description |
---|---|---|
o | cardano-tx-db-file-open | Open file |
a | cardano-tx-db-file-annotate | Add a note to the file |
w | cardano-tx-db-file-write | Write the file to disk. This overwrites the file with your changes |
c | cardano-tx-db-file-name-copy | Copy the file path into the kill-ring |
d | cardano-tx-db-file-delete | Delete file from the database. Optionally from disk too. |
cardano-tx-address-load
calculates addresses from registered files and loads
them on the address database. Call it after registering new files. This doesn’t
work for files originating from the Hardware device as they produce extended
keys. For those files use cardano-tx-address-hw-load
.
To visualize addresses loaded into your database call cardano-tx-db-addresses
.
This opens a view with all registered addresses. You can toggle which ones to
actively watch(query UTxO balance), copy the address to the keyboard or edit the
annotation.
Shortcut | Function | Description |
---|---|---|
a | cardano-tx-db-address-annotate | Add note to address |
c | cardano-tx-db-address-copy | Copy address to kill-ring |
w | cardano-tx-db-address-toggle-watch | Query this address when looking for UTxOs |
d | cardano-tx-db-address-delete | Delete address from database |
The goal is to directly create the transaction in your editor instead of using the CLI commands when crafting of the transaction.
To launch the editor call M-x cardano-tx-new
. It will list all the UTxOs that
you control on your wallet for you to spend. This might take a while as it is an
expensive query for the cardano-node
[fn:1]. Select one or many, you can still
include more into your transaction during the edit process later on. A new
buffer opens with the basic spending transaction template you can directly edit.
Have a look at the next annotated example. It is a larger than usual transaction(2 inputs - 4 outputs), because the goal of this tool is to demonstrate that it doesn’t get cumbersome as the transaction scope grows. It is a simple and standard yaml file. The structure reflects intuitively what the transaction itself is about. I’m sure you can understand it just by reading it.
# These are the inputs for the transaction.
inputs:
- utxo: a7c5d4ab42016fa2cbdcbdb03133a9c6826ad5432f2a30e4b5ed32c1ac4c86f0#1
- utxo: bd61923ca80f4789a2a7eddbe57e200fcb3af84b7d990a2fb5bc30efc71ba440#1
# Outputs are defined in the same way.
outputs:
# A simple payment output to this address
- address: addr_test1qznwk2s30nyvtgn20z27kqlnezxn6gu3ud8f3zyrxfae3ymk2wgk4wl2rz04eaqmq9fnxhyn56az0c4d3unvcvg2yw4qt6aaad
amount:
lovelace: 10000000
# Payment to a Plutus script. The AlwaysSucceeds script
- address: addr_test1wpnlxv2xv9a9ucvnvzqakwepzl9ltx7jzgm53av2e9ncv4sysemm8
amount:
lovelace: 1234567
# You must include the datum. This tool calculates the hash for you.
datum: [2, "the always succeeds contract", {"with a": "mixed type datum"}]
# Payment to another Plutus script
- address: addr_test1wzxfj3l2es945szu8wd6mm9jnkj7wze2zwtagkhdmn62gxqnvz87d
amount:
lovelace: 20000000
# This script requires a typed datum, because the script input is a 2-tuple of ints
# In this case the input is the path to a file that has the typed specification
# of the datum
datumfile: "plutus-data/tuple_ints(-5,6)"
# ALWAYS think about your change address
- address: addr_test1qpsfwsr4eqjfe49md9wpnyp3ws5emf4z3k6xqagvm880zgnk2wgk4wl2rz04eaqmq9fnxhyn56az0c4d3unvcvg2yw4qmkmv4t
change: true # The cardano-cli balances it. Only lovelaces for now
Not only is it readable, you get the advantages of syntax highlighting, indentation, auto-completion and more editing tools from the editor. You can of course write comments in between the lines, because yaml allows that. That is not possible within a bash script that uses long commands with line breaks. You only get to comment around the blocks of instructions.
When creating this transaction there are utility functions that help you with some input. For example:
cardano-tx-helm-utxos
Pick from utxos that are in your wallet for easy input.cardano-tx-address-pick
Pick from all your registered addressescardano-tx-available-balance
Calculates, displays and loads to kill-ring the balance not yet committed to transaction outputs.
The Plutus scripts we send funds in this transaction are
contracts/AlwaysSucceeds.plutus
and contracts/list-in-range.plutus
. The
first takes any datum, the second takes a two element tuple to define a range.
That’s why the datum needs to be a tuple, and why we need to use the typed
version for the datum, because tuples are not available as JSON values.
In this repository you can find the datum file used for this example in the path
plutus-data/tuple_ints(-5,6)
, and it has this content.
{"constructor":0,"fields":[{"int":-5},{"int":6}]}
To send the transaction just use shortcut C-c C-c
or call M-x
cardano-tx-edit-finish
. That will build the transaction, calculate the fees,
sign it, submit it, close the editing window and copy the transaction id to the
clipboard for you to look for it in your favorite explorer.
This transaction has the id 591d446e2ed8951e07cd9260df0eaec308e7b6eb75cae68124344bec09c9a75a, and is on the Preview Testnet.
The editor uses in general the build
command to craft the transaction, which
requires a change address. Unfortunately, that change address only balances the
transaction in lovelace and is a required field. However, if your change is
exactly zero lovelace the transaction would still work(see
IntersectMBO/cardano-node#3041). You can thus use
than function cardano-tx-available-balance
to balance the transaction and once
you try to build it extract the minimum fee value from the error message. Then
put that value as an extra field on the transaction description:
fee: 189432
Re-balance your transaction outputs and try again, the change address although
required will not show up on the crafted transaction, and the fee field is only
a help to balance the transaction, as the build
command does not use it.
Currently, it only makes sense to pay the minimum fee in Cardano. Yet, if it one
day implements a market for fees, where a higher fee would help you get ahead on
the mempool and prioritize your transaction you can set your fee. For that use
the fee
field, but delete the change address output. That will use the
build-raw
command where you specify the fee.
Minting tokens is again simple and doable with a single specification. Again, exemplifying with a rather large transaction, where I’ll mint two kinds of tokens: a fungible token with unconstrained minting policy and a NFT policy. Additionally, the NFT metadata will include its metadata.
Launch the editor with M-x cardano-tx-new
, and pick some UTxOs to fund the
mint transaction. It is a big transaction, don’t get overwhelmed by the forest
they are only trees. Follow the comments, a lot is going on in this transaction.
To help you write the minting specification typing mint
followed by <TAB>
will use yasnippet to load minting template specification.
inputs:
- utxo: bd61923ca80f4789a2a7eddbe57e200fcb3af84b7d990a2fb5bc30efc71ba440#0
# Minting policies are characterized by the policy-id, here you can name them,
# and use that name throughout the transaction. The editor will then replace the
# name for the policy-id when creating the transaction.
mint:
# This first policy(reward-tokens) only requires one witness to mint. You can mint
# anytime you want as long as you have the key. I can use them as reward points.
# I can keep minting to reward users.
reward-tokens: # This is my first policy name
policy: # Declare the policy. A single signature is enough
type: sig
keyHash: 73a144c2762078541ac9d258714121da5044069dc442cc7fe1fb0471 # fourth
assets: # Here is the amount of assets to mint. I name each of the tokens
gold: 100
platinum: 50
# This second policy are two NFTs. It honors XKCD, and mints NFTs that link to
# a particular comic. The minting policy requires 2 witnesses and has a time lock
# to ensure that no more assets are minted under this policy after the slot passed
xkcd: # this is the policy name
policy:
type: all
scripts:
- type: sig
keyHash: a6eb2a117cc8c5a26a7895eb03f3c88d3d2391e34e988883327b9893 # second
- type: sig
keyHash: 9bcde05606b1fbd5f5390b3ebbba0f523bddba5822027c856ebc336a # third
- type: before
slot: 3979246 # this is the time lock
assets: # Minting two unique NFTs
networking: 1
frustration: 1
# You need to help the tool when using scripts by enumerating which witnesses
# need to sign the transaction. These are the keys on your wallet. I commented
# in the previous scripts which keyHash maps to which key
# You don't need this hint on normal spending, because it can infer which key owns which UTxO.
witness:
- second
- third
- fourth
# For Mary Era Timelocked NFTs don't forget to match the validity interval, with
# the one on the time lock policy
validity-interval:
invalid-hereafter: 3979246
# invalid before:
# The metadata here allows to describe the NFTs. You can then see them on an explorer
metadata:
721:
xkcd: # policy name
networking: # token name
id: 1
name: "Networking"
description: "Our company is agile and lean with a focus on the long tail."
image: ipfs://Qmbu8L59m5YHxo7kSCnfZa9DLSApyLFXTpbcJo6tx8vzzq
frustration: # token name
id: 2
name: "Frustration"
description: "Don't worry, I can do it in under a minute."
image: ipfs://QmdunoNVjXe8aLFHvPqWdjNZmSfQBnrhb1pPwLcEAJcVUR
# Finally the 4 output. I distribute the newly minted tokens across multiple addresses
outputs:
- address: addr_test1vzdumczkq6clh4048y9nawa6pafrhhd6tq3qyly9d67rx6sq3zpq7 # third-enterprise
amount:
xkcd: # policy name
networking: 1 # token name
reward-tokens: # other policy name
gold: 40 # corresponding token name
lovelace: 2000000
- address: addr_test1qznwk2s30nyvtgn20z27kqlnezxn6gu3ud8f3zyrxfae3ymk2wgk4wl2rz04eaqmq9fnxhyn56az0c4d3unvcvg2yw4qt6aaad # second
amount:
reward-tokens:
gold: 60
platinum: 15
lovelace: 3678910
- address: addr_test1qpsfwsr4eqjfe49md9wpnyp3ws5emf4z3k6xqagvm880zgnk2wgk4wl2rz04eaqmq9fnxhyn56az0c4d3unvcvg2yw4qmkmv4t
amount:
xkcd:
frustration: 1
reward-tokens:
platinum: 35
lovelace: 4002413
# ALWAYS think about your change address
- address: addr_test1qpsfwsr4eqjfe49md9wpnyp3ws5emf4z3k6xqagvm880zgnk2wgk4wl2rz04eaqmq9fnxhyn56az0c4d3unvcvg2yw4qmkmv4t
change: true
Have a look at the transaction on an testnet explorer: b679f4aab00161e0e96b3b3b61611f849fb9f075aeff351fdf3c6cc1954496c7 Notice that the token names are still described by human readable strings. The editor translates those names to hexadecimal values when creating the transaction as required by the cardano-node>=1.33.
The transaction to register and delegate at the same time looks like this:
inputs:
- utxo: b679f4aab00161e0e96b3b3b61611f849fb9f075aeff351fdf3c6cc1954496c7#0
certificates:
# Standard certificates
- registration:
# vkey-file: # optionally pick the staking verification key file
# deregistration: true
- delegation:
pool: pool1a7h89sr6ymj9g2a9tm6e6dddghl64tp39pj78f6cah5ewgd4px0
# vkey-file: # optionally pick the staking verification key file
# Specify the certificate file
# - file:
# You must sign with the stake key to authorize the certificate
witness:
- stake
outputs:
# ALWAYS think about your change address
- address: addr_test1qpsfwsr4eqjfe49md9wpnyp3ws5emf4z3k6xqagvm880zgnk2wgk4wl2rz04eaqmq9fnxhyn56az0c4d3unvcvg2yw4qmkmv4t
change: true
It is important to note, that you must register the stake address before you
delegate your stake. If you are doing both actions in the same transaction, then
make sure that the registration
item is before the delegation
item (like in
this example) otherwise the transaction will fail. If you want to do this on
separate transactions, it still holds to register before you delegate.
This sample transaction is also on the testnet under the txid: 649bc635b27d372f5274e439b70718732cea816483ab47c93ef6ec3d941fc0a0
Withdrawing is again just another element of your transaction.
input:
- utxo: 8bdfcfa7faa87f32c624700d1bec7fb0cd3af0ed3fb9e7a5e1121bc52433e645#0
outputs:
# ALWAYS think about your change address
- address: addr_test1qpsfwsr4eqjfe49md9wpnyp3ws5emf4z3k6xqagvm880zgnk2wgk4wl2rz04eaqmq9fnxhyn56az0c4d3unvcvg2yw4qmkmv4t
change: true
withdrawals:
# Specify from which staking address you withdraw the rewards
- address: stake_test1urpklgzqsh9yqz8pkyuxcw9dlszpe5flnxjtl55epla6ftqktdyfz
amount:
lovelace: 315716
# You must sign with the stake key because you spend from the staking address
witness:
- stake
The function cardano-tx-rewards
receives as input the staking addresses and
helps you with the total amount in the rewards.
The Plutus script in this example has this validator script, and corresponds to
the script in the file contracts/list-in-range.plutus
.
{-# INLINABLE rangeContract #-}
rangeContract :: (Integer, Integer) -> [Integer] -> ScriptContext -> P.Bool
rangeContract (l,h) redeemer _ = P.all (\x -> l P.<= x P.&& (x P.<= h)) redeemer
data RangeContract
instance Scripts.ValidatorTypes RangeContract where
type instance DatumType RangeContract = (Integer, Integer)
type instance RedeemerType RangeContract = [Integer]
rangeContractInstance :: Scripts.TypedValidator RangeContract
rangeContractInstance = Scripts.mkTypedValidator @RangeContract
$$(PlutusTx.compile [|| rangeContract ||])
$$(PlutusTx.compile [|| wrap ||])
where
wrap = Scripts.wrapValidator @(Integer, Integer) @[Integer]
As you see we needed a two element tuple for the datum to define a range. The redeemer must be a list of “arbitrary length”, but all elements must be integers within the range defined by the datum. This is exercise 4.d of the Alonzo-testnet exercises.
One transaction that solves this constraint is:
inputs:
# This is the UTxO that created in the previous section
# Because it is a Plutus script. To unclock it we need to provide extra
# information like the Plutus script, datum and redeemer
- utxo: 591d446e2ed8951e07cd9260df0eaec308e7b6eb75cae68124344bec09c9a75a#3
# path to the script file
script-file: "contracts/list-in-range.plutus"
# path to the typed datum
datumfile: "plutus-data/tuple_ints(-5,6)"
# I can directly specify a JSON value. List are JSON values and thus
# can be directly parsed. There is no need to write the typed version in a file.
redeemer: [2, -5, -1, 4, 0, 3, 1, 6, -4]
collateral: 649bc635b27d372f5274e439b70718732cea816483ab47c93ef6ec3d941fc0a0#0
outputs:
# ALWAYS think about your change address
- address: addr_test1qpsfwsr4eqjfe49md9wpnyp3ws5emf4z3k6xqagvm880zgnk2wgk4wl2rz04eaqmq9fnxhyn56az0c4d3unvcvg2yw4qmkmv4t
change: true
C-c C-c
or calling M-x cardano-tx-edit-finish
, builds and submits the
transaction. In this case the transaction is
76fd80c71c9e81cd68e2682a2a5da4ec83eff7beb2381714fb8aa85dc4056d3a and you can
find it on the preview testnet explorer.
That’s it. This tool reflects the transaction crafting with a User Interface, that is the transaction itself and takes care of all the details about parsing the input, signing and submitting.
The same scripts you used for minting policies are usable to secure funds. Those
are simple multisig and timelock scripts. To create one of those scripts call
the function cardano-tx-new-script
. It will open an editor window where you
can write the clauses of your script. The yasnippet shortcut ns
expands into
the clauses of a simple script. Simple scripts are recursive, thus you can go as
deep as you want stating you spending clauses.
Press C-c C-c
to save the script. This will convert the script from it’s YAML
editing form to a JSON file and save it on your cardano-tx-db-keyring-dir
for
later use using the script hash as file name. Please understand that after that
step you should never modify that file. If you need a new script with slight
variations, make a new script and it to the database and keep that copy.
Visiting cardano-tx-db-typed-files
you can see the newly created script. I
advise you to also write a description of it using the annotation feature. Later
you can call cardano-tx-address-load
to calculate the address of this script
and have it available for use.
If you installed the cardano-wallet the main entry point is the interactive
function cardano-wallet-balances
, which opens a buffer with a table showing
the balances of all your registered wallets. To register a wallet call
cardano-wallet-create
, it will ask for the name of the wallet, a file
containing the seed phrase(use the previous section for that), and a password to
lock up your wallet. Once registered cardano-wallet
will scan the blockchain
for transactions pertaining your wallet, that takes a fair amount of time the
first time, then it stays in watch mode and keeps synchronizing with the latest
state of the blockchain.
From the balances view you can interact with each wallet using this shortcut functions:
Shortcut | Function | Description |
RET | cardano-wallet-describe | Show the information about the wallet |
s | cardano-wallet-tx-new | Create a new payment transaction |
l | cardano-wallet-addresses | List all addresses associated to wallet |
t | cardano-wallet-tx-log | List all the transactions from this wallet |
d | cardano-wallet-delete | Remove this wallet |
cardano-wallet-helm-pick
is the entry point to work with each of your wallets
individually. Gives you the same functionality you have from the balances view.
Its menu lets start a payment transaction, list all addresses, look at the
transaction history, and show a description of the wallet.
You can register your hardware wallet public keys using the command
cardano-wallet-hw-register
. In this case you can create directly payment
transaction from this interface. When opening this wallet from the address view
it is also possible to instantiate their verification keys.
When creating transactions the editor is much more restricted, as only payments are possible, you can only specify outputs. The wallet takes care off the inputs through coin selection. If you have registered your hardware wallet it also takes care of calling the hardware device to witness the transaction and submit it.
The file ouroboros.el
contains a simple implementation of The Shelley
Networking Protocol to connect to the node and query information. You can use it
for the local state query mini-protocol, for example:
(progn
(setq sock (ouroboros-connect "path/to/cardano-node.socket" 2))
;; After connection immediately engage in another mini protocol otherwise the server drops the connection
(ouroboros-local sock 'acquire 'tip))
(ouroboros-local sock 'query 'chain-point)
(ouroboros-local sock 'query 'block-no)
(ouroboros-local sock 'query 'system-start)
(ouroboros-local sock 'query 'hard-fork-eras)
(ouroboros-local sock 'query 'current-era)
(ouroboros-local sock 'query '(shelley epoch-no))
(ouroboros-local sock 'query `(shelley non-myopic-member-rewards
,(ouroboros-non-myopic-stake '(123456 456789133))))
(ouroboros-local sock 'query '(shelley current-params))
(ouroboros-local sock 'query '(shelley proposed-params))
(ouroboros-local sock 'query '(shelley stake-distribution))
(ouroboros-local sock 'query `(shelley utxo-by-address
,(ouroboros-address-query
'("addr_test1vpsfwsr4eqjfe49md9wpnyp3ws5emf4z3k6xqagvm880zgs2k5jvj"
"addr_test1zqeh2kmcf3wlp8jjlzve75mmvnmyac730p8j33zkxdawy7xn5qmqcmgt2t5gzpygzpr3y2y72d9ftuydut8qr8tqvqvs06lg42"))))
(ouroboros-local sock 'query '(shelley utxo-whole))
(->
(ouroboros-local sock 'query '(shelley cbor-wrap epoch-no))
(cbor-tag-content)
(cbor->elisp))
(ouroboros-local sock 'query `(shelley filtered-delegations-and-reward-accounts
,(ouroboros-reward-addresses
'("stake_test17r9cs7pxyf2nzlwg64fkf646kwq0mq9ucjlscefdthyj33sy8f0js"
"stake_test1upm98yt2h04p386u7sdsz5entjf6dw38u2kc7fkvxy9z82s5f2lrh"))))
(ouroboros-local sock 'query '(shelley genesis-config))
(ouroboros-local sock 'query '(shelley reward-provenance))
(ouroboros-local sock 'query `(shelley utxo-by-tx-in
,(ouroboros-utxo
'("c6a1c03c473753c932277634a39e8a3bacf4ae792eac174ab1e1b272d142db1f#0"))))
(ouroboros-local sock 'query '(shelley stake-pools))
(ouroboros-local sock 'query `(shelley stake-pool-params
,(cbor-tag-create
:number 258
:content ["13ab5c2838adaf649eb7e974779b705bb2b997c3c8132c3700c78dfe"
"96788607f51dfaf3d115594e09cc6b75740035b8da05891995434268"])))
(ouroboros-local sock 'query '(shelley reward-info-pools))
(ouroboros-local sock 'release)
(ouroboros-local sock 'done)
I published a written document about all available queries in https://arsmagna.xyz/docs/network-lsq/. A short video series teaching you about the node communication and the local state query is available on YouTube. https://www.youtube.com/watch?v=rAWPudH55D4&list=PLwRUn-ZyfKJx2sj5hgJqL68KCTq7aSvkpG
This an awarded project of the Cardano Summit 2021 - Plutus Pioneer Capstone Challenge. You can read about it on the IOHK blog, and watch the interview with some of the winners. I hope it raises awareness of this tool and also to call attention to my Catalyst proposal to fund the further development of this tool.
If you are a Doom-Emacs user, you might realize that it becomes extra cumbersome to find the buffers from this tool. That is because of Doom’s philosophy of what makes an interesting buffer. You can tell Doom that these buffers are interesting by including the following code on your configuration file.
(add-hook! 'doom-real-buffer-functions
(defun cardano-interesting-buffer (b)
"Whether the current buffer's major-mode is a cardano mode."
(with-current-buffer b
(memq major-mode '(cardano-tx-db-addresses-mode
cardano-tx-db-files-mode
cardano-tx-mode
cardano-wallet-tx-log-mode)))))
[fn:1] Finding the UTxOs takes a while and thus your editor blocks during that time. Since the cardano-node=1.33 the UTxO set moved from RAM to Disk and that makes this query even slower.