This repository has been archived by the owner on Nov 13, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
1,007 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
##STate | ||
state.json | ||
|
||
.DS_Store | ||
# Logs | ||
logs | ||
*.log | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}, {}); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
|
||
} | ||
|
Oops, something went wrong.