Support Strike for Lightning Network
This commit is contained in:
parent
8d4a36865b
commit
3f9c139f83
11 changed files with 175 additions and 11 deletions
20
dev/strike.js
Normal file
20
dev/strike.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
const strike = require('../lib/plugins/wallet/strike/strike')
|
||||||
|
const BN = require('../lib/bn')
|
||||||
|
|
||||||
|
const account = {token: 'xxx'}
|
||||||
|
|
||||||
|
strike.newAddress(account, {cryptoCode: 'BTC', cryptoAtoms: BN(10000)})
|
||||||
|
.then(r => {
|
||||||
|
console.log(r)
|
||||||
|
|
||||||
|
const toAddress = r
|
||||||
|
const requested = null
|
||||||
|
const cryptoCode = 'BTC'
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
strike.getStatus(account, toAddress, requested, cryptoCode)
|
||||||
|
.then(console.log)
|
||||||
|
.catch(r => console.log(r.message))
|
||||||
|
}, 2000)
|
||||||
|
})
|
||||||
|
.catch(console.log)
|
||||||
|
|
@ -100,6 +100,7 @@
|
||||||
"fields": [
|
"fields": [
|
||||||
"ticker",
|
"ticker",
|
||||||
"wallet",
|
"wallet",
|
||||||
|
"layer2",
|
||||||
"exchange",
|
"exchange",
|
||||||
"zeroConf"
|
"zeroConf"
|
||||||
]
|
]
|
||||||
|
|
@ -499,6 +500,18 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"code": "layer2",
|
||||||
|
"displayBottom": "Layer 2",
|
||||||
|
"fieldType": "account",
|
||||||
|
"fieldClass": "layer2",
|
||||||
|
"fieldValidation": [
|
||||||
|
{
|
||||||
|
"code": "required"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": "no-layer2"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"code": "exchange",
|
"code": "exchange",
|
||||||
"displayBottom": "Exchange",
|
"displayBottom": "Exchange",
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,9 @@ function fetchData () {
|
||||||
{code: 'coinbase', display: 'Coinbase', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC', 'BCH']},
|
{code: 'coinbase', display: 'Coinbase', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC', 'BCH']},
|
||||||
{code: 'mock-ticker', display: 'Mock ticker', class: 'ticker', cryptos: ALL_CRYPTOS},
|
{code: 'mock-ticker', display: 'Mock ticker', class: 'ticker', cryptos: ALL_CRYPTOS},
|
||||||
{code: 'bitcoind', display: 'bitcoind', class: 'wallet', cryptos: ['BTC']},
|
{code: 'bitcoind', display: 'bitcoind', class: 'wallet', cryptos: ['BTC']},
|
||||||
{code: 'lnd', display: 'Lightning Network', class: 'wallet', cryptos: ['BTC']},
|
{code: 'no-layer2', display: 'No Layer 2', class: 'layer2', cryptos: ALL_CRYPTOS},
|
||||||
|
{code: 'strike', display: 'Strike (LN)', class: 'layer2', cryptos: ['BTC']},
|
||||||
|
{code: 'lnd', display: 'Lightning Network', class: 'layer2', cryptos: ['BTC']},
|
||||||
{code: 'geth', display: 'geth', class: 'wallet', cryptos: ['ETH']},
|
{code: 'geth', display: 'geth', class: 'wallet', cryptos: ['ETH']},
|
||||||
{code: 'zcashd', display: 'zcashd', class: 'wallet', cryptos: ['ZEC']},
|
{code: 'zcashd', display: 'zcashd', class: 'wallet', cryptos: ['ZEC']},
|
||||||
{code: 'litecoind', display: 'litecoind', class: 'wallet', cryptos: ['LTC']},
|
{code: 'litecoind', display: 'litecoind', class: 'wallet', cryptos: ['LTC']},
|
||||||
|
|
|
||||||
40
lib/layer2.js
Normal file
40
lib/layer2.js
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
const configManager = require('./config-manager')
|
||||||
|
const ph = require('./plugin-helper')
|
||||||
|
|
||||||
|
function fetch (settings, cryptoCode) {
|
||||||
|
const plugin = configManager.cryptoScoped(cryptoCode, settings.config).layer2
|
||||||
|
const layer2 = ph.load(ph.LAYER2, plugin)
|
||||||
|
const account = settings.accounts[plugin]
|
||||||
|
|
||||||
|
return Promise.resolve({layer2, account})
|
||||||
|
}
|
||||||
|
|
||||||
|
function newAddress (settings, info) {
|
||||||
|
return fetch(settings, info.cryptoCode)
|
||||||
|
.then(r => r.layer2.newAddress(r.account, info))
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatus (settings, tx) {
|
||||||
|
return fetch(settings, tx.cryptoCode)
|
||||||
|
.then(r => r.layer2.getStatus(r.account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
function cryptoNetwork (settings, cryptoCode) {
|
||||||
|
const plugin = configManager.cryptoScoped(cryptoCode, settings.config).layer2
|
||||||
|
const layer2 = ph.load(ph.LAYER2, plugin)
|
||||||
|
const account = settings.accounts[plugin]
|
||||||
|
|
||||||
|
if (!layer2.cryptoNetwork) return Promise.resolve(false)
|
||||||
|
return layer2.cryptoNetwork(account, cryptoCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLayer2Address (address) {
|
||||||
|
return address.split(':').length >= 2
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isLayer2Address,
|
||||||
|
newAddress,
|
||||||
|
getStatus,
|
||||||
|
cryptoNetwork
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ const pluginCodes = {
|
||||||
TICKER: 'ticker',
|
TICKER: 'ticker',
|
||||||
EXCHANGE: 'exchange',
|
EXCHANGE: 'exchange',
|
||||||
WALLET: 'wallet',
|
WALLET: 'wallet',
|
||||||
|
LAYER2: 'layer2',
|
||||||
SMS: 'sms',
|
SMS: 'sms',
|
||||||
EMAIL: 'email',
|
EMAIL: 'email',
|
||||||
ZERO_CONF: 'zero-conf'
|
ZERO_CONF: 'zero-conf'
|
||||||
|
|
@ -21,7 +22,7 @@ function load (type, pluginCode) {
|
||||||
|
|
||||||
if (!pluginCode) throw new Error(`No plugin defined for ${type}`)
|
if (!pluginCode) throw new Error(`No plugin defined for ${type}`)
|
||||||
|
|
||||||
if (pluginCode.search(/[a-z0-9\-]/) === -1) {
|
if (pluginCode.search(/[a-z0-9-]/) === -1) {
|
||||||
throw new Error(`Unallowed plugin name: ${pluginCode}`)
|
throw new Error(`Unallowed plugin name: ${pluginCode}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
58
lib/plugins/layer2/strike/strike.js
Normal file
58
lib/plugins/layer2/strike/strike.js
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
const axios = require('axios')
|
||||||
|
const _ = require('lodash/fp')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
newAddress,
|
||||||
|
getStatus,
|
||||||
|
cryptoNetwork
|
||||||
|
}
|
||||||
|
|
||||||
|
function cryptoNetwork (account, cryptoCode) {
|
||||||
|
return Promise.resolve('test')
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkCryptoCode (cryptoCode) {
|
||||||
|
if (cryptoCode !== 'BTC') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode))
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCharge (account, chargeId) {
|
||||||
|
return axios({
|
||||||
|
method: 'get',
|
||||||
|
url: `https://api.strike.acinq.co/api/v1/charges/${chargeId}`,
|
||||||
|
auth: {username: account.token, password: ''}
|
||||||
|
}).then(_.get('data'))
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCharge (account, info) {
|
||||||
|
const data = {
|
||||||
|
amount: info.cryptoAtoms.toNumber(),
|
||||||
|
currency: 'btc',
|
||||||
|
description: 'Lamassu cryptomat cash-out'
|
||||||
|
}
|
||||||
|
|
||||||
|
return axios({
|
||||||
|
method: 'post',
|
||||||
|
url: 'https://api.strike.acinq.co/api/v1/charges',
|
||||||
|
auth: {username: account.token, password: ''},
|
||||||
|
data
|
||||||
|
}).then(_.get('data'))
|
||||||
|
}
|
||||||
|
|
||||||
|
function newAddress (account, info) {
|
||||||
|
return checkCryptoCode(info.cryptoCode)
|
||||||
|
.then(() => createCharge(account, info))
|
||||||
|
.then(_.tap(console.log))
|
||||||
|
.then(r => `strike:${r.id}:${r.payment_hash}:${r.payment_request}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatus (account, toAddress, requested, cryptoCode) {
|
||||||
|
return checkCryptoCode(cryptoCode)
|
||||||
|
.then(() => {
|
||||||
|
const parts = _.split(':', toAddress)
|
||||||
|
const chargeId = parts[1]
|
||||||
|
|
||||||
|
return getCharge(account, chargeId)
|
||||||
|
.then(r => ({status: r.paid ? 'confirmed' : 'notSeen'}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -40,15 +40,11 @@ function updateAndLoadSanctions () {
|
||||||
.then(() => logger.info('Sanctions database updated.'))
|
.then(() => logger.info('Sanctions database updated.'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const pp = require('./pp')
|
|
||||||
function updateCoinAtmRadar () {
|
function updateCoinAtmRadar () {
|
||||||
const config = settings().config
|
const config = settings().config
|
||||||
|
|
||||||
return pi().getRates()
|
return pi().getRates()
|
||||||
.then(rates => {
|
.then(rates => coinAtmRadar.update({rates, config}))
|
||||||
pp('DEBUG200')(rates)
|
|
||||||
return coinAtmRadar.update({rates, config})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function start (__settings) {
|
function start (__settings) {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ const reboots = {}
|
||||||
const devMode = argv.dev || options.http
|
const devMode = argv.dev || options.http
|
||||||
|
|
||||||
function checkHasLightning (settings) {
|
function checkHasLightning (settings) {
|
||||||
return configManager.cryptoScoped('BTC', settings.config).wallet === 'lnd'
|
return configManager.cryptoScoped('BTC', settings.config).layer2 !== 'no-layer2'
|
||||||
}
|
}
|
||||||
|
|
||||||
function poll (req, res, next) {
|
function poll (req, res, next) {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ const fs = pify(require('fs'))
|
||||||
|
|
||||||
const options = require('./options')
|
const options = require('./options')
|
||||||
const ph = require('./plugin-helper')
|
const ph = require('./plugin-helper')
|
||||||
|
const layer2 = require('./layer2')
|
||||||
|
|
||||||
const FETCH_INTERVAL = 5000
|
const FETCH_INTERVAL = 5000
|
||||||
const INSUFFICIENT_FUNDS_CODE = 570
|
const INSUFFICIENT_FUNDS_CODE = 570
|
||||||
|
|
@ -39,6 +40,12 @@ function fetchWallet (settings, cryptoCode) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isLayer2 (tx) {
|
||||||
|
return _.isNil(tx.isLightning)
|
||||||
|
? layer2.isLayer2Address(tx.toAddress)
|
||||||
|
: tx.isLightning
|
||||||
|
}
|
||||||
|
|
||||||
const lastBalance = {}
|
const lastBalance = {}
|
||||||
|
|
||||||
function _balance (settings, cryptoCode) {
|
function _balance (settings, cryptoCode) {
|
||||||
|
|
@ -74,6 +81,8 @@ function sendCoins (settings, toAddress, cryptoAtoms, cryptoCode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function newAddress (settings, info) {
|
function newAddress (settings, info) {
|
||||||
|
if (isLayer2(info)) return layer2.newAddress(settings, info)
|
||||||
|
|
||||||
return fetchWallet(settings, info.cryptoCode)
|
return fetchWallet(settings, info.cryptoCode)
|
||||||
.then(r => r.wallet.newAddress(r.account, info))
|
.then(r => r.wallet.newAddress(r.account, info))
|
||||||
}
|
}
|
||||||
|
|
@ -89,6 +98,8 @@ function newFunding (settings, cryptoCode, address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWalletStatus (settings, tx) {
|
function getWalletStatus (settings, tx) {
|
||||||
|
if (isLayer2(tx)) return layer2.getStatus(settings, tx)
|
||||||
|
|
||||||
return fetchWallet(settings, tx.cryptoCode)
|
return fetchWallet(settings, tx.cryptoCode)
|
||||||
.then(r => r.wallet.getStatus(r.account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode))
|
.then(r => r.wallet.getStatus(r.account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37222,11 +37222,20 @@ var _user$project$NavBar$view = F2(
|
||||||
ctor: '::',
|
ctor: '::',
|
||||||
_0: {
|
_0: {
|
||||||
ctor: '_Tuple3',
|
ctor: '_Tuple3',
|
||||||
_0: 'Twilio',
|
_0: 'Strike',
|
||||||
_1: _user$project$CoreTypes$AccountRoute('twilio'),
|
_1: _user$project$CoreTypes$AccountRoute('strike'),
|
||||||
_2: true
|
_2: true
|
||||||
},
|
},
|
||||||
_1: {ctor: '[]'}
|
_1: {
|
||||||
|
ctor: '::',
|
||||||
|
_0: {
|
||||||
|
ctor: '_Tuple3',
|
||||||
|
_0: 'Twilio',
|
||||||
|
_1: _user$project$CoreTypes$AccountRoute('twilio'),
|
||||||
|
_2: true
|
||||||
|
},
|
||||||
|
_1: {ctor: '[]'}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
schemas/strike.json
Normal file
14
schemas/strike.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"code": "strike",
|
||||||
|
"display": "Strike",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"code": "token",
|
||||||
|
"display": "API Token",
|
||||||
|
"fieldType": "password",
|
||||||
|
"secret": true,
|
||||||
|
"required": true,
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue