feat: decouple l-s entrypoint
This commit is contained in:
parent
2a2c1fccc8
commit
f4d6b5e454
48 changed files with 411 additions and 232 deletions
1
.env
1
.env
|
|
@ -1 +0,0 @@
|
|||
LAMASSU_DB=DEV
|
||||
59
.sample.env
Normal file
59
.sample.env
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
## Database variables
|
||||
|
||||
# Used to describe which database to use. Possible values include: DEV, RELEASE, STRESS_TEST
|
||||
LAMASSU_DB=
|
||||
|
||||
# Postgres related environment variables
|
||||
POSTGRES_USER=
|
||||
POSTGRES_PASSWORD=
|
||||
POSTGRES_HOST=
|
||||
POSTGRES_PORT=
|
||||
POSTGRES_DB=
|
||||
|
||||
## File paths
|
||||
|
||||
# Certificate-related variables
|
||||
LAMASSU_CA_PATH=
|
||||
CA_PATH=
|
||||
CERT_PATH=
|
||||
KEY_PATH=
|
||||
|
||||
# Full path to where the wallet's mnemonic is stored
|
||||
MNEMONIC_PATH=
|
||||
|
||||
MIGRATE_STATE_PATH=
|
||||
|
||||
## Directories
|
||||
|
||||
BLOCKCHAIN_DIR=
|
||||
OFAC_DATA_DIR=
|
||||
ID_PHOTO_CARD_DIR=
|
||||
FRONT_CAMERA_DIR=
|
||||
OPERATOR_DATA_DIR=
|
||||
|
||||
## URLs
|
||||
|
||||
STRIKE_BASE_URL=
|
||||
COIN_ATM_RADAR_URL=
|
||||
|
||||
## OFAC Sources variables
|
||||
|
||||
# These variables map to each other, similar to a zip HOF. Entries are separated by commas
|
||||
# Example:
|
||||
# OFAC_SOURCES_NAMES=name1,name2
|
||||
# OFAC_SOURCES_URLS=url1,url2
|
||||
OFAC_SOURCES_NAMES=
|
||||
OFAC_SOURCES_URLS=
|
||||
|
||||
## Misc
|
||||
|
||||
HOSTNAME=
|
||||
LOG_LEVEL=
|
||||
LIGHTNING_NETWORK_DAEMON=
|
||||
|
||||
## Deprecated or in deprecation
|
||||
|
||||
HTTP=
|
||||
DEV_MODE=
|
||||
|
||||
## Uncategorized variables
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var pgp = require('pg-promise')()
|
||||
var psqlUrl = require('../lib/options').postgresql
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
var db = pgp(psqlUrl)
|
||||
var pgp = require('pg-promise')()
|
||||
|
||||
const { PSQL_URL } = require('../lib/constants')
|
||||
|
||||
var db = pgp(PSQL_URL)
|
||||
|
||||
db.manyOrNone(`select * from transactions where incoming=false
|
||||
and stage='final_request' and authority='machine'`)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const options = require('../lib/options-loader')()
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
if (!options.opts.frontCameraDir) {
|
||||
options.opts.frontCameraDir = '/opt/lamassu-server/frontcamera'
|
||||
const setEnvVariable = require('../tools/set-env-var')
|
||||
|
||||
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, '\t'), 'utf8')
|
||||
if (!process.env.FRONT_CAMERA_DIR) {
|
||||
setEnvVariable('FRONT_CAMERA_DIR', '/opt/lamassu-server/frontcamera')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
const hdkey = require('ethereumjs-wallet/hdkey')
|
||||
const hkdf = require('futoin-hkdf')
|
||||
const db = require('../lib/db')
|
||||
|
|
@ -9,14 +11,14 @@ const mnemonicHelpers = require('../lib/mnemonic-helpers')
|
|||
const pify = require('pify')
|
||||
const fs = pify(require('fs'))
|
||||
|
||||
const options = require('../lib/options')
|
||||
const MNEMONIC_PATH = process.env.MNEMONIC_PATH
|
||||
|
||||
const defaultPrefixPath = "m/44'/60'/1'/0'"
|
||||
const paymentPrefixPath = "m/44'/60'/0'/0'"
|
||||
|
||||
const address = process.argv[2]
|
||||
|
||||
if (!options || !options.mnemonicPath) {
|
||||
if (!MNEMONIC_PATH) {
|
||||
console.error(`Unable to fetch mnemonic from your account!`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
|
@ -47,7 +49,7 @@ function searchForHdIndex (address) {
|
|||
}
|
||||
|
||||
function fetchMnemonic () {
|
||||
return fs.readFile(options.mnemonicPath, 'utf8')
|
||||
return fs.readFile(MNEMONIC_PATH, 'utf8')
|
||||
.then(mnemonic => computeSeed(mnemonic))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
#!/usr/bin/env node
|
||||
const FileStore = require('migrate/lib/file-store')
|
||||
|
||||
const _ = require('lodash/fp')
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
const db = require('../lib/db')
|
||||
const migrate = require('../lib/migrate')
|
||||
const options = require('../lib/options')
|
||||
const { asyncLocalStorage, defaultStore } = require('../lib/async-storage')
|
||||
|
||||
const MIGRATE_STATE_PATH = process.env.MIGRATE_STATE_PATH
|
||||
|
||||
const createMigration = `CREATE TABLE IF NOT EXISTS migrations (
|
||||
id serial PRIMARY KEY,
|
||||
data json NOT NULL
|
||||
|
|
@ -14,7 +20,7 @@ const select = 'select * from migrations limit 1'
|
|||
|
||||
const getMigrateFile = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
new FileStore(options.migrateStatePath).load((err, store) => {
|
||||
new FileStore(MIGRATE_STATE_PATH).load((err, store) => {
|
||||
if (err) return reject(err)
|
||||
return resolve(store)
|
||||
})
|
||||
|
|
@ -26,7 +32,7 @@ asyncLocalStorage.run(store, () => {
|
|||
db.none(createMigration)
|
||||
.then(() => Promise.all([db.oneOrNone(select), getMigrateFile()]))
|
||||
.then(([qResult, migrateFile]) => {
|
||||
process.env.SKIP_SERVER_LOGS = !(qResult && qResult.data.migrations.find(({ title }) => title === '1572524820075-server-support-logs.js'))
|
||||
process.env.SKIP_SERVER_LOGS = !(qResult && _.find(({ title }) => title === '1572524820075-server-support-logs.js', qResult.data.migrations ?? []))
|
||||
if (!qResult && migrateFile) {
|
||||
return db.none('insert into migrations (id, data) values (1, $1)', [migrateFile])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
const options = require('../lib/options')
|
||||
const MNEMONIC_PATH = process.env.MNEMONIC_PATH
|
||||
|
||||
const mnemonic = fs.readFileSync(options.mnemonicPath, 'utf8').trim()
|
||||
const mnemonic = fs.readFileSync(MNEMONIC_PATH, 'utf8').trim()
|
||||
console.log(mnemonic)
|
||||
|
|
|
|||
|
|
@ -2,22 +2,12 @@
|
|||
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs')
|
||||
const setEnvVariable = require('../tools/set-env-var')
|
||||
|
||||
const ofacSources = [
|
||||
{
|
||||
name: 'sdn_advanced',
|
||||
url: 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml'
|
||||
},
|
||||
{
|
||||
name: 'cons_advanced',
|
||||
url: 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml'
|
||||
}
|
||||
]
|
||||
|
||||
const options = require('../lib/options-loader')()
|
||||
|
||||
if (!options.opts.ofacSources) {
|
||||
options.opts.ofacSources = ofacSources
|
||||
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, ' '), 'utf8')
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
if (!process.env.OFAC_SOURCES_NAMES && !process.env.OFAC_SOURCES_URLS) {
|
||||
setEnvVariable('OFAC_SOURCES_NAMES', 'sdn_advanced,cons_advanced')
|
||||
setEnvVariable('OFAC_SOURCES_URLS', 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml,https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,14 @@
|
|||
const fs = require('fs')
|
||||
const hkdf = require('futoin-hkdf')
|
||||
|
||||
const options = require('../lib/options')
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
const mnemonicHelpers = require('../lib/mnemonic-helpers')
|
||||
|
||||
const mnemonic = fs.readFileSync(options.mnemonicPath, 'utf8').trim()
|
||||
const MNEMONIC_PATH = process.env.MNEMONIC_PATH
|
||||
|
||||
const mnemonic = fs.readFileSync(MNEMONIC_PATH, 'utf8').trim()
|
||||
const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic)
|
||||
|
||||
console.log(hkdf(masterSeed, 16, { salt: 'lamassu-server-salt', info: 'operator-id' }).toString('hex'))
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
const { asyncLocalStorage, defaultStore } = require('../lib/async-storage')
|
||||
const userManagement = require('../lib/new-admin/graphql/modules/userManagement')
|
||||
const authErrors = require('../lib/new-admin/graphql/errors/authentication')
|
||||
const options = require('../lib/options')
|
||||
|
||||
const name = process.argv[2]
|
||||
const role = process.argv[3]
|
||||
const domain = options.hostname
|
||||
const domain = process.env.HOSTNAME
|
||||
|
||||
if (!domain) {
|
||||
console.error('No hostname configured in lamassu.json')
|
||||
console.error('No hostname configured in the environment')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,25 +6,26 @@ const fs = require('fs')
|
|||
const path = require('path')
|
||||
const os = require('os')
|
||||
const mnemonicHelpers = require('../lib/mnemonic-helpers')
|
||||
const options = require('../lib/options-loader')()
|
||||
const setEnvVariable = require('../tools/set-env-var')
|
||||
|
||||
if (!options.opts.mnemonicPath && options.opts.seedPath) {
|
||||
const seed = fs.readFileSync(options.opts.seedPath, 'utf8').trim()
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
if (!process.env.MNEMONIC_PATH && process.env.SEED_PATH) {
|
||||
const seed = fs.readFileSync(process.env.SEED_PATH, 'utf8').trim()
|
||||
const mnemonic = mnemonicHelpers.fromSeed(seed)
|
||||
|
||||
if (process.argv[2] === '--prod') {
|
||||
options.opts.mnemonicPath = path.resolve('/etc', 'lamassu', 'mnemonics', 'mnemonic.txt')
|
||||
setEnvVariable('MNEMONIC_PATH', path.resolve('/etc', 'lamassu', 'mnemonics', 'mnemonic.txt'))
|
||||
} else {
|
||||
options.opts.mnemonicPath = path.resolve(os.homedir(), '.lamassu', 'mnemonics', 'mnemonic.txt')
|
||||
setEnvVariable('MNEMONIC_PATH', path.resolve(os.homedir(), '.lamassu', 'mnemonics', 'mnemonic.txt'))
|
||||
}
|
||||
|
||||
if (!fs.existsSync(path.dirname(options.opts.mnemonicPath))) {
|
||||
fs.mkdirSync(path.dirname(options.opts.mnemonicPath))
|
||||
if (!fs.existsSync(path.dirname(process.env.MNEMONIC_PATH))) {
|
||||
fs.mkdirSync(path.dirname(process.env.MNEMONIC_PATH))
|
||||
}
|
||||
|
||||
if (!fs.existsSync(options.opts.mnemonicPath)) {
|
||||
fs.writeFileSync(options.opts.mnemonicPath, mnemonic, 'utf8')
|
||||
if (!fs.existsSync(process.env.MNEMONIC_PATH)) {
|
||||
fs.writeFileSync(process.env.MNEMONIC_PATH, mnemonic, 'utf8')
|
||||
}
|
||||
|
||||
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, '\t'), 'utf8')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,13 @@
|
|||
'use strict'
|
||||
|
||||
const pgp = require('pg-promise')()
|
||||
const psqlUrl = require('../lib/options').postgresql
|
||||
|
||||
const db = pgp(psqlUrl)
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
const { PSQL_URL } = require('../lib/constants')
|
||||
|
||||
const db = pgp(PSQL_URL)
|
||||
|
||||
db.many('select data from user_config', 'exchanges')
|
||||
.then(rows => {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
const login = require('../lib/admin/login')
|
||||
const options = require('../lib/options')
|
||||
|
||||
const name = process.argv[2]
|
||||
const domain = options.hostname
|
||||
const domain = process.env.HOSTNAME
|
||||
|
||||
if (!domain) {
|
||||
console.error('No hostname configured in lamassu.json')
|
||||
console.error('No hostname configured in the environment')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ require('es6-promise').polyfill()
|
|||
|
||||
var notifier = require('../lib/notifier')
|
||||
var db = require('../lib/postgresql_interface')
|
||||
var psqlUrl = require('../lib/options').postgres
|
||||
const { PSQL_URL } = require('../lib/constants')
|
||||
|
||||
function getBalances () {
|
||||
return [
|
||||
|
|
@ -11,7 +11,7 @@ function getBalances () {
|
|||
]
|
||||
}
|
||||
|
||||
db.init(psqlUrl)
|
||||
db.init(PSQL_URL)
|
||||
notifier.init(db, getBalances, {lowBalanceThreshold: 10})
|
||||
console.log('DEBUG0')
|
||||
notifier.checkStatus()
|
||||
|
|
|
|||
|
|
@ -6,21 +6,21 @@ const fs = require('fs')
|
|||
const path = require('path')
|
||||
const os = require('os')
|
||||
const bip39 = require('bip39')
|
||||
const options = require('../lib/options-loader')()
|
||||
const setEnvVariable = require('../tools/set-env-var')
|
||||
|
||||
if (options.opts.mnemonicPath && !options.opts.seedPath) {
|
||||
const mnemonic = fs.readFileSync(options.opts.mnemonicPath, 'utf8')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
if (process.env.MNEMONIC_PATH && !process.env.SEED_PATH) {
|
||||
const mnemonic = fs.readFileSync(process.env.MNEMONIC_PATH, 'utf8')
|
||||
const seed = bip39.mnemonicToEntropy(mnemonic.split('\n').join(' ').trim()).toString('hex')
|
||||
|
||||
options.opts.seedPath = path.resolve(os.homedir(), '.lamassu', 'seeds', 'seed.txt')
|
||||
setEnvVariable('SEED_PATH', path.resolve(os.homedir(), '.lamassu', 'seeds', 'seed.txt'))
|
||||
|
||||
if (!fs.existsSync(path.dirname(options.opts.seedPath))) {
|
||||
fs.mkdirSync(path.dirname(options.opts.seedPath))
|
||||
if (!fs.existsSync(path.dirname(process.env.SEED_PATH))) {
|
||||
fs.mkdirSync(path.dirname(process.env.SEED_PATH))
|
||||
}
|
||||
|
||||
if (!fs.existsSync(options.opts.seedPath)) {
|
||||
fs.writeFileSync(options.opts.seedPath, seed, 'utf8')
|
||||
if (!fs.existsSync(process.env.SEED_PATH)) {
|
||||
fs.writeFileSync(process.env.SEED_PATH, seed, 'utf8')
|
||||
}
|
||||
|
||||
fs.writeFileSync(options.path, JSON.stringify(options.opts, null, '\t'), 'utf8')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ const _ = require('lodash/fp')
|
|||
const machineLoader = require('../machine-loader')
|
||||
const T = require('../time')
|
||||
const logger = require('../logger')
|
||||
const options = require('../options')
|
||||
|
||||
const accounts = require('./accounts')
|
||||
const config = require('./config')
|
||||
|
|
@ -35,18 +34,20 @@ const supportServer = require('./admin-support')
|
|||
|
||||
const NEVER = new Date(Date.now() + 100 * T.years)
|
||||
const REAUTHENTICATE_INTERVAL = T.minute
|
||||
const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
|
||||
const frontCameraBasedir = _.get('frontCameraDir', options)
|
||||
const operatorDataBasedir = _.get('operatorDataDir', options)
|
||||
|
||||
const HOSTNAME = process.env.HOSTNAME
|
||||
const KEY_PATH = process.env.KEY_PATH
|
||||
const CERT_PATH = process.env.CERT_PATH
|
||||
const ID_PHOTO_CARD_DIR = process.env.ID_PHOTO_CARD_DIR
|
||||
const FRONT_CAMERA_DIR = process.env.FRONT_CAMERA_DIR
|
||||
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
|
||||
|
||||
const devMode = argv.dev
|
||||
|
||||
const version = require('../../package.json').version
|
||||
logger.info('Version: %s', version)
|
||||
|
||||
const hostname = options.hostname
|
||||
|
||||
if (!hostname) {
|
||||
if (!HOSTNAME) {
|
||||
logger.error('no hostname specified.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
|
@ -82,7 +83,7 @@ app.get('/api/totem', (req, res) => {
|
|||
|
||||
if (!name) return res.status(400).send('Name is required')
|
||||
|
||||
return pairing.totem(hostname, name)
|
||||
return pairing.totem(HOSTNAME, name)
|
||||
.then(totem => res.send(totem))
|
||||
})
|
||||
|
||||
|
|
@ -222,27 +223,27 @@ app.use((err, req, res, next) => {
|
|||
})
|
||||
|
||||
const certOptions = {
|
||||
key: fs.readFileSync(options.keyPath),
|
||||
cert: fs.readFileSync(options.certPath)
|
||||
key: fs.readFileSync(KEY_PATH),
|
||||
cert: fs.readFileSync(CERT_PATH)
|
||||
}
|
||||
|
||||
app.use(serveStatic(path.resolve(__dirname, 'public')))
|
||||
|
||||
if (!fs.existsSync(idPhotoCardBasedir)) {
|
||||
makeDir.sync(idPhotoCardBasedir)
|
||||
if (!fs.existsSync(ID_PHOTO_CARD_DIR)) {
|
||||
makeDir.sync(ID_PHOTO_CARD_DIR)
|
||||
}
|
||||
|
||||
if (!fs.existsSync(frontCameraBasedir)) {
|
||||
makeDir.sync(frontCameraBasedir)
|
||||
if (!fs.existsSync(FRONT_CAMERA_DIR)) {
|
||||
makeDir.sync(FRONT_CAMERA_DIR)
|
||||
}
|
||||
|
||||
if (!fs.existsSync(operatorDataBasedir)) {
|
||||
makeDir.sync(operatorDataBasedir)
|
||||
if (!fs.existsSync(OPERATOR_DATA_DIR)) {
|
||||
makeDir.sync(OPERATOR_DATA_DIR)
|
||||
}
|
||||
|
||||
app.use('/id-card-photo', serveStatic(idPhotoCardBasedir, {index: false}))
|
||||
app.use('/front-camera-photo', serveStatic(frontCameraBasedir, {index: false}))
|
||||
app.use('/operator-data', serveStatic(operatorDataBasedir, {index: false}))
|
||||
app.use('/id-card-photo', serveStatic(ID_PHOTO_CARD_DIR, {index: false}))
|
||||
app.use('/front-camera-photo', serveStatic(FRONT_CAMERA_DIR, {index: false}))
|
||||
app.use('/operator-data', serveStatic(OPERATOR_DATA_DIR, {index: false}))
|
||||
|
||||
function register (req, res, next) {
|
||||
const otp = req.query.otp
|
||||
|
|
@ -259,7 +260,7 @@ function register (req, res, next) {
|
|||
const cookieOpts = {
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
domain: hostname,
|
||||
domain: HOSTNAME,
|
||||
sameSite: true,
|
||||
expires: NEVER
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ const _ = require('lodash/fp')
|
|||
const serveStatic = require('serve-static')
|
||||
const path = require('path')
|
||||
|
||||
const options = require('../options')
|
||||
const KEY_PATH = process.env.KEY_PATH
|
||||
const CERT_PATH = process.env.CERT_PATH
|
||||
const LAMASSU_CA_PATH = process.env.LAMASSU_CA_PATH
|
||||
|
||||
app.use(morgan('dev'))
|
||||
app.use(helmet({noCache: true}))
|
||||
|
|
@ -20,9 +22,9 @@ app.use(serveStatic(path.resolve(__dirname, '..', '..', 'public'), {
|
|||
}))
|
||||
|
||||
const certOptions = {
|
||||
key: fs.readFileSync(options.keyPath),
|
||||
cert: fs.readFileSync(options.certPath),
|
||||
ca: [fs.readFileSync(options.lamassuCaPath)],
|
||||
key: fs.readFileSync(KEY_PATH),
|
||||
cert: fs.readFileSync(CERT_PATH),
|
||||
ca: [fs.readFileSync(LAMASSU_CA_PATH)],
|
||||
requestCert: true,
|
||||
rejectUnauthorized: true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,19 +4,18 @@ const readFile = pify(fs.readFile)
|
|||
const crypto = require('crypto')
|
||||
const baseX = require('base-x')
|
||||
|
||||
const options = require('../options')
|
||||
const db = require('../db')
|
||||
const pairing = require('../pairing')
|
||||
|
||||
const ALPHA_BASE = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'
|
||||
const bsAlpha = baseX(ALPHA_BASE)
|
||||
|
||||
const CA_PATH = process.env.CA_PATH
|
||||
|
||||
const unpair = pairing.unpair
|
||||
|
||||
function totem (hostname, name) {
|
||||
const caPath = options.caPath
|
||||
|
||||
return readFile(caPath)
|
||||
return readFile(CA_PATH)
|
||||
.then(data => {
|
||||
const caHash = crypto.createHash('sha256').update(data).digest()
|
||||
const token = crypto.randomBytes(32)
|
||||
|
|
|
|||
15
lib/app.js
15
lib/app.js
|
|
@ -1,8 +1,11 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const http = require('http')
|
||||
const https = require('https')
|
||||
const argv = require('minimist')(process.argv.slice(2))
|
||||
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
const { asyncLocalStorage, defaultStore } = require('./async-storage')
|
||||
const routes = require('./routes')
|
||||
const logger = require('./logger')
|
||||
|
|
@ -10,11 +13,13 @@ const poller = require('./poller')
|
|||
const settingsLoader = require('./new-settings-loader')
|
||||
const configManager = require('./new-config-manager')
|
||||
const complianceTriggers = require('./compliance-triggers')
|
||||
const options = require('./options')
|
||||
const ofac = require('./ofac/index')
|
||||
const ofacUpdate = require('./ofac/update')
|
||||
|
||||
const devMode = argv.dev || options.http
|
||||
const KEY_PATH = process.env.KEY_PATH
|
||||
const CERT_PATH = process.env.CERT_PATH
|
||||
|
||||
const devMode = argv.dev || process.env.HTTP
|
||||
|
||||
const version = require('../package.json').version
|
||||
logger.info('Version: %s', version)
|
||||
|
|
@ -66,8 +71,8 @@ function startServer (settings) {
|
|||
.then(() => {
|
||||
poller.setup(['public'])
|
||||
const httpsServerOptions = {
|
||||
key: fs.readFileSync(options.keyPath),
|
||||
cert: fs.readFileSync(options.certPath),
|
||||
key: fs.readFileSync(KEY_PATH),
|
||||
cert: fs.readFileSync(CERT_PATH),
|
||||
requestCert: true,
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
|
|
@ -80,7 +85,7 @@ function startServer (settings) {
|
|||
const localPort = 3030
|
||||
const localServer = http.createServer(routes.localApp)
|
||||
|
||||
if (options.devMode) logger.info('In dev mode')
|
||||
if (devMode) logger.info('In dev mode')
|
||||
|
||||
server.listen(port, () => {
|
||||
logger.info('lamassu-server listening on port ' +
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
const fs = require('fs')
|
||||
|
||||
const options = require('../options')
|
||||
|
||||
const common = require('./common')
|
||||
|
||||
const MOUNT_POINT = options.blockchainDir
|
||||
const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR
|
||||
|
||||
const MOUNT_POINT = BLOCKCHAIN_DIR
|
||||
|
||||
module.exports = {prepareVolume}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ const inquirer = require('inquirer')
|
|||
const _ = require('lodash/fp')
|
||||
|
||||
const { utils: coinUtils } = require('@lamassu/coins')
|
||||
const options = require('../options')
|
||||
const settingsLoader = require('../new-settings-loader')
|
||||
const wallet = require('../wallet')
|
||||
|
||||
|
|
@ -29,10 +28,12 @@ const PLUGINS = {
|
|||
ZEC: require('./zcash.js')
|
||||
}
|
||||
|
||||
const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR
|
||||
|
||||
module.exports = {run}
|
||||
|
||||
function installedVolumeFilePath (crypto) {
|
||||
return path.resolve(coinUtils.cryptoDir(crypto, options.blockchainDir), '.installed')
|
||||
return path.resolve(coinUtils.cryptoDir(crypto, BLOCKCHAIN_DIR), '.installed')
|
||||
}
|
||||
|
||||
function isInstalledVolume (crypto) {
|
||||
|
|
@ -63,7 +64,7 @@ function processCryptos (codes) {
|
|||
common.es('sudo supervisorctl reread')
|
||||
common.es('sudo supervisorctl update')
|
||||
|
||||
const blockchainDir = options.blockchainDir
|
||||
const blockchainDir = BLOCKCHAIN_DIR
|
||||
const backupDir = path.resolve(os.homedir(), 'backups')
|
||||
const rsyncCmd = `( \
|
||||
(crontab -l 2>/dev/null || echo -n "") | grep -v "@daily rsync ".*"wallet.dat"; \
|
||||
|
|
@ -83,7 +84,7 @@ function processCryptos (codes) {
|
|||
|
||||
function setupCrypto (crypto) {
|
||||
logger.info(`Installing ${crypto.display}...`)
|
||||
const cryptoDir = coinUtils.cryptoDir(crypto, options.blockchainDir)
|
||||
const cryptoDir = coinUtils.cryptoDir(crypto, BLOCKCHAIN_DIR)
|
||||
makeDir.sync(cryptoDir)
|
||||
const cryptoPlugin = plugin(crypto)
|
||||
const oldDir = process.cwd()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
const axios = require('axios')
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
const pify = require('pify')
|
||||
const fs = pify(require('fs'))
|
||||
|
||||
const db = require('../db')
|
||||
const configManager = require('../new-config-manager')
|
||||
const complianceTriggers = require('../compliance-triggers')
|
||||
const options = require('../options')
|
||||
const logger = require('../logger')
|
||||
const plugins = require('../plugins')
|
||||
const { getOperatorId } = require('../operator')
|
||||
|
|
@ -15,6 +11,8 @@ const { getOperatorId } = require('../operator')
|
|||
const TIMEOUT = 10000
|
||||
const MAX_CONTENT_LENGTH = 2000
|
||||
|
||||
const COIN_ATM_RADAR_URL = process.env.COIN_ATM_RADAR_URL
|
||||
|
||||
// How long a machine can be down before it's considered offline
|
||||
const STALE_INTERVAL = '2 minutes'
|
||||
|
||||
|
|
@ -112,7 +110,7 @@ function getMachines (rates, settings) {
|
|||
}
|
||||
|
||||
function sendRadar (data) {
|
||||
const url = _.get(['coinAtmRadar', 'url'], options)
|
||||
const url = COIN_ATM_RADAR_URL
|
||||
|
||||
if (_.isEmpty(url)) {
|
||||
return Promise.reject(new Error('Missing coinAtmRadar url!'))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
const T = require('./time')
|
||||
|
||||
const POSTGRES_USER = process.env.POSTGRES_USER
|
||||
const POSTGRES_PASSWORD = process.env.POSTGRES_PASSWORD
|
||||
const POSTGRES_HOST = process.env.POSTGRES_HOST
|
||||
const POSTGRES_PORT = process.env.POSTGRES_PORT
|
||||
const POSTGRES_DB = process.env.POSTGRES_DB
|
||||
|
||||
const PSQL_URL = `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}`
|
||||
|
||||
const anonymousCustomer = {
|
||||
uuid: '47ac1184-8102-11e7-9079-8f13a7117867',
|
||||
name: 'anonymous'
|
||||
|
|
@ -39,5 +47,6 @@ module.exports = {
|
|||
CASH_OUT_MINIMUM_AMOUNT_OF_CASSETTES,
|
||||
CASH_OUT_MAXIMUM_AMOUNT_OF_CASSETTES,
|
||||
WALLET_SCORE_THRESHOLD,
|
||||
RECEIPT
|
||||
RECEIPT,
|
||||
PSQL_URL
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,20 +13,20 @@ const BN = require('./bn')
|
|||
const anonymous = require('../lib/constants').anonymousCustomer
|
||||
const complianceOverrides = require('./compliance_overrides')
|
||||
const users = require('./users')
|
||||
const options = require('./options')
|
||||
const writeFile = util.promisify(fs.writeFile)
|
||||
const notifierQueries = require('./notifier/queries')
|
||||
const notifierUtils = require('./notifier/utils')
|
||||
const NUM_RESULTS = 1000
|
||||
const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
|
||||
const frontCameraBaseDir = _.get('frontCameraDir', options)
|
||||
const operatorDataDir = _.get('operatorDataDir', options)
|
||||
const sms = require('./sms')
|
||||
const settingsLoader = require('./new-settings-loader')
|
||||
const logger = require('./logger')
|
||||
|
||||
const TX_PASSTHROUGH_ERROR_CODES = ['operatorCancel']
|
||||
|
||||
const ID_PHOTO_CARD_DIR = process.env.ID_PHOTO_CARD_DIR
|
||||
const FRONT_CAMERA_DIR = process.env.FRONT_CAMERA_DIR
|
||||
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
|
||||
|
||||
/**
|
||||
* Add new customer
|
||||
*
|
||||
|
|
@ -673,7 +673,7 @@ function updatePhotoCard (id, patch) {
|
|||
const rpath = _.join(path.sep, _.map(_.wrap(_.join, ''), _.take(3, _.chunk(2, _.split('', hash)))))
|
||||
|
||||
// i.e. ../<lamassu-server-home>/idphotocard/24/0e/85
|
||||
const dirname = path.join(idPhotoCardBasedir, rpath)
|
||||
const dirname = path.join(ID_PHOTO_CARD_DIR, rpath)
|
||||
|
||||
// create the directory tree if needed
|
||||
_.attempt(() => makeDir.sync(dirname))
|
||||
|
|
@ -736,7 +736,7 @@ function updatePhotos (imagesData, id, dir) {
|
|||
function updateIdCardData (patch, id) {
|
||||
/* TODO: fetch operator id */
|
||||
const operatorId = 'id-operator'
|
||||
const directory = `${operatorDataDir}/${operatorId}/${id}/`
|
||||
const directory = `${OPERATOR_DATA_DIR}/${operatorId}/${id}/`
|
||||
|
||||
return Promise.resolve(patch)
|
||||
.then(patch => {
|
||||
|
|
@ -755,7 +755,7 @@ function updateTxCustomerPhoto (imageData) {
|
|||
return Promise.resolve(imageData)
|
||||
.then(imageData => {
|
||||
const newPatch = {}
|
||||
const directory = `${operatorDataDir}/customersphotos`
|
||||
const directory = `${OPERATOR_DATA_DIR}/customersphotos`
|
||||
|
||||
if (_.isEmpty(imageData)) {
|
||||
return
|
||||
|
|
@ -826,7 +826,7 @@ function updateFrontCamera (id, patch) {
|
|||
const rpath = _.join(path.sep, _.map(_.wrap(_.join, ''), _.take(3, _.chunk(2, _.split('', hash)))))
|
||||
|
||||
// i.e. ../<lamassu-server-home>/idphotocard/24/0e/85
|
||||
const dirname = path.join(frontCameraBaseDir, rpath)
|
||||
const dirname = path.join(FRONT_CAMERA_DIR, rpath)
|
||||
|
||||
// create the directory tree if needed
|
||||
_.attempt(() => makeDir.sync(dirname))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const Pgp = require('pg-promise')
|
|||
const uuid = require('uuid')
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
const psqlUrl = require('../lib/options').postgresql
|
||||
const { PSQL_URL } = require('./constants')
|
||||
const logger = require('./logger')
|
||||
const eventBus = require('./event-bus')
|
||||
const { asyncLocalStorage, defaultStore } = require('./async-storage')
|
||||
|
|
@ -87,7 +87,7 @@ const pgp = Pgp({
|
|||
}
|
||||
})
|
||||
|
||||
const db = stripDefaultDbFuncs(pgp(psqlUrl))
|
||||
const db = stripDefaultDbFuncs(pgp(PSQL_URL))
|
||||
|
||||
eventBus.subscribe('log', args => {
|
||||
if (process.env.SKIP_SERVER_LOGS) return
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
const winston = require('winston')
|
||||
const Postgres = require('./pg-transport')
|
||||
const options = require('./options')
|
||||
const { PSQL_URL } = require('./constants')
|
||||
|
||||
const LOG_LEVEL = process.env.LOG_LEVEL
|
||||
|
||||
const logger = new winston.Logger({
|
||||
level: options.logLevel,
|
||||
level: LOG_LEVEL,
|
||||
transports: [
|
||||
new (winston.transports.Console)({
|
||||
timestamp: true,
|
||||
|
|
@ -12,7 +14,7 @@ const logger = new winston.Logger({
|
|||
humanReadableUnhandledException: true
|
||||
}),
|
||||
new Postgres({
|
||||
connectionString: options.postgresql,
|
||||
connectionString: PSQL_URL,
|
||||
tableName: 'server_logs',
|
||||
handleExceptions: true,
|
||||
humanReadableUnhandledException: true
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ const cors = require('cors')
|
|||
const helmet = require('helmet')
|
||||
const nocache = require('nocache')
|
||||
const cookieParser = require('cookie-parser')
|
||||
const { ApolloServer, AuthenticationError } = require('apollo-server-express')
|
||||
const { graphqlUploadExpress } = require('graphql-upload')
|
||||
const { ApolloServer } = require('apollo-server-express')
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') })
|
||||
|
||||
const { asyncLocalStorage, defaultStore } = require('../async-storage')
|
||||
const options = require('../options')
|
||||
const users = require('../users')
|
||||
const logger = require('../logger')
|
||||
|
||||
const { AuthDirective } = require('./graphql/directives')
|
||||
|
|
@ -25,13 +25,16 @@ const { USER_SESSIONS_CLEAR_INTERVAL } = require('../constants')
|
|||
const { session, cleanUserSessions, buildApolloContext } = require('./middlewares')
|
||||
|
||||
const devMode = require('minimist')(process.argv.slice(2)).dev
|
||||
const idPhotoCardBasedir = _.get('idPhotoCardDir', options)
|
||||
const frontCameraBasedir = _.get('frontCameraDir', options)
|
||||
const operatorDataBasedir = _.get('operatorDataDir', options)
|
||||
|
||||
const hostname = options.hostname
|
||||
if (!hostname) {
|
||||
logger.error('no hostname specified.')
|
||||
const HOSTNAME = process.env.HOSTNAME
|
||||
const KEY_PATH = process.env.KEY_PATH
|
||||
const CERT_PATH = process.env.CERT_PATH
|
||||
const ID_PHOTO_CARD_DIR = process.env.ID_PHOTO_CARD_DIR
|
||||
const FRONT_CAMERA_DIR = process.env.FRONT_CAMERA_DIR
|
||||
const OPERATOR_DATA_DIR = process.env.OPERATOR_DATA_DIR
|
||||
|
||||
if (!HOSTNAME) {
|
||||
logger.error('No hostname specified.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -77,16 +80,16 @@ apolloServer.applyMiddleware({
|
|||
// cors on app for /api/register endpoint.
|
||||
app.use(cors({ credentials: true, origin: devMode && 'https://localhost:3001' }))
|
||||
|
||||
app.use('/id-card-photo', serveStatic(idPhotoCardBasedir, { index: false }))
|
||||
app.use('/front-camera-photo', serveStatic(frontCameraBasedir, { index: false }))
|
||||
app.use('/operator-data', serveStatic(operatorDataBasedir, { index: false }))
|
||||
app.use('/id-card-photo', serveStatic(ID_PHOTO_CARD_DIR, { index: false }))
|
||||
app.use('/front-camera-photo', serveStatic(FRONT_CAMERA_DIR, { index: false }))
|
||||
app.use('/operator-data', serveStatic(OPERATOR_DATA_DIR, { index: false }))
|
||||
|
||||
// Everything not on graphql or api/register is redirected to the front-end
|
||||
app.get('*', (req, res) => res.sendFile(path.resolve(__dirname, '..', '..', 'public', 'index.html')))
|
||||
|
||||
const certOptions = {
|
||||
key: fs.readFileSync(options.keyPath),
|
||||
cert: fs.readFileSync(options.certPath)
|
||||
key: fs.readFileSync(KEY_PATH),
|
||||
cert: fs.readFileSync(CERT_PATH)
|
||||
}
|
||||
|
||||
function run () {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
const express = require('express')
|
||||
const path = require('path')
|
||||
const { ApolloServer } = require('apollo-server-express')
|
||||
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../../.env') })
|
||||
|
||||
const { typeDefs, resolvers } = require('./graphql/schema')
|
||||
const logger = require('../logger')
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,9 @@ const router = express.Router()
|
|||
const session = require('express-session')
|
||||
const PgSession = require('connect-pg-simple')(session)
|
||||
const db = require('../../db')
|
||||
const options = require('../../options')
|
||||
const { USER_SESSIONS_TABLE_NAME } = require('../../constants')
|
||||
const { getOperatorId } = require('../../operator')
|
||||
|
||||
const hostname = options.hostname
|
||||
|
||||
router.use('*', async (req, res, next) => getOperatorId('authentication').then(({ operatorId }) => session({
|
||||
store: new PgSession({
|
||||
pgPromise: db,
|
||||
|
|
|
|||
|
|
@ -5,24 +5,25 @@ const crypto = require('crypto')
|
|||
const baseX = require('base-x')
|
||||
const { parse, NIL } = require('uuid')
|
||||
|
||||
const options = require('../../options')
|
||||
const db = require('../../db')
|
||||
const pairing = require('../../pairing')
|
||||
|
||||
const ALPHA_BASE = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'
|
||||
const bsAlpha = baseX(ALPHA_BASE)
|
||||
|
||||
const CA_PATH = process.env.CA_PATH
|
||||
const HOSTNAME = process.env.HOSTNAME
|
||||
|
||||
const unpair = pairing.unpair
|
||||
|
||||
function totem (name) {
|
||||
const caPath = options.caPath
|
||||
return readFile(caPath)
|
||||
return readFile(CA_PATH)
|
||||
.then(data => {
|
||||
const caHash = crypto.createHash('sha256').update(data).digest()
|
||||
const token = crypto.randomBytes(32)
|
||||
const hexToken = token.toString('hex')
|
||||
const caHexToken = crypto.createHash('sha256').update(hexToken).digest('hex')
|
||||
const buf = Buffer.concat([caHash, token, Buffer.from(options.hostname)])
|
||||
const buf = Buffer.concat([caHash, token, Buffer.from(HOSTNAME)])
|
||||
const sql = 'insert into pairing_tokens (token, name) values ($1, $3), ($2, $3)'
|
||||
|
||||
return db.none(sql, [hexToken, caHexToken, name])
|
||||
|
|
|
|||
|
|
@ -4,23 +4,24 @@ const util = require('util')
|
|||
const loader = require('./loading')
|
||||
const matcher = require('./matching')
|
||||
const nameUtils = require('./name-utils')
|
||||
const options = require('../options')
|
||||
const _ = require('lodash/fp')
|
||||
const logger = require('../logger')
|
||||
|
||||
const debugLog = require('../pp')(__filename) // KOSTIS TODO: remove
|
||||
|
||||
const OFAC_DATA_DIR = process.env.OFAC_DATA_DIR
|
||||
|
||||
let structs = null
|
||||
|
||||
const readdir = util.promisify(fs.readdir)
|
||||
|
||||
function load () {
|
||||
if (!options.ofacDataDir) {
|
||||
const message = 'The ofacDataDir option has not been set in lamassu.json'
|
||||
if (!OFAC_DATA_DIR) {
|
||||
const message = 'The ofacDataDir option has not been set in the environment'
|
||||
return Promise.reject(new Error(message))
|
||||
}
|
||||
|
||||
const ofacSourcesDir = path.join(options.ofacDataDir, 'sources')
|
||||
const ofacSourcesDir = path.join(OFAC_DATA_DIR, 'sources')
|
||||
|
||||
return readdir(ofacSourcesDir)
|
||||
.then(_.flow(
|
||||
|
|
|
|||
|
|
@ -4,12 +4,23 @@ const url = require('url')
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const util = require('util')
|
||||
const options = require('../options')
|
||||
const _ = require('lodash/fp')
|
||||
const logger = require('../logger')
|
||||
|
||||
const DOWNLOAD_DIR = path.resolve('/tmp')
|
||||
|
||||
const OFAC_DATA_DIR = process.env.OFAC_DATA_DIR
|
||||
const OFAC_SOURCES_NAMES = process.env.OFAC_SOURCES_NAMES.split(',')
|
||||
const OFAC_SOURCES_URLS = process.env.OFAC_SOURCES_URLS.split(',')
|
||||
|
||||
const ofacSources = _.map(
|
||||
it => ({
|
||||
name: it[0],
|
||||
url: it[1]
|
||||
}),
|
||||
_.zip(OFAC_SOURCES_NAMES, OFAC_SOURCES_URLS)
|
||||
)
|
||||
|
||||
function mkdir (path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.mkdir(path, err => {
|
||||
|
|
@ -97,14 +108,12 @@ const moveToSourcesDir = (srcFile, ofacSourcesDir) => {
|
|||
}
|
||||
|
||||
function update () {
|
||||
const OFAC_DATA_DIR = options.ofacDataDir
|
||||
|
||||
if (!OFAC_DATA_DIR) {
|
||||
throw new Error('ofacDataDir must be defined in lamassu.json')
|
||||
throw new Error('ofacDataDir must be defined in the environment')
|
||||
}
|
||||
|
||||
if (!options.ofacSources) {
|
||||
logger.error('ofacSources must be defined in lamassu.json')
|
||||
if (!ofacSources) {
|
||||
logger.error('ofacSources must be defined in the environment')
|
||||
}
|
||||
|
||||
const OFAC_SOURCES_DIR = path.join(OFAC_DATA_DIR, 'sources')
|
||||
|
|
@ -125,7 +134,7 @@ function update () {
|
|||
return {}
|
||||
})
|
||||
|
||||
const promiseNewEtags = Promise.resolve(options.ofacSources || [])
|
||||
const promiseNewEtags = Promise.resolve(ofacSources || [])
|
||||
.then(sources => Promise.all(_.map(promiseGetEtag, sources))
|
||||
.then(etags => _.map(
|
||||
([source, etag]) => ({...source, etag}),
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ const os = require('os')
|
|||
const argv = require('minimist')(process.argv.slice(2))
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
require('dotenv').config()
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
|
||||
const DATABASE = process.env.LAMASSU_DB ?? 'PROD'
|
||||
const dbMapping = psqlConf => ({
|
||||
STRESS_TEST: _.replace('lamassu', 'lamassu_stress', psqlConf),
|
||||
PAZUZ: _.replace('lamassu', 'lamassu_pazuz', psqlConf),
|
||||
RELEASE: _.replace('lamassu', 'lamassu_release', psqlConf),
|
||||
DEV: _.replace('lamassu', 'lamassu', psqlConf),
|
||||
PROD: _.replace('lamassu', 'lamassu', psqlConf)
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ const fs = require('fs')
|
|||
const pify = require('pify')
|
||||
const readFile = pify(fs.readFile)
|
||||
const db = require('./db')
|
||||
const options = require('./options')
|
||||
const logger = require('./logger')
|
||||
const uuid = require('uuid')
|
||||
|
||||
const CA_PATH = process.env.CA_PATH
|
||||
|
||||
// A machine on an older version (no multicassette code) could be paired with a server with multicassette code.
|
||||
// This makes sure that the server stores a default value
|
||||
const DEFAULT_NUMBER_OF_CASSETTES = 2
|
||||
|
|
@ -58,8 +59,7 @@ function authorizeCaDownload (caToken) {
|
|||
.then(r => {
|
||||
if (r.expired) throw new Error('Expired')
|
||||
|
||||
const caPath = options.caPath
|
||||
return readFile(caPath, {encoding: 'utf8'})
|
||||
return readFile(CA_PATH, {encoding: 'utf8'})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ const _ = require('lodash/fp')
|
|||
const request = require('request-promise')
|
||||
const { utils: coinUtils } = require('@lamassu/coins')
|
||||
|
||||
const options = require('../../options')
|
||||
|
||||
const blockchainDir = options.blockchainDir
|
||||
const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR
|
||||
|
||||
module.exports = {
|
||||
fetch, fetchDigest, parseConf, rpcConfig
|
||||
|
|
@ -108,7 +106,7 @@ function parseConf (confPath) {
|
|||
|
||||
function rpcConfig (cryptoRec) {
|
||||
try {
|
||||
const configPath = coinUtils.configPath(cryptoRec, blockchainDir)
|
||||
const configPath = coinUtils.configPath(cryptoRec, BLOCKCHAIN_DIR)
|
||||
const config = parseConf(configPath)
|
||||
return {
|
||||
username: config.rpcuser,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const axios = require('axios')
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
const options = require('../../../options')
|
||||
const STRIKE_BASE_URL = process.env.STRIKE_BASE_URL
|
||||
|
||||
module.exports = {
|
||||
newAddress,
|
||||
|
|
@ -9,7 +9,7 @@ module.exports = {
|
|||
cryptoNetwork
|
||||
}
|
||||
|
||||
axios.defaults.baseURL = _.get('strike.baseUrl', options)
|
||||
axios.defaults.baseURL = STRIKE_BASE_URL
|
||||
if (_.isEmpty(axios.defaults.baseURL)) {
|
||||
throw new Error('Missing Strike baseUrl!')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@ const lnd = require('lnd-async')
|
|||
const BN = require('../../../bn')
|
||||
const E = require('../../../error')
|
||||
const { utils: coinUtils } = require('@lamassu/coins')
|
||||
const options = require('../../../options')
|
||||
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
const cryptoRec = coinUtils.getCryptoCurrency('BTC')
|
||||
const unitScale = cryptoRec.unitScale
|
||||
|
||||
const LND = process.env.LIGHTNING_NETWORK_DAEMON
|
||||
|
||||
module.exports = {
|
||||
balance,
|
||||
sendCoins,
|
||||
|
|
@ -20,7 +21,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
function connect () {
|
||||
return lnd.connect(options.lnd || {})
|
||||
return lnd.connect(LND || {})
|
||||
}
|
||||
|
||||
function cryptoNetwork (account, cryptoCode, settings, operatorId) {
|
||||
|
|
|
|||
|
|
@ -7,14 +7,13 @@ const { default: PQueue } = require('p-queue')
|
|||
const BN = require('../../../bn')
|
||||
const E = require('../../../error')
|
||||
const { logger } = require('../../../blockchain/common')
|
||||
const options = require('../../../options')
|
||||
const jsonRpc = require('../../common/json-rpc')
|
||||
|
||||
const blockchainDir = options.blockchainDir
|
||||
const BLOCKCHAIN_DIR = process.env.BLOCKCHAIN_DIR
|
||||
|
||||
const cryptoRec = utils.getCryptoCurrency(COINS.XMR)
|
||||
const configPath = utils.configPath(cryptoRec, blockchainDir)
|
||||
const walletDir = path.resolve(utils.cryptoDir(cryptoRec, blockchainDir), 'wallets')
|
||||
const configPath = utils.configPath(cryptoRec, BLOCKCHAIN_DIR)
|
||||
const walletDir = path.resolve(utils.cryptoDir(cryptoRec, BLOCKCHAIN_DIR), 'wallets')
|
||||
|
||||
const DIGEST_QUEUE = new PQueue({
|
||||
concurrency: 1,
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ const E = require('../../../error')
|
|||
const _ = require('lodash/fp')
|
||||
|
||||
const ENV = process.env.NODE_ENV === undefined || process.env.NODE_ENV === 'development' ? 'development' : 'production'
|
||||
const SUPPORTED_COINS = ['BTC', 'ZEC', 'LTC', 'BCH', 'DASH', 'ETH']
|
||||
const SUPPORTED_COINS = ['BTC']
|
||||
|
||||
const axios = require('axios').create({
|
||||
// TODO: get rejectUnauthorized true to work
|
||||
baseURL: ENV === 'development' ? 'https://localhost:5555/api/' : process.env.PAZUZ_API_WALLET_URL,
|
||||
baseURL: `${process.env.WALLET_URL}/api`,
|
||||
httpsAgent: new https.Agent({
|
||||
rejectUnauthorized: false
|
||||
})
|
||||
|
|
@ -22,9 +22,8 @@ function balance (account, cryptoCode, settings, operatorId) {
|
|||
return checkCryptoCode(cryptoCode)
|
||||
.then(() => {
|
||||
return axios.post('/balance', {
|
||||
account,
|
||||
cryptoCode,
|
||||
settings,
|
||||
config: settings.config,
|
||||
operatorId
|
||||
})
|
||||
})
|
||||
|
|
@ -39,9 +38,8 @@ function sendCoins (account, tx, settings, operatorId) {
|
|||
return checkCryptoCode(cryptoCode)
|
||||
.then(() => {
|
||||
return axios.post('/sendCoins', {
|
||||
account,
|
||||
tx,
|
||||
settings,
|
||||
config: settings.config,
|
||||
operatorId
|
||||
})
|
||||
})
|
||||
|
|
@ -57,10 +55,9 @@ function sendCoins (account, tx, settings, operatorId) {
|
|||
function newAddress (account, info, tx, settings, operatorId) {
|
||||
return checkCryptoCode(info.cryptoCode)
|
||||
.then(() => axios.post('/newAddress', {
|
||||
account,
|
||||
info,
|
||||
tx,
|
||||
settings,
|
||||
config: settings.config,
|
||||
operatorId
|
||||
}))
|
||||
.then(({ data }) => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ const morgan = require('morgan')
|
|||
const nocache = require('nocache')
|
||||
|
||||
const logger = require('./logger')
|
||||
const options = require('./options')
|
||||
|
||||
const authorize = require('./middlewares/authorize')
|
||||
const errorHandler = require('./middlewares/errorHandler')
|
||||
|
|
@ -41,7 +40,7 @@ const configRequiredRoutes = [
|
|||
'/tx',
|
||||
'/verify_promo_code'
|
||||
]
|
||||
const devMode = argv.dev || options.http
|
||||
const devMode = argv.dev || process.env.HTTP
|
||||
|
||||
// middleware setup
|
||||
app.use(compression({ threshold: 500 }))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ const pify = require('pify')
|
|||
const fs = pify(require('fs'))
|
||||
|
||||
const mnemonicHelpers = require('./mnemonic-helpers')
|
||||
const options = require('./options')
|
||||
const ph = require('./plugin-helper')
|
||||
const layer2 = require('./layer2')
|
||||
const httpError = require('./route-helpers').httpError
|
||||
|
|
@ -20,6 +19,8 @@ const INSUFFICIENT_FUNDS_CODE = 570
|
|||
const INSUFFICIENT_FUNDS_NAME = 'InsufficientFunds'
|
||||
const ZERO_CONF_EXPIRATION = 60000
|
||||
|
||||
const MNEMONIC_PATH = process.env.MNEMONIC_PATH
|
||||
|
||||
function computeSeed (masterSeed) {
|
||||
return hkdf(masterSeed, 32, { salt: 'lamassu-server-salt', info: 'wallet-seed' })
|
||||
}
|
||||
|
|
@ -29,7 +30,7 @@ function computeOperatorId (masterSeed) {
|
|||
}
|
||||
|
||||
function fetchWallet (settings, cryptoCode) {
|
||||
return fs.readFile(options.mnemonicPath, 'utf8')
|
||||
return fs.readFile(MNEMONIC_PATH, 'utf8')
|
||||
.then(mnemonic => {
|
||||
const masterSeed = mnemonicHelpers.toEntropyBuffer(mnemonic)
|
||||
const plugin = configManager.getWalletSettings(cryptoCode, settings.config).wallet
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ const hkdf = require('futoin-hkdf')
|
|||
|
||||
const state = require('../lib/middlewares/state')
|
||||
const mnemonicHelpers = require('../lib/mnemonic-helpers')
|
||||
const options = require('../lib/options')
|
||||
|
||||
function computeOperatorId (masterSeed) {
|
||||
return hkdf(masterSeed, 16, { salt: 'lamassu-server-salt', info: 'operator-id' }).toString('hex')
|
||||
|
|
@ -13,7 +12,7 @@ function computeOperatorId (masterSeed) {
|
|||
|
||||
function getMnemonic () {
|
||||
if (state.mnemonic) return Promise.resolve(state.mnemonic)
|
||||
return fs.readFile(options.mnemonicPath, 'utf8').then(mnemonic => {
|
||||
return fs.readFile(process.env.MNEMONIC_PATH, 'utf8').then(mnemonic => {
|
||||
state.mnemonic = mnemonic
|
||||
return mnemonic
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@ SKIP_PREFLIGHT_CHECK=true
|
|||
HTTPS=true
|
||||
REACT_APP_TYPE_CHECK_SANCTUARY=false
|
||||
PORT=3001
|
||||
REACT_APP_BUILD_TARGET=LAMASSU
|
||||
REACT_APP_BUILD_TARGET=PAZUZ
|
||||
|
|
@ -170,10 +170,13 @@ const Accounting = () => {
|
|||
]
|
||||
|
||||
return (
|
||||
!loading && (
|
||||
<>
|
||||
<TitleSection title="Accounting" />
|
||||
<Assets
|
||||
balance={operatorData.fiatBalances[operatorData.preferredFiatCurrency]}
|
||||
balance={
|
||||
operatorData.fiatBalances[operatorData.preferredFiatCurrency]
|
||||
}
|
||||
hedgingReserve={operatorData.hedgingReserve ?? 0}
|
||||
currency={operatorData.preferredFiatCurrency}
|
||||
/>
|
||||
|
|
@ -187,6 +190,7 @@ const Accounting = () => {
|
|||
/>
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export default Accounting
|
||||
|
|
|
|||
32
tools/build-dev-env.js
Normal file
32
tools/build-dev-env.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
const fs = require('fs')
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
|
||||
const setEnvVariable = require('./set-env-var')
|
||||
|
||||
fs.copyFileSync(path.resolve(__dirname, '../.sample.env'), path.resolve(__dirname, '../.env'))
|
||||
|
||||
setEnvVariable('LAMASSU_DB', 'DEV')
|
||||
setEnvVariable('POSTGRES_USER', 'postgres')
|
||||
setEnvVariable('POSTGRES_PASSWORD', 'postgres123')
|
||||
setEnvVariable('POSTGRES_HOST', 'localhost')
|
||||
setEnvVariable('POSTGRES_PORT', '5432')
|
||||
setEnvVariable('POSTGRES_DB', 'lamassu')
|
||||
|
||||
setEnvVariable('CA_PATH', `${process.env.PWD}/certs/Lamassu_OP_Root_CA.pem`)
|
||||
setEnvVariable('CERT_PATH', `${process.env.PWD}/certs/Lamassu_OP.pem`)
|
||||
setEnvVariable('KEY_PATH', `${process.env.PWD}/certs/Lamassu_OP.key`)
|
||||
|
||||
setEnvVariable('MNEMONIC_PATH', `${process.env.HOME}/.lamassu/mnemonics/mnemonic.txt`)
|
||||
setEnvVariable('MIGRATE_STATE_PATH', `${process.env.HOME}/.lamassu/.migrate`)
|
||||
|
||||
setEnvVariable('OFAC_DATA_DIR', `${process.env.HOME}/.lamassu/ofac`)
|
||||
setEnvVariable('ID_PHOTO_CARD_DIR', `${process.env.HOME}/.lamassu/idphotocard`)
|
||||
setEnvVariable('FRONT_CAMERA_DIR', `${process.env.HOME}/.lamassu/frontcamera`)
|
||||
setEnvVariable('OPERATOR_DATA_DIR', `${process.env.HOME}/.lamassu/operatordata`)
|
||||
|
||||
setEnvVariable('OFAC_SOURCES_NAMES', 'sdn_advanced,cons_advanced')
|
||||
setEnvVariable('OFAC_SOURCES_URLS', 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml,https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml')
|
||||
|
||||
setEnvVariable('HOSTNAME', 'localhost')
|
||||
setEnvVariable('LOG_LEVEL', 'debug')
|
||||
45
tools/build-prod-env.js
Normal file
45
tools/build-prod-env.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
const fs = require('fs')
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
const argv = require('minimist')(process.argv.slice(2))
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
const setEnvVariable = require('./set-env-var')
|
||||
|
||||
const requiredParams = ['db-password', 'hostname']
|
||||
|
||||
if (!_.isEqual(_.intersection(_.keys(argv), requiredParams), requiredParams)) {
|
||||
console.error('Usage: node tools/build-prod-env.js --db-password <DB_PASSWORD> --hostname <IP>')
|
||||
process.exit(2)
|
||||
}
|
||||
|
||||
fs.copyFileSync(path.resolve(__dirname, '../.sample.env'), path.resolve(__dirname, '../.env'))
|
||||
|
||||
setEnvVariable('POSTGRES_USER', 'lamassu_pg')
|
||||
setEnvVariable('POSTGRES_PASSWORD', `${argv['db-password']}`)
|
||||
setEnvVariable('POSTGRES_HOST', 'localhost')
|
||||
setEnvVariable('POSTGRES_PORT', '5432')
|
||||
setEnvVariable('POSTGRES_DB', 'lamassu')
|
||||
|
||||
setEnvVariable('LAMASSU_CA_PATH', `/etc/ssl/certs/Lamassu_CA.pem`)
|
||||
setEnvVariable('CA_PATH', `/etc/ssl/certs/Lamassu_OP_Root_CA.pem`)
|
||||
setEnvVariable('CERT_PATH', `/etc/ssl/certs/Lamassu_OP.pem`)
|
||||
setEnvVariable('KEY_PATH', `/etc/ssl/certs/Lamassu_OP.key`)
|
||||
|
||||
setEnvVariable('MNEMONIC_PATH', `/etc/lamassu/mnemonics/mnemonic.txt`)
|
||||
setEnvVariable('MIGRATE_STATE_PATH', `/etc/lamassu/.migrate`)
|
||||
|
||||
setEnvVariable('BLOCKCHAIN_DIR', `/mnt/blockchains`)
|
||||
setEnvVariable('OFAC_DATA_DIR', `/var/lamassu/ofac`)
|
||||
setEnvVariable('ID_PHOTO_CARD_DIR', `/opt/lamassu-server/idphotocard`)
|
||||
setEnvVariable('FRONT_CAMERA_DIR', `/opt/lamassu-server/frontcamera`)
|
||||
setEnvVariable('OPERATOR_DATA_DIR', `/opt/lamassu-server/operatordata`)
|
||||
|
||||
setEnvVariable('STRIKE_BASE_URL', `https://api.strike.acinq.co/api/`)
|
||||
setEnvVariable('COIN_ATM_RADAR_URL', `https://coinatmradar.info/api/lamassu/`)
|
||||
|
||||
setEnvVariable('OFAC_SOURCES_NAMES', 'sdn_advanced,cons_advanced')
|
||||
setEnvVariable('OFAC_SOURCES_URLS', 'https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml,https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml')
|
||||
|
||||
setEnvVariable('HOSTNAME', `${argv.hostname}`)
|
||||
setEnvVariable('LOG_LEVEL', 'info')
|
||||
|
|
@ -91,32 +91,6 @@ rm /tmp/Lamassu_OP.csr.pem
|
|||
mkdir -p $OFAC_DATA_DIR/sources
|
||||
touch $OFAC_DATA_DIR/etags.json
|
||||
|
||||
cat <<EOF > $CONFIG_DIR/lamassu.json
|
||||
{
|
||||
"postgresql": "psql://postgres:$POSTGRES_PASS@localhost/lamassu",
|
||||
"mnemonicPath": "$MNEMONIC_FILE",
|
||||
"caPath": "$CA_PATH",
|
||||
"certPath": "$SERVER_CERT_PATH",
|
||||
"keyPath": "$SERVER_KEY_PATH",
|
||||
"hostname": "$DOMAIN",
|
||||
"logLevel": "debug",
|
||||
"lamassuCaPath": "$LAMASSU_CA_PATH",
|
||||
"migrateStatePath": "$MIGRATE_STATE_PATH",
|
||||
"ofacDataDir": "$OFAC_DATA_DIR",
|
||||
"ofacSources": [
|
||||
{
|
||||
"name": "sdn_advanced",
|
||||
"url": "https://www.treasury.gov/ofac/downloads/sanctions/1.0/sdn_advanced.xml"
|
||||
},
|
||||
{
|
||||
"name": "cons_advanced",
|
||||
"url": "https://www.treasury.gov/ofac/downloads/sanctions/1.0/cons_advanced.xml"
|
||||
}
|
||||
],
|
||||
"idPhotoCardDir": "$IDPHOTOCARD_DIR",
|
||||
"frontCameraDir": "$FRONTCAMERA_DIR",
|
||||
"operatorDataDir": "$OPERATOR_DIR"
|
||||
}
|
||||
EOF
|
||||
node tools/build-dev-env.js
|
||||
|
||||
echo "Done."
|
||||
|
|
|
|||
24
tools/set-env-var.js
Normal file
24
tools/set-env-var.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
const fs = require('fs')
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
|
||||
const setEnvVariable = (key, value) => {
|
||||
const ENV_VARIABLES = fs.readFileSync(path.resolve(__dirname, '../.env'), 'utf-8').split(os.EOL)
|
||||
const target = ENV_VARIABLES.indexOf(ENV_VARIABLES.find(line => line.match(new RegExp(`^${key}=`))))
|
||||
|
||||
if (target < 0) {
|
||||
// The variable doesn't exist, add it
|
||||
ENV_VARIABLES.push(`${key}=${value}`)
|
||||
} else {
|
||||
// .env already has that variable set, or at least has the definition of its key
|
||||
//
|
||||
// This is currently circumventing a possible bug on dotenv
|
||||
// where the variables on this script were showing up as undefined on the first run despite the key existing,
|
||||
// while on a second run they'd appear as empty string, as intended
|
||||
ENV_VARIABLES.splice(target, 1, `${key}=${value}`)
|
||||
}
|
||||
|
||||
fs.writeFileSync(path.resolve(__dirname, '../.env'), ENV_VARIABLES.join(os.EOL))
|
||||
}
|
||||
|
||||
module.exports = setEnvVariable
|
||||
Loading…
Add table
Add a link
Reference in a new issue