Browse Source
Convert the walletUnlocker object to a class with an interface that is consistent with the Lightning class.renovate/lint-staged-8.x
Tom Kirkpatrick
6 years ago
8 changed files with 139 additions and 56 deletions
@ -1,36 +1,117 @@ |
|||
import fs from 'fs' |
|||
// @flow
|
|||
|
|||
import grpc from 'grpc' |
|||
import { loadSync } from '@grpc/proto-loader' |
|||
import walletUnlockerMethods from './walletUnlockerMethods' |
|||
import StateMachine from 'javascript-state-machine' |
|||
import LndConfig from './config' |
|||
import { getDeadline, validateHost, createSslCreds, createMacaroonCreds } from './util' |
|||
import methods from './walletUnlockerMethods' |
|||
import { mainLog } from '../utils/log' |
|||
|
|||
export const initWalletUnlocker = lndConfig => { |
|||
const walletUnlockerObj = walletUnlocker(lndConfig) |
|||
const walletUnlockerMethodsCallback = (event, msg, data) => |
|||
walletUnlockerMethods(lndConfig, walletUnlockerObj, mainLog, event, msg, data) |
|||
/** |
|||
* Creates an LND grpc client lightning service. |
|||
* @returns {WalletUnlocker} |
|||
*/ |
|||
class WalletUnlocker { |
|||
service: any |
|||
lndConfig: LndConfig |
|||
_fsm: StateMachine |
|||
|
|||
return walletUnlockerMethodsCallback |
|||
} |
|||
// Transitions provided by the state machine.
|
|||
connect: any |
|||
disconnect: any |
|||
terminate: any |
|||
is: any |
|||
can: any |
|||
state: string |
|||
|
|||
constructor(lndConfig: LndConfig) { |
|||
this.service = null |
|||
this.lndConfig = lndConfig |
|||
|
|||
// Initialize the state machine.
|
|||
this._fsm() |
|||
} |
|||
|
|||
// ------------------------------------
|
|||
// FSM Callbacks
|
|||
// ------------------------------------
|
|||
|
|||
/** |
|||
* Connect to the gRPC interface and verify it is functional. |
|||
* @return {Promise<rpc.lnrpc.WalletUnlocker>} |
|||
*/ |
|||
async onBeforeConnect() { |
|||
mainLog.info('Connecting to WalletUnlocker gRPC service') |
|||
const { rpcProtoPath, host, cert, macaroon } = this.lndConfig |
|||
|
|||
// Verify that the host is valid before creating a gRPC client that is connected to it.
|
|||
return await validateHost(host).then(async () => { |
|||
// Load the gRPC proto file.
|
|||
// The following options object closely approximates the existing behavior of grpc.load.
|
|||
// See https://github.com/grpc/grpc-node/blob/master/packages/grpc-protobufjs/README.md
|
|||
const options = { |
|||
keepCase: true, |
|||
longs: Number, |
|||
enums: String, |
|||
defaults: true, |
|||
oneofs: true |
|||
} |
|||
const packageDefinition = loadSync(rpcProtoPath, options) |
|||
|
|||
export const walletUnlocker = lndConfig => { |
|||
const lndCert = fs.readFileSync(lndConfig.cert) |
|||
const credentials = grpc.credentials.createSsl(lndCert) |
|||
|
|||
// Load the gRPC proto file.
|
|||
// The following options object closely approximates the existing behavior of grpc.load
|
|||
// See https://github.com/grpc/grpc-node/blob/master/packages/grpc-protobufjs/README.md
|
|||
const options = { |
|||
keepCase: true, |
|||
longs: Number, |
|||
enums: String, |
|||
defaults: true, |
|||
oneofs: true |
|||
// Load gRPC package definition as a gRPC object hierarchy.
|
|||
const rpc = grpc.loadPackageDefinition(packageDefinition) |
|||
|
|||
// Create ssl and macaroon credentials to use with the gRPC client.
|
|||
const [sslCreds, macaroonCreds] = await Promise.all([ |
|||
createSslCreds(cert), |
|||
createMacaroonCreds(macaroon) |
|||
]) |
|||
const credentials = grpc.credentials.combineChannelCredentials(sslCreds, macaroonCreds) |
|||
|
|||
// Create a new gRPC client instance.
|
|||
this.service = new rpc.lnrpc.WalletUnlocker(host, credentials) |
|||
|
|||
// Wait for the gRPC connection to be established.
|
|||
return new Promise((resolve, reject) => { |
|||
grpc.waitForClientReady(this.service, getDeadline(2), err => { |
|||
if (err) { |
|||
return reject(err) |
|||
} |
|||
return resolve() |
|||
}) |
|||
}) |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* Discomnnect the gRPC service. |
|||
*/ |
|||
onBeforeDisconnect() { |
|||
mainLog.info('Disconnecting from WalletUnlocker gRPC service') |
|||
if (this.service) { |
|||
this.service.close() |
|||
} |
|||
} |
|||
const packageDefinition = loadSync(lndConfig.rpcProtoPath, options) |
|||
|
|||
// Load gRPC package definition as a gRPC object hierarchy.
|
|||
const rpc = grpc.loadPackageDefinition(packageDefinition) |
|||
// ------------------------------------
|
|||
// Helpers
|
|||
// ------------------------------------
|
|||
|
|||
// Instantiate a new connection to the WalletUnlocker interface.
|
|||
return new rpc.lnrpc.WalletUnlocker(lndConfig.host, credentials) |
|||
/** |
|||
* Hook up lnd restful methods. |
|||
*/ |
|||
registerMethods(event: Event, msg: string, data: any) { |
|||
return methods(this.service, mainLog, event, msg, data, this.lndConfig) |
|||
} |
|||
} |
|||
|
|||
StateMachine.factory(WalletUnlocker, { |
|||
init: 'ready', |
|||
transitions: [ |
|||
{ name: 'connect', from: 'ready', to: 'connected' }, |
|||
{ name: 'disconnect', from: 'connected', to: 'ready' } |
|||
] |
|||
}) |
|||
|
|||
export default WalletUnlocker |
|||
|
Loading…
Reference in new issue