A Step-by-Step Guide to Building Your Smart Order Router Bot with Kupo, Cardano Node, and Docker
This guide provides a detailed walkthrough on setting up a Smart Order Router (SOR) using Kupo, Cardano Node, and Docker. It’s designed for those with a basic understanding of these technologies and aims to streamline the SOR deployment process.
Contents:
1. Prerequisites
- Required to install tools and software: Git, Docker
2. Setting Up the SOR Environment
- Cloning the SOR repository from GitHub.
- Installing and configuring the Cardano Node.
- Steps for installing Kupo on your local machine.
3. Creating and Configuring a Wallet
- Generating signing keys using Cardano CLI.
- Building a wallet address for the mainnet.
- Extracting the CBOR Hex value for the signing key.
4. Preparing Collateral UTXO Reference
- Sending ADA to the newly created wallet.
- Identifying and setting the COLLATERAL_UTXO_REF.
5. Running Kupo Instance
- Editing and running the kupo-mainnet.sh script based on your configuration or create your own kupo-service to run independently
- Confirming successful Kupo instance launch.
6. Building and Running the SOR Using Docker
- Building the SOR Docker image.
- Running the SOR with the customized Docker command.
7. Monitoring and Troubleshooting
- How to view logs and manage the SOR instance.
8. Additional Resources
- Links to Smart Order Router, Kupo, Cardano Node documentation for deeper insights.
Let’s start.
Assuming that your want to run your SOR on Linux environment
Install Git
sudo apt update
sudo apt install git
git --versionInstall Docker
Installing docker depends on your operation system.
I would recommend you follow the official installation guide based on your system.
Follow the guidance from the link here: https://docs.docker.com/engine/install/
Setting Up the SOR Environment
Cloning the SOR repository from GitHub.
git clone https://github.com/geniusyield/smart-order-router.git SORRun cardano node
I would recommend you following one of these documentation regarding cardano node:
- Installation with docker here
- Installation by creating a service for setting up your node , here (Recommended to simplify your own SOR installation)
Installation of Kupo
Installation can be done via 3 different paths:
- From pre-compiled executables
- From docker
- From source
I chose the first option, so here are the steps that I did:
Donwload Kupo:
wget https://github.com/CardanoSolutions/kupo/releases/tag/v2.7/kupo-2.7.2-arm64-Linux.tar.gzExtract the downloaded tar.gz file:
tar -xzvf kupo-2.7.2-arm64-Linux.tar.gzMove the Kupo binary to a directory in your PATH, such as /usr/local/bin:
mv kupo-2.7.2-arm64-Linux/bin/kupo /usr/local/bin/Make Kupo binary executyable:
chmod +x /usr/local/bin/kupoEnsure Kupo installation is working
kupo --version3. Creating and Configuring a Wallet
- Generating signing keys using Cardano CLI.
cd node/
./cardano-cli address key-gen \
--verification-key-file bot.vkey \
--signing-key-file bot.skeyAbove command will create the bot.skey, bot.vkey which are the the private signing key, the verification key of the bot respectively. Then you need to create an address for the mainnet based on the bot.vkey which is already created by following this command:
- Building a wallet address for the mainnet.
./cardano-cli address build \
--payment-verification-key-file bot.vkey \
--mainnet \
--out-file bot.addr- Extracting the CBOR Hex value for the signing key.
The bot.skey that you created above contains the cborHex value which is going to be used afterwards when we need to set PAYMENT_SIGNING_KEY_CBOR_HEX value.
Get Aggelos K’s stories in your inbox
Join Medium for free to get updates from this writer.
So in order to find its value, you can do the command under node/ folder as well (this command can be done wherever you have saved your bot addresses and private/verification keys):
cat bot.skey | jq -r '.cborHex'This value should not be shared to anyone but is going to be used later.
4. Preparing Collateral UTXO Reference
Sending ADA to the newly created wallet
In this stage you need to send at least 5 ADA in your newly created wallet, in one or more transactions , which one of them is going to be used for collateral.
Identifying and setting the COLLATERAL_UTXO_REF
After sending the ADA to your wallet, you can query the address to see the utxos:
./cardano-cli query utxo --address $(cat bot.addr) --mainnet --socket-path /root/node/sockets/node.socketwhere you will see something like this:
TxHash TxIx Amount
--------------------------------------------------------------------------------------
fbfa56e74a0ed92e53c6ed94dc290610d918760e25a700c5a96aee4c62562286 0 5000000 lovelace + TxOutDatumNoneAssign the result to COLLATERAL_UTXO_REF (TxHash#Tx), for example: (COLLATERAL_UTXO_REF=fbfa56e74a0ed92e53c6ed94dc290610d918760e25a700c5a96aee4c62562286#0)
5. Running Kupo Instance
- Editing and running the kupo-mainnet.sh script based on your configuration OR create your own kupo-service to run independently. I will write both ways below so select based on your preference.
- Goal of this step is to run your own Kupo Instance either by updating the script under SOR/scripts/kupo-mainnet.sh (simpler) OR by creating a kupo service (recommended)
Update your own kupo-mainnet.sh
cd SOR/scripts/
nano kupo-mainnet.shFROM_BABBAGE=72316796.c58a24ba8203e7629422a24d9dc68ce2ed495420bf40d9dab124373655161a20
MATCH_ORDERS=22f6999d4effc0ade05f6e1a70b702c65d6b3cdf0e301e4a8267f585.*
MATCH_BOT=<your bot.addr here>
MATCH_MINTING_POLICY_REF=1@062f97b0e64130bc18b4a227299a62d6d59a4ea852a4c90db3de2204a2cd19ea
MATCH_VALIDATOR_REF=2@062f97b0e64130bc18b4a227299a62d6d59a4ea852a4c90db3de2204a2cd19ea
MATCH_CONFIG_ADDR=addr1w9zr09hgj7z6vz3d7wnxw0u4x30arsp5k8avlcm84utptls8uqd0z
kupo \
--host 0.0.0.0 \
--port 1442 \
--node-socket /root/node/sockets/node.socket \
--node-config /root/node/configuration/cardano/mainnet-config.json \
--since $FROM_BABBAGE \
--defer-db-indexes \
--match $MATCH_ORDERS \
--match $MATCH_BOT \
--match $MATCH_MINTING_POLICY_REF \
--match $MATCH_VALIDATOR_REF \
--match $MATCH_CONFIG_ADDR \
--prune-utxo \
--workdir /root/node/kupo/sor/dbAbove we updated the script by setting variables that will be used to run Kupo instance and also to point to your local cardano node configuration and node socket path. Which means that whatever you see above next to — node-socket , — node-config and — workdir should be updated based on your local environment respectively.
Confirming successful Kupo instance launch.
./kupo-mainnet.shOR
Create your own Kupo Service
Create a New Service File: Open a new service file in the /etc/systemd/system/ directory with your preferred text editor. For example, you can use nano:
sudo nano /etc/systemd/system/kupo.serviceAdd Service Configuration: In the service file, add the following configuration (adjust paths and options according to your setup):
[Unit]
Description=Kupo Service
After=network.target
[Service]
ExecStart=/usr/local/bin/kupo [Your Kupo Arguments Here]
WorkingDirectory=/root/SOR/scripts
Restart=always
User=root
[Install]
WantedBy=multi-user.targetYour arguments should be the same arguments as you would put them in kupo-mainnet.sh so like this in above case:
[Service]
ExecStart=/usr/local/bin/kupo --host 0.0.0.0 --port 1442 --node-socket /root/node/sockets/node.socket --node-config /root/node/configuration/cardano/mainnet-config.json --since 72316796.c58a24ba8203e7629422a24d9dc68ce2ed495420bf40d9dab124373655161a20 --defer-db-indexes --match 22f6999d4effc0ade05f6e1a70b702c65d6b3cdf0e301e4a8267f585.* --match <YOUR BOT ADDRESS HERE> --match 1@062f97b0e64130bc18b4a227299a62d6d59a4ea852a4c90db3de2204a2cd19ea --match 2@062f97b0e64130bc18b4a227299a62d6d59a4ea852a4c90db3de2204a2cd19ea --match addr1w9zr09hgj7z6vz3d7wnxw0u4x30arsp5k8avlcm84utptls8uqd0z --prune-utxo --workdir /root/node/kupo/sor/dbbut instead of <YOUR BOT ADDRESS HERE> you should put your own bot.addr.
Also, Replace /usr/local/bin/kupo with the actual path to the kupo binary if it's different.
Reload Systemd and Enable Service: After saving and closing the file:
sudo systemctl daemon-reload
sudo systemctl enable kupo.service
sudo systemctl start kupo.serviceCheck Status: To ensure the service is running correctly:
sudo systemctl status kupo.serviceor you can check the latest 100 lines of the logs like this:
journalctl -u kupo.service --lines=100Normally you have to see something like this:
6. Building and Running the SOR Using Docker
Since cardano node and Kupo instance are running properly, you are close to run your own SOR:
Building the SOR Docker image
cd ~
cd SOR
docker build .Running the SOR with the customized Docker command
Update values based on your configuration of:
PAYMENT_SIGNING_KEY_CBOR_HEX= - follow the instructions above and put the correct value-
COLLATERAL_UTXO_REF= - follow the instructions above and put the correct value -
KUPO_URL=http://your.server.ip.here:1442
CARDANO_NODE_SOCKET_PATH=/root/node/sockets/node.socket
CARDANO_NETWORK=mainnetPAYMENT_SIGNING_KEY_CBOR_HEX:This is the CBOR Hex representation of your payment signing key. You already have the bot.skey file, so you need to extract the cborHex value from it.
COLLATERAL_UTXO_REF: This refers to a specific unspent transaction output (UTXO) that the bot will use as collateral. You need to identify a UTXO from the wallet address used by the bot. You can use the cardano-cli query utxo command to list UTXOs for your bot’s address, as I have shown above.
You are ready to launch your Smart Order Router (SOR) bot:
Firstly copy the docker image that you build before after executing below command:
docker image lsThen run your own SOR with docker by following this command
docker run -it -d \
-e BOTC_SKEY="{\"cborHex\": \"$PAYMENT_SIGNING_KEY_CBOR_HEX\", \"type\": \"PaymentSigningKeyShelley_ed25519\", \"description\": \"Payment Signing Key\"}" \
-e BOTC_COLLATERAL="$COLLATERAL_UTXO_REF" \
-e BOTC_CONFIG="{\"coreProvider\": { \"socketPath\": \"/cardano/node/socket\", \"kupoUrl\": \"$KUPO_URL\" }, \"networkId\": \"$CARDANO_NETWORK\", \"logging\": [{ \"type\": { \"tag\": \"stderr\" }, \"severity\": \"Info\", \"verbosity\": \"V2\" }], \"utxoCacheEnable\": false }" \
-v $CARDANO_NODE_SOCKET_PATH:/cardano/node/socket \
0e57bdd15e6bwhere 0e57bdd15e6b is an example of the IMAGE ID of the last build image for SOR. On your environment will be found with the result of the command above about ```docker image ls```
And that was it. Your SOR should run from now on. Your SOR should expect matches from this moment. Good luck!
7. Monitoring and Troubleshooting
- How to view logs and manage the SOR instance.
docker ps -a
docker logs <CONTAINER ID>8. Additional Resources
- Smart Order Router Repository,
- Kupo,
- Cardano Node documentation
- How to become SOR operator — Workshop with DR Lars Brunjes
- What is a Smart Order Router (SOR) in the Genius Yield Platform?
Many credits for the above documentation goes also to Hummus for his contribution to setting up the bot and for the technical documentation.
Genius Yield — Genius Yield Greece — Genius Yield Italia — Genius X









