Skip to content
This repository has been archived by the owner on Nov 13, 2020. It is now read-only.

Commit

Permalink
Split commands (#11)
Browse files Browse the repository at this point in the history
* Change toggle question

* Import wallet and networks from tdex-sdk

* Create swap request comand

* Create trade command

* Add trade command to commander

* Add flags

* Rename module

* Add helper for datadir

* Add method for writing/reading binary and parsing a swap request

* Use helper method

* Always save to file and print to stdout if needed

* Add reading/writing to file to accept and complete actions

* Remove useless methods

* Fix request swap command and add flags to accept and complete

* Push transaction if needed

* Remove google-protobuf from deps

* Update lockfile

* Remove datadir and add fileExists helpers

* Use current directory for default and check for valid path istead of asbolute

* Add --file flag to specify different file from default one

* Promisify writeBinary

* Add buy order

* Fix typo

* Add buy order to swap request

* Add use of tickers to wallet balance

* Fix swap request toggle message

* Add command description and fix order

* Fix typo

* Update readme

* Update yarn.lock to pull latest liquidjs and ignore .bin files from git

* Check file existance

* Log errors in swap complete

* Check valid amount

* Update deps

Co-authored-by: Marco Argentieri <marco@vulpem.com>
  • Loading branch information
altafan and tiero authored May 6, 2020
1 parent acea6ff commit 993c386
Show file tree
Hide file tree
Showing 15 changed files with 578 additions and 449 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
##STate
# Bin files
*.bin
##State
state.json
dist
.DS_Store
Expand Down
87 changes: 71 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ $ tdex-cli help
```sh
# Mainnet
$ tdex-cli netwrok liquid
$ tdex-cli network liquid
# Public regtest Nigiri
$ tdex-cli netwrok regtest
$ tdex-cli network regtest
# Local Nigiri or Electrum REST server
$ tdex-cli network regtest --explorer localhost:3001
```
Expand Down Expand Up @@ -100,44 +100,99 @@ $ tdex-cli wallet
$ tdex-cli wallet balance
```


### Swap

* Start a swap against the selected provider
* Create a swap request message

> NOTICE With the --local flag you can export manually the SwapRequest message without the need of a connection with the provider.
> NOTICE With the —-output flag you can customize the output file
> NOTICE With the —-print flag you can print the request in JSON format to stdout
```sh
$ tdex-cli swap
$ tdex-cli swap request
=========*** Swap ***==========

✔ Which asset do you want to send? · USDT / LBTC
✔ Which asset do you want to send? USDT / LBTC
✔ How much do you want to send? · 0.5
✔ How much do you want to receive? · 3000
Gotcha! You will send LBTC 0.5 and receive USDT 3000
✔ Are you sure continue? (y/N) · true
SwapRequest message saved into ./swap_request.bin
```

* Import manually a SwapRequest and sign a resulting SwapAccept message

> NOTICE With the —-file flag you can customize the input file
> NOTICE With the —-output flag you can customize the output file
Sending SwapRequest to provider...
```sh
$ cd path/to/swap_request.bin
$ tdex-cli swap accept
=========*** Swap ***==========

Swap has been accepted!
SwapRequest message: {
"id": "Q1xH1HV5",
"amountP": 11000000000,
"assetP": "bd7f2f6630497c247044a56d2d092b96f2a1e7cca81d00056a64dd7bf281694d",
"amountR": 10000000,
"assetR": "5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225",
"transaction": "cHNldP8BAHYCAAAAAAFGbhOAQ4zClf/b6eM/3WOlOjTGrXXy0axWweYaRdzdkwAAAAAA/////wEBJbJRBw4pyhkEPPM8zXMk4t2rA+zErgted8T8Dlz2yVoBAAAAAACYloAAFgAUf1pUznALvRdb2IseeB9EUJ/8FZEAAAAAAAEBQgFNaYHye91kagUAHajM56HylisJLW2lRHAkfEkwZi9/vQEAAAACj6auAAAWABR/WlTOcAu9F1vYix54H0RQn/wVkQAA",
"inputBlindingKeyMap": [],
"outputBlindingKeyMap": []
}
✔ Do you accept the proposed terms? (y/N) · true

Signing with private key...
Sending SwapComplete to provider...

Swap completed!
√ Done

SwapAccept message saved into ./swap_accept.bin
```

* Import manually a SwapRequest and sign a resulting SwapAccept message
* Import a SwapAccept message and sign a resulting SwapComplete message

> NOTICE With the —-file flag you can customize the input file
> NOTICE With the —-output flag you can customize the output file
> NOTICE With the --push flag you can print the hex encoded extracted transaction and broadcast to the network
```sh
$ tdex-cli swap accept <message>
$ tdex-cli swap complete
=========*** Swap ***==========

SwapAccept message: {
"id": "2z0V5XRX",
"requestId": "Q1xH1HV5",
"transaction": "cHNldP8BAP26AQIAAAAAA0ZuE4BDjMKV/9vp4z/dY6U6NMatdfLRrFbB5hpF3N2TAAAAAAD/////d7xePTC4ySCytltLkWIrKYVCgMDO0OWPxLYr1Ambp2EDAAAAAP////8Xi84xzOgYsQr9TFGzdt7PaIhnK2D3td4LrzolBBCMMgMAAAAA/////wUBJbJRBw4pyhkEPPM8zXMk4t2rA+zErgted8T8Dlz2yVoBAAAAAACYloAAFgAUf1pUznALvRdb2IseeB9EUJ/8FZEBTWmB8nvdZGoFAB2ozOeh8pYrCS1tpURwJHxJMGYvf70BAAAAAo+mrgAAFgAUzFEDYTJiiyak/avQesx3bwpPzrkBJbJRBw4pyhkEPPM8zXMk4t2rA+zErgted8T8Dlz2yVoBAAAAAAQsHYAAFgAUzFEDYTJiiyak/avQesx3bwpPzrkBJbJRBw4pyhkEPPM8zXMk4t2rA+zErgted8T8Dlz2yVoBAAAAAAX10dIAFgAUZZvttdPTx6sS1/hTI8OhtsBg774BJbJRBw4pyhkEPPM8zXMk4t2rA+zErgted8T8Dlz2yVoBAAAAAAAAA6oAAAAAAAAAAQFCAU1pgfJ73WRqBQAdqMznofKWKwktbaVEcCR8STBmL3+9AQAAAAKPpq4AABYAFH9aVM5wC70XW9iLHngfRFCf/BWRAAEBQgElslEHDinKGQQ88zzNcyTi3asD7MSuC153xPwOXPbJWgEAAAAABMS0AAAWABTMUQNhMmKLJqT9q9B6zHdvCk/OuSICA3AU/RQbLnq+Yh7tdR4aWBM0LkaNqJ4awVkFNxOysQd6RzBEAiAvIE7plQg7uqFLMbU+1xJAT8CakCpJRPQgTpdIR3pOfwIgSRN0o7Py1IHQEv/CjPJlnl39HWRa4IKgRPbNd2vG53YBAAEBQgElslEHDinKGQQ88zzNcyTi3asD7MSuC153xPwOXPbJWgEAAAAABfXVfAAWABRlm+2109PHqxLX+FMjw6G2wGDvviICAlFGRCD8yYouTNNHr+KKMtdpKH2s2GFHarhYuqQ70wjzRzBEAiBxnHoX/HBTyIjgnYXN7MU4/zwBfgXC7U5r3eTRgM+2dAIgOkx2Xw6+6ACU+TK7QKV3ymDvIOzgEeFK2egs2lPUpBIBAAAAAAAA",
"inputBlindingKeyMap": [],
"outputBlindingKeyMap": []
}
✔ Are you sure to confirm? (y/N) · true

Signing with private key...

√ Done

SwapComplete message saved into ./swap_completed.bin
```

* Import a SwapAccept message and sign a resulting SwapComplete message

> NOTICE With the --push flag you can print the hex encoded extracted transaction and broadcast to the network
### Trade

* Start a swap against the selected provider

```sh
$ tdex-cli swap complete <message>
$ tdex-cli trade
=========*** Trade ***==========

✔ Do you want to buy or sell 5ac9? · SELL / BUY
✔ How much do you want to sell? · 0.5
Gotcha! You will send LBTC 0.5 and receive USDT 3000
✔ Are you sure continue? (y/N) · true

Sending Trade proposal to provider...
Signing with private key...
Trade completed!

tx hash c05beaea74dcbdb87a8f1f1e598a536517884ebcc15a6061832b77c7f41a30d2
```

## Development
Expand Down
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,12 @@
"chalk": "^3.0.0",
"commander": "^5.0.0",
"enquirer": "^2.3.4",
"google-protobuf": "^3.11.4",
"liquidjs-lib": "vulpemventures/liquidjs-lib",
"tdex-protobuf": "sevenlab/tdex-protobuf",
"tdex-sdk": "sevenlab/tdex-sdk"
},
"devDependencies": {
"@types/chalk": "^2.2.0",
"@types/commander": "^2.12.2",
"@types/google-protobuf": "^3.7.2",
"@types/inquirer": "^6.5.0",
"@types/node": "^12.12.31",
"@types/ora": "^3.2.0",
Expand Down
7 changes: 5 additions & 2 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import marketPriceAction from './marketPriceAction';
import walletAction from './walletAction';
import walletBalanceAction from './walletBalanceAction';

import swapAction from './swapAction';
import swapRequestAction from './swapRequestAction';
import swapAcceptAction from './swapAcceptAction';
import swapCompleteAction from './swapCompleteAction';

import tradeAction from './tradeAction';

export {
connectAction,
infoAction,
Expand All @@ -21,7 +23,8 @@ export {
marketListAction,
walletAction,
walletBalanceAction,
swapAction,
swapRequestAction,
swapAcceptAction,
swapCompleteAction,
tradeAction,
};
4 changes: 2 additions & 2 deletions src/actions/marketAction.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { info, log, error } from '../logger';

import State from '../state';
import { networks } from 'liquidjs-lib';
import { networks } from 'tdex-sdk';
const state = new State();

export default function (pair: string): void {
Expand All @@ -21,7 +21,7 @@ export default function (pair: string): void {

const LBTC = (networks as any)[network.chain].assetHash;
const tickers = (provider.markets as any)[pair];
const hashes = Object.values(tickers);
const hashes = Object.keys(tickers);
const baseAsset = hashes.find((h) => h === LBTC);
const quoteAsset = hashes.find((h) => h !== LBTC);
const assets = { baseAsset, quoteAsset };
Expand Down
104 changes: 69 additions & 35 deletions src/actions/swapAcceptAction.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import axios from 'axios';
import * as PathModule from 'path';
import { Wallet, WalletInterface, fetchUtxos, Swap } from 'tdex-sdk';

import { info, log, error, success } from '../logger';
import State from '../state';
import { WalletInterface, fromWIF, fetchUtxos } from '../wallet';
import { decrypt } from '../crypto';
import { makeid, TAXI_API_URL } from '../helpers';
const state = new State();

import { TAXI_API_URL, readBinary, writeBinary, fileExists } from '../helpers';
//eslint-disable-next-line
const { Confirm, Password } = require('enquirer');

const state = new State();
const confirm = new Confirm({
name: 'question',
message: 'Do you accept the proposed terms?',
Expand All @@ -20,32 +20,53 @@ const password = new Password({
message: 'Type your password',
});

export default function (message: string): void {
export default async function (cmdObj: any): Promise<void> {
info('=========*** Swap ***==========\n');

const { wallet, network } = state.get();

let swapRequestFile: string;
if (cmdObj.file) {
swapRequestFile = PathModule.resolve(cmdObj.file);
} else {
swapRequestFile = PathModule.resolve(process.cwd(), 'swap_request.bin');
}

if (!network.selected) return error('Select a valid network first');

if (!wallet.selected)
return error(
'A wallet is required. Create or restoste with wallet command'
);

let json: any;
try {
json = JSON.parse(message);
} catch (ignore) {
return error('Not a valid SwapRequest message');
if (!fileExists(swapRequestFile)) {
return error('File is not valid or does not exist');
}

log(JSON.stringify(json, undefined, 2));
log();

const psbtBase64 = json.transaction;

let walletInstance: WalletInterface;

confirm
.run()
if (
cmdObj.output &&
(!cmdObj.output.endsWith('.bin') ||
!fileExists(PathModule.dirname(PathModule.resolve(cmdObj.output))))
)
return error('Output path id not valid');

let swapRequest: any,
serializedSwapRequest: Uint8Array,
walletInstance: WalletInterface,
swapAccept: any,
swapAcceptFile: string;

readBinary(swapRequestFile)
.then((data: Uint8Array) => {
serializedSwapRequest = data;
const json = Swap.parse({
message: serializedSwapRequest,
type: 'SwapRequest',
});
swapRequest = JSON.parse(json);
log(`SwapRequest message: ${JSON.stringify(swapRequest, undefined, 2)}`);
return confirm.run();
})
.then((keepGoing: boolean) => {
if (!keepGoing) throw 'Canceled';

Expand All @@ -62,20 +83,20 @@ export default function (message: string): void {
? decrypt(wallet.keystore.value, passwordOrWif)
: passwordOrWif;

walletInstance = fromWIF(wif, network.chain);
walletInstance = Wallet.fromWIF(wif, network.chain);

return fetchUtxos(walletInstance.address, network.explorer);
})
.then((utxos: Array<any>) => {
// Add inputs and putputs to psbt

const unsignedPsbt = walletInstance.updateTx(
psbtBase64,
swapRequest.transaction,
utxos,
json.amount_r,
json.amount_p,
json.asset_r,
json.asset_p
swapRequest.amountR,
swapRequest.amountP,
swapRequest.assetR,
swapRequest.assetP
);

const body = { psbt: unsignedPsbt };
Expand All @@ -102,18 +123,31 @@ export default function (message: string): void {
.then((signedPsbt: string) => {
success('\n√ Done\n');

//eslint-disable-next-line
const TradeReply = {
SwapAccept: {
id: makeid(8),
requestId: json.id,
transaction: signedPsbt,
},
};
const swap = new Swap({ chain: network.chain });
swapAccept = swap.accept({
message: serializedSwapRequest,
psbtBase64: signedPsbt,
});

success(
`\nSwapAccept message\n\n${JSON.stringify(TradeReply.SwapAccept)}`
const defaultPath = PathModule.resolve(
PathModule.dirname(swapRequestFile),
'swap_accept.bin'
);
swapAcceptFile = cmdObj.output
? PathModule.resolve(cmdObj.output)
: defaultPath;
return writeBinary(swapAcceptFile, swapAccept);
})
.then(() => {
success(`SwapAccept message saved into ${swapAcceptFile}`);

if (cmdObj.print) {
const json = Swap.parse({
message: swapAccept,
type: 'SwapAccept',
});
log(`\nSwapAccept message\n\n${json}`);
}
})
.catch(error);
}
Loading

0 comments on commit 993c386

Please sign in to comment.