-
Notifications
You must be signed in to change notification settings - Fork 7
How to submit transaction via cardano tx CLI
In this example we will be using cardano-address
, cardano-tx
and cardano-wallet
command line tools to construct and then send transaction on Cardano Testnet. We will show how to:
- derive addresses from the known mnemonic sentences with
cardano-address
- construct transaction using
cardano-tx
- and, finally, submit this transaction on chain using
cardano-wallet transaction submit
Above operations will be presented for:
cardano-address
, cardano-tx
and cardano-wallet
CLI utilites can be found on their respective release pages on GitHub.
Please note that for some steps of this tutorial we need to have cardano-node
and cardano-wallet
running. In particular this is needed for submitting a transaction or checking payment fee using cardano-wallet
. Instructions for running cardano-wallet
and cardano-node
can be found here
It is however not needed for constructing a transaction via cardano-tx
.
In the example we will be using an Shelley wallet identified by following mnemonic sentence:
tooth extend water monkey hub magnet uncover cherry shrug sheriff sugar unique memory nurse solve nature pepper phrase hour stick slight anchor earth cave
The balance of the wallet is 10 ADA (10 000 000 Lovelace). All funds are placed on the address of the wallet, which we can derive using cardano-address
utility:
Let's assume that our mnemonic phrase is saved in a file: shelley_phrase.prv
.
cat shelley_phrase.prv \
| cardano-address key from-recovery-phrase Shelley \
| cardano-address key child 1852H/1815H/0H/0/0 \
| cardano-address key public \
| cardano-address address payment --network-tag testnet
addr_test1vr5egevl9mmukz5ccwlnjl2tsftn0fa7d9gdt7ngpyfes9g434s4t
ℹ️ Since this was the first external address of our Shelley wallet, we know that the derivation path of the underlying private key is
1852H/1815H/0H/0/0
. The second address would be1852H/1815H/0H/0/1
and so forth...
In this example, funds were sent to this address as the first output of a transaction with id 17e21cf64c07bfee7ff5e19fbc0a99ab13c9fb1eef62ed6101846de5b2459de5
. On a 0-based index, it makes it the output #0.
The transaction needs to be signed with the key owning funds at the address.
We can use cardano-addresses
CLI utility to get the key that we'll use for signing our transaction.
XPRV=`cat shelley_phrase.prv \
| cardano-address key from-recovery-phrase Shelley \
| cardano-address key child 1852H/1815H/0H/0/0 --base16`
Before we send transaction we need to specify the change, i.e. the how much of the remaining funds need to go back to our wallet.
This is extremely important! if we don't specify the change all remaining funds will be lost and we end up with balance 0 on our wallet after the transaction.
First, let's derive a change address using cardano-address
:
cat shelley_phrase.prv \
| cardano-address key from-recovery-phrase Shelley \
| cardano-address key child 1852H/1815H/0H/0/1 \
| cardano-address key public \
| cardano-address address payment --network-tag testnet
addr_test1vq7jm88trfrmcxmzkaycefykk948kjaucmvhah5ph2rzr6ccwd4rn
The change is calculated as total_balance - amount_to_be_sent - fee
.
In this example we will be sending 1 ADA (1000000 lovelace) to a destination address 2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1
. As stated before the source wallet has total balance of 10 ADA (10 000 000 lovelaces), therefore the amount to be send back as a change should be:
10000000 - 1000000 - fee
We can check the fee using cardano-wallet
API:
curl -X POST http://localhost:8090/v2/wallets/4157603597d008fd8fe88b84f72696809e9a6a06/payment-fees \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"payments": [
{
"address": "2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1",
"amount": { "quantity": 1000000, "unit": "lovelace" }
} ] }' | jq
......
{
"estimated_min": {
"quantity": 167965,
"unit": "lovelace"
},
"estimated_max": {
"quantity": 167965,
"unit": "lovelace"
}
}
Ok, so finally the change should be:
10000000 - 1000000 - 167965 = 8832035
Finally we can construct transaction using cardano-tx
CLI.
cardano-tx empty 1097911063 \
| cardano-tx add-input 0 17e21cf64c07bfee7ff5e19fbc0a99ab13c9fb1eef62ed6101846de5b2459de5 \
| cardano-tx add-output 1000000 2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1 \
| cardano-tx add-output 8832035 addr_test1vq7jm88trfrmcxmzkaycefykk948kjaucmvhah5ph2rzr6ccwd4rn \
| cardano-tx lock \
| cardano-tx sign-with $XPRV \
| cardano-tx serialize --base16
command | explanation |
---|---|
cardano-tx empty 1097911063 |
Specify Network Magic for Testnet. |
cardano-tx add-input 0 17e21cf6... |
The input for the transaction to be send will come from this particular transaction id that is already in_ledger for the source wallet. |
cardano-tx add-output 1000000 2cWKMJemoBaj... |
We will be sending 1 ADA to this destination address. |
cardano-tx add-output 8832035 addr_test1... |
We need to send the remaining change back to the source wallet 10000000 - 1000000 - 167965 = 8832035
|
cardano-tx lock |
Lock the transaction, so it can be signed. |
cardano-tx sign-with $XPRV |
Sign transaction. |
cardano-tx serialize --base16 |
Serialize it, so it can be submitted via cardano-wallet . |
Now we can send the transaction over using cardano-wallet transaction submit
:
cardano-wallet transaction submit 82839f8200d81858248258206fdbeda74dad6d75999b895573a13f78ab7629d4c93454b322dd97678425665a01ff9f8282d818582883581c8011d974e8746a3b83cf145cde56b0053ad3fbe6dc62c5ab97f42309a102451a4170cb17001afb04e5681a000f42408282d818584983581c78e321d18854e2a570408086fafcc10021f003e751c3598a17535813a201581e581c60040b5457954023e04c2f1d890342bb2b05b96535df583e8b9bc34202451a4170cb17001a1899b5fe1a0086b1bfffa0818200d8185885825840fe6b954427a3f5dc659cfb6c93a3dc882db4664844267b5e1dba6b71957b3e073f20b66f616fba86a983fae9541dcb8b77c28676cc32f80ac28445d8b58ce34c5840ec3fcc115c706d12daa16a146427fbfd1bbd1d670fae8b35e2ab58b2e5e1c0aea8a243abcef590354ad30af4fbab0e019a5fbe156ad8d85816afdc7aef2b150f
Ok.
{
"id": "e26e56411e10282700313e66dbe04b2f3fc201378417d2d135bca0f34df52e5c"
}
In the example we will be using an Byron random wallet identified by following mnemonic sentence:
gym trend inject keen drink example truck enter treat ahead stock walnut
The balance of the wallet is 10 ADA (10 000 000 Lovelace). All funds are placed on the address of the wallet, which we can derive using cardano-address
utility:
Let's assume that our mnemonic phrase is saved in a file: byron_phrase.prv
.
cat byron_phrase.prv \
| cardano-address key from-recovery-phrase Byron > root.prv
cat root.prv\
| cardano-address key child --legacy 14H/42H \
| cardano-address key public \
| cardano-address address bootstrap --root $(cat root.prv | cardano-address key public) \
--network-tag testnet 14H/42H
37btjrVyb4KCjbmtj3biA1rRw4goVKUJJAHbnGExxUkuWT2ygshYCLowpQFAC6MxVVPcNXLDMZgBa1M1W6UYbAuCr4wx61NLZ7KGLGRZgwxq7T91wt
In this example, funds were sent to this address as the second output of a transaction with id 8a4419bc68dd5660ddae604d1469584b2cf39c088c0d9fc43fc52db179be249e
. On a 0-based index, it makes it the output #1.
The transaction needs to be signed with the key owning funds at the address.
We can use cardano-addresses
CLI utility to get the key that we'll use for signing our transaction.
XPRV=`cat root.prv \
| cardano-address key child --legacy 14H/42H --base16`
Before we send transaction we need to specify the change, i.e. the how much of the remaining funds need to go back to our wallet.
This is extremely important! if we don't specify the change all remaining funds will be lost and we end up with balance 0 on our wallet after the transaction.
First, let's derive a change address using cardano-address
:
cat byron_phrase.prv \
| cardano-address key from-recovery-phrase Byron > root.prv
cat root.prv\
| cardano-address key child --legacy 14H/43H \
| cardano-address key public \
| cardano-address address bootstrap --root $(cat root.prv | cardano-address key public) \
--network-tag testnet 14H/43H
37btjrVyb4KDPuJkYFzkHe7gxQRJi7PiUCM5xBPqUcvPxwneifgKf7BqwRwF6NetY4xMX6zaaNhY1wHhTR2duKvppSbgWwNUqKhsne3tt9AZSdHA9B
The change is calculated as total_balance - amount_to_be_sent - fee
.
In this example we will be sending 1 ADA (1000000 lovelace) to a destination address 2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1
. As stated before the source wallet has total balance of 10 ADA (10 000 000 lovelaces), therefore the amount to be send back as a change should be:
10000000 - 1000000 - fee
We can check the fee using cardano-wallet
API:
curl -X POST http://localhost:8090/v2/byron-wallets/b890d442ff66870fda819d34aed71393993b074b/payment-fees \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"payments": [
{
"address": "2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1",
"amount": { "quantity": 1000000, "unit": "lovelace" }
} ] }' | jq
......
{
"estimated_min": {
"quantity": 172673,
"unit": "lovelace"
},
"estimated_max": {
"quantity": 172673,
"unit": "lovelace"
}
}
Ok, so finally the change should be:
10000000 - 1000000 - 172673 = 8827327
Finally we can construct transaction using cardano-tx
CLI.
cardano-tx empty 1097911063 \
| cardano-tx add-input 1 8a4419bc68dd5660ddae604d1469584b2cf39c088c0d9fc43fc52db179be249e \
| cardano-tx add-output 1000000 2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1 \
| cardano-tx add-output 8827327 37btjrVyb4KDPuJkYFzkHe7gxQRJi7PiUCM5xBPqUcvPxwneifgKf7BqwRwF6NetY4xMX6zaaNhY1wHhTR2duKvppSbgWwNUqKhsne3tt9AZSdHA9B \
| cardano-tx lock \
| cardano-tx sign-with $XPRV \
| cardano-tx serialize --base16
command | explanation |
---|---|
cardano-tx empty 1097911063 |
Specify Network Magic for Testnet. |
cardano-tx add-input 1 8a4419... |
The input for the transaction to be send will come from this particular transaction id that is already in_ledger for the source wallet. |
cardano-tx add-output 1000000 2cWKMJemoBaj... |
We will be sending 1 ADA to this destination address. |
cardano-tx add-output 8830231 37btjrVy... |
We need to send the remaining change back to the source wallet 10000000 - 1000000 - 172673 = 8827327
|
cardano-tx lock |
Lock the transaction, so it can be signed. |
cardano-tx sign-with $XPRV |
Sign transaction. |
cardano-tx serialize --base16 |
Serialize it, so it can be submitted via cardano-wallet . |
Now we can send the transaction over using cardano-wallet transaction submit
:
cardano-wallet transaction submit 82839f8200d81858248258206fdbeda74dad6d75999b895573a13f78ab7629d4c93454b322dd97678425665a01ff9f8282d818582883581c8011d974e8746a3b83cf145cde56b0053ad3fbe6dc62c5ab97f42309a102451a4170cb17001afb04e5681a000f42408282d818584983581c78e321d18854e2a570408086fafcc10021f003e751c3598a17535813a201581e581c60040b5457954023e04c2f1d890342bb2b05b96535df583e8b9bc34202451a4170cb17001a1899b5fe1a0086b1bfffa0818200d8185885825840fe6b954427a3f5dc659cfb6c93a3dc882db4664844267b5e1dba6b71957b3e073f20b66f616fba86a983fae9541dcb8b77c28676cc32f80ac28445d8b58ce34c5840ec3fcc115c706d12daa16a146427fbfd1bbd1d670fae8b35e2ab58b2e5e1c0aea8a243abcef590354ad30af4fbab0e019a5fbe156ad8d85816afdc7aef2b150f
Ok.
{
"id": "e26e56411e10282700313e66dbe04b2f3fc201378417d2d135bca0f34df52e5c"
}
In the example we will be using an Icarus sequential wallet identified by following mnemonic sentence:
theme book settle across rhythm year riot primary day sudden nest develop purpose check stove
The balance of the wallet is 10 ADA (10 000 000 Lovelace). All funds are placed on the first address of the wallet, which we can derive using cardano-address
utility:
Let's assume that our mnemonic phrase is saved in a file: icarus_phrase.prv
.
cat icarus_phrase.prv \
| cardano-address key from-recovery-phrase Icarus \
| cardano-address key child 44H/1815H/0H/0/0 \
| cardano-address key public \
| cardano-address address bootstrap --network-tag testnet
2cWKMJemoBakRJh43zNuFrkjApyUVVjQn2eFkjfSdfye4JLzfK9zSngUSvTT1P4TNWB79
In this example, funds were sent to this address as the second output of a transaction with id 29657703d662e9c36845c2f61505e96e92128605ff9eb4b635ec659ed4998625
. On a 0-based index, it makes it the output #1.
The transaction needs to be signed with the key owning funds at the address.
We can use cardano-addresses
CLI utility to get the key that we'll use for signing our transaction.
XPRV=`cat icarus_phrase.prv \
| cardano-address key from-recovery-phrase Icarus \
| cardano-address key child 44H/1815H/0H/0/0 --base16`
ℹ️ Since this was the first external address of our wallet, we know that the derivation path of the underlying private key is
44H/1815H/0H/0/0
. The second address would be44H/1815H/0H/0/1
and so forth...
Before we send transaction we need to specify the change, i.e. the how much of the remaining funds need to go back to our wallet.
This is extremely important! if we don't specify the change all remaining funds will be lost and we end up with balance 0 on our wallet after the transaction.
First, let's derive a change address using cardano-address
:
echo "theme book settle across rhythm year riot primary day sudden nest develop purpose check stove" \
| cardano-address key from-recovery-phrase Icarus \
| cardano-address key child 44H/1815H/0H/0/1 \
| cardano-address key public \
| cardano-address address bootstrap --network-tag testnet
2cWKMJemoBajEoat816orhcEnFnkgdPgjKS3mwtg4Ccto8mu1odk6KJrfmtx9CkpUuXHp
The change is calculated as total_balance - amount_to_be_sent - fee
.
In this example we will be sending 1 ADA (1000000 lovelace) to a destination address 2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1
. As stated before the source wallet has total balance of 10 ADA (10 000 000 lovelaces), therefore the amount to be send back as a change should be:
10000000 - 1000000 - fee
We can check the fee using cardano-wallet
API:
curl -X POST http://localhost:8090/v2/byron-wallets/e7d4416c1c8e1c7a8fb7639c1145f5b3d4d8b1cf/payment-fees \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"payments": [
{
"address": "2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1",
"amount": { "quantity": 1000000, "unit": "lovelace" }
} ] }' | jq
......
Ok.
{
"estimated_min": {
"quantity": 169769,
"unit": "lovelace"
},
"estimated_max": {
"quantity": 169769,
"unit": "lovelace"
}
}
Ok, so finally the change should be:
10000000 - 1000000 - 169769 = 8830231
Finally we can construct transaction using cardano-tx
CLI.
cardano-tx empty 1097911063 \
| cardano-tx add-input 1 29657703d662e9c36845c2f61505e96e92128605ff9eb4b635ec659ed4998625 \
| cardano-tx add-output 1000000 2cWKMJemoBajGP6n7JUo52neaRtxHTCWF1R9q7uA8PvexKFKvMMGvEAF9fSMCdzJZUUj1 \
| cardano-tx add-output 8830231 2cWKMJemoBajEoat816orhcEnFnkgdPgjKS3mwtg4Ccto8mu1odk6KJrfmtx9CkpUuXHp \
| cardano-tx lock \
| cardano-tx sign-with $XPRV \
| cardano-tx serialize --base16
command | explanation |
---|---|
cardano-tx empty 1097911063 |
Specify Network Magic for Testnet. |
cardano-tx add-input 1 2965770... |
The input for the transaction to be send will come from this particular transaction id that is already in_ledger for the source wallet. |
cardano-tx add-output 1000000 2cWKMJemoBaj... |
We will be sending 1 ADA to this destination address. |
cardano-tx add-output 8830231 2cWKMJemoBaj... |
We need to send the remaining change back to the source wallet 10000000 - 1000000 - 169769 = 8830231
|
cardano-tx lock |
Lock the transaction, so it can be signed. |
cardano-tx sign-with $XPRV |
Sign transaction. |
cardano-tx serialize --base16 |
Serialize it, so it can be submitted via cardano-wallet . |
Now we can send the transaction over using cardano-wallet transaction submit
:
cardano-wallet transaction submit 82839f8200d818582482582029657703d662e9c36845c2f61505e96e92128605ff9eb4b635ec659ed499862501ff9f8282d818582883581c8011d974e8746a3b83cf145cde56b0053ad3fbe6dc62c5ab97f42309a102451a4170cb17001afb04e5681a000f42408282d818582883581c7e708fd52abd2263f453c0a4fdc4713a024f33fcd0acd25f058a01cda102451a4170cb17001a212741771a0086bd17ffa0818200d818588582584065eca1dee6ba9b2ef4c8515d430d800e9a2e4628062083da3f3c327eb0dccc2410723b6c2ab4b18feffe6931140d1d2ecfeb6a28ea6f0ec9fe6a5e9ac4838fd0584093f745130999ab80411b5899a39358ff3bebe470952d222b0f394bb169e1effef06587e92b38276542684583dc0eef6a9cee5acf8d1d491535dd841c5eaf5209
Ok.
{
"id": "e26e56411e10282700313e66dbe04b2f3fc201378417d2d135bca0f34df52e5c"
}