@ambosstech/lightning-mpp-adapter-lnd 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +298 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +68 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +265 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
- package/proto/lightning.proto +56 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
LndLightningProvider: () => LndLightningProvider,
|
|
34
|
+
createGrpcTransport: () => createGrpcTransport,
|
|
35
|
+
createRestTransport: () => createRestTransport,
|
|
36
|
+
mapLndError: () => mapLndError
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(index_exports);
|
|
39
|
+
|
|
40
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_typescript@5.7.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
|
|
41
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
42
|
+
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
43
|
+
|
|
44
|
+
// src/grpc-client.ts
|
|
45
|
+
var grpc = __toESM(require("@grpc/grpc-js"), 1);
|
|
46
|
+
var protoLoader = __toESM(require("@grpc/proto-loader"), 1);
|
|
47
|
+
var import_node_url = require("url");
|
|
48
|
+
var import_node_path = require("path");
|
|
49
|
+
var __dirname = (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
50
|
+
var PROTO_PATH = (0, import_node_path.join)(__dirname, "..", "proto", "lightning.proto");
|
|
51
|
+
function createGrpcTransport(config) {
|
|
52
|
+
const tlsCert = typeof config.tlsCert === "string" ? Buffer.from(config.tlsCert, "utf-8") : config.tlsCert;
|
|
53
|
+
const macaroonHex = typeof config.macaroon === "string" ? config.macaroon : config.macaroon.toString("hex");
|
|
54
|
+
const sslCreds = grpc.credentials.createSsl(tlsCert);
|
|
55
|
+
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(
|
|
56
|
+
(_params, callback) => {
|
|
57
|
+
const metadata = new grpc.Metadata();
|
|
58
|
+
metadata.add("macaroon", macaroonHex);
|
|
59
|
+
callback(null, metadata);
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
const combinedCreds = grpc.credentials.combineChannelCredentials(
|
|
63
|
+
sslCreds,
|
|
64
|
+
macaroonCreds
|
|
65
|
+
);
|
|
66
|
+
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
|
|
67
|
+
keepCase: true,
|
|
68
|
+
longs: String,
|
|
69
|
+
enums: String,
|
|
70
|
+
defaults: true,
|
|
71
|
+
oneofs: true
|
|
72
|
+
});
|
|
73
|
+
const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
|
|
74
|
+
const client = new lnrpc.Lightning(config.host, combinedCreds);
|
|
75
|
+
function promisify(method) {
|
|
76
|
+
return (req) => new Promise((resolve, reject) => {
|
|
77
|
+
method.call(client, req, (err, res) => {
|
|
78
|
+
if (err) reject(err);
|
|
79
|
+
else resolve(res);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const grpcAddInvoice = promisify(client.addInvoice);
|
|
84
|
+
const grpcSendPaymentSync = promisify(client.sendPaymentSync);
|
|
85
|
+
const grpcLookupInvoice = promisify(client.lookupInvoice);
|
|
86
|
+
return {
|
|
87
|
+
async addInvoice(params) {
|
|
88
|
+
const res = await grpcAddInvoice(params);
|
|
89
|
+
return {
|
|
90
|
+
r_hash: Buffer.from(res.r_hash).toString("hex"),
|
|
91
|
+
payment_request: res.payment_request
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
async sendPaymentSync(params) {
|
|
95
|
+
const res = await grpcSendPaymentSync(params);
|
|
96
|
+
return {
|
|
97
|
+
payment_preimage: Buffer.from(res.payment_preimage).toString("hex"),
|
|
98
|
+
payment_error: res.payment_error,
|
|
99
|
+
payment_hash: Buffer.from(res.payment_hash).toString("hex")
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
async lookupInvoice(params) {
|
|
103
|
+
const res = await grpcLookupInvoice(params);
|
|
104
|
+
return {
|
|
105
|
+
state: res.state,
|
|
106
|
+
r_preimage: Buffer.from(res.r_preimage).toString("hex"),
|
|
107
|
+
value: res.value
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
close() {
|
|
111
|
+
client.close();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/rest-client.ts
|
|
117
|
+
var import_lightning_mpp_sdk = require("@ambosstech/lightning-mpp-sdk");
|
|
118
|
+
function createRestTransport(config) {
|
|
119
|
+
const baseUrl = config.url.replace(/\/$/, "");
|
|
120
|
+
const macaroonHex = typeof config.macaroon === "string" ? config.macaroon : config.macaroon.toString("hex");
|
|
121
|
+
const fetchFn = config.fetch ?? globalThis.fetch;
|
|
122
|
+
async function request(path, options = {}) {
|
|
123
|
+
const url = `${baseUrl}${path}`;
|
|
124
|
+
let response;
|
|
125
|
+
try {
|
|
126
|
+
response = await fetchFn(url, {
|
|
127
|
+
...options,
|
|
128
|
+
headers: {
|
|
129
|
+
"Grpc-Metadata-macaroon": macaroonHex,
|
|
130
|
+
"Content-Type": "application/json",
|
|
131
|
+
...options.headers
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
} catch (error) {
|
|
135
|
+
throw new import_lightning_mpp_sdk.ConnectionError(`LND REST request failed: ${url}`, {
|
|
136
|
+
cause: error
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const body = await response.json();
|
|
140
|
+
if (!response.ok) {
|
|
141
|
+
const err = new Error(
|
|
142
|
+
body.message ?? body.error ?? `HTTP ${response.status}`
|
|
143
|
+
);
|
|
144
|
+
err.code = body.code;
|
|
145
|
+
err.details = body.message ?? body.error;
|
|
146
|
+
throw err;
|
|
147
|
+
}
|
|
148
|
+
return body;
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
async addInvoice(params) {
|
|
152
|
+
const body = { value: String(params.value) };
|
|
153
|
+
if (params.memo) body.memo = params.memo;
|
|
154
|
+
if (params.expiry) body.expiry = String(params.expiry);
|
|
155
|
+
const res = await request(
|
|
156
|
+
"/v1/invoices",
|
|
157
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
158
|
+
);
|
|
159
|
+
return {
|
|
160
|
+
r_hash: (0, import_lightning_mpp_sdk.base64ToHex)(res.r_hash),
|
|
161
|
+
payment_request: res.payment_request
|
|
162
|
+
};
|
|
163
|
+
},
|
|
164
|
+
async sendPaymentSync(params) {
|
|
165
|
+
const body = { payment_request: params.payment_request };
|
|
166
|
+
if (params.amt !== void 0) {
|
|
167
|
+
body.amt = String(params.amt);
|
|
168
|
+
}
|
|
169
|
+
if (params.fee_limit) {
|
|
170
|
+
body.fee_limit = { fixed: String(params.fee_limit.fixed) };
|
|
171
|
+
}
|
|
172
|
+
const res = await request("/v1/channels/transactions", {
|
|
173
|
+
method: "POST",
|
|
174
|
+
body: JSON.stringify(body)
|
|
175
|
+
});
|
|
176
|
+
return {
|
|
177
|
+
payment_preimage: res.payment_preimage ? (0, import_lightning_mpp_sdk.base64ToHex)(res.payment_preimage) : "",
|
|
178
|
+
payment_error: res.payment_error ?? "",
|
|
179
|
+
payment_hash: res.payment_hash ? (0, import_lightning_mpp_sdk.base64ToHex)(res.payment_hash) : ""
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
async lookupInvoice(params) {
|
|
183
|
+
const hashUrl = (0, import_lightning_mpp_sdk.hexToBase64Url)(params.r_hash_str);
|
|
184
|
+
const res = await request(`/v1/invoice/${hashUrl}`);
|
|
185
|
+
return {
|
|
186
|
+
state: res.state,
|
|
187
|
+
r_preimage: res.r_preimage ? (0, import_lightning_mpp_sdk.base64ToHex)(res.r_preimage) : "",
|
|
188
|
+
value: res.value ?? "0"
|
|
189
|
+
};
|
|
190
|
+
},
|
|
191
|
+
close() {
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/error-mapper.ts
|
|
197
|
+
var import_lightning_mpp_sdk2 = require("@ambosstech/lightning-mpp-sdk");
|
|
198
|
+
var UNAVAILABLE = 14;
|
|
199
|
+
var UNAUTHENTICATED = 16;
|
|
200
|
+
var DEADLINE_EXCEEDED = 4;
|
|
201
|
+
function mapLndError(error) {
|
|
202
|
+
const grpcError = error;
|
|
203
|
+
const code = grpcError.code;
|
|
204
|
+
const details = (grpcError.details ?? grpcError.message ?? "").toLowerCase();
|
|
205
|
+
if (code === UNAUTHENTICATED) {
|
|
206
|
+
return new import_lightning_mpp_sdk2.AuthenticationError("LND authentication failed", {
|
|
207
|
+
cause: error
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
if (code === UNAVAILABLE) {
|
|
211
|
+
return new import_lightning_mpp_sdk2.ConnectionError("LND node unavailable", { cause: error });
|
|
212
|
+
}
|
|
213
|
+
if (code === DEADLINE_EXCEEDED) {
|
|
214
|
+
return new import_lightning_mpp_sdk2.PaymentTimeoutError("LND request timed out", { cause: error });
|
|
215
|
+
}
|
|
216
|
+
if (details.includes("invoice expired") || details.includes("invoice is expired")) {
|
|
217
|
+
return new import_lightning_mpp_sdk2.InvoiceExpiredError("Invoice has expired", { cause: error });
|
|
218
|
+
}
|
|
219
|
+
if (details.includes("unable to find a path") || details.includes("no route") || details.includes("insufficient capacity")) {
|
|
220
|
+
return new import_lightning_mpp_sdk2.RouteNotFoundError("No route found", { cause: error });
|
|
221
|
+
}
|
|
222
|
+
if (details.includes("insufficient balance") || details.includes("not enough balance") || details.includes("insufficient funds")) {
|
|
223
|
+
return new import_lightning_mpp_sdk2.InsufficientBalanceError("Insufficient balance", {
|
|
224
|
+
cause: error
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return new import_lightning_mpp_sdk2.ConnectionError(
|
|
228
|
+
`LND error: ${grpcError.details ?? grpcError.message ?? "unknown"}`,
|
|
229
|
+
{ cause: error }
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// src/lnd-provider.ts
|
|
234
|
+
var LndLightningProvider = class {
|
|
235
|
+
transport;
|
|
236
|
+
constructor(config) {
|
|
237
|
+
this.transport = config.transport === "rest" ? createRestTransport(config) : createGrpcTransport(config);
|
|
238
|
+
}
|
|
239
|
+
async createInvoice(params) {
|
|
240
|
+
try {
|
|
241
|
+
const response = await this.transport.addInvoice({
|
|
242
|
+
value: params.amountSats,
|
|
243
|
+
memo: params.memo,
|
|
244
|
+
expiry: params.expirySecs
|
|
245
|
+
});
|
|
246
|
+
return {
|
|
247
|
+
bolt11: response.payment_request,
|
|
248
|
+
paymentHash: response.r_hash
|
|
249
|
+
};
|
|
250
|
+
} catch (error) {
|
|
251
|
+
throw mapLndError(error);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async payInvoice(params) {
|
|
255
|
+
try {
|
|
256
|
+
const request = { payment_request: params.bolt11 };
|
|
257
|
+
if (params.amountSats !== void 0) {
|
|
258
|
+
request.amt = params.amountSats;
|
|
259
|
+
}
|
|
260
|
+
if (params.maxFeeSats !== void 0) {
|
|
261
|
+
request.fee_limit = { fixed: params.maxFeeSats };
|
|
262
|
+
}
|
|
263
|
+
const response = await this.transport.sendPaymentSync(request);
|
|
264
|
+
if (response.payment_error) {
|
|
265
|
+
throw new Error(response.payment_error);
|
|
266
|
+
}
|
|
267
|
+
return { preimage: response.payment_preimage };
|
|
268
|
+
} catch (error) {
|
|
269
|
+
throw mapLndError(error);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async lookupInvoice(params) {
|
|
273
|
+
try {
|
|
274
|
+
const response = await this.transport.lookupInvoice({
|
|
275
|
+
r_hash_str: params.paymentHash
|
|
276
|
+
});
|
|
277
|
+
const settled = response.state === "SETTLED";
|
|
278
|
+
return {
|
|
279
|
+
settled,
|
|
280
|
+
preimage: settled ? response.r_preimage : void 0,
|
|
281
|
+
amountSats: response.value ? Number(response.value) : void 0
|
|
282
|
+
};
|
|
283
|
+
} catch (error) {
|
|
284
|
+
throw mapLndError(error);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
close() {
|
|
288
|
+
this.transport.close();
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
292
|
+
0 && (module.exports = {
|
|
293
|
+
LndLightningProvider,
|
|
294
|
+
createGrpcTransport,
|
|
295
|
+
createRestTransport,
|
|
296
|
+
mapLndError
|
|
297
|
+
});
|
|
298
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_typescript@5.7.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js","../src/grpc-client.ts","../src/rest-client.ts","../src/error-mapper.ts","../src/lnd-provider.ts"],"sourcesContent":["export { LndLightningProvider } from \"./lnd-provider.js\";\nexport { createGrpcTransport } from \"./grpc-client.js\";\nexport { createRestTransport } from \"./rest-client.js\";\nexport { mapLndError } from \"./error-mapper.js\";\nexport type {\n LndConfig,\n LndGrpcConfig,\n LndRestConfig,\n LndTransport,\n} from \"./types.js\";\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import * as grpc from \"@grpc/grpc-js\";\nimport * as protoLoader from \"@grpc/proto-loader\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\nimport type { LndGrpcConfig, LndTransport } from \"./types.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst PROTO_PATH = join(__dirname, \"..\", \"proto\", \"lightning.proto\");\n\nexport function createGrpcTransport(config: LndGrpcConfig): LndTransport {\n const tlsCert =\n typeof config.tlsCert === \"string\"\n ? Buffer.from(config.tlsCert, \"utf-8\")\n : config.tlsCert;\n\n const macaroonHex =\n typeof config.macaroon === \"string\"\n ? config.macaroon\n : config.macaroon.toString(\"hex\");\n\n const sslCreds = grpc.credentials.createSsl(tlsCert);\n\n const macaroonCreds = grpc.credentials.createFromMetadataGenerator(\n (_params, callback) => {\n const metadata = new grpc.Metadata();\n metadata.add(\"macaroon\", macaroonHex);\n callback(null, metadata);\n },\n );\n\n const combinedCreds = grpc.credentials.combineChannelCredentials(\n sslCreds,\n macaroonCreds,\n );\n\n const packageDefinition = protoLoader.loadSync(PROTO_PATH, {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n });\n\n const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc as any;\n const client = new lnrpc.Lightning(config.host, combinedCreds);\n\n function promisify<TReq, TRes>(\n method: (req: TReq, cb: (err: any, res: TRes) => void) => void,\n ): (req: TReq) => Promise<TRes> {\n return (req: TReq) =>\n new Promise((resolve, reject) => {\n method.call(client, req, (err: any, res: TRes) => {\n if (err) reject(err);\n else resolve(res);\n });\n });\n }\n\n const grpcAddInvoice = promisify(client.addInvoice);\n const grpcSendPaymentSync = promisify(client.sendPaymentSync);\n const grpcLookupInvoice = promisify(client.lookupInvoice);\n\n return {\n async addInvoice(params) {\n const res: any = await grpcAddInvoice(params);\n return {\n r_hash: Buffer.from(res.r_hash).toString(\"hex\"),\n payment_request: res.payment_request,\n };\n },\n async sendPaymentSync(params) {\n const res: any = await grpcSendPaymentSync(params);\n return {\n payment_preimage: Buffer.from(res.payment_preimage).toString(\"hex\"),\n payment_error: res.payment_error,\n payment_hash: Buffer.from(res.payment_hash).toString(\"hex\"),\n };\n },\n async lookupInvoice(params) {\n const res: any = await grpcLookupInvoice(params);\n return {\n state: res.state,\n r_preimage: Buffer.from(res.r_preimage).toString(\"hex\"),\n value: res.value,\n };\n },\n close() {\n client.close();\n },\n };\n}\n","import {\n ConnectionError,\n base64ToHex,\n hexToBase64Url,\n} from \"@ambosstech/lightning-mpp-sdk\";\nimport type { LndRestConfig, LndTransport } from \"./types.js\";\n\nexport function createRestTransport(config: LndRestConfig): LndTransport {\n const baseUrl = config.url.replace(/\\/$/, \"\");\n\n const macaroonHex =\n typeof config.macaroon === \"string\"\n ? config.macaroon\n : config.macaroon.toString(\"hex\");\n\n const fetchFn = config.fetch ?? globalThis.fetch;\n\n async function request<T>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${baseUrl}${path}`;\n let response: Response;\n try {\n response = await fetchFn(url, {\n ...options,\n headers: {\n \"Grpc-Metadata-macaroon\": macaroonHex,\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n } catch (error) {\n throw new ConnectionError(`LND REST request failed: ${url}`, {\n cause: error,\n });\n }\n\n const body = (await response.json()) as any;\n if (!response.ok) {\n const err: any = new Error(\n body.message ?? body.error ?? `HTTP ${response.status}`,\n );\n err.code = body.code;\n err.details = body.message ?? body.error;\n throw err;\n }\n return body as T;\n }\n\n return {\n async addInvoice(params) {\n const body: any = { value: String(params.value) };\n if (params.memo) body.memo = params.memo;\n if (params.expiry) body.expiry = String(params.expiry);\n\n const res = await request<{ r_hash: string; payment_request: string }>(\n \"/v1/invoices\",\n { method: \"POST\", body: JSON.stringify(body) },\n );\n\n return {\n r_hash: base64ToHex(res.r_hash),\n payment_request: res.payment_request,\n };\n },\n\n async sendPaymentSync(params) {\n const body: any = { payment_request: params.payment_request };\n if (params.amt !== undefined) {\n body.amt = String(params.amt);\n }\n if (params.fee_limit) {\n body.fee_limit = { fixed: String(params.fee_limit.fixed) };\n }\n\n const res = await request<{\n payment_preimage: string;\n payment_error: string;\n payment_hash: string;\n }>(\"/v1/channels/transactions\", {\n method: \"POST\",\n body: JSON.stringify(body),\n });\n\n return {\n payment_preimage: res.payment_preimage\n ? base64ToHex(res.payment_preimage)\n : \"\",\n payment_error: res.payment_error ?? \"\",\n payment_hash: res.payment_hash ? base64ToHex(res.payment_hash) : \"\",\n };\n },\n\n async lookupInvoice(params) {\n const hashUrl = hexToBase64Url(params.r_hash_str);\n const res = await request<{\n state: string;\n r_preimage: string;\n value: string;\n }>(`/v1/invoice/${hashUrl}`);\n\n return {\n state: res.state,\n r_preimage: res.r_preimage ? base64ToHex(res.r_preimage) : \"\",\n value: res.value ?? \"0\",\n };\n },\n\n close() {\n // no-op for REST\n },\n };\n}\n","import {\n AuthenticationError,\n ConnectionError,\n InsufficientBalanceError,\n InvoiceExpiredError,\n type LightningError,\n PaymentTimeoutError,\n RouteNotFoundError,\n} from \"@ambosstech/lightning-mpp-sdk\";\n\ninterface GrpcError {\n code?: number;\n details?: string;\n message?: string;\n}\n\n// gRPC status codes\nconst UNAVAILABLE = 14;\nconst UNAUTHENTICATED = 16;\nconst DEADLINE_EXCEEDED = 4;\n\nexport function mapLndError(error: unknown): LightningError {\n const grpcError = error as GrpcError;\n const code = grpcError.code;\n const details = (grpcError.details ?? grpcError.message ?? \"\").toLowerCase();\n\n if (code === UNAUTHENTICATED) {\n return new AuthenticationError(\"LND authentication failed\", {\n cause: error,\n });\n }\n\n if (code === UNAVAILABLE) {\n return new ConnectionError(\"LND node unavailable\", { cause: error });\n }\n\n if (code === DEADLINE_EXCEEDED) {\n return new PaymentTimeoutError(\"LND request timed out\", { cause: error });\n }\n\n if (\n details.includes(\"invoice expired\") ||\n details.includes(\"invoice is expired\")\n ) {\n return new InvoiceExpiredError(\"Invoice has expired\", { cause: error });\n }\n\n if (\n details.includes(\"unable to find a path\") ||\n details.includes(\"no route\") ||\n details.includes(\"insufficient capacity\")\n ) {\n return new RouteNotFoundError(\"No route found\", { cause: error });\n }\n\n if (\n details.includes(\"insufficient balance\") ||\n details.includes(\"not enough balance\") ||\n details.includes(\"insufficient funds\")\n ) {\n return new InsufficientBalanceError(\"Insufficient balance\", {\n cause: error,\n });\n }\n\n // Fallback\n return new ConnectionError(\n `LND error: ${grpcError.details ?? grpcError.message ?? \"unknown\"}`,\n { cause: error },\n );\n}\n","import type {\n CreateInvoiceParams,\n CreateInvoiceResult,\n LightningProvider,\n LookupInvoiceParams,\n LookupInvoiceResult,\n PayInvoiceParams,\n PayInvoiceResult,\n} from \"@ambosstech/lightning-mpp-sdk\";\nimport { createGrpcTransport } from \"./grpc-client.js\";\nimport { createRestTransport } from \"./rest-client.js\";\nimport { mapLndError } from \"./error-mapper.js\";\nimport type { LndConfig, LndTransport } from \"./types.js\";\n\nexport class LndLightningProvider implements LightningProvider {\n private transport: LndTransport;\n\n constructor(config: LndConfig) {\n this.transport =\n config.transport === \"rest\"\n ? createRestTransport(config)\n : createGrpcTransport(config);\n }\n\n async createInvoice(\n params: CreateInvoiceParams,\n ): Promise<CreateInvoiceResult> {\n try {\n const response = await this.transport.addInvoice({\n value: params.amountSats,\n memo: params.memo,\n expiry: params.expirySecs,\n });\n\n return {\n bolt11: response.payment_request,\n paymentHash: response.r_hash,\n };\n } catch (error) {\n throw mapLndError(error);\n }\n }\n\n async payInvoice(params: PayInvoiceParams): Promise<PayInvoiceResult> {\n try {\n const request: any = { payment_request: params.bolt11 };\n if (params.amountSats !== undefined) {\n request.amt = params.amountSats;\n }\n if (params.maxFeeSats !== undefined) {\n request.fee_limit = { fixed: params.maxFeeSats };\n }\n\n const response = await this.transport.sendPaymentSync(request);\n\n if (response.payment_error) {\n throw new Error(response.payment_error);\n }\n\n return { preimage: response.payment_preimage };\n } catch (error) {\n throw mapLndError(error);\n }\n }\n\n async lookupInvoice(\n params: LookupInvoiceParams,\n ): Promise<LookupInvoiceResult> {\n try {\n const response = await this.transport.lookupInvoice({\n r_hash_str: params.paymentHash,\n });\n\n const settled = response.state === \"SETTLED\";\n return {\n settled,\n preimage: settled ? response.r_preimage : undefined,\n amountSats: response.value ? Number(response.value) : undefined,\n };\n } catch (error) {\n throw mapLndError(error);\n }\n }\n\n close(): void {\n this.transport.close();\n }\n}\n"],"mappings":"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","names":["import_lightning_mpp_sdk"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { LightningProvider, CreateInvoiceParams, CreateInvoiceResult, PayInvoiceParams, PayInvoiceResult, LookupInvoiceParams, LookupInvoiceResult, LightningError } from '@ambosstech/lightning-mpp-sdk';
|
|
2
|
+
|
|
3
|
+
interface LndGrpcConfig {
|
|
4
|
+
transport: "grpc";
|
|
5
|
+
/** LND gRPC host:port, e.g. "127.0.0.1:10009" */
|
|
6
|
+
host: string;
|
|
7
|
+
/** TLS certificate as PEM string or raw bytes */
|
|
8
|
+
tlsCert: string | Buffer;
|
|
9
|
+
/** Admin macaroon as hex string or raw bytes */
|
|
10
|
+
macaroon: string | Buffer;
|
|
11
|
+
}
|
|
12
|
+
interface LndRestConfig {
|
|
13
|
+
transport: "rest";
|
|
14
|
+
/** LND REST URL, e.g. "https://127.0.0.1:8080" */
|
|
15
|
+
url: string;
|
|
16
|
+
/** Admin macaroon as hex string or raw bytes */
|
|
17
|
+
macaroon: string | Buffer;
|
|
18
|
+
/** Optional: custom fetch for environments that need TLS cert handling */
|
|
19
|
+
fetch?: typeof globalThis.fetch;
|
|
20
|
+
}
|
|
21
|
+
type LndConfig = LndGrpcConfig | LndRestConfig;
|
|
22
|
+
/** Internal transport interface shared by gRPC and REST clients */
|
|
23
|
+
interface LndTransport {
|
|
24
|
+
addInvoice(params: {
|
|
25
|
+
value: number;
|
|
26
|
+
memo?: string;
|
|
27
|
+
expiry?: number;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
r_hash: string;
|
|
30
|
+
payment_request: string;
|
|
31
|
+
}>;
|
|
32
|
+
sendPaymentSync(params: {
|
|
33
|
+
payment_request: string;
|
|
34
|
+
amt?: number;
|
|
35
|
+
fee_limit?: {
|
|
36
|
+
fixed: number;
|
|
37
|
+
};
|
|
38
|
+
}): Promise<{
|
|
39
|
+
payment_preimage: string;
|
|
40
|
+
payment_error: string;
|
|
41
|
+
payment_hash: string;
|
|
42
|
+
}>;
|
|
43
|
+
lookupInvoice(params: {
|
|
44
|
+
r_hash_str: string;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
state: string;
|
|
47
|
+
r_preimage: string;
|
|
48
|
+
value: string;
|
|
49
|
+
}>;
|
|
50
|
+
close(): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
declare class LndLightningProvider implements LightningProvider {
|
|
54
|
+
private transport;
|
|
55
|
+
constructor(config: LndConfig);
|
|
56
|
+
createInvoice(params: CreateInvoiceParams): Promise<CreateInvoiceResult>;
|
|
57
|
+
payInvoice(params: PayInvoiceParams): Promise<PayInvoiceResult>;
|
|
58
|
+
lookupInvoice(params: LookupInvoiceParams): Promise<LookupInvoiceResult>;
|
|
59
|
+
close(): void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
declare function createGrpcTransport(config: LndGrpcConfig): LndTransport;
|
|
63
|
+
|
|
64
|
+
declare function createRestTransport(config: LndRestConfig): LndTransport;
|
|
65
|
+
|
|
66
|
+
declare function mapLndError(error: unknown): LightningError;
|
|
67
|
+
|
|
68
|
+
export { type LndConfig, type LndGrpcConfig, LndLightningProvider, type LndRestConfig, type LndTransport, createGrpcTransport, createRestTransport, mapLndError };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { LightningProvider, CreateInvoiceParams, CreateInvoiceResult, PayInvoiceParams, PayInvoiceResult, LookupInvoiceParams, LookupInvoiceResult, LightningError } from '@ambosstech/lightning-mpp-sdk';
|
|
2
|
+
|
|
3
|
+
interface LndGrpcConfig {
|
|
4
|
+
transport: "grpc";
|
|
5
|
+
/** LND gRPC host:port, e.g. "127.0.0.1:10009" */
|
|
6
|
+
host: string;
|
|
7
|
+
/** TLS certificate as PEM string or raw bytes */
|
|
8
|
+
tlsCert: string | Buffer;
|
|
9
|
+
/** Admin macaroon as hex string or raw bytes */
|
|
10
|
+
macaroon: string | Buffer;
|
|
11
|
+
}
|
|
12
|
+
interface LndRestConfig {
|
|
13
|
+
transport: "rest";
|
|
14
|
+
/** LND REST URL, e.g. "https://127.0.0.1:8080" */
|
|
15
|
+
url: string;
|
|
16
|
+
/** Admin macaroon as hex string or raw bytes */
|
|
17
|
+
macaroon: string | Buffer;
|
|
18
|
+
/** Optional: custom fetch for environments that need TLS cert handling */
|
|
19
|
+
fetch?: typeof globalThis.fetch;
|
|
20
|
+
}
|
|
21
|
+
type LndConfig = LndGrpcConfig | LndRestConfig;
|
|
22
|
+
/** Internal transport interface shared by gRPC and REST clients */
|
|
23
|
+
interface LndTransport {
|
|
24
|
+
addInvoice(params: {
|
|
25
|
+
value: number;
|
|
26
|
+
memo?: string;
|
|
27
|
+
expiry?: number;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
r_hash: string;
|
|
30
|
+
payment_request: string;
|
|
31
|
+
}>;
|
|
32
|
+
sendPaymentSync(params: {
|
|
33
|
+
payment_request: string;
|
|
34
|
+
amt?: number;
|
|
35
|
+
fee_limit?: {
|
|
36
|
+
fixed: number;
|
|
37
|
+
};
|
|
38
|
+
}): Promise<{
|
|
39
|
+
payment_preimage: string;
|
|
40
|
+
payment_error: string;
|
|
41
|
+
payment_hash: string;
|
|
42
|
+
}>;
|
|
43
|
+
lookupInvoice(params: {
|
|
44
|
+
r_hash_str: string;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
state: string;
|
|
47
|
+
r_preimage: string;
|
|
48
|
+
value: string;
|
|
49
|
+
}>;
|
|
50
|
+
close(): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
declare class LndLightningProvider implements LightningProvider {
|
|
54
|
+
private transport;
|
|
55
|
+
constructor(config: LndConfig);
|
|
56
|
+
createInvoice(params: CreateInvoiceParams): Promise<CreateInvoiceResult>;
|
|
57
|
+
payInvoice(params: PayInvoiceParams): Promise<PayInvoiceResult>;
|
|
58
|
+
lookupInvoice(params: LookupInvoiceParams): Promise<LookupInvoiceResult>;
|
|
59
|
+
close(): void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
declare function createGrpcTransport(config: LndGrpcConfig): LndTransport;
|
|
63
|
+
|
|
64
|
+
declare function createRestTransport(config: LndRestConfig): LndTransport;
|
|
65
|
+
|
|
66
|
+
declare function mapLndError(error: unknown): LightningError;
|
|
67
|
+
|
|
68
|
+
export { type LndConfig, type LndGrpcConfig, LndLightningProvider, type LndRestConfig, type LndTransport, createGrpcTransport, createRestTransport, mapLndError };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// src/grpc-client.ts
|
|
2
|
+
import * as grpc from "@grpc/grpc-js";
|
|
3
|
+
import * as protoLoader from "@grpc/proto-loader";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { dirname, join } from "path";
|
|
6
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
var PROTO_PATH = join(__dirname, "..", "proto", "lightning.proto");
|
|
8
|
+
function createGrpcTransport(config) {
|
|
9
|
+
const tlsCert = typeof config.tlsCert === "string" ? Buffer.from(config.tlsCert, "utf-8") : config.tlsCert;
|
|
10
|
+
const macaroonHex = typeof config.macaroon === "string" ? config.macaroon : config.macaroon.toString("hex");
|
|
11
|
+
const sslCreds = grpc.credentials.createSsl(tlsCert);
|
|
12
|
+
const macaroonCreds = grpc.credentials.createFromMetadataGenerator(
|
|
13
|
+
(_params, callback) => {
|
|
14
|
+
const metadata = new grpc.Metadata();
|
|
15
|
+
metadata.add("macaroon", macaroonHex);
|
|
16
|
+
callback(null, metadata);
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
const combinedCreds = grpc.credentials.combineChannelCredentials(
|
|
20
|
+
sslCreds,
|
|
21
|
+
macaroonCreds
|
|
22
|
+
);
|
|
23
|
+
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
|
|
24
|
+
keepCase: true,
|
|
25
|
+
longs: String,
|
|
26
|
+
enums: String,
|
|
27
|
+
defaults: true,
|
|
28
|
+
oneofs: true
|
|
29
|
+
});
|
|
30
|
+
const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc;
|
|
31
|
+
const client = new lnrpc.Lightning(config.host, combinedCreds);
|
|
32
|
+
function promisify(method) {
|
|
33
|
+
return (req) => new Promise((resolve, reject) => {
|
|
34
|
+
method.call(client, req, (err, res) => {
|
|
35
|
+
if (err) reject(err);
|
|
36
|
+
else resolve(res);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const grpcAddInvoice = promisify(client.addInvoice);
|
|
41
|
+
const grpcSendPaymentSync = promisify(client.sendPaymentSync);
|
|
42
|
+
const grpcLookupInvoice = promisify(client.lookupInvoice);
|
|
43
|
+
return {
|
|
44
|
+
async addInvoice(params) {
|
|
45
|
+
const res = await grpcAddInvoice(params);
|
|
46
|
+
return {
|
|
47
|
+
r_hash: Buffer.from(res.r_hash).toString("hex"),
|
|
48
|
+
payment_request: res.payment_request
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
async sendPaymentSync(params) {
|
|
52
|
+
const res = await grpcSendPaymentSync(params);
|
|
53
|
+
return {
|
|
54
|
+
payment_preimage: Buffer.from(res.payment_preimage).toString("hex"),
|
|
55
|
+
payment_error: res.payment_error,
|
|
56
|
+
payment_hash: Buffer.from(res.payment_hash).toString("hex")
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
async lookupInvoice(params) {
|
|
60
|
+
const res = await grpcLookupInvoice(params);
|
|
61
|
+
return {
|
|
62
|
+
state: res.state,
|
|
63
|
+
r_preimage: Buffer.from(res.r_preimage).toString("hex"),
|
|
64
|
+
value: res.value
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
close() {
|
|
68
|
+
client.close();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/rest-client.ts
|
|
74
|
+
import {
|
|
75
|
+
ConnectionError,
|
|
76
|
+
base64ToHex,
|
|
77
|
+
hexToBase64Url
|
|
78
|
+
} from "@ambosstech/lightning-mpp-sdk";
|
|
79
|
+
function createRestTransport(config) {
|
|
80
|
+
const baseUrl = config.url.replace(/\/$/, "");
|
|
81
|
+
const macaroonHex = typeof config.macaroon === "string" ? config.macaroon : config.macaroon.toString("hex");
|
|
82
|
+
const fetchFn = config.fetch ?? globalThis.fetch;
|
|
83
|
+
async function request(path, options = {}) {
|
|
84
|
+
const url = `${baseUrl}${path}`;
|
|
85
|
+
let response;
|
|
86
|
+
try {
|
|
87
|
+
response = await fetchFn(url, {
|
|
88
|
+
...options,
|
|
89
|
+
headers: {
|
|
90
|
+
"Grpc-Metadata-macaroon": macaroonHex,
|
|
91
|
+
"Content-Type": "application/json",
|
|
92
|
+
...options.headers
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
} catch (error) {
|
|
96
|
+
throw new ConnectionError(`LND REST request failed: ${url}`, {
|
|
97
|
+
cause: error
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const body = await response.json();
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
const err = new Error(
|
|
103
|
+
body.message ?? body.error ?? `HTTP ${response.status}`
|
|
104
|
+
);
|
|
105
|
+
err.code = body.code;
|
|
106
|
+
err.details = body.message ?? body.error;
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
return body;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
async addInvoice(params) {
|
|
113
|
+
const body = { value: String(params.value) };
|
|
114
|
+
if (params.memo) body.memo = params.memo;
|
|
115
|
+
if (params.expiry) body.expiry = String(params.expiry);
|
|
116
|
+
const res = await request(
|
|
117
|
+
"/v1/invoices",
|
|
118
|
+
{ method: "POST", body: JSON.stringify(body) }
|
|
119
|
+
);
|
|
120
|
+
return {
|
|
121
|
+
r_hash: base64ToHex(res.r_hash),
|
|
122
|
+
payment_request: res.payment_request
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
async sendPaymentSync(params) {
|
|
126
|
+
const body = { payment_request: params.payment_request };
|
|
127
|
+
if (params.amt !== void 0) {
|
|
128
|
+
body.amt = String(params.amt);
|
|
129
|
+
}
|
|
130
|
+
if (params.fee_limit) {
|
|
131
|
+
body.fee_limit = { fixed: String(params.fee_limit.fixed) };
|
|
132
|
+
}
|
|
133
|
+
const res = await request("/v1/channels/transactions", {
|
|
134
|
+
method: "POST",
|
|
135
|
+
body: JSON.stringify(body)
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
payment_preimage: res.payment_preimage ? base64ToHex(res.payment_preimage) : "",
|
|
139
|
+
payment_error: res.payment_error ?? "",
|
|
140
|
+
payment_hash: res.payment_hash ? base64ToHex(res.payment_hash) : ""
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
async lookupInvoice(params) {
|
|
144
|
+
const hashUrl = hexToBase64Url(params.r_hash_str);
|
|
145
|
+
const res = await request(`/v1/invoice/${hashUrl}`);
|
|
146
|
+
return {
|
|
147
|
+
state: res.state,
|
|
148
|
+
r_preimage: res.r_preimage ? base64ToHex(res.r_preimage) : "",
|
|
149
|
+
value: res.value ?? "0"
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
close() {
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/error-mapper.ts
|
|
158
|
+
import {
|
|
159
|
+
AuthenticationError,
|
|
160
|
+
ConnectionError as ConnectionError2,
|
|
161
|
+
InsufficientBalanceError,
|
|
162
|
+
InvoiceExpiredError,
|
|
163
|
+
PaymentTimeoutError,
|
|
164
|
+
RouteNotFoundError
|
|
165
|
+
} from "@ambosstech/lightning-mpp-sdk";
|
|
166
|
+
var UNAVAILABLE = 14;
|
|
167
|
+
var UNAUTHENTICATED = 16;
|
|
168
|
+
var DEADLINE_EXCEEDED = 4;
|
|
169
|
+
function mapLndError(error) {
|
|
170
|
+
const grpcError = error;
|
|
171
|
+
const code = grpcError.code;
|
|
172
|
+
const details = (grpcError.details ?? grpcError.message ?? "").toLowerCase();
|
|
173
|
+
if (code === UNAUTHENTICATED) {
|
|
174
|
+
return new AuthenticationError("LND authentication failed", {
|
|
175
|
+
cause: error
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
if (code === UNAVAILABLE) {
|
|
179
|
+
return new ConnectionError2("LND node unavailable", { cause: error });
|
|
180
|
+
}
|
|
181
|
+
if (code === DEADLINE_EXCEEDED) {
|
|
182
|
+
return new PaymentTimeoutError("LND request timed out", { cause: error });
|
|
183
|
+
}
|
|
184
|
+
if (details.includes("invoice expired") || details.includes("invoice is expired")) {
|
|
185
|
+
return new InvoiceExpiredError("Invoice has expired", { cause: error });
|
|
186
|
+
}
|
|
187
|
+
if (details.includes("unable to find a path") || details.includes("no route") || details.includes("insufficient capacity")) {
|
|
188
|
+
return new RouteNotFoundError("No route found", { cause: error });
|
|
189
|
+
}
|
|
190
|
+
if (details.includes("insufficient balance") || details.includes("not enough balance") || details.includes("insufficient funds")) {
|
|
191
|
+
return new InsufficientBalanceError("Insufficient balance", {
|
|
192
|
+
cause: error
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return new ConnectionError2(
|
|
196
|
+
`LND error: ${grpcError.details ?? grpcError.message ?? "unknown"}`,
|
|
197
|
+
{ cause: error }
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/lnd-provider.ts
|
|
202
|
+
var LndLightningProvider = class {
|
|
203
|
+
transport;
|
|
204
|
+
constructor(config) {
|
|
205
|
+
this.transport = config.transport === "rest" ? createRestTransport(config) : createGrpcTransport(config);
|
|
206
|
+
}
|
|
207
|
+
async createInvoice(params) {
|
|
208
|
+
try {
|
|
209
|
+
const response = await this.transport.addInvoice({
|
|
210
|
+
value: params.amountSats,
|
|
211
|
+
memo: params.memo,
|
|
212
|
+
expiry: params.expirySecs
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
bolt11: response.payment_request,
|
|
216
|
+
paymentHash: response.r_hash
|
|
217
|
+
};
|
|
218
|
+
} catch (error) {
|
|
219
|
+
throw mapLndError(error);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async payInvoice(params) {
|
|
223
|
+
try {
|
|
224
|
+
const request = { payment_request: params.bolt11 };
|
|
225
|
+
if (params.amountSats !== void 0) {
|
|
226
|
+
request.amt = params.amountSats;
|
|
227
|
+
}
|
|
228
|
+
if (params.maxFeeSats !== void 0) {
|
|
229
|
+
request.fee_limit = { fixed: params.maxFeeSats };
|
|
230
|
+
}
|
|
231
|
+
const response = await this.transport.sendPaymentSync(request);
|
|
232
|
+
if (response.payment_error) {
|
|
233
|
+
throw new Error(response.payment_error);
|
|
234
|
+
}
|
|
235
|
+
return { preimage: response.payment_preimage };
|
|
236
|
+
} catch (error) {
|
|
237
|
+
throw mapLndError(error);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async lookupInvoice(params) {
|
|
241
|
+
try {
|
|
242
|
+
const response = await this.transport.lookupInvoice({
|
|
243
|
+
r_hash_str: params.paymentHash
|
|
244
|
+
});
|
|
245
|
+
const settled = response.state === "SETTLED";
|
|
246
|
+
return {
|
|
247
|
+
settled,
|
|
248
|
+
preimage: settled ? response.r_preimage : void 0,
|
|
249
|
+
amountSats: response.value ? Number(response.value) : void 0
|
|
250
|
+
};
|
|
251
|
+
} catch (error) {
|
|
252
|
+
throw mapLndError(error);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
close() {
|
|
256
|
+
this.transport.close();
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
export {
|
|
260
|
+
LndLightningProvider,
|
|
261
|
+
createGrpcTransport,
|
|
262
|
+
createRestTransport,
|
|
263
|
+
mapLndError
|
|
264
|
+
};
|
|
265
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/grpc-client.ts","../src/rest-client.ts","../src/error-mapper.ts","../src/lnd-provider.ts"],"sourcesContent":["import * as grpc from \"@grpc/grpc-js\";\nimport * as protoLoader from \"@grpc/proto-loader\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\nimport type { LndGrpcConfig, LndTransport } from \"./types.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst PROTO_PATH = join(__dirname, \"..\", \"proto\", \"lightning.proto\");\n\nexport function createGrpcTransport(config: LndGrpcConfig): LndTransport {\n const tlsCert =\n typeof config.tlsCert === \"string\"\n ? Buffer.from(config.tlsCert, \"utf-8\")\n : config.tlsCert;\n\n const macaroonHex =\n typeof config.macaroon === \"string\"\n ? config.macaroon\n : config.macaroon.toString(\"hex\");\n\n const sslCreds = grpc.credentials.createSsl(tlsCert);\n\n const macaroonCreds = grpc.credentials.createFromMetadataGenerator(\n (_params, callback) => {\n const metadata = new grpc.Metadata();\n metadata.add(\"macaroon\", macaroonHex);\n callback(null, metadata);\n },\n );\n\n const combinedCreds = grpc.credentials.combineChannelCredentials(\n sslCreds,\n macaroonCreds,\n );\n\n const packageDefinition = protoLoader.loadSync(PROTO_PATH, {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n });\n\n const lnrpc = grpc.loadPackageDefinition(packageDefinition).lnrpc as any;\n const client = new lnrpc.Lightning(config.host, combinedCreds);\n\n function promisify<TReq, TRes>(\n method: (req: TReq, cb: (err: any, res: TRes) => void) => void,\n ): (req: TReq) => Promise<TRes> {\n return (req: TReq) =>\n new Promise((resolve, reject) => {\n method.call(client, req, (err: any, res: TRes) => {\n if (err) reject(err);\n else resolve(res);\n });\n });\n }\n\n const grpcAddInvoice = promisify(client.addInvoice);\n const grpcSendPaymentSync = promisify(client.sendPaymentSync);\n const grpcLookupInvoice = promisify(client.lookupInvoice);\n\n return {\n async addInvoice(params) {\n const res: any = await grpcAddInvoice(params);\n return {\n r_hash: Buffer.from(res.r_hash).toString(\"hex\"),\n payment_request: res.payment_request,\n };\n },\n async sendPaymentSync(params) {\n const res: any = await grpcSendPaymentSync(params);\n return {\n payment_preimage: Buffer.from(res.payment_preimage).toString(\"hex\"),\n payment_error: res.payment_error,\n payment_hash: Buffer.from(res.payment_hash).toString(\"hex\"),\n };\n },\n async lookupInvoice(params) {\n const res: any = await grpcLookupInvoice(params);\n return {\n state: res.state,\n r_preimage: Buffer.from(res.r_preimage).toString(\"hex\"),\n value: res.value,\n };\n },\n close() {\n client.close();\n },\n };\n}\n","import {\n ConnectionError,\n base64ToHex,\n hexToBase64Url,\n} from \"@ambosstech/lightning-mpp-sdk\";\nimport type { LndRestConfig, LndTransport } from \"./types.js\";\n\nexport function createRestTransport(config: LndRestConfig): LndTransport {\n const baseUrl = config.url.replace(/\\/$/, \"\");\n\n const macaroonHex =\n typeof config.macaroon === \"string\"\n ? config.macaroon\n : config.macaroon.toString(\"hex\");\n\n const fetchFn = config.fetch ?? globalThis.fetch;\n\n async function request<T>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${baseUrl}${path}`;\n let response: Response;\n try {\n response = await fetchFn(url, {\n ...options,\n headers: {\n \"Grpc-Metadata-macaroon\": macaroonHex,\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n } catch (error) {\n throw new ConnectionError(`LND REST request failed: ${url}`, {\n cause: error,\n });\n }\n\n const body = (await response.json()) as any;\n if (!response.ok) {\n const err: any = new Error(\n body.message ?? body.error ?? `HTTP ${response.status}`,\n );\n err.code = body.code;\n err.details = body.message ?? body.error;\n throw err;\n }\n return body as T;\n }\n\n return {\n async addInvoice(params) {\n const body: any = { value: String(params.value) };\n if (params.memo) body.memo = params.memo;\n if (params.expiry) body.expiry = String(params.expiry);\n\n const res = await request<{ r_hash: string; payment_request: string }>(\n \"/v1/invoices\",\n { method: \"POST\", body: JSON.stringify(body) },\n );\n\n return {\n r_hash: base64ToHex(res.r_hash),\n payment_request: res.payment_request,\n };\n },\n\n async sendPaymentSync(params) {\n const body: any = { payment_request: params.payment_request };\n if (params.amt !== undefined) {\n body.amt = String(params.amt);\n }\n if (params.fee_limit) {\n body.fee_limit = { fixed: String(params.fee_limit.fixed) };\n }\n\n const res = await request<{\n payment_preimage: string;\n payment_error: string;\n payment_hash: string;\n }>(\"/v1/channels/transactions\", {\n method: \"POST\",\n body: JSON.stringify(body),\n });\n\n return {\n payment_preimage: res.payment_preimage\n ? base64ToHex(res.payment_preimage)\n : \"\",\n payment_error: res.payment_error ?? \"\",\n payment_hash: res.payment_hash ? base64ToHex(res.payment_hash) : \"\",\n };\n },\n\n async lookupInvoice(params) {\n const hashUrl = hexToBase64Url(params.r_hash_str);\n const res = await request<{\n state: string;\n r_preimage: string;\n value: string;\n }>(`/v1/invoice/${hashUrl}`);\n\n return {\n state: res.state,\n r_preimage: res.r_preimage ? base64ToHex(res.r_preimage) : \"\",\n value: res.value ?? \"0\",\n };\n },\n\n close() {\n // no-op for REST\n },\n };\n}\n","import {\n AuthenticationError,\n ConnectionError,\n InsufficientBalanceError,\n InvoiceExpiredError,\n type LightningError,\n PaymentTimeoutError,\n RouteNotFoundError,\n} from \"@ambosstech/lightning-mpp-sdk\";\n\ninterface GrpcError {\n code?: number;\n details?: string;\n message?: string;\n}\n\n// gRPC status codes\nconst UNAVAILABLE = 14;\nconst UNAUTHENTICATED = 16;\nconst DEADLINE_EXCEEDED = 4;\n\nexport function mapLndError(error: unknown): LightningError {\n const grpcError = error as GrpcError;\n const code = grpcError.code;\n const details = (grpcError.details ?? grpcError.message ?? \"\").toLowerCase();\n\n if (code === UNAUTHENTICATED) {\n return new AuthenticationError(\"LND authentication failed\", {\n cause: error,\n });\n }\n\n if (code === UNAVAILABLE) {\n return new ConnectionError(\"LND node unavailable\", { cause: error });\n }\n\n if (code === DEADLINE_EXCEEDED) {\n return new PaymentTimeoutError(\"LND request timed out\", { cause: error });\n }\n\n if (\n details.includes(\"invoice expired\") ||\n details.includes(\"invoice is expired\")\n ) {\n return new InvoiceExpiredError(\"Invoice has expired\", { cause: error });\n }\n\n if (\n details.includes(\"unable to find a path\") ||\n details.includes(\"no route\") ||\n details.includes(\"insufficient capacity\")\n ) {\n return new RouteNotFoundError(\"No route found\", { cause: error });\n }\n\n if (\n details.includes(\"insufficient balance\") ||\n details.includes(\"not enough balance\") ||\n details.includes(\"insufficient funds\")\n ) {\n return new InsufficientBalanceError(\"Insufficient balance\", {\n cause: error,\n });\n }\n\n // Fallback\n return new ConnectionError(\n `LND error: ${grpcError.details ?? grpcError.message ?? \"unknown\"}`,\n { cause: error },\n );\n}\n","import type {\n CreateInvoiceParams,\n CreateInvoiceResult,\n LightningProvider,\n LookupInvoiceParams,\n LookupInvoiceResult,\n PayInvoiceParams,\n PayInvoiceResult,\n} from \"@ambosstech/lightning-mpp-sdk\";\nimport { createGrpcTransport } from \"./grpc-client.js\";\nimport { createRestTransport } from \"./rest-client.js\";\nimport { mapLndError } from \"./error-mapper.js\";\nimport type { LndConfig, LndTransport } from \"./types.js\";\n\nexport class LndLightningProvider implements LightningProvider {\n private transport: LndTransport;\n\n constructor(config: LndConfig) {\n this.transport =\n config.transport === \"rest\"\n ? createRestTransport(config)\n : createGrpcTransport(config);\n }\n\n async createInvoice(\n params: CreateInvoiceParams,\n ): Promise<CreateInvoiceResult> {\n try {\n const response = await this.transport.addInvoice({\n value: params.amountSats,\n memo: params.memo,\n expiry: params.expirySecs,\n });\n\n return {\n bolt11: response.payment_request,\n paymentHash: response.r_hash,\n };\n } catch (error) {\n throw mapLndError(error);\n }\n }\n\n async payInvoice(params: PayInvoiceParams): Promise<PayInvoiceResult> {\n try {\n const request: any = { payment_request: params.bolt11 };\n if (params.amountSats !== undefined) {\n request.amt = params.amountSats;\n }\n if (params.maxFeeSats !== undefined) {\n request.fee_limit = { fixed: params.maxFeeSats };\n }\n\n const response = await this.transport.sendPaymentSync(request);\n\n if (response.payment_error) {\n throw new Error(response.payment_error);\n }\n\n return { preimage: response.payment_preimage };\n } catch (error) {\n throw mapLndError(error);\n }\n }\n\n async lookupInvoice(\n params: LookupInvoiceParams,\n ): Promise<LookupInvoiceResult> {\n try {\n const response = await this.transport.lookupInvoice({\n r_hash_str: params.paymentHash,\n });\n\n const settled = response.state === \"SETTLED\";\n return {\n settled,\n preimage: settled ? response.r_preimage : undefined,\n amountSats: response.value ? Number(response.value) : undefined,\n };\n } catch (error) {\n throw mapLndError(error);\n }\n }\n\n close(): void {\n this.transport.close();\n }\n}\n"],"mappings":"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","names":["ConnectionError"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ambosstech/lightning-mpp-adapter-lnd",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"proto",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"clean": "rm -rf dist"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@ambosstech/lightning-mpp-sdk": "workspace:*",
|
|
30
|
+
"@grpc/grpc-js": "^1.12.0",
|
|
31
|
+
"@grpc/proto-loader": "^0.7.13"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"tsup": "^8.3.0",
|
|
35
|
+
"typescript": "~5.7.0",
|
|
36
|
+
"vitest": "^2.1.0"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
package lnrpc;
|
|
4
|
+
|
|
5
|
+
option go_package = "github.com/lightningnetwork/lnd/lnrpc";
|
|
6
|
+
|
|
7
|
+
service Lightning {
|
|
8
|
+
rpc AddInvoice (Invoice) returns (AddInvoiceResponse);
|
|
9
|
+
rpc LookupInvoice (PaymentHash) returns (Invoice);
|
|
10
|
+
rpc SendPaymentSync (SendRequest) returns (SendResponse);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
message Invoice {
|
|
14
|
+
string memo = 1;
|
|
15
|
+
bytes r_preimage = 3;
|
|
16
|
+
bytes r_hash = 4;
|
|
17
|
+
int64 value = 5;
|
|
18
|
+
bool settled = 6;
|
|
19
|
+
int64 creation_date = 7;
|
|
20
|
+
int64 settle_date = 8;
|
|
21
|
+
string payment_request = 9;
|
|
22
|
+
int64 expiry = 15;
|
|
23
|
+
string state = 30;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
message AddInvoiceResponse {
|
|
27
|
+
bytes r_hash = 1;
|
|
28
|
+
string payment_request = 2;
|
|
29
|
+
uint64 add_index = 16;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
message PaymentHash {
|
|
33
|
+
string r_hash_str = 1;
|
|
34
|
+
bytes r_hash = 2;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
message SendRequest {
|
|
38
|
+
bytes dest = 1;
|
|
39
|
+
int64 amt = 2;
|
|
40
|
+
string payment_request = 6;
|
|
41
|
+
FeeLimit fee_limit = 8;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
message FeeLimit {
|
|
45
|
+
oneof limit {
|
|
46
|
+
int64 fixed = 1;
|
|
47
|
+
int64 fixed_msat = 3;
|
|
48
|
+
int64 percent = 2;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
message SendResponse {
|
|
53
|
+
string payment_error = 1;
|
|
54
|
+
bytes payment_preimage = 2;
|
|
55
|
+
bytes payment_hash = 5;
|
|
56
|
+
}
|