Support Strike for Lightning Network

This commit is contained in:
Josh Harvey 2018-05-26 14:09:47 +03:00
parent 8d4a36865b
commit 3f9c139f83
11 changed files with 175 additions and 11 deletions

20
dev/strike.js Normal file
View 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)

View file

@ -100,6 +100,7 @@
"fields": [
"ticker",
"wallet",
"layer2",
"exchange",
"zeroConf"
]
@ -499,6 +500,18 @@
}
]
},
{
"code": "layer2",
"displayBottom": "Layer 2",
"fieldType": "account",
"fieldClass": "layer2",
"fieldValidation": [
{
"code": "required"
}
],
"default": "no-layer2"
},
{
"code": "exchange",
"displayBottom": "Exchange",

View file

@ -180,7 +180,9 @@ function fetchData () {
{code: 'coinbase', display: 'Coinbase', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC', 'BCH']},
{code: 'mock-ticker', display: 'Mock ticker', class: 'ticker', cryptos: ALL_CRYPTOS},
{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: 'zcashd', display: 'zcashd', class: 'wallet', cryptos: ['ZEC']},
{code: 'litecoind', display: 'litecoind', class: 'wallet', cryptos: ['LTC']},

40
lib/layer2.js Normal file
View 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
}

View file

@ -7,6 +7,7 @@ const pluginCodes = {
TICKER: 'ticker',
EXCHANGE: 'exchange',
WALLET: 'wallet',
LAYER2: 'layer2',
SMS: 'sms',
EMAIL: 'email',
ZERO_CONF: 'zero-conf'
@ -21,7 +22,7 @@ function load (type, pluginCode) {
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}`)
}

View 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'}))
})
}

View file

@ -40,15 +40,11 @@ function updateAndLoadSanctions () {
.then(() => logger.info('Sanctions database updated.'))
}
const pp = require('./pp')
function updateCoinAtmRadar () {
const config = settings().config
return pi().getRates()
.then(rates => {
pp('DEBUG200')(rates)
return coinAtmRadar.update({rates, config})
})
.then(rates => coinAtmRadar.update({rates, config}))
}
function start (__settings) {

View file

@ -31,7 +31,7 @@ const reboots = {}
const devMode = argv.dev || options.http
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) {

View file

@ -8,6 +8,7 @@ const fs = pify(require('fs'))
const options = require('./options')
const ph = require('./plugin-helper')
const layer2 = require('./layer2')
const FETCH_INTERVAL = 5000
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 = {}
function _balance (settings, cryptoCode) {
@ -74,6 +81,8 @@ function sendCoins (settings, toAddress, cryptoAtoms, cryptoCode) {
}
function newAddress (settings, info) {
if (isLayer2(info)) return layer2.newAddress(settings, info)
return fetchWallet(settings, info.cryptoCode)
.then(r => r.wallet.newAddress(r.account, info))
}
@ -89,6 +98,8 @@ function newFunding (settings, cryptoCode, address) {
}
function getWalletStatus (settings, tx) {
if (isLayer2(tx)) return layer2.getStatus(settings, tx)
return fetchWallet(settings, tx.cryptoCode)
.then(r => r.wallet.getStatus(r.account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode))
}

View file

@ -37222,11 +37222,20 @@ var _user$project$NavBar$view = F2(
ctor: '::',
_0: {
ctor: '_Tuple3',
_0: 'Twilio',
_1: _user$project$CoreTypes$AccountRoute('twilio'),
_0: 'Strike',
_1: _user$project$CoreTypes$AccountRoute('strike'),
_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
View file

@ -0,0 +1,14 @@
{
"code": "strike",
"display": "Strike",
"fields": [
{
"code": "token",
"display": "API Token",
"fieldType": "password",
"secret": true,
"required": true,
"value": ""
}
]
}