ErgoDexTool is a command-line interface for Ergo blockchain. It is implemented in Scala using Ergo Appkit Commands framework. ErgoDexTool is a Java application which uses Java 8 or later compliant JRE for execution. In addition you can compile ErgoDexTool to a native executable using GraalVM's native-image. This capability is inherited from Appkit, which is native-image friendly by design.
Native executables are especially attractive for CLI tools, because of the very fast start up times (comparing to a typical start up pause of a JVM based executable). Please follow the installation instructions to setup ErgoDexTool on your system.
There are three participants (buyer, seller and the matcher) of the DEX dApp which create five
different transaction types. The buyer wants to swap ergAmt
ERGs for tAmt
of TID
tokens (or seller wants to sell, who send the orders first doesn't matter). Both the buyer
and the seller can cancel their orders. The DEX off-chain service can find matching orders
and create a special Swap
transaction to complete the exchange without knowledge of any
secrets, thus both the buyer and the seller are in full control of their funds.
The following diagram fully specifies all the five transactions of the DEX scenario. For each transaction there is a corresponding command in ErgoDexTool as well as additional commands to list orders, create tokens etc (see Commands).
Installation of ErgoDexTool on your computer is simple and depend on how you want to obtain the executable binary files.
- you can build ErgoDexTool yourself from source code (which is a recommended method for security sensitive software) and use the executables generated this way.
- or alternatively (if you trust the developers) you can download pre-built executables and install from release package.
The instructions below should work on POSIX OSes (i.e. Linux, MacOS) and were tested on MacOS.
You need to have git installed on your system. Open Terminal and use the following commands to clone the ErgoDexTool source code.
$ git clone https://github.com/ergoplatfoeckm/ergo-dex.git
Cloning into 'ergo-dex'...
...
Once the clone operation is complete you can compile ErgoDexTool.
In order to compile ErgoDexTool you need to have SBT installed on your system.
Run the following commands to build a Java fat jar file with ErgoDexTool and all the
dependencies needed to run it using the java
launcher.
$ cd ergo-dex
$ sbt assembly
you should see the output which looks like the following
[info] Loading global plugins from ~/.sbt/1.0/plugins
...
[info] Packaging ./target/scala-2.12//ergodex-0.1.0.jar ...
[info] Done packaging.
[success] Total time: 31 s, completed Mar 19, 2020 1:22:27 PM
Now run the compiled ErgoDexTool using the following command which runs the ErgoDexTool CLI application. Note, you should run this command while in the root folder of the cloned ErgoDexTool repository.
$ java -jar target/scala-2.12/ergodex-0.1.0.jar --conf ergo_tool_config.json
Please specify command name and parameters.
Usage:
ergotool [options] action [action parameters]
Available actions:
dex:BuyOrder <wallet file> <ergAmount> <tokenId> <tokenAmount>, <dexFee>
put a token buyer order with given <tokenId> and <tokenAmount> to buy at given <ergPrice> price with <dexFee> as a reward for anyone who matches this order with a seller, with wallet's address to be used for withdrawal
with the given <wallet file> to sign transaction (requests storage password)
dex:CancelOrder <wallet file> <orderBoxId>
claim an unspent buy/sell order (by <orderBoxId>) and sends the ERGs/tokens to the address of this wallet (requests storage password)
dex:IssueToken <wallet file> <ergAmount> <tokenAmount> <tokenName> <tokenDesc> <tokenNumberOfDecimals>
issue a token with given <tokenName>, <tokenAmount>, <tokenDesc>, <tokenNumberOfDecimals> and <ergAmount> with the given <wallet file> to sign transaction (requests storage password)
dex:ListMatchingOrders
show matching token seller's and buyer's orders
dex:ListMyOrders <address>
show buy and sell orders created from the given address
dex:MatchOrders <wallet file> <sellerHolderBoxId> <buyerHolderBoxId> <minDexFee
match an existing token seller's order (by <sellerHolderBoxId>) and an existing buyer's order (by <buyerHolderBoxId) and send tokens to buyer's address(extracted from buyer's order) and Ergs to seller's address(extracted from seller's order) claiming the minimum fee of <minDexFee> with the given <wallet file> to sign transaction (requests storage password)
dex:SellOrder <wallet file> <ergPrice> <tokenId> <tokenAmount> <dexFee>
put a token seller order with given <tokenId> and <tokenAmount> for sale at given <ergPrice> price with <dexFee> as a reward for anyone who matches this order with buyer, with wallet's address to be used for withdrawal
with the given <wallet file> to sign transaction (requests storage password)
dex:ShowOrderBook <tokenId>
show order book, sell and buy order for a given token id
help <commandName>
prints usage help for a command
Options:
--conf
configuration file path relative to the local directory (Example: `--conf ergo_tool.json`
--dry-run
Forces the command to report what will be done by the operation without performing the actual operation.
--limit-list
Specifies a number of items in the output list.
--print-json
Forces the commands to print json instead of table rows.
The command prints usage information with the available commands and options.
Release packages are published on the releases page. Please download the appropriate archive and extract it locally on you computer.
A unit of execution in ErgoDexTool is a command. Specify the command by its name followed by options and parameters when you start the tool in the command line.
$ ./ergo-dex.sh dex:IssueToken --conf my_config.json storage.json 1000000 1000 "TKN" "DEX test token" "2"
The command option has the name with --
prefix (i.e. --conf
) and the value (i.e.
my_config.json
) which goes after the whitespace. Options (name-value pairs) can go
anywhere in the command line. The tool first extracts all the options from the command
line and uses all the remaining components as the command name and parameters.
For further detail of how the ErgoDexTool parses a command line see this description.
Click on the command name to open its detailed description.
Command | Description |
---|---|
dex:IssueToken | <wallet file> <ergAmount> <tokenAmount> <tokenName> <tokenDesc> <tokenNumberOfDecimals> issue a token with given tokenName , tokenAmount , tokenDesc , tokenNumberOfDecimals and ergAmount with the given wallet file to sign transaction (requests storage password) |
TODO generate table for the rest of the commands
The first operation in the lifecycle of a new token is its issue. Ergo natively support issue, storage and transfer of tokens. Use ErgoDexTool to issue tokens according to the EIP-4 Standard.
You can issue a token by creating a new box with the ergAmount
of ERGs and (tokenId
,
tokenAmount
) pair in the R2
register. The tool automatically selects tokenId
using
the id of the first input box of the transaction.
You also need to specify additional parameters of the command to fill up registers
(as the EIP-4 Standard
requires).
The dex:IssueToken
command uses a wallet storage given by the <wallet file>
parameter
to transfer the ergAmount
amount of ERGs to a new box with tokens. The new box belongs
to the same wallet given by <wallet file>
.
The following ErgoDexTool command allows to issue a new token on the Ergo blockchain.
$ ./ergo-dex.sh dex:IssueToken "storage/E2.json" 50000000 1000000 "TKN" "Generic token" 2
Creating prover... Ok
Loading unspent boxes from at address 9hHDQb26AjnJUXxcqriqY1mnhpLuUeC81C4pggtK7tupr92Ea1K... Ok
Signing the transaction... Ok
...
When we have tokens in a box we can sell them on Ergo DEX by creating a sell order and
submit it to the order book. In ErgoDexTool implementation we create orders and store them
directly on the Ergo blockchain. The created order is the ask
box (see diagram)
protected with the special seller contract holding the minimum amount of ERGs (minErg
)
and tokenAmount
of the TID
tokens.
/** The `sellOrder` contract which protects the `ask` box (see the diagram)
* @param ergAmt nanoERG amount seller wants to receive for the tokens
* @param pkSeller public key of the seller
* @return sigma protocol proposition (see ErgoTree Specification)
*/
def sellOrder(ctx: Context, ergAmt: Long, pkSeller: SigmaProp): SigmaProp = {
import ctx._
pkSeller || (
OUTPUTS.size > 1 &&
OUTPUTS(1).R4[Coll[Byte]].isDefined
) && {
val knownBoxId = OUTPUTS(1).R4[Coll[Byte]].get == SELF.id
OUTPUTS(1).value >= ergAmt &&
knownBoxId &&
OUTPUTS(1).propositionBytes == pkSeller.propBytes
}
}
The contract is implemented in the repository of certified contracts.
The sellOrder
contract guarantees the following:
- The seller can spend the
ask
box at any time, which is the way for a seller to cancel the order - Anyone else can create a swap transaction which spends both the
ask
box and the matchedbid
box atomically (see the diagram and also buy tokens).
Use the following command to create a new ask
box to sell tokens:
$ ./ergo-dex.sh dex:SellOrder storage/secret.json 10000000 "d0105f7469be3ac90f16d943b29133f16c3bf4d85bd754656194cead849baf1e" 3 5000000
Storage password>
Creating prover... Ok
Loading unspent boxes from at address 3WxrCKgrcmS7oPpWXgwuKNiB1JSNEmpyqaXPM1cBrXiJY1jhk4Ep... Ok
Signing the transaction... Ok
You may also want to buy tokens, either because you believe it's value is going to surge
or you need one to participate in a dApp which require having some tokens or whatever
reason you may have. You can create a buy order and submit it to the order book. The
created order is a bid
box (see diagram) protected with the special buyer contract.
The bid
box holds the necessary amount of ERGs and whose contract checks the swap
conditions (given tokenId
and tAmt
you want to buy).
/** The `buyOrder` contract which protects the `bid` box (see the diagram)
* @param tokenId token id to buy
* @param tAmt token amount to buy
* @param pkBuyer public key for the buyer
* @return sigma protocol proposition (see ErgoTree Specification)
*/
def buyer(
ctx: Context,
tokenId: Coll[Byte],
tAmt: Long,
pkBuyer: SigmaProp
): SigmaProp = {
import ctx._
pkBuyer || {
(OUTPUTS.nonEmpty && OUTPUTS(0).R4[Coll[Byte]].isDefined) && {
val tokens = OUTPUTS(0).tokens
val tokenDataCorrect = tokens.nonEmpty &&
tokens(0)._1 == tokenId &&
tokens(0)._2 >= tAmt
val knownId = OUTPUTS(0).R4[Coll[Byte]].get == SELF.id
tokenDataCorrect &&
OUTPUTS(0).propositionBytes == pkBuyer.propBytes &&
knownId
}
}
}
The contract is implemented in the repository of certified contracts.
The buyOrder
contract guarantees the following:
- The buyer can spend the
bid
box at any time, which is the way for a buyer to cancel the order - Anyone else can create a swap transaction which spends both the
ask
box and the matchedbid
box atomically (see the diagram and also buy tokens).
Use the following command to create a new buy order to buy tokens:
$ ./ergo-dex.sh dex:BuyOrder storage/secret.json 10000000 "d0105f7469be3ac90f16d943b29133f16c3bf4d85bd754656194cead849baf1e" 3 5000000
Storage password>
Creating prover... Ok
Loading unspent boxes from at address 3WxrCKgrcmS7oPpWXgwuKNiB1JSNEmpyqaXPM1cBrXiJY1jhk4Ep... Ok
Signing the transaction... Ok
To show your outstanding buy/sell orders (that use your public key in their contracts) use
dex:ListMyOrders
command:
$ ./ergo-dex.sh dex:ListMyOrders "9hHDQb26AjnJUXxcqriqY1mnhpLuUeC81C4pggtK7tupr92Ea1K"
Storage password>
Creating prover... Ok
Loading seller boxes... Ok
Loading buyer boxes... Ok
Orders created with key 9hHDQb26AjnJUXxcqriqY1mnhpLuUeC81C4pggtK7tupr92Ea1K:
Sell:
Box id Token ID Token amount Token price Box value
357bba87df0299ed692e3945fcf6ab88465e0dc7fff6db48957c939603ae23f0 d0105f7469be3ac90f16d943b29133f16c3bf4d85bd754656194cead849baf1e 3 10000000 5000000
Buy:
Box id Token ID Token amount Box value
To show all outstanding sell and buy orders for a particular token use dex:ShowOrderBook
command. Below is an example of using dex:ShowOrderBook
:
$ ./ergo-dex.sh dex:ShowOrderBook "56cf33485be550cc32cf607255be8dc8c32522d0539f6f01d44028dc1d190450"
Loading seller boxes... Ok
Loading buyer boxes... Ok
Order book for token 56cf33485be550cc32cf607255be8dc8c32522d0539f6f01d44028dc1d190450:
Sell orders:
BoxId Token Amount Erg Amount(including DEX fee)
10008261a053ffb63919a410059a4e6bf1c87de6020198138544ebcbf9c2182c 100 1005000000
Buy orders:
BoxId Token Amount Erg Amount(including DEX fee)
8cc5b491f31db054f80c93b08704155fa68fa3a8477b87a8c0ef7097cda3c80d 100 1005000000
You can use the dex:MatchOrders
command to match and swap buy and sell orders.
The command creates and sends a new transaction which spends the bid
and ask
boxes
with matching ergAmt
and tAmt
values.
The command:
- requests the storage password from the user, reads the storage file, unlocks it using password and gets the secret to sign the transaction;
- finds the boxes with buyer's and seller's orders (using
buyerHolderBoxId
andsellerHolderBoxId
); - computes the amount of change (including dexFee and checking it is at least
minDexFee
); - create output boxes for buyer's tokens and seller's Ergs;
- create a transaction spending buyer's and seller's order boxes and sign it using sender`s key.
$ ./ergo-dex.sh dex:MatchOrders storage "10008261a053ffb63919a410059a4e6bf1c87de6020198138544ebcbf9c2182c" "d5b150c73baad5debbaaeab27ee269cbd487ff0dcab8ff0cd5084dff8f0db167" 1000000
Storage password>
Creating prover... Ok
Loading seller's box (10008261a053ffb63919a410059a4e6bf1c87de6020198138544ebcbf9c2182c)... Ok
Loading buyer's box (d5b150c73baad5debbaaeab27ee269cbd487ff0dcab8ff0cd5084dff8f0db167)... Ok
Signing the transaction... Ok
To cancel a buy/sell order you need to "spend" the box of the order (bid
of ask
boxes
on the diagram) by sending its assets (coins and/or tokens) back to your own address. Use
the following command to spend sell/buy order box and send the assets home:
$ ./ergo-dex.sh dex:CancelOrder storage/secret.json "357bba87df0299ed692e3945fcf6ab88465e0dc7fff6db48957c939603ae23f0"
Storage password>
Creating prover... Ok
Loading order's box (357bba87df0299ed692e3945fcf6ab88465e0dc7fff6db48957c939603ae23f0)... Ok
Signing the transaction... Ok
All kinds of contributions are equally welcome. Don't hesitate to file a PR with fixes of typos, documentation out of sync or something you believe should be fixed. If you wish to start hacking on the code, you can file an issue with the description of what you want to do. Not sure about your idea? Get in touch with a direct message.
ScalaDocs for the latest releases are always available on project site. Please submit a PR if you find typos or mistakes.
You may need to re-generate reflection and resources configs for native-image utility.
To do that run ErgoDexToolSpec with native-image-agent
configured.
The following should be added to command line.
-agentlib:native-image-agent=config-merge-dir=graal/META-INF/native-image
After that you will have to review changes made in the files and remove unnecessary declarations.