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

Commit

Permalink
Add info,connect,market commands
Browse files Browse the repository at this point in the history
  • Loading branch information
tiero committed Mar 26, 2020
1 parent c7af137 commit 0ffb77e
Show file tree
Hide file tree
Showing 12 changed files with 1,007 additions and 258 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
##STate
state.json

.DS_Store
# Logs
logs
*.log
Expand Down
4 changes: 2 additions & 2 deletions .tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"outDir": "./src",
"outDir": "./dist",
"sourceMap": false,
"strict": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"moduleResolution": "node"
},
"include": [
"ts_src/*.ts"
"src/*.ts"
],
"exclude": [
"**/*.spec.ts",
Expand Down
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,65 @@
# alpha-wallet
Wallet CLI for making swaps on TDEX

## Development

**Requirements**

* Node/npm or yarn


* Install deps

```sh
yarn install
```

* Build .ts files

```sh
yarn build
```

* Build and Test

```sh
yarn test
```

* Try it out locally

```sh
npm install -g
tdex-cli --version
```


## Usage

* Install

```sh
npm install -g tdex-cli
```

* Connect to a liquidity provider

```sh
tdex-cli connect https://tdex.vulpem.com
```

* Select a market to use for trading

```sh
tdex-cli market LBTC-USDT
```










16 changes: 10 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
{
"name": "alpha-wallet",
"version": "1.0.0",
"main": "index.js",
"author": "Vulpem Ventures",
"license": "MIT",
"bin": {
"tdex-cli": "./dist/index.js"
},
"scripts": {
"build": "tsc -p ./tsconfig.json"
"build": "npx tsc -p ./.tsconfig.json",
"clean": "npx rimraf dist",
"test": "npm run build && npm run unit",
"unit": "npx mocha tests/**/*.js"
},
"dependencies": {
"chalk": "^3.0.0",
"commander": "^5.0.0",
"inquirer": "^7.1.0",
"liquidjs-lib": "vulpemventures/liquidjs-lib",
"ora": "^4.0.3",
"protobufjs": "~6.8.9"
"liquidjs-lib": "vulpemventures/liquidjs-lib"
},
"devDependencies": {
"@types/chalk": "^2.2.0",
"@types/commander": "^2.12.2",
"@types/inquirer": "^6.5.0",
"@types/node": "^12.12.31",
"@types/ora": "^3.2.0",
"mocha": "^7.1.1",
"rimraf": "^3.0.2",
"typescript": "^3.8.3"
}
}
36 changes: 36 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// @ts-nocheck
import { URL } from 'url';

export function isValidUrl(s) {
try {
new URL(s);
return true;
} catch (err) {
return false;
}
}

export function mergeDeep(...objects) {
const isObject = obj => obj && typeof obj === 'object';

return objects.reduce((prev, obj) => {
Object.keys(obj).forEach(key => {
const pVal = prev[key];
const oVal = obj[key];

if (Array.isArray(pVal) && Array.isArray(oVal)) {
prev[key] = [...oVal];
}
else if (isObject(pVal) && isObject(oVal)) {
prev[key] = mergeDeep(pVal, oVal);
}
else {
prev[key] = oVal;
}
});

return prev;
}, {});
}


125 changes: 125 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/usr/bin/env node

// 0. Load from WIF/Create keyPair
// 1. Select an endpoint and connect to the daemon
// 2. Select asset pair and Fetch his market rate
// 3. Start swap proposal
// 4. Parsing acceptance from the daemon & sign
// 5. Sending signed swap back to daemon.

import * as path from 'path';
import { program } from 'commander';

//Components
import Wallet, { fromWIF } from './wallet';
import { log, error, info, success } from './logger';
import State from './state';
//Helpers
import { isValidUrl } from './helpers';

const pkg = require('../package.json');
const state = new State({ path: path.resolve(__dirname, "../state.json") })
//Loggers

//const w = fromWIF("cNiZ5A2UgR11Kw79QsgqeziPJLXVnftGVBmeHZag53RcvDod5SsW", "regtest");
//console.log(w.address)

program
.version(pkg.version)

program
.command('info')
.description('Get info about the current session')
.action(() => {
info('=========*** Info ***==========\n')

const { market, provider } = state.get();

if (provider.selected)
log(`Endpoint: ${provider.endpoint}`);

if (market.selected)
log(`Market: ${market.pair}`);


})
/**
* Connect
*/
program
.command('connect <endpoint>')
.description('Select the default liquidity provider')
.action((endpoint) => {
info('=========*** Provider ***==========\n')

if (!isValidUrl(endpoint))
return error('The provided endpoint URL is not valid');

// TODO: Connect to provided endpoint and fetch the available pairs along with his pubkey
const pairs = ['LBTC-USDT', 'LBTC-EQUI'];
state.set({ provider: { endpoint, pairs, selected: true }});

return log(`Current provider endpoint: ${endpoint}`)
});

/**
* Market
*/
program
.command('market [pair]')
.option('-ls, --list', 'Get available assets pairs for the selected provider')
.description('Select the default asset pair to use for the swap')
.addHelpCommand(false)
.action((pair, cmdObj) => {
info('=========*** Market ***==========\n');

const { provider, market } = state.get();
if (!provider.selected)
return error('A provider is required. Select with connect <endpoint> command');

if (cmdObj.list)
return provider.pairs.forEach(p => log(p))

if (!pair)
return error('An asset pair is required. Get all the avilable ones with the --list option');

if (!provider.pairs.includes(pair))
return error('Pair not suppported by the selcted provider');

if (!market.selected && market.pair !== pair)
state.set({ market: { selected: true, pair }});

//TODO: Fetch the price from the daemon
log(`Current market: ${pair}`);
log();
success(`Price: 1 asset_a is equal to X asset_b at timestamp`);
});


/**
* Wallet
*/

program
.command('wallet [wif]')
.description('Create new key pair or import from WIF')
.action((wif) => {
info('=========*** Wallet ***==========');


});

/**
* swap
*/
program
.command('swap <amount> <asset>')
.description('Make a swap proposal of <amount> <asset>')
.action(() => {

});




program.parse(process.argv);
6 changes: 6 additions & 0 deletions src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {red, blue, greenBright} from 'chalk';

export const log = console.log;
export const error = (msg:string) => log(red(msg));
export const info = (msg:string) => log(blue(msg));
export const success = (msg:string) => log(greenBright(msg));
92 changes: 92 additions & 0 deletions src/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as fs from 'fs';
import { mergeDeep } from './helpers';

export interface StateInterface {
state: StateObjectInterface,
stateSerialized: String,
path: String,
set(newState: Object): void,
get(): StateObjectInterface
}

export interface StateObjectInterface {
provider: StateProviderInterface,
market: StateMarketInterface
}

export interface StateProviderInterface {
selected: Boolean,
endpoint: String,
pubkey: String,
pairs: Array<string>
}

export interface StateMarketInterface {
selected: Boolean,
pair: String,
price: Object
}

const initialState = {
provider: {
selected: false,
endpoint: "",
pubkey: "",
pairs: []
},
market: {
selected: false,
pair: "",
price: {
timestamp: null,
value: null
}
}
}

export default class State implements StateInterface {

state: StateObjectInterface
path: string
stateSerialized: string

constructor(args:any) {

const { path } = args;

if (fs.existsSync(path)) {
const read = fs.readFileSync(path, 'utf8');
this.stateSerialized = read;
this.state = JSON.parse(read);
} else {
const serialized = JSON.stringify(initialState, undefined, 2)
this.stateSerialized = serialized;
this.state = initialState;
fs.writeFileSync(path, serialized, { encoding:'utf8', flag:'w' })
}

this.path = path;
}

set(obj: Object): void {

const currentState = this.get();

const newState = mergeDeep(currentState, obj);

this.state = newState;
this.stateSerialized = JSON.stringify(newState, undefined, 2)
fs.writeFileSync(this.path, this.stateSerialized, { encoding:'utf8', flag:'w' })
}

get(): StateObjectInterface {
const read = fs.readFileSync(this.path, 'utf8');
this.stateSerialized = read;
this.state = JSON.parse(read);

return this.state;
}


}

Loading

0 comments on commit 0ffb77e

Please sign in to comment.