🎉 Get the party started
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.env
|
||||
node_modules
|
||||
64
README.md
Normal file
64
README.md
Normal 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
49
index.js
Normal 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
159
package-lock.json
generated
Normal 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
16
package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user