-
-
Notifications
You must be signed in to change notification settings - Fork 71
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
Aleksei Lebedev
committed
Mar 12, 2020
0 parents
commit 6d54540
Showing
29 changed files
with
2,831 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Install EditorConfig Plugin on your IDE for one coding style | ||
# EditorConfig is awesome: http://EditorConfig.org | ||
|
||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true | ||
indent_style = tab | ||
tab_width = 4 | ||
[*.md] | ||
max_line_length = off | ||
trim_trailing_whitespace = false |
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,44 @@ | ||
module.exports = { | ||
"parserOptions": { | ||
"ecmaVersion": 8, | ||
"sourceType": "module" | ||
}, | ||
"rules": { | ||
quotes: ["error", "single"], | ||
"semi": "warn", // обязательно ; | ||
"semi-spacing": ["error", {"before": false, "after": true}], | ||
"indent": ["error", "tab"], | ||
"space-infix-ops": "error",// отступы вокруг + - * / = и тд | ||
"eqeqeq": "error", // обязательно === и !== (нельзя == и !=) | ||
// "no-eq-null": "error", // обязательно === и !== (нельзя == и !=) но тоько в отношении null | ||
"curly": "error", // проверка шаблонов `${name}` | ||
// "space-before-function-paren": [ // отступ до и после function | ||
// "error", { | ||
// "anonymous": "always", | ||
// "named": "always", | ||
// "asyncArrow": "ignore" | ||
// } | ||
// ], | ||
"key-spacing": ["error", { "mode": "strict" }], // оформление обЪекта | ||
"space-in-parens": ["error", "never"], // запрет отступов ( a,b) | ||
"computed-property-spacing": ["error", "never"], // запрет лишних отступов в выражениях a[ i] | ||
"array-bracket-spacing": ["error", "never"], | ||
"no-multi-spaces": "error", // запрет лишних пробелов var a = 2 | ||
"no-sparse-arrays": "warn", // предупреждение при дырке в массиве | ||
"no-mixed-spaces-and-tabs": "error", // нельзя миксовать табы и пробелы | ||
"keyword-spacing": ["error", { "after": true }], | ||
"comma-spacing": ["error", { "before": false, "after": true }], // отступ после запятой, а перед нельзя | ||
"no-undef":"error", | ||
"array-callback-return": "error" // коллбек методов массива типа arr.map arr.filter должны иметь return в коллбеке | ||
}, | ||
"env": { | ||
"browser": true, | ||
"node": true | ||
}, | ||
"globals": { | ||
"Vue":true, | ||
"Symbol":true, | ||
"Promise":true, | ||
}, | ||
"plugins": [] | ||
} |
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 @@ | ||
node_modules/ | ||
logs/ | ||
.vscode/ | ||
package-lock.json | ||
tests.js | ||
config.test |
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,91 @@ | ||
ADAMANT Trading & Market making bot is a software that allows to run trades on crypto exchanges or make fake volume. Trading is a mode when bot run orders according to some strategy. It can be profitable or not. | ||
In Market making mode, the bot places orders and execute them by himself, making a trade volume. | ||
Trade bots work in ADAMANT Messenger chats directly. | ||
|
||
Features: | ||
|
||
* Managed with your commands using ADAMANT Messenger | ||
* Easy to install and configure | ||
* Free and open source | ||
* Fill order books | ||
* Market making | ||
* Stores and displays statistics | ||
|
||
Supported exchanges (more in progress): | ||
|
||
* [IDCM](https://idcm.io/invitation/receive?code=LM5510&lang=en) | ||
|
||
Available commands: ask a bot with `/help` command. Read more: [M](). | ||
|
||
# Installation | ||
|
||
## Requirements | ||
|
||
* Ubuntu 16 / Ubuntu 18 (other OS had not been tested) | ||
* NodeJS v 8+ | ||
* MongoDB ([installation instructions](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/)) | ||
|
||
## Setup | ||
|
||
``` | ||
su - adamant | ||
git clone https://github.com/Adamant-im/adamant-tradebot | ||
cd ./adamant-tradebot | ||
npm i | ||
``` | ||
|
||
## Pre-launch tuning | ||
|
||
``` | ||
nano config.json | ||
``` | ||
|
||
Parameters: | ||
|
||
* `exchange` <string> Exchange to work with. Available values see above. Case insensitive, obligatory. | ||
* `pair` <string> Pair to with on the exchange. Obligatory. | ||
* `apikey` <string> Exchange's account API key for connection. Obligatory. | ||
* `apisecret` <string> Exchange's account API secret for connection. Obligatory. | ||
* `apipassword` <string> Exchange's account trade password. If needed for exchange. | ||
* `passPhrase` <string> The bot's secret phrase for accepting commands. Obligatory. Bot's ADM address will correspond this passPhrase. | ||
* `admin_accounts` <string, array> ADAMANT accounts to accept commands from. Commands from other accounts will not be executed. At lease one account. | ||
* `notify_non_admins` <boolean> Notify non-admins that they are not admins. If false, bot will be silent. | ||
* `node_ADM` <string, array> List of nodes for API work, obligatorily | ||
* `infoservice` <string, array> List of [ADAMANT InfoServices](https://github.com/Adamant-im/adamant-currencyinfo-services) for catching exchange rates, recommended | ||
* `slack` <string> Token for Slack alerts for the bot’s administrator. No alerts if not set. | ||
* `adamant_notify` <string> ADM address for the bot’s administrator. Recommended. | ||
* `socket` <boolean> If to use WebSocket connection. Recommended for better user experience. | ||
* `ws_type` <string> Choose socket connection, "ws" or "wss" depending on your server. | ||
* `bot_name` <string> Bot's name for notifications. | ||
* `welcome_string` <string> How to reply user in-chat, if unknown command received. | ||
|
||
## Launching | ||
|
||
You can start the Bot with the `node app` command, but it is recommended to use the process manager for this purpose. | ||
|
||
``` | ||
pm2 start --name tradebot app.js | ||
``` | ||
|
||
## Add Bot to cron | ||
|
||
``` | ||
crontab -e | ||
``` | ||
|
||
Add string: | ||
|
||
``` | ||
@reboot cd /home/adamant/adamant-tradebot && pm2 start --name tradebot app.js | ||
``` | ||
|
||
## Updating | ||
|
||
``` | ||
su - adamant | ||
cd ./adamant-tradebot | ||
pm2 stop tradebot | ||
mv config.json config_bup.json && git pull && mv config_bup.json config.json | ||
npm i | ||
pm2 start --name tradebot app.js | ||
``` |
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,42 @@ | ||
const notify = require('./helpers/notify'); | ||
const db = require('./modules/DB'); | ||
const Store = require('./modules/Store'); | ||
const checker = require('./modules/checkerTransactions'); | ||
const doClearDB = process.argv.includes('clear_db'); | ||
const config = require('./modules/configReader'); | ||
const txParser = require('./modules/incomingTxsParser'); | ||
const log = require('./helpers/log'); | ||
|
||
// Socket connection | ||
const api = require('./modules/api'); | ||
api.socket.initSocket({socket: config.socket, wsType: config.ws_type, onNewMessage: txParser, admAddress: Store.user.ADM.address}); | ||
|
||
setTimeout(init, 5000); | ||
|
||
function init() { | ||
require('./server'); | ||
try { | ||
if (doClearDB) { | ||
console.log('Clearing database..'); | ||
db.systemDb.db.drop(); | ||
db.incomingTxsDb.db.drop(); | ||
notify(`*${config.notifyName}: database cleared*. Manually stop the Bot now.`, 'info'); | ||
} else { | ||
|
||
db.systemDb.findOne().then(system => { | ||
if (system) { | ||
Store.lastBlock = system.lastBlock; | ||
} else { // if 1st start | ||
Store.updateLastBlock(); | ||
} | ||
checker(); | ||
require('./trade/mm_trader').run(); | ||
notify(`*${config.notifyName} started* for address _${Store.user.ADM.address}_ (ver. ${Store.version}).`, 'info'); | ||
}); | ||
} | ||
|
||
} catch (e) { | ||
notify(`${config.notifyName} is not started. Error: ${e}`, 'error'); | ||
process.exit(1); | ||
} | ||
} |
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,75 @@ | ||
{ | ||
|
||
/** The bot's secret phrase for accepting commands. | ||
Bot's ADM address will correspond this passPhrase. | ||
**/ | ||
"passPhrase": "distance expect praise frequent..", | ||
|
||
/** List of nodes to fetch transactions. | ||
If one become unavailable, bot will choose live one. | ||
**/ | ||
|
||
"node_ADM": [ | ||
"http://localhost:36666", | ||
"https://endless.adamant.im", | ||
"https://clown.adamant.im", | ||
"https://bid.adamant.im", | ||
"https://unusual.adamant.im", | ||
"https://debate.adamant.im", | ||
"http://185.231.245.26:36666", | ||
"https://lake.adamant.im" | ||
], | ||
|
||
/** Socket connection is recommended for better user experience **/ | ||
"socket": true, | ||
|
||
/** Choose socket connection, "ws" or "wss" depending on your server **/ | ||
"ws_type": "ws", | ||
|
||
/** List of ADAMANT InfoServices for catching exchange rates **/ | ||
"infoservice": [ | ||
"https://info.adamant.im" | ||
], | ||
|
||
/** ADAMANT accounts to accept commands from. Commands from other accounts will not be executed. **/ | ||
"admin_accounts": [ | ||
"U123.." | ||
], | ||
|
||
/** Notify non-admins that they are not admins. If false, bot will be silent. **/ | ||
"notify_non_admins": true, | ||
|
||
/** Exchange to work with. Available values: "idcm". Case insensitive. **/ | ||
"exchange": "IDCM", | ||
|
||
/** Pair to trade **/ | ||
"pair": "ADM/BTC", | ||
|
||
/** Exchange's account API key for connection **/ | ||
"apikey": "YOUR-KEY..", | ||
|
||
/** Exchange's account API secret for connection **/ | ||
"apisecret": "YOUR-SECRET..", | ||
|
||
/** Exchange's account trade password. If needed. **/ | ||
"apipassword": "YOUR-TRADE-PASS", | ||
|
||
/** How to reply user in-chat, if first unknown command received. **/ | ||
"welcome_string": "Hi! 😊 I'm a trade and market making bot. ℹ️ Learn more about me on ADAMANT’s blog or type **/help** to see what I can.", | ||
|
||
/** Bot's name for notifications **/ | ||
"bot_name": "Lovely Trade Bot", | ||
|
||
/** ADAMANT address for notifications and monitoring (if needed, recommended) **/ | ||
"adamant_notify": "", | ||
|
||
/** Slack key for notifications and monitoring (if needed) **/ | ||
"slack": "https://hooks.slack.com/services/...", | ||
|
||
/** Port for getting debug info. | ||
Do not set for live bots, use only for debugging. | ||
Allows to get DBs records like http://ip:port/db?tb=incomingTxsDb | ||
**/ | ||
"api": false | ||
|
||
} |
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,3 @@ | ||
module.exports = { | ||
SAT: 100000000 | ||
}; |
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,70 @@ | ||
module.exports = (db) => { | ||
return class { | ||
constructor(data = {}, isSave) { | ||
this.db = db; | ||
Object.assign(this, data); | ||
if (isSave){ | ||
this.save(); | ||
} | ||
} | ||
static get db() { | ||
return db; | ||
} | ||
static find(a) { // return Array | ||
return new Promise((resolve, reject) => { | ||
this.db.find(a).toArray((err, data) => { | ||
resolve(data.map(d=>new this(d))); | ||
}); | ||
}); | ||
} | ||
static aggregate(a) { // return Array | ||
return new Promise((resolve, reject) => { | ||
this.db.aggregate(a).toArray((err, data) => { | ||
resolve(data.map(d=>new this(d))); | ||
}); | ||
}); | ||
} | ||
static findOne(a) { | ||
return new Promise((resolve, reject) => { | ||
db.findOne(a).then((doc, b) => { | ||
if (!doc) { | ||
resolve(doc); | ||
} else { | ||
resolve(new this(doc)); | ||
} | ||
}); | ||
}); | ||
} | ||
_data() { | ||
const data = {}; | ||
for (let field in this){ | ||
if (!['db', '_id'].includes(field)){ | ||
data[field] = this[field]; | ||
} | ||
} | ||
return data; | ||
} | ||
async update(obj, isSave){ | ||
Object.assign(this, obj); | ||
if (isSave){ | ||
await this.save(); | ||
} | ||
} | ||
save() { | ||
return new Promise((resolve, reject) => { | ||
if (!this._id) { | ||
db.insertOne(this._data(), (err, res) => { | ||
this._id = res.insertedId; | ||
resolve(this._id); | ||
}); | ||
} else { | ||
db.updateOne({_id: this._id}, { | ||
$set: this._data() | ||
}, {upsert: true}).then(() => { | ||
resolve(this._id); | ||
}); | ||
} | ||
}); | ||
} | ||
}; | ||
}; |
Oops, something went wrong.