Skip to content

Instantly share code, notes, and snippets.

@rossigee
Created June 22, 2025 02:44
Show Gist options
  • Save rossigee/7390b12269a21dc5afd4b1ae56607c85 to your computer and use it in GitHub Desktop.
Save rossigee/7390b12269a21dc5afd4b1ae56607c85 to your computer and use it in GitHub Desktop.
LND wallet unlocker triggered from AMQP message
// package.json:
// {
// "dependencies": {
// "@grpc/grpc-js": "^1.12.6",
// "@grpc/proto-loader": "^0.7.13",
// "amqplib": "^0.10.5"
// }
//}
const fs = require('fs');
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const amqp = require('amqplib');
// Configuration
const LND_HOST = 'lnd.your.lan:10009';
const TLS_CERT_PATH = '/etc/ssl/certs/ca-certificates.crt';
const AMQP_HOST = process.env.AMQP_HOST;
const AMQP_PASSWORD = process.env.AMQP_PASSWORD;
const QUEUE_NAME = process.env.QUEUE_NAME;
// Load the proto file
const loaderOptions = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
};
const packageDefinition = protoLoader.loadSync('/usr/local/src/lnd/lnrpc/walletunlocker.proto', loaderOptions);
const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
// Set up SSL credentials
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA'; // Required for LND's ECDSA cert
const lndCert = fs.readFileSync(TLS_CERT_PATH);
const sslCreds = grpc.credentials.createSsl(lndCert);
// Create the gRPC client
const walletUnlocker = new lnrpc.WalletUnlocker(LND_HOST, sslCreds);
// Unlock wallet function
function unlockWallet(password) {
return new Promise((resolve, reject) => {
const request = {
wallet_password: Buffer.from(process.env.WALLET_PASSWORD, 'utf-8'), // Password must be a Buffer
};
walletUnlocker.unlockWallet(request, (err, response) => {
if (err) {
reject(err);
return;
}
resolve(response);
});
});
}
// Function to consume messages from the AMQP queue
async function consumeMessages() {
try {
const url = `amqp://unlocker:${AMQP_PASSWORD}@${AMQP_HOST}/unlockers`;
console.log(`Connecting to message queue...`);
const connection = await amqp.connect(url);
const channel = await connection.createChannel();
await channel.assertQueue(QUEUE_NAME, { durable: true });
console.log('Waiting for messages in %s. To exit press CTRL+C', QUEUE_NAME);
channel.consume(QUEUE_NAME, async (msg) => {
if (msg !== null) {
const messageContent = msg.content.toString();
console.log('Received message:', messageContent);
try {
const jsonMessage = JSON.parse(messageContent);
console.log(jsonMessage);
const response = await unlockWallet(jsonMessage.password);
console.log('Wallet unlocked successfully:', response);
} catch (error) {
console.error('Error processing message:', error);
}
channel.ack(msg);
}
});
} catch (error) {
console.error('Error connecting to RabbitMQ:', error);
}
}
async function main() {
consumeMessages();
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment