Інтеграція з Eclair (Lightning)
Eclair — реалізація Lightning Network на Scala від ACINQ. На відміну від LND з його монолітною архітектурою, Eclair строго слідує BOLT специфікаціям й відомий production надійністю: на ньому працює Phoenix wallet (мобільний Lightning гаманець ACINQ) й кілька великих сервісів. Якщо ваш стек JVM-based або ви вже працюєте з ACINQ екосистемою — це природний вибір.
Запуск та конфігурація
Вимоги
Eclair потребує Bitcoin Core ноди для доступу до blockchain даних. Нейтрино (спрощений режим) Eclair не підтримує — потрібна повна нода.
eclair.conf (Typesafe Config формат):
eclair {
chain = "mainnet"
server.port = 9735
api.enabled = true
api.port = 8080
api.password = "your-api-password"
bitcoind {
host = "localhost"
rpcport = 8332
rpcuser = "bitcoinrpc"
rpcpassword = "rpcpassword"
zmqblock = "tcp://127.0.0.1:28334"
zmqtx = "tcp://127.0.0.1:28335"
}
# Політика комісій для routing
router.path-finding.default.max-fee-flat-sat = 21
router.path-finding.default.max-fee-proportional = 0.01 // 1%
# Лімити каналів
max-htlc-value-in-flight-msat = 100000000000 // 1 BTC у msat
}
HTTP API: основні операції
Eclair надає REST API (form-encoded POST запити, не JSON body — це часто викликає плутанину):
# Інформація про ноду
curl -u :your-password http://localhost:8080/getinfo
# Відкрити канал
curl -u :your-password http://localhost:8080/open \
-d nodeId=<peer_pubkey> \
-d fundingSatoshis=1000000 \
-d pushMsat=0
# Створити invoice
curl -u :your-password http://localhost:8080/createinvoice \
-d description="Payment for order 123" \
-d amountMsat=50000000 \
-d expireIn=3600
# Відправити платіж
curl -u :your-password http://localhost:8080/payinvoice \
-d invoice=lnbc500u1p... \
-d blocking=true
TypeScript клієнт
import axios from "axios";
import FormData from "form-data";
class EclairClient {
private readonly http = axios.create({
baseURL: `http://${this.host}:${this.port}`,
auth: { username: "", password: this.password },
});
async createInvoice(params: {
amountMsat: number;
description: string;
expireIn?: number;
}): Promise<{ serialized: string; paymentHash: string }> {
const form = new FormData();
form.append("amountMsat", params.amountMsat.toString());
form.append("description", params.description);
if (params.expireIn) form.append("expireIn", params.expireIn.toString());
const { data } = await this.http.post("/createinvoice", form, {
headers: form.getHeaders(),
});
return data;
}
async payInvoice(invoice: string, maxFeeMsat?: number): Promise<PaymentResult> {
const form = new FormData();
form.append("invoice", invoice);
form.append("blocking", "true"); // чекаємо результату
if (maxFeeMsat) form.append("maxFeeFlatMsat", maxFeeMsat.toString());
const { data } = await this.http.post("/payinvoice", form, {
headers: form.getHeaders(),
});
return data;
}
async getPayment(paymentHash: string): Promise<PaymentStatus> {
const form = new FormData();
form.append("paymentHash", paymentHash);
const { data } = await this.http.post("/getsentinfo", form, {
headers: form.getHeaders(),
});
return data[0];
}
}
WebHooks: real-time события
Eclair підтримує WebHook нотифікації про события — основний спосіб реагувати на вхідні платежі без polling:
// eclair.conf
eclair.api.webhooks = [
{
id = "my-backend"
url = "https://your-backend.com/eclair/webhook"
secret = "webhook-secret-for-hmac"
}
]
Типи подій:
type EclairEvent =
| { type: "payment-received"; paymentHash: string; amount: number; timestamp: number }
| { type: "payment-sent"; paymentHash: string; amount: number; feesPaid: number }
| { type: "payment-failed"; paymentHash: string; failures: string[] }
| { type: "channel-opened"; channelId: string; remotePubkey: string; capacity: number }
| { type: "channel-closed"; channelId: string; reason: string };
Обробник webhook з верифікацією підпису:
app.post("/eclair/webhook", (req, res) => {
const signature = req.headers["x-eclair-hmac"];
const expectedSig = createHmac("sha256", WEBHOOK_SECRET)
.update(JSON.stringify(req.body))
.digest("hex");
if (signature !== expectedSig) {
return res.status(401).send("Invalid signature");
}
const event: EclairEvent = req.body;
if (event.type === "payment-received") {
handleIncomingPayment(event.paymentHash, event.amount);
}
res.sendStatus(200);
});
Особливості Eclair порівняно з LND
BOLT-12 підтримка — Eclair реалізує BOLT-12 Offers раніше й повніше, ніж LND. Якщо вам потрібні reusable payment codes або offline платіжні схеми — Eclair преимущество.
Trampoline routing — механізм делегування pathfinding на проміжну ноду. Критично для мобільних клієнтів (Phoenix використовує це): легкий клієнт не хоче зберігати повний граф мережі. Eclair — одна з небагатьох реалізацій з production підтримкою Trampoline.
# Відправити через trampoline
curl -u :password http://localhost:8080/payinvoice \
-d invoice=lnbc... \
-d trampolineNodeId=<trampoline_pubkey> \
-d blocking=true
API стиль: form-encoded замість JSON. Це не баг, це design decision. Генерувати form data з існуючих JSON структур — одна додаткова строка.
Metrologia: Eclair експортує метрики через вбудований Kamon instrumentation. Prometheus ендпоінт включається конфігурацією:
kamon.prometheus.embedded-server.port = 9095
Типові сценарії інтеграції
Merchant платежі
- Користувач вибирає "оплата Lightning" → POST
/createinvoice→ QR код / BOLT-11 строка - Webhook
payment-received→ оновити статус замовлення в БД - Дублюючий polling через
/getreceivedinfoдля надійності (на випадок пропущеного webhook)
Масові виплати
async function bulkPayout(payments: { invoice: string; maxFeeMsat: number }[]) {
const results = await Promise.allSettled(
payments.map((p) => eclairClient.payInvoice(p.invoice, p.maxFeeMsat))
);
const failed = results
.map((r, i) => ({ result: r, payment: payments[i] }))
.filter((r) => r.result.status === "rejected");
// Логування помилок, retry з exponential backoff
for (const { payment, result } of failed) {
logger.error("Payment failed", { invoice: payment.invoice, reason: result });
}
}
Канальна політика для routing ноди
Eclair дозволяє встановлювати індивідуальні fee політики на канал:
# Оновити політику для конкретного каналу
curl -u :password http://localhost:8080/updaterelayfee \
-d channelId=<channel_id> \
-d feeBaseMsat=1000 \
-d feeProportionalMillionths=100 # 0.01%
Моніторинг production ноди
Ключові метрики для Eclair:
-
channels.countза станом (NORMAL, CLOSING, OFFLINE) -
payment.sent.success_rate— % успішних вихідних платежів -
payment.received.count/amount— вхідний потік -
router.graph.nodesйchannels— розмір мережі видимий ноді
Grafana дашборд з цими метриками — стандартна операційна необхідність для будь-якої Lightning ноди з більш ніж кількома каналами.
Срок інтеграції Eclair у існуючий backend (прийом й відправка платежів, webhook обробка, моніторинг): 3–5 тижнів.







