From 0e571e896521d70bb4ba655abfa35963ca086262 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Tue, 10 Nov 2020 11:17:07 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A0=20Refactor=20to=20use=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +++++------ commands/stack.js | 31 ++++++++++++++++++++++++++++ commands/withdraw.js | 25 ++++++++++++++++++++++ index.js | 24 ++++++++++++++++++++++ package.json | 8 ++++---- stack.js | 49 -------------------------------------------- withdraw.js | 47 ------------------------------------------ 7 files changed, 89 insertions(+), 107 deletions(-) create mode 100644 commands/stack.js create mode 100644 commands/withdraw.js create mode 100644 index.js delete mode 100644 stack.js delete mode 100644 withdraw.js diff --git a/README.md b/README.md index c33a4aa..703c555 100644 --- a/README.md +++ b/README.md @@ -113,21 +113,21 @@ You should regularly take ownership of your coins by withdrawing to your own wal This can either be done manually or it can be automated. The script provided here will only withdraw to a previously defined Bitcoin address if the relative fees do not exceed a certain limit. -*It is optional to run the witdrawal script.* +*It is optional to run the withdrawal script.* ### Example 1 - Max. relative fee: 0.5% - Fixed Kraken fee: ₿ 0.00050 - Balance: ₿ 0.06000 -- \> No withdrawal since fee actual (0.83%) is too high +➡️ No withdrawal since fee actual (0.83%) is too high ### Example 2 - Max. relative fee: 0.5% - Fixed Kraken fee: ₿ 0.00050 - Balance: ₿ 0.12000 -- \> Withdrawal executed since actual fee (0.42%) is low enough +➡️ Withdrawal executed since actual fee (0.42%) is low enough In case you plan to automatically withdraw from Kraken, a withdrawal method must first be defined. If you already set up a methode you can reuse it. @@ -144,9 +144,7 @@ You should see something like this: ```text 💡 Relative fee of withdrawal amount: 5.57% -❌ Don't withdraw now. Fee is too high – max rel. fee: 0.50% - -🚨 THIS WAS JUST A VALIDATION RUN, NO WITHDRAWAL HAS BEEN PLACED! +❌ Fee is too high – max rel. fee: 0.50% ``` It is recommended to run the withdrawal script every time you stacked sats: @@ -155,7 +153,7 @@ It is recommended to run the withdrawal script every time you stacked sats: npm run withdraw-sats ``` -Since it can take a couple seconds or minutes for your order to fill, you should run the following script maybe a couple hours later after your `stack-sats` script ran. +Since it can take a couple seconds or minutes for your order to fill, you should run the following script a couple hours later after your `stack-sats` script. Just set up a second cron job which executes the following script. Here's a sample `withdraw-sats.sh` script: diff --git a/commands/stack.js b/commands/stack.js new file mode 100644 index 0000000..3b19453 --- /dev/null +++ b/commands/stack.js @@ -0,0 +1,31 @@ +module.exports = async (kraken, validate, getEnv) => { + const [fiat, amount] = getEnv('KRAKEN_API_FIAT', 'KRAKEN_BUY_AMOUNT') + + // https://www.kraken.com/features/api + const crypto = 'XBT' + const pair = `X${crypto}Z${fiat}` + + // 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('💰 Balance:', fiatBalance, fiat, '/', cryptoBalance, crypto, '\n') + console.log('📈 Ask:', ask, fiat) + console.log('📉 Bid:', bid, fiat, '\n') + + // Place order + const details = { pair, type: 'buy', ordertype: 'limit', price, volume } + if (validate) details.validate = true + + const { result: { descr: { order }, txid } } = await kraken.api('AddOrder', details) + + console.log('💸 Order:', order) + if (txid) console.log('📎 Transaction ID:', txid.join(', ')) +} diff --git a/commands/withdraw.js b/commands/withdraw.js new file mode 100644 index 0000000..154f4cc --- /dev/null +++ b/commands/withdraw.js @@ -0,0 +1,25 @@ +module.exports = async (kraken, validate, getEnv) => { + const [maxFee, key] = getEnv('KRAKEN_MAX_REL_FEE', 'KRAKEN_WITHDRAW_KEY') + + // https://api.kraken.com/0/private/WithdrawInfo + const asset = 'XBT' + const withdrawdetails = { asset, key, amount: 0 } + + // Get withdrawal information + const { result: { limit, fee } } = await kraken.api('WithdrawInfo', withdrawdetails) + const relFee = 1/parseFloat(limit)*parseFloat(fee) + + console.log(`💡 Relative fee of withdrawal amount: ${(relFee*100).toFixed(2)}%`) + + // Place withdrawal when fee is low enough (relatively) + if (relFee < maxFee/100) { + console.log(`💰 Withdraw ${limit} ${asset} now.`) + const withdraw = { asset, key, amount: limit } + if (!validate) { + const { result: { refid } } = await kraken.api('Withdraw', withdraw) + if (refid) console.log(`📎 Withdrawal reference ID: ${refid}`) + } + } else { + console.log(`❌ Fee is too high - max rel. fee: ${parseFloat(maxFee).toFixed(2)}%`) + } +} diff --git a/index.js b/index.js new file mode 100644 index 0000000..7569f4f --- /dev/null +++ b/index.js @@ -0,0 +1,24 @@ +const assert = require('assert') +const Kraken = require('kraken-api') + +const getEnv = (...vars) => vars.map(name => { + const value = process.env[name] + assert(value, `Provide the ${name} environment variable.`) + return value +}) +const command = process.argv[2].replace('--cmd=', '') +const validate = process.argv.includes('--validate') || process.env['KRAKEN_DRY_RUN_PLACE_NO_ORDER'] + +;(async () => { + try { + const [apiKey, secret] = getEnv('KRAKEN_API_KEY', 'KRAKEN_API_SECRET') + const kraken = new Kraken(apiKey, secret) + + const cmd = require(`./commands/${command}`) + await cmd(kraken, validate, getEnv) + + if (validate) console.log('\n🚨 THIS WAS JUST A VALIDATION RUN!') + } catch (err) { + console.log(`\n🚨 Failure:`, err.message) + } +})() diff --git a/package.json b/package.json index 435bcc7..b6ad236 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,10 @@ "license": "MIT", "main": "stack.js", "scripts": { - "stack-sats": "node stack.js", - "withdraw-sats": "node withdraw.js", - "test:stack-sats": "node stack.js --validate", - "test:withdraw-sats": "node withdraw.js --validate" + "stack-sats": "node index.js --cmd=stack", + "withdraw-sats": "node index.js --cmd=withdraw", + "test:stack-sats": "node index.js --cmd=stack --validate", + "test:withdraw-sats": "node index.js --cmd=withdraw --validate" }, "dependencies": { "kraken-api": "1.0.0" diff --git a/stack.js b/stack.js deleted file mode 100644 index 73c2b92..0000000 --- a/stack.js +++ /dev/null @@ -1,49 +0,0 @@ -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('💰 Balance:', fiatBalance, fiat, '/', cryptoBalance, crypto, '\n') - console.log('📈 Ask:', ask, fiat) - console.log('📉 Bid:', bid, fiat, '\n') - - // Place order - try { - const details = { pair, type: 'buy', ordertype: 'limit', price, volume } - if (validate) details.validate = true - - const { result: { descr: { order }, txid } } = await kraken.api('AddOrder', details) - - console.log('💸 Order:', order) - if (txid) console.log('📎 Transaction ID:', txid.join(', ')) - if (validate) console.log('\n🚨 THIS WAS JUST A VALIDATION RUN, NO ORDER HAS BEEN PLACED!') - } catch (err) { - console.log(`\n🚨 Failure:`, err.message) - } -})() diff --git a/withdraw.js b/withdraw.js deleted file mode 100644 index 4decf07..0000000 --- a/withdraw.js +++ /dev/null @@ -1,47 +0,0 @@ -const assert = require('assert') -const Kraken = require('kraken-api') - -const { - KRAKEN_API_KEY: key, - KRAKEN_API_SECRET: secret, - KRAKEN_MAX_REL_FEE: max_fee, - KRAKEN_WITHDRAW_KEY: wdr_key -} = process.env - -assert(key && secret, 'Provide the KRAKEN_API_KEY and KRAKEN_API_SECRET environment variables.') -assert(max_fee && wdr_key, 'Provide the KRAKEN_MAX_REL_FEE and KRAKEN_WITHDRAW_KEY environment variables.') - -// https://www.kraken.com/features/api -const kraken = new Kraken(key, secret) -const asset = 'XBT' -const validate = process.argv[2] === '--validate' - -;(async () => { - // Get withdrawal information - // URL: https://api.kraken.com/0/private/WithdrawInfo - const withdrawdetails = { asset, key: wdr_key, amount: 0 } - try { - const { result: { limit, fee } } = await kraken.api('WithdrawInfo', withdrawdetails); - const rel_fee = 1/parseFloat(limit)*parseFloat(fee) - console.log(`💡 Relative fee of withdrawal amount: ${(rel_fee*100).toFixed(2)}%`) - - // Place withdrawal when fee is low enough (relatively) - if (rel_fee < max_fee/100) { - console.log(`💰 Withdraw ${limit} ${asset} now.`) - const withdraw = { asset, key: wdr_key, amount: limit } - if (!validate) { - try { - const { result: { refid } } = await kraken.api('Withdraw', withdraw) - if (refid) console.log(`📎 Withdrawal reference ID: ${refid}`) - } catch (err) { - console.log(`\n🚨 Failure:`, err.message) - } - } - } else { - console.log(`❌ Don't withdraw now. Fee is too high - max rel. fee: ${parseFloat(max_fee).toFixed(2)}%`); - } - } catch (err) { - console.log(`\n🚨 Failure:`, err.message) - } - if (validate) console.log('\n🚨 THIS WAS JUST A VALIDATION RUN, NO WITHDRAWAL HAS BEEN PLACED!') -})()