🎉 Get the party started

This commit is contained in:
Dennis Reimann
2020-04-28 21:43:55 +02:00
commit 7fb83e187a
5 changed files with 290 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.env
node_modules

64
README.md Normal file
View File

@@ -0,0 +1,64 @@
# Stacking Sats on Kraken
First off: Here's to you, [Bittr](https://getbittr.com/) you will be missed! 😢
This script is not a full replacement for the incredible service Bittr offered, but it's a start:
Automate your Stacking Sats process by regularly placing buy orders using the [Kraken API](https://www.kraken.com/features/api).
## ✋ Caveat
You need to install the dependency [kraken-api](https://github.com/nothingisdead/npm-kraken-api), which is a third-party package.
It has a minimal set of dependencies and I've done my best to audit its code.
Also the version is fixed, so that unwanted changes do not slip in.
However: Use this at your own risk and decide for yourself whether or not you want to run this script and its dependencies!
## 📦 Setup
Prerequisite: At least the current LTS version of [Node.js](https://nodejs.org/).
Install the dependencies:
```sh
npm install
```
Setup the environment variables for the script:
```sh
export KRAKEN_API_KEY="apiKeyFromTheKrakenSettings"
export KRAKEN_API_SECRET="privateKeyFromTheKrakenSettings"
export KRAKEN_API_FIAT="USD" # the governmental shitcoin you are selling
export KRAKEN_BUY_AMOUNT=21 # fiat amount you trade for the future of money
```
Use a dry run to test the script and see the output without placing an order:
```sh
npm test
```
You should see something like this sample output:
```text
💰 Balance: 210000.00 USD / 21.0 XBT
📈 Ask: 21000.2 USD
📉 Bid: 21000.1 USD
🧾 Order: 0.21212121 XBT at 21000.1 USD
💸 Placed order: buy 0.21212121 XBTUSD @ limit 21000.1 / TXID: 2121212121
```
## 🤑 Stack sats
When you are good to go, execute this command in a regular interval:
```sh
npm run stack-sats
```
Now go wild and triggeer it via a weekly or even daily cron job.
[Stay humble!](https://twitter.com/matt_odell/status/1117222441867194374) 🙏

49
index.js Normal file
View File

@@ -0,0 +1,49 @@
const assert = require('assert')
const Kraken = require('kraken-api')
const {
KRAKEN_API_KEY: key,
KRAKEN_API_SECRET: secret,
KRAKEN_API_FIAT: fiat,
KRAKEN_BUY_AMOUNT: amount
} = process.env
assert(key && secret, 'Provide the KRAKEN_API_KEY and KRAKEN_API_SECRET environment variables.')
assert(fiat && amount, 'Provide the KRAKEN_API_FIAT and KRAKEN_BUY_AMOUNT environment variables.')
// https://www.kraken.com/features/api
const kraken = new Kraken(key, secret)
const crypto = 'XBT'
const pair = `X${crypto}Z${fiat}`
const validate = process.argv[2] === '--validate'
;(async () => {
// Fetch and display information
const { result: { [`Z${fiat}`]: fiatBalance, [`X${crypto}`]: cryptoBalance } } = await kraken.api('Balance')
const { result: { [pair]: { a: [a], b: [b] } } } = await kraken.api('Ticker', { pair })
const ask = parseFloat(a)
const bid = parseFloat(b)
const price = bid
// Calculate volume and adjust precision
const volume = (amount / price).toFixed(8)
console.log('\n')
console.log('💰 Balance:', fiatBalance, fiat, '/', cryptoBalance, crypto, '\n')
console.log('📈 Ask:', ask, fiat)
console.log('📉 Bid:', bid, fiat, '\n')
console.log('🧾 Order:', volume, crypto, 'at', price, fiat, '\n')
// Place order
try {
const details = { pair, type: 'buy', ordertype: 'limit', price, volume, validate }
const { result: { descr: { order } }, txid } = await kraken.api('AddOrder', details)
console.log('💸 Placed order:', order, '/ TXID:', txid, '\n')
} catch (err) {
console.error(`🚨 Failure:`, err.message, '\n')
} finally {
if (validate) console.warn('🚨 THIS WAS JUST A VALIDATION RUN, NO ORDER HAS BEEN PLACED!', '\n')
}
})()

159
package-lock.json generated Normal file
View File

@@ -0,0 +1,159 @@
{
"name": "kraken-dca",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"decompress-response": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
"requires": {
"mimic-response": "^1.0.0"
}
},
"duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
},
"get-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
},
"got": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz",
"integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==",
"requires": {
"decompress-response": "^3.2.0",
"duplexer3": "^0.1.4",
"get-stream": "^3.0.0",
"is-plain-obj": "^1.1.0",
"is-retry-allowed": "^1.0.0",
"is-stream": "^1.0.0",
"isurl": "^1.0.0-alpha5",
"lowercase-keys": "^1.0.0",
"p-cancelable": "^0.3.0",
"p-timeout": "^1.1.1",
"safe-buffer": "^5.0.1",
"timed-out": "^4.0.0",
"url-parse-lax": "^1.0.0",
"url-to-options": "^1.0.1"
}
},
"has-symbol-support-x": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
"integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw=="
},
"has-to-string-tag-x": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
"integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
"requires": {
"has-symbol-support-x": "^1.4.1"
}
},
"is-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz",
"integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA="
},
"is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
},
"is-retry-allowed": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
"integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg=="
},
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"isurl": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
"integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
"requires": {
"has-to-string-tag-x": "^1.2.0",
"is-object": "^1.0.1"
}
},
"kraken-api": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/kraken-api/-/kraken-api-1.0.0.tgz",
"integrity": "sha512-JAfLh9Laks+2KZTM/WW+bpy+iZfImUok0aeLBOb0ehwTEGvcBWWAXlmkthhJXfUTSoOIHuoqqToC94+iBeBBAg==",
"requires": {
"got": "^7.1.0",
"qs": ">=6.4.0"
}
},
"lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
},
"mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
},
"p-cancelable": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz",
"integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw=="
},
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
},
"p-timeout": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
"integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=",
"requires": {
"p-finally": "^1.0.0"
}
},
"prepend-http": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
},
"qs": {
"version": "6.9.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
"integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw=="
},
"safe-buffer": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
},
"timed-out": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
"integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
},
"url-parse-lax": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
"integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
"requires": {
"prepend-http": "^1.0.1"
}
},
"url-to-options": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
"integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k="
}
}
}

16
package.json Normal file
View File

@@ -0,0 +1,16 @@
{
"private": true,
"name": "stacking-sats-kraken",
"version": "0.1.0",
"description": "Use the Kraken API to stack sats",
"author": "Dennis Reimann <mail@dennisreimann.de>",
"license": "MIT",
"main": "index.js",
"scripts": {
"stack-sats": "node index.js",
"test": "node index.js --validate"
},
"dependencies": {
"kraken-api": "1.0.0"
}
}