Интеграция с Eclair (Lightning)
Eclair — реализация Lightning Network на Scala от ACINQ. В отличие от LND с его монолитной архитектурой, Eclair строго следует BOLT спецификациям и известен производственной надёжностью: на нём работает 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 endpoint включается конфигурацией:
kamon.prometheus.embedded-server.port = 9095
Типичные сценарии интеграции
Merchant платежи
- Пользователь выбирает "оплата Lightning" → POST
/createinvoice→ QR код / BOLT-11 строка - Webhook
payment-received→ обновить статус заказа в БД - Дублирующий polling через
/getreceivedinfoдля надёжности (на случай missed 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 недель.







