astra-lightning 1.1.4 → 1.1.6

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.
@@ -31,6 +31,9 @@ export type CreateInvoiceArgs = AuthenticatedLightningArgs<{
31
31
  asset_id?: string;
32
32
  peer_pubkey?: string;
33
33
  tpr?: any;
34
+ group_key?: string;
35
+ price_oracle_metadata?: string;
36
+
34
37
  }>;
35
38
 
36
39
  export type CreateInvoiceResult = {
@@ -20,6 +20,10 @@ const { parse } = Date;
20
20
  const { round } = Math;
21
21
  const tokensAsMtok = (tokens) => (BigInt(tokens) * BigInt(1e3)).toString();
22
22
  const type = "default";
23
+ const isDuplicateInvoiceError = (err = {}) => {
24
+ const message = err.details || err.message || String();
25
+ return typeof message === "string" && message.includes(invoiceExistsError);
26
+ };
23
27
 
24
28
  /** Create a Lightning invoice.
25
29
 
@@ -81,7 +85,10 @@ module.exports = (args, cbk) => {
81
85
 
82
86
  // Check arguments
83
87
  validate: (cbk) => {
84
- if (!!args.expires_at && new Date().toISOString() > args.expires_at) {
88
+ if (
89
+ !!args.expires_at &&
90
+ Math.floor(Date.now() / 1000) > Number(args.expires_at)
91
+ ) {
85
92
  return cbk([400, "ExpectedFutureDateForInvoiceExpiration"]);
86
93
  }
87
94
 
@@ -163,9 +170,10 @@ module.exports = (args, cbk) => {
163
170
  ({ addAddress, hints, mtokens, preimage }, cbk) => {
164
171
  const fallbackAddress = !addAddress ? String() : addAddress.address;
165
172
  const createdAt = new Date();
166
- const expireAt = !args.expires_at ? null : parse(args.expires_at);
167
-
173
+ const expireAt = !args.expires_at ? null : Math.floor(args.expires_at*msPerSec);
174
+
168
175
  const expiryMs = !expireAt ? null : expireAt - createdAt.getTime();
176
+
169
177
  if (!args.asset_id) {
170
178
  return args.lnd.default.addInvoice(
171
179
  {
@@ -183,7 +191,7 @@ module.exports = (args, cbk) => {
183
191
  value_msat: mtokens,
184
192
  },
185
193
  (err, response) => {
186
- if (!!err && err.details === invoiceExistsError) {
194
+ if (!!err && isDuplicateInvoiceError(err)) {
187
195
  return cbk([409, "InvoiceWithGivenHashAlreadyExists"]);
188
196
  }
189
197
 
@@ -228,6 +236,10 @@ module.exports = (args, cbk) => {
228
236
  }
229
237
  );
230
238
  } else {
239
+ const expiry = !expiryMs
240
+ ? defaultExpirySec
241
+ : round(expiryMs / msPerSec)
242
+
231
243
  return args.tpr.taproot_asset_channels.addInvoice(
232
244
  {
233
245
  asset_id: hexAsBuffer(args.asset_id),
@@ -236,9 +248,7 @@ module.exports = (args, cbk) => {
236
248
  invoice_request: {
237
249
  cltv_expiry: !args.cltv_delta ? undefined : args.cltv_delta,
238
250
  description_hash: hexAsBuffer(args.description_hash),
239
- expiry: !expiryMs
240
- ? defaultExpirySec
241
- : round(expiryMs / msPerSec),
251
+ expiry: expiry,
242
252
  fallback_addr: fallbackAddress,
243
253
  is_blinded: !!args.is_encrypting_routes,
244
254
  memo: args.description,
@@ -246,12 +256,13 @@ module.exports = (args, cbk) => {
246
256
  r_preimage: preimage || undefined,
247
257
  route_hints: hints || undefined,
248
258
  },
259
+ group_key: args.group_key ? hexAsBuffer(args.group_key) : undefined,
260
+ price_oracle_metadata: args.price_oracle_metadata,
249
261
  },
250
262
  (err, response) => {
251
- if (!!err && err.details === invoiceExistsError) {
263
+ if (!!err && isDuplicateInvoiceError(err)) {
252
264
  return cbk([409, "InvoiceWithGivenHashAlreadyExists"]);
253
265
  }
254
-
255
266
  if (!!err) {
256
267
  return cbk([503, "AddInvoiceError", { err }]);
257
268
  }
@@ -7,6 +7,8 @@ export type PaymentTaprootInvoiceArgs = AuthenticatedLightningArgs<{
7
7
  asset_id: string;
8
8
  asset_amount: number;
9
9
  peer_pubkey: string;
10
+ price_oracle_metadata?: string;
11
+ group_key?: string;
10
12
  payment_request: {
11
13
  payment_request: string;
12
14
  fee_limit_sat: number;
@@ -43,6 +43,8 @@ module.exports = (args) => {
43
43
  asset_amount: args.asset_amount,
44
44
  peer_pubkey: hexAsBuffer(args.peer_pubkey),
45
45
  payment_request: args.payment_request,
46
+ price_oracle_metadata: args.price_oracle_metadata ? args.price_oracle_metadata : undefined,
47
+ group_key: args.group_key ? hexAsBuffer(args.group_key) : undefined,
46
48
  }
47
49
  const sub = args.tpr.taproot_asset_channels.sendPayment(callRequest);
48
50
  const ret = {
package/package.json CHANGED
@@ -53,5 +53,5 @@
53
53
  "directory": "test/typescript"
54
54
  },
55
55
  "types": "index.d.ts",
56
- "version": "1.1.4"
56
+ "version": "1.1.6"
57
57
  }
package/test.js CHANGED
@@ -5,8 +5,15 @@ const {
5
5
  decodePaymentRequest,
6
6
  decodeAssetPayReq,
7
7
  createInvoice,
8
+ signMessage,
9
+ getIdentity,
10
+ subscribeToInvoices,
11
+ subscribeToPastPayments
8
12
  } = require("./index.js");
9
13
  const fs = require("fs");
14
+ const crypto = require("crypto");
15
+ const { createHash } = require("crypto");
16
+
10
17
  // const dayjs = require("dayjs");
11
18
  /* const LND_TLS_CERT =
12
19
  "/Users/wjl/Documents/gamichi/2024/astra/volumes/server/tls.cert";
@@ -22,17 +29,17 @@ const LND_SOCKET = "54.92.19.81:10109"; */
22
29
  // const invoice =
23
30
  // "lnbcrt10u1p5q3r0zpp50v0asn72aav354e27cals6l7j76sln0pzzvxktgur2wmlkf44mfqdy0f3hxv6fmv9ehxet5f9zr5dtzvscnywtyx56rjcnyxcuxxctyxc6xvvnrxfjxyvf5xymnxvnpx5erxef5x56rvcf58ymrvvnrxvunqefcvvcngv3ex3skzdm98q6rkctdda6kuap6xycrqwscqzzsxqrrssrzjqg3zz9zaagxqxan9fqzr6k7yvf900uf26m0z7c2g0rf55raupqclpakyc0a4gzq2v5qqqqlgqqqqqqgq2qsp58qmfwjwdrvr9dzjs2esms3cpvvgff3g4hsunszne3v7wszwcq62s9qxpqysgqscq2e3sqa0pfe5yzjdnp8q4temjazdw6y77c49tpvnhz0d4kjux92tw3gy9vvrh68qqef594frdp2uqhvwjy0sd7ezdcanvlln2rusgpg5w96t";
24
31
 
25
- const LND_SOCKET = "127.0.0.1:8444";
26
32
  const LND_MACAROON =
27
- "0201036c6e6402f801030a10cd485d60d65e48a8f253aeca1f20d5e51201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e657261746512047265616400000620d0b51747c52a6444a78c9e08947671f20362dfffc89404c10afb68d09e72a6e2";
33
+ "0201036c6e6402f801030a1020a1bf5a962e198f49d7d0cb5dacb7221201301a160a0761646472657373120472656164120577726974651a130a04696e666f120472656164120577726974651a170a08696e766f69636573120472656164120577726974651a210a086d616361726f6f6e120867656e6572617465120472656164120577726974651a160a076d657373616765120472656164120577726974651a170a086f6666636861696e120472656164120577726974651a160a076f6e636861696e120472656164120577726974651a140a057065657273120472656164120577726974651a180a067369676e6572120867656e6572617465120472656164000006207db76ec2a58ad259d4a4a5d3c4cff4bbd48b8667dee0cfdbf7e0299303fae9c6";
28
34
  const LND_TPROOT_ASSET_MACAROON =
29
- "0201047461706402d001030a10d5485d60d65e48a8f253aeca1f20d5e51201301a180a09616464726573736573120472656164120577726974651a150a06617373657473120472656164120577726974651a170a086368616e6e656c73120472656164120577726974651a150a066461656d6f6e120472656164120577726974651a130a046d696e74120472656164120577726974651a150a0670726f6f6673120472656164120577726974651a120a03726671120472656164120577726974651a170a08756e6976657273651204726561641205777269746500000620501385af6ee7b06d073829f55af1a69d6a3ecc4cfb59129c88c379a429f44440";
30
- const base64Cert =
31
- "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNERENDQWJLZ0F3SUJBZ0lSQUo3Rys0QzdYWldMN3hzMzk3bjMyUGd3Q2dZSUtvWkl6ajBFQXdJd01ERWcKTUI0R0ExVUVDaE1YYkdsMFpDQmhkWFJ2WjJWdVpYSmhkR1ZrSUdObGNuUXhEREFLQmdOVkJBTVRBMkp2WWpBZQpGdzB5TlRFeU1ESXdNakEzTURoYUZ3MHlOekF4TWpjd01qQTNNRGhhTURBeElEQWVCZ05WQkFvVEYyeHBkR1FnCllYVjBiMmRsYm1WeVlYUmxaQ0JqWlhKME1Rd3dDZ1lEVlFRREV3TmliMkl3V1RBVEJnY3Foa2pPUFFJQkJnZ3EKaGtqT1BRTUJCd05DQUFTU3BKdmh6M1lXVG5jTFVNR3Rvb1poUHNTVmlwR09RTWszbHkyMGRqUUk2OXd1M2gyRAphdG5TVGRSOTBCT2FhWUlrZ1lXRWpWV3Era1VDSWxXdjliMmJvNEdzTUlHcE1BNEdBMVVkRHdFQi93UUVBd0lDCnBEQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBVEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVcKQkJTaE9PZDArRmxSL0xzZ0t0MWROQktKQXBwSkREQlNCZ05WSFJFRVN6QkpnZ05pYjJLQ0NXeHZZMkZzYUc5egpkSUlFZFc1cGVJSUtkVzVwZUhCaFkydGxkSUlIWW5WbVkyOXVib2NFZndBQUFZY1FBQUFBQUFBQUFBQUFBQUFBCkFBQUFBWWNFckJNQUF6QUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpRUExRm8xakg3Z0IzY2pBblNSaUNKbDF3a1kKZGYxYnZVd1JSSzl0V1NIclFlc0NJR2tKQWkxWk5hNm9DeXFpemNObXZORmpUWXJHY1BmRUxxTCtiSjAyZUIvbAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==";
32
- const assetId =
33
- "b787a089e60451305c090b7b3604b7a107e13d0a955c8ed1043d874a448aa465";
34
- const invoice =
35
+ "0201047461706402d001030a1027a1bf5a962e198f49d7d0cb5dacb7221201301a180a09616464726573736573120472656164120577726974651a150a06617373657473120472656164120577726974651a170a086368616e6e656c73120472656164120577726974651a150a066461656d6f6e120472656164120577726974651a130a046d696e74120472656164120577726974651a150a0670726f6f6673120472656164120577726974651a120a03726671120472656164120577726974651a170a08756e69766572736512047265616412057772697465000006201bcecd78be5724f8127277b4b68fb65ce6cf2b502585d20318da22b3d473a20e";
36
+ const LND_SOCKET = "regtest.lnfi.network:10019";
37
+ const LND_TLS_CERT =
38
+ "/Users/jim/Documents/gamichi/2024/astra/packages/server/volumes/tls.cert";
39
+ const base64Cert = fs.readFileSync(LND_TLS_CERT).toString("base64");
35
40
  "";
41
+ const assetId ="f7ac99f2c068f1157c787012f50cb043437505c309c6d8685e135cd8481b1e9d";
42
+
36
43
 
37
44
  const { lnd } = authenticatedLndGrpc({
38
45
  cert: base64Cert,
@@ -45,6 +52,37 @@ const { lnd: tpr } = authenticatedLndGrpc({
45
52
  socket: LND_SOCKET,
46
53
  });
47
54
 
55
+ const getPriceOrcaleMetadata = async ({
56
+ assetId,
57
+ transaction_type = "0",
58
+ amount = "1000",
59
+ request_id,
60
+ }) => {
61
+ if (!request_id) {
62
+ throw new Error("request_id is required to build price_oracle_metadata");
63
+ }
64
+
65
+ const price_oracle_metadata = {
66
+ type: "bridge",
67
+ asset_id: assetId,
68
+ transaction_type,
69
+ amount,
70
+ request_id,
71
+ };
72
+
73
+ const messageToSign = Object.values(price_oracle_metadata).join("");
74
+ const { signature } = await signMessage({ lnd, message: messageToSign });
75
+ const public_key =
76
+ "02607b201503d39fe886cc13637f4dcfa45ea6a83d6b1f5ab8ce780e1157af1718";
77
+
78
+ return {
79
+ ...price_oracle_metadata,
80
+ public_key,
81
+ sign: signature,
82
+ raw_data: JSON.stringify(price_oracle_metadata)
83
+ };
84
+ };
85
+
48
86
  const payWithTpr = async (invoice, assetId) => {
49
87
  // const provider = new ethers.JsonRpcProvider('https://eth-sepolia.g.alchemy.com/v2/ClvXGqSMvZ6nEb_G5ekJGsZwNdsp72oz');
50
88
  // const lspSigner = new ethers.Wallet('dd5862c69e641fb052092d34724ce62764186abf87474656f2b2149684dca754', provider);
@@ -57,7 +95,7 @@ const payWithTpr = async (invoice, assetId) => {
57
95
  // request: invoice
58
96
  // })
59
97
 
60
- const ret = await getChannels({ lnd }).catch((error) => console.log(error));
98
+ /* const ret = await getChannels({ lnd }).catch((error) => console.log(error));
61
99
 
62
100
  const filterChannels = ret.channels.filter(
63
101
  (channel) =>
@@ -102,23 +140,34 @@ const payWithTpr = async (invoice, assetId) => {
102
140
  throw new Error(
103
141
  `channelId: ${maxLocalBalanceChannel.channel_id} not enough balance`
104
142
  );
105
- }
106
- const peerPubkey = maxLocalBalanceChannel.partner_public_key;
143
+ } */
144
+ const peerPubkey = "03b24a4bf911ffd26ac1d5e5f2440a3c2f6974e4cc85d2ef54e17ee6d3717433d3";
145
+
146
+
147
+ const decodedReq = await decodeAssetPayReq({ lnd, request: invoice }).then(res => res.destination);
148
+ const priceOracleMetadata = await getPriceOrcaleMetadata({
149
+ assetId,
150
+ transaction_type: "1",
151
+ amount: 0,
152
+ request_id: decodedReq.pay_req.payment_hash,
153
+ });
107
154
  const retPay = await payTaprootInvoice({
108
155
  lnd: lnd,
109
156
  tpr: tpr,
110
157
  asset_id: assetId,
111
- asset_amount: 10,
158
+ asset_amount: decodedReq.asset_amount,
112
159
  peer_pubkey: peerPubkey,
113
160
  payment_request: {
114
161
  payment_request: invoice,
115
162
  fee_limit_sat: 1000,
116
163
  allow_self_payment: true,
117
164
  timeout_seconds: 60 * 5,
118
- outgoing_chan_id: maxLocalBalanceChannel.channel_id,
165
+ outgoing_chan_id: "118422899869679616",
119
166
  },
167
+ price_oracle_metadata: priceOracleMetadata.raw_data,
120
168
  }).catch((e) => {
121
169
  console.log("error", e.message);
170
+ throw e;
122
171
  });
123
172
  console.log("ret", retPay);
124
173
 
@@ -175,20 +224,53 @@ const payWithTpr = async (invoice, assetId) => {
175
224
  // }
176
225
  // queryBalance();
177
226
 
227
+
228
+
178
229
  const addTapdInvoice = async () => {
230
+ const secret = crypto.randomBytes(32);
231
+ const preimage = secret.toString("hex");
232
+ const hash = createHash("sha256").update(secret).digest("hex");
233
+
234
+ /*
235
+ "sign": "lncli.signmessage(type + asset_id+ transaction_type+ amount + request_id )"
236
+ {
237
+ "type": "bridge",
238
+ "asset_id": "9fe1643dd1ae81208fde67d1bce2b3a3a6cd158a868d3c6774eb075b4f032004",
239
+ "transaction_type": "0", //0买 1卖
240
+ "amount": "4100",
241
+ "request_id": "hash(preimage)",
242
+ "public_key": "0261f6cc4cdc3b59c9910badebd6d0c34f7f9357320a349af906ecf750dda0bcc4",
243
+ "sign": "lncli.signmessage(type + asset_id+ transaction_type+ amount + request_id )"
244
+ }
245
+ */
246
+ const price_oracle_metadata = await getPriceOrcaleMetadata({
247
+ assetId,
248
+ transaction_type: "0",
249
+ amount: "1000",
250
+ request_id: hash,
251
+ });
252
+
253
+ console.log("price_oracle_metadata", price_oracle_metadata);
254
+
255
+ //return;
179
256
  const ret = await createInvoice({
180
257
  lnd,
181
258
  tpr,
182
- mtokens: 1000,
259
+ mtokens: 1000000,
260
+ // expires_at:'1764839000',
261
+ peer_pubkey:"03b24a4bf911ffd26ac1d5e5f2440a3c2f6974e4cc85d2ef54e17ee6d3717433d3",
183
262
  asset_id: assetId,
263
+ price_oracle_metadata: JSON.stringify(price_oracle_metadata),
264
+ secret: preimage,
265
+
184
266
  }).catch((e) => {
185
- console.error("Failed to create invoice:", e.message);
267
+ console.error("Failed to create invoice:", e);
186
268
  });
187
269
  console.log("🚀 ~ addTapdInvoice ~ ret:", ret);
188
270
  };
189
271
 
190
272
  const decodeTapdInvoice = async()=>{
191
- const invoice ='lnbcrt1200u1p5ja2pgpp58ahjcpwgt9zcvda6cchnrl5wyr4r9vjg487qrxvlh7vd88rxnhssdqqcqzzsxqr23srzjqw7ng5fg7qnyr49nm9qtt6nvnwxfefpygrctxdmfx9uf8l0awcaura2jdhvguyylxuqqqqlgqqqqqqgq2qsp5g54dp5lug8dqne4pglj0j0tglv3rtawk76rlqmqcppavfy8dzr4q9qxpqysgqt9jde9vcwpc27ayzpv7q3j63nej52xfjeuhew65y22zvd0vjans9hz206sxf67n8zz6mr803d7skpcz762vqaj6mrf0uwlxtdtv6u9qpahal9g'
273
+ const invoice ='lnbcrt114742690p1p55hxxjpp584aulkj02vhaqujfv0lv5dtyuw4vrnk67uvx77q4y20md22sxz3sdqqcqzzsxqr23srzjqf7j7xl8rhpycc932pcy382w7f6d664vydks93nuwmtfxh00hft2da0glksvd4c3acqqqqlgqqqqqqgq2qsp5duc6ezxqyllkxqvevmr34d852nplfknk3jc2dvwktv2gh3pdrxus9qxpqysgqc67uh6vl2epzj32s0qf86v7hpygs3tps3ejy9uca78p2w0dgfjnzshlxpfmwws6xwecw0c7z47jvuglywhqg4tq260h7tv30sxkvxqgqpeufpe'
192
274
  const ret = await decodeAssetPayReq({
193
275
  asset_id: assetId,
194
276
  pay_req_string: invoice,
@@ -210,7 +292,7 @@ const getBestLndChannel = async (asset) => {
210
292
  return {channels: []};
211
293
  });
212
294
 
213
- console.log("🚀 ~ getBestLndChannel ~ ret:", ret);
295
+
214
296
 
215
297
  let filterChannels = [];
216
298
  let sortTprChannels = [];
@@ -257,6 +339,8 @@ const getBestLndChannel = async (asset) => {
257
339
  return hasLocal || hasFunding || hasRemote;
258
340
  });
259
341
 
342
+ console.log('filterChannels',filterChannels)
343
+
260
344
 
261
345
  sortTprChannels = filterChannels.sort((a, b) => {
262
346
  let aData;
@@ -337,7 +421,14 @@ const getBestLndChannel = async (asset) => {
337
421
  };
338
422
 
339
423
  const test = async () => {
340
- await addTapdInvoice();
424
+ const ret = await getIdentity({ lnd });
425
+ console.log("🚀 ~ test ~ ret:", ret)
426
+ //getBestLndChannel({assetId, isBTC: false})
427
+ /* const sub = subscribeToInvoices({ lnd });
428
+ sub.on("invoice_updated",async(invoice)=>{
429
+ console.log('invoice',invoice)
430
+ }) */
431
+ //await addTapdInvoice();
341
432
  //await decodeTapdInvoice();
342
433
  //await listChannels();
343
434
  // const ret = await getBestLndChannel({
@@ -361,6 +452,11 @@ const test = async () => {
361
452
  // },
362
453
  // });
363
454
  // console.log("🚀 ~ test ~ retPay:", retPay)
455
+
456
+ /* const sub = subscribeToPastPayments({ lnd });
457
+ sub.on("payment", async (payment) => {
458
+ console.log('payment',payment)
459
+ }); */
364
460
 
365
461
  };
366
462
  test();