# Komodo DeFi Framework Walkthrough

Now that you have the Komodo DeFi Framework installed you are ready for your first atomic swap!

Since we're testing Komodo DeFi Framework as a back end, we're going to be doing a few things that a normal user using a GUI will not be expected to do.

Let's open up the terminal and get started.

# Setting Up the Coin List

In the Komodo ecosystem we use two blockchain coins, RICK and MORTY, for testing purposes. These coins are freely distributed and have no blockchain scarcity, so you don't want to treat these coins as real currency. Also, if you lose them or destroy them, there's no need to stress. You can always grab more from our faucet.

Let's set up a file in the ~/atomicDEX-API/target/debug directory to import the settings for these test coins. Make a file called coins and place the following text into it:

[
  {
    "coin": "RICK",
    "asset": "RICK",
    "fname": "RICK (TESTCOIN)",
    "rpcport": 25435,
    "txversion": 4,
    "overwintered": 1,
    "mm2": 1,
    "protocol": {
      "type": "UTXO"
    }
  },
  {
    "coin": "MORTY",
    "asset": "MORTY",
    "fname": "MORTY (TESTCOIN)",
    "rpcport": 16348,
    "txversion": 4,
    "overwintered": 1,
    "mm2": 1,
    "protocol": {
      "type": "UTXO"
    }
  }
]

Save this file. Komodo DeFi Framework will search for it automatically on launch.

TIP

The coins file in this linked repository (opens new window) contains the standard coin configuration file used in GUI software.

The electrum server configuration for enabling coins can also be found in the the electrums directory (opens new window) in the KomodoPlatform-coins repository.

# RPC password

We also need to choose a password.

Make it a secure one by including at least 8 characters, both uppercase and lowercase letters, and a few numbers and symbols.

Write this down in a safe location where you won't lose it.

We have our initial materials, let's launch the software.

# Initiate Komodo DeFi Framework 2.0

Look at the following command below, but don't execute it yet:

stdbuf -oL ./mm2 "{\"gui\":\"Docs_Walkthru\",\"netid\":7777, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"YOUR_PASSPHRASE_HERE\", \"rpc_password\":\"YOUR_PASSWORD_HERE\"}" &

Replace YOUR_PASSPHRASE_HERE and YOUR_PASSWORD_HERE with your actual passphrase and password, and then execute the command in the terminal.

Here is an approximate interpretation of the arguments in the command, to help you see what's happening:

Argument (Value) Description
gui Docs_Walkthru information about your GUI; place essential info about your application (name, version, etc.) here. For example: Komodo Mobile Wallet iOS 1.0.1
netid 7777 this tells the Komodo DeFi Framework which network to join. 7777 is the default network, though you can set this to a different value to use a separate network if seednodes exist for it.
passphrase YOUR_PASSPHRASE_HERE your passphrase; this is the source of each of your coins' private keys
rpc_password YOUR_PASSWORD_HERE your password for protected RPC methods (userpass)
userhome /${HOME#"/"} the path to your home, called from your environment variables and entered as a regular expression

Having executed the command, you should see output similar to the following:

29 19:39:41, lp_coins:796] ticker = "BTC", method = Some("enable"), block_count = 0 😅 2019-01-29 20:39:41 +0100 [coin KMD no-conf] Warning, coin KMD is used without a corresponding configuration.
cant open.(/root/.komodo/komodo.conf)
29 19:39:41, lp_coins:796] ticker = "KMD", method = Some("enable"), block_count = 0
RPCport.7783 remoteport.7782, nanoports 47762 47772 47782
29 19:39:41, peers:942] initialize] netid 7777 public key ab44ae49d2ff89295ee9a0574e89a2bdd7bfbb4f1a34f7d5c0256cf06e89485d preferred port 47773 drill false
connected to push.(tcp://333.333.333.333:47762) pushsock.0 valid.1  | connected to sub.(tcp://333.333.333.333:47772) subsock.1 valid.1 numactive.1
connected to push.(tcp://333.333.333.333:47762) pushsock.2 valid.1  | connected to sub.(tcp://333.333.333.333:47772) subsock.3 valid.1 numactive.1
_LPaddpeer 333.333.333.333 -> numpeers.2 mypubsock.-1 other.(0)
29 19:39:41, rpc:334] >>>>>>>>>> DEX stats 127.0.0.1:7783 DEX stats API enabled at unixtime.1548790781 <<<<<<<<<
· 2019-01-29 20:39:41 +0100 [dht-boot] DHT bootstrap ... Done.
New priority.1 max_Reserved_msgs.1
29 19:40:01, lp_signatures:613] lp_notify_recv] hailed by peer: 127.0.0.85
29 19:40:01, peers:996] investigate_peer] ip 127.0.0.85 preferred port 7803
29 19:40:01, peers:355] Sending a ping to V4(127.0.0.85:7803)…
connected to push.(tcp://127.0.0.85:7793) pushsock.4 valid.1  | connected to sub.(tcp://127.0.0.85:7803) subsock.5 valid.1 numactive.2
_LPaddpeer 127.0.0.85 -> numpeers.3

The terminal will then repeat similar output to the following every so often:

04 21:28:47, peers:996] investigate_peer] ip 54.36.126.42 preferred port 7803
04 21:28:47, peers:355] Sending a ping to V4(54.36.126.42:7803)…
04 21:29:08, lp_signatures:613] lp_notify_recv] hailed by peer: 54.36.126.42

If you see something similar, the Komodo DeFi Framework is up and running!

TIP

When using the Komodo DeFi Framework on a VPS without accompanying tools such as tmux or screen, Komodo recommends that the user add the command nohup to the Komodo DeFi Framework launch command. This addition ensures that the Komodo DeFi Framework instance is not shutdown when the user logs out.

Example:

stdbuf -oL nohup ./mm2 "{\"gui\":\"Docs_Walkthru\",\"netid\":7777, \"userhome\":\"/${HOME#"/"}\", \"passphrase\":\"YOUR_PASSPHRASE_HERE\", \"rpc_password\":\"YOUR_PASSWORD_HERE\"}" &

# Setting userpass Environment Variable

TIP

Userpass will be renamed to rpc_password for clarity in the near future

Make a new file in the ~/atomicDEX-API/target/debug directory called userpass and enter the following text, including the rpc_password you specified earlier:

export userpass="RPC_PASSWORD"

Save it, and then in the terminal execute:

source userpass

Test it by executing:

echo $userpass

You should see your userpass as a returned value.

TIP

The userpass environment variable will remain in our terminal's memory until we close the session. When we open up a new session later, we need to create the userpass environment variable again. Later, a GUI designer can create functionality to perform this automatically.

# Connect to the Relevant Coin Networks

While we did set up the coins' configuration properties in the internal files, MM2 isn't going to connect to their blockchain networks immediately.

One reason for this is that if you trade between many coins, the startup process would require connecting to every coin all at once.

We'll tell MM2 that we're ready to activate these coins now.

Execute the following command:

curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"RICK\",\"servers\":[{\"url\":\"electrum1.cipig.net:10017\"},{\"url\":\"electrum2.cipig.net:10017\"},{\"url\":\"electrum3.cipig.net:10017\"}]}"

You should get a similar response:

{
  "address": "RLgAgBFHFbG2ma9MDTHyKL5vovftMepBkE",
  "coin": "RICK",
  "balance": 16.95595733,
  "result": "success"
}

You are now connected to the RICK test-blockchain network.

Let's connect to MORTY (note it uses a different Electrum port).

curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"electrum\",\"coin\":\"MORTY\",\"servers\":[{\"url\":\"electrum1.cipig.net:10018\"},{\"url\":\"electrum2.cipig.net:10018\"},{\"url\":\"electrum3.cipig.net:10018\"}]}"

You should get a similar response:

{
  "address": "RLgAgBFHFbG2ma9MDTHyKL5vovftMepBkE",
  "coin": "MORTY",
  "balance": 11.27710708,
  "result": "success"
}

You are now connected to the MORTY test-blockchain network.

# Get MORTY From a Faucet

Note that in the examples the address, RLgAgBFHFbG2ma9MDTHyKL5vovftMepBkE, is present in both returned responses.

You will see a different address in your returned responses.

This address is unique to you and you will use it for our trades here.

We don't recommend placing anything valuable in this address for now, as Komodo DeFi Framework is still in testing.

On the other hand, RICK and MORTY have no real value, so you can place as much in here as you like!

Let's retrieve some MORTY.

Click on this link (opens new window) and you should see an address input box.

Place your address in there, fill out the reCaptcha to prove you're a human, and hit OK.

In a minute or so a few MORTY coins will arrive in your address.

You can check by executing this command:

curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"my_balance\",\"coin\":\"MORTY\"}"

You should see a similar response:

{
  "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ",
  "balance": 77.7,
  "coin": "MORTY"
}

You now have MORTY.

# Observing the Orderbook

The Komodo DeFi Framework uses a decentralized orderbook to allow users to buy and sell from each other without having to rely on a centralized service. This gives it an increased level of security, as there is no central agency that can manipulate prices. This also prevents "wash" trading, where trading activity is faked.

To see the orderbook's current state, execute the following command:

curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"RICK\",\"rel\":\"MORTY\"}"

This sends a request to MM2 to see who is willing to give up RICK for MORTY.

The call will return a similar result:

{
  "bids": [],
  "numbids": 0,
  "biddepth": 0,
  "asks": [
    {
      "coin": "RICK",
      "address": "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh",
      "price": "0.89999998",
      "price_rat": [
        [1, [813957463, 471859]],
        [1, [0, 524288]]
      ],
      "price_fraction": {
        "numer": "2026619787280727",
        "denom": "2251799813685248"
      },
      "maxvolume": "10855.85028615",
      "max_volume_rat": [
        [1, [3593286463, 1389548]],
        [1, [0, 128]]
      ],
      "max_volume_fraction": {
        "numer": "5968066809508671",
        "denom": "549755813888"
      },
      "pubkey": "5a2f1c468b7083c4f7649bf68a50612ffe7c38b1d62e1ece3829ca88e7e7fd12",
      "age": 5,
      "zcredits": 0,
      "uuid": "5bff6021-b086-477e-b874-f45d898933fe",
      "is_mine": false
    }
  ],
  "numasks": 1,
  "askdepth": 0,
  "base": "RICK",
  "rel": "MORTY",
  "timestamp": 1549319941,
  "netid": 7777
}

This is the current orderbook.

Notice that the output is not easily readable in the terminal. This is where we start using jq.

You may remember that we installed software called jq during the setup process. jq is optional, but it is recommended as it makes reading the output in the terminal easier.

To activate jq, simply add the following to the end of any command: | jq.

For example:

curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"orderbook\",\"base\":\"RICK\",\"rel\":\"MORTY\"}" | jq

(If using jq gives you troubles, you can remove it from any of the commands without issue. It is only here for convenience.)

Here's the response:

{
  "bids": [],
  "numbids": 0,
  "biddepth": 0,
  "asks": [
    {
      "coin": "RICK",
      "address": "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh",
      "price": "2",
      "price_rat": [
        [1, [2]],
        [1, [1]]
      ],
      "price_fraction": {
        "numer": "2",
        "denom": "1"
      },
      "maxvolume": "10855.85028615",
      "max_volume_rat": [
        [1, [3593286463, 1389548]],
        [1, [0, 128]]
      ],
      "max_volume_fraction": {
        "numer": "5968066809508671",
        "denom": "549755813888"
      },
      "pubkey": "5a2f1c468b7083c4f7649bf68a50612ffe7c38b1d62e1ece3829ca88e7e7fd12",
      "age": 9,
      "zcredits": 0,
      "uuid": "5bff6021-b086-477e-b874-f45d898933fe",
      "is_mine": false
    }
  ],
  "numasks": 1,
  "askdepth": 0,
  "base": "RICK",
  "rel": "MORTY",
  "timestamp": 1549320152,
  "netid": 7777
}

That's much easier to read. We can easily see someone with the address RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh.

"address": "RJTYiYeJ8eVvJ53n2YbrVmxWNNMVZjDGLh",

They are willing to give up RICK for MORTY.

"base": "RICK",
"rel": "MORTY",

They are asking 2 MORTY for every 1 RICK.

"price": 2,

They have a total of 10855.85028615 available to trade.

"maxvolume": 10855.85028615,

# Initiate a Swap

Let's create a RICK/MORTY buy order

curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"buy\",\"base\":\"RICK\",\"rel\":\"MORTY\",\"volume\":\"1\",\"price\":\"2\"}" | jq

You should receive a similar response:

{
  "result": {
    "action": "Buy",
    "base": "RICK",
    "base_amount": "1",
    "dest_pub_key": "0000000000000000000000000000000000000000000000000000000000000000",
    "method": "request",
    "rel": "MORTY",
    "rel_amount": "2",
    "sender_pubkey": "c213230771ebff769c58ade63e8debac1b75062ead66796c8d793594005f3920",
    "uuid": "288743e2-92a5-471e-92d5-bb828a2303c3"
  }
}

If you see order data in the response, the order was successfully submitted to the network.

Your swap is not yet started, however.

From here, everything is automated.

If your order is matched you will see something similar in terminal output:

26 10:51:50, lp_ordermatch:333] Entering the taker_swap_loop RICK/MORTY
26 10:51:51, lp_ordermatch:490] CONNECTED.({"dest_pub_key":"c213230771ebff769c58ade63e8debac1b75062ead66796c8d793594005f3920","maker_order_uuid":"cbe664e7-3be5-4b45-9bd0-03c6a785e636","method":"connected","sender_pubkey":"199fe4169c30f464bc022273de0c893b4e2864128cdc9f7126fa24bc0910fd0e","taker_order_uuid":"c4d1b840-ebe8-4e44-9cb8-f6c767d3972f"})
26 10:52:12, lp_swap:1629] Received 'negotiation@c4d1b840-ebe8-4e44-9cb8-f6c767d3972f' (69 bytes, crc 794323698)
26 10:52:12, lp_swap:1658] Sending 'negotiation-reply@c4d1b840-ebe8-4e44-9cb8-f6c767d3972f' (69 bytes, crc 2294558621)
26 10:52:53, lp_swap:1665] Received 'negotiated@c4d1b840-ebe8-4e44-9cb8-f6c767d3972f' (1 bytes, crc 2768625435)
26 10:53:00, lp_swap:1731] Taker fee tx hash 2e019f6eb2e43b4d96c6400c86c0b65364024a21e8feb555aa108d3c9518989c
26 10:53:00, lp_swap:1740] Sending 'taker-fee@c4d1b840-ebe8-4e44-9cb8-f6c767d3972f' (244 bytes, crc 3461506896)
26 10:53:44, lp_swap:1748] Received 'maker-payment@c4d1b840-ebe8-4e44-9cb8-f6c767d3972f' (242 bytes, crc 2227964296)
26 10:53:44, lp_swap:1764] Got maker payment 5648da6db5143551fa6ceffe7ef7b0a21b2a4dd479cb7a12dd46f73f2fd87597
26 10:53:45, rpc_clients:111] Waiting for tx 5648da6db5143551fa6ceffe7ef7b0a21b2a4dd479cb7a12dd46f73f2fd87597 confirmations, now 0, required 1
26 10:53:56, rpc_clients:111] Waiting for tx 5648da6db5143551fa6ceffe7ef7b0a21b2a4dd479cb7a12dd46f73f2fd87597 confirmations, now 0, required 1
26 10:54:06, rpc_clients:111] Waiting for tx 5648da6db5143551fa6ceffe7ef7b0a21b2a4dd479cb7a12dd46f73f2fd87597 confirmations, now 0, required 1
26 10:54:16, rpc_clients:111] Waiting for tx 5648da6db5143551fa6ceffe7ef7b0a21b2a4dd479cb7a12dd46f73f2fd87597 confirmations, now 0, required 1
26 10:54:27, rpc_clients:111] Waiting for tx 5648da6db5143551fa6ceffe7ef7b0a21b2a4dd479cb7a12dd46f73f2fd87597 confirmations, now 0, required 1
26 10:54:43, lp_swap:1863] Taker payment tx hash 368a9ee2db36feb6870266695be72e8ed8d1beb2afd95d62920f1d620941fff2
26 10:54:44, lp_swap:1885] Sending 'taker-payment@c4d1b840-ebe8-4e44-9cb8-f6c767d3972f' (242 bytes, crc 3588913089)
26 10:57:11, lp_swap:1902] Taker payment spend tx 364c0df46028be2439f15a31ddae534a98d0e20ec22464c69a9086807f3afc89
26 10:57:14, lp_swap:1949] Maker payment spend tx b8c2a30f23cebb48f0d8fe0a048a65755ca5b8f56f4c68f80d044acd0f8e1ce6
· 2019-06-26 17:57:14 +0700 [swap uuid=c4d1b840-ebe8-4e44-9cb8-f6c767d3972f] Finished
    Maker payment spent...
    Taker payment spent...
    Taker payment sent...
    Maker payment validated and confirmed...
    Maker payment wait confirm started...
    Maker payment received...
    Taker fee sent...
    Negotiated...
    Started...

When you see that last line, you know that your swap went through:

29 22:48:03, lp_ordermatch:781] Swap finished successfully

Let's check by looking at your RICK balance. Execute this command:

curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"my_balance\",\"coin\":\"RICK\"}" | jq

You should receive a similar response, the balance will be a bit less than volume set on trade as you have to pay the fee to mine your swap transaction:

{
  "address": "RQNUR7qLgPUgZxYbvU9x5Kw93f6LU898CQ",
  "balance": 0.99999,
  "coin": "RICK"
}

Congratulations! You are one of the first people in history to trade a currency without any help from a middleman and without even having to know your trading partner.

When you are finished, exit using the following command:

curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"stop\"}"

Please reach out to us on Discord (opens new window) and tell us about your experience.