lnlink-server 1.1.7 → 1.1.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lnlink-server",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "private": false,
5
5
  "main": "index.js",
6
6
  "electron": "lnlink.js",
@@ -0,0 +1,25 @@
1
+ -- CreateTable
2
+ CREATE TABLE "exchange_orders" (
3
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
4
+ "payment_hash" TEXT NOT NULL,
5
+ "btc_invoice" TEXT NOT NULL,
6
+ "btc_amount" TEXT NOT NULL,
7
+ "rgb_invoice" TEXT,
8
+ "asset_id" TEXT NOT NULL,
9
+ "asset_amount" TEXT NOT NULL,
10
+ "preimage" TEXT,
11
+ "status" TEXT NOT NULL,
12
+ "error_message" TEXT,
13
+ "htlc_expiry_at" INTEGER NOT NULL,
14
+ "created_at" INTEGER NOT NULL,
15
+ "updated_at" INTEGER NOT NULL
16
+ );
17
+
18
+ -- CreateIndex
19
+ CREATE UNIQUE INDEX "exchange_orders_payment_hash_key" ON "exchange_orders"("payment_hash");
20
+
21
+ -- CreateIndex
22
+ CREATE INDEX "exchange_orders_status_idx" ON "exchange_orders"("status");
23
+
24
+ -- CreateIndex
25
+ CREATE INDEX "exchange_orders_created_at_idx" ON "exchange_orders"("created_at");
@@ -0,0 +1,27 @@
1
+ -- RedefineTables
2
+ PRAGMA defer_foreign_keys=ON;
3
+ PRAGMA foreign_keys=OFF;
4
+ CREATE TABLE "new_exchange_orders" (
5
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
6
+ "payment_hash" TEXT NOT NULL,
7
+ "btc_invoice" TEXT NOT NULL,
8
+ "btc_amount" TEXT NOT NULL,
9
+ "rgb_invoice" TEXT,
10
+ "asset_id" TEXT NOT NULL,
11
+ "asset_amount" TEXT NOT NULL,
12
+ "preimage" TEXT,
13
+ "status" TEXT NOT NULL,
14
+ "error_message" TEXT,
15
+ "btc_retry_count" INTEGER NOT NULL DEFAULT 0,
16
+ "htlc_expiry_at" INTEGER NOT NULL,
17
+ "created_at" INTEGER NOT NULL,
18
+ "updated_at" INTEGER NOT NULL
19
+ );
20
+ INSERT INTO "new_exchange_orders" ("asset_amount", "asset_id", "btc_amount", "btc_invoice", "created_at", "error_message", "htlc_expiry_at", "id", "payment_hash", "preimage", "rgb_invoice", "status", "updated_at") SELECT "asset_amount", "asset_id", "btc_amount", "btc_invoice", "created_at", "error_message", "htlc_expiry_at", "id", "payment_hash", "preimage", "rgb_invoice", "status", "updated_at" FROM "exchange_orders";
21
+ DROP TABLE "exchange_orders";
22
+ ALTER TABLE "new_exchange_orders" RENAME TO "exchange_orders";
23
+ CREATE UNIQUE INDEX "exchange_orders_payment_hash_key" ON "exchange_orders"("payment_hash");
24
+ CREATE INDEX "exchange_orders_status_idx" ON "exchange_orders"("status");
25
+ CREATE INDEX "exchange_orders_created_at_idx" ON "exchange_orders"("created_at");
26
+ PRAGMA foreign_keys=ON;
27
+ PRAGMA defer_foreign_keys=OFF;
@@ -134,6 +134,27 @@ model LnlinkTransaction {
134
134
  @@map("lnlink_transactions")
135
135
  }
136
136
 
137
+ model ExchangeOrder {
138
+ id Int @id @default(autoincrement())
139
+ payment_hash String @unique
140
+ btc_invoice String
141
+ btc_amount String
142
+ rgb_invoice String?
143
+ asset_id String
144
+ asset_amount String
145
+ preimage String?
146
+ status String
147
+ error_message String?
148
+ btc_retry_count Int @default(0)
149
+ htlc_expiry_at Int
150
+ created_at Int
151
+ updated_at Int
152
+
153
+ @@index([status])
154
+ @@index([created_at])
155
+ @@map("exchange_orders")
156
+ }
157
+
137
158
  // LnLink Orders Table
138
159
  model LnlinkOrder {
139
160
  id Int @id @default(autoincrement())
@@ -5,7 +5,8 @@ let isAdvancedConfigVisible = false
5
5
  function openExternalUrl(url) {
6
6
  if (window.electronAPI && window.electronAPI.openExternal) {
7
7
  window.electronAPI.openExternal(url)
8
- } else {
8
+ }
9
+ else {
9
10
  // Fallback for non-Electron environments
10
11
  window.open(url, "_blank")
11
12
  }
@@ -62,7 +63,7 @@ async function fetchNetworkConfigs() {
62
63
  // nostrRelays: item.nostrRelays ? [item.nostrRelays] : [],
63
64
  nostrRelays: [
64
65
  "wss://relay01.lnfi.network",
65
- "wss://relay.snort.social",
66
+ "wss://vault.iris.to",
66
67
  ],
67
68
  officialLndPeer: item.lndPeerId,
68
69
  officialLndPeerHost: item.lndPeerHost,
@@ -80,12 +81,14 @@ async function fetchNetworkConfigs() {
80
81
  networkConfigs = apiConfigs
81
82
  console.log("Network configs updated from API")
82
83
  }
83
- } else {
84
+ }
85
+ else {
84
86
  console.warn(
85
87
  "API returned success but no data or invalid format, using default configs.",
86
88
  )
87
89
  }
88
- } catch (error) {
90
+ }
91
+ catch (error) {
89
92
  console.error(
90
93
  "Error fetching network configs, using default configs:",
91
94
  error,
@@ -128,7 +131,8 @@ function showErrorModal(message) {
128
131
  document.getElementById("errorModal"),
129
132
  )
130
133
  errorModal.show()
131
- } else {
134
+ }
135
+ else {
132
136
  console.error("Error:", message)
133
137
  }
134
138
  }
@@ -142,7 +146,8 @@ function showSuccessModal(message) {
142
146
  document.getElementById("successModal"),
143
147
  )
144
148
  successModal.show()
145
- } else {
149
+ }
150
+ else {
146
151
  console.log("Success:", message)
147
152
  }
148
153
  }
@@ -188,11 +193,13 @@ function showConfirmModal(message, onConfirm, onCancel) {
188
193
  }
189
194
 
190
195
  confirmModal.show()
191
- } else {
196
+ }
197
+ else {
192
198
  // eslint-disable-next-line no-alert
193
199
  if (confirm(message.replace(/<[^>]*>/g, ""))) {
194
200
  if (onConfirm) onConfirm()
195
- } else {
201
+ }
202
+ else {
196
203
  if (onCancel) onCancel()
197
204
  }
198
205
  }
@@ -202,20 +209,22 @@ function showConfirmModal(message, onConfirm, onCancel) {
202
209
  function getStatusClass(value) {
203
210
  const strValue = String(value).toLowerCase()
204
211
  if (
205
- strValue === "true" ||
206
- strValue === "running" ||
207
- strValue === "active" ||
208
- strValue === "online"
212
+ strValue === "true"
213
+ || strValue === "running"
214
+ || strValue === "active"
215
+ || strValue === "online"
209
216
  ) {
210
217
  return { class: "status-success", icon: "fas fa-check-circle" }
211
- } else if (
212
- strValue === "false" ||
213
- strValue === "stopped" ||
214
- strValue === "inactive" ||
215
- strValue === "offline"
218
+ }
219
+ else if (
220
+ strValue === "false"
221
+ || strValue === "stopped"
222
+ || strValue === "inactive"
223
+ || strValue === "offline"
216
224
  ) {
217
225
  return { class: "status-error", icon: "fas fa-times-circle" }
218
- } else if (strValue.includes("pending") || strValue.includes("waiting")) {
226
+ }
227
+ else if (strValue.includes("pending") || strValue.includes("waiting")) {
219
228
  return { class: "status-warning", icon: "fas fa-clock" }
220
229
  }
221
230
  return { class: "", icon: "fas fa-info-circle" }
@@ -227,12 +236,12 @@ async function getInfo(showLoading = true) {
227
236
 
228
237
  // Show loading state
229
238
  if (showLoading) {
230
- mainContent.innerHTML =
231
- '<div class="loading-container"><div class="loading"></div><div>Loading information...</div></div>'
239
+ mainContent.innerHTML
240
+ = "<div class=\"loading-container\"><div class=\"loading\"></div><div>Loading information...</div></div>"
232
241
  }
233
242
 
234
243
  try {
235
- const res = await fetch("/api/lnd/info").then((res) => res.json())
244
+ const res = await fetch("/api/lnd/info").then(res => res.json())
236
245
 
237
246
  if (res.code === 200) {
238
247
  if (res.data) {
@@ -250,23 +259,26 @@ async function getInfo(showLoading = true) {
250
259
  renderConfigurationForm(res.data, torReachable)
251
260
  }
252
261
  }
253
- } else if (
254
- res.code === 500 &&
255
- res.message === "Please init the wallet or init owner first"
262
+ }
263
+ else if (
264
+ res.code === 500
265
+ && res.message === "Please init the wallet or init owner first"
256
266
  ) {
257
267
  // Fetch network configs only when needed for configuration
258
268
  await fetchNetworkConfigs()
259
269
 
260
270
  // If wallet/owner not initialized, show configuration form
261
271
  renderConfigurationForm({})
262
- } else {
263
- mainContent.innerHTML =
264
- '<div class="alert alert-danger"><i class="fas fa-exclamation-triangle"></i> Failed to load information</div>'
265
272
  }
266
- } catch (error) {
273
+ else {
274
+ mainContent.innerHTML
275
+ = "<div class=\"alert alert-danger\"><i class=\"fas fa-exclamation-triangle\"></i> Failed to load information</div>"
276
+ }
277
+ }
278
+ catch (error) {
267
279
  console.error("Failed to get info:", error)
268
- mainContent.innerHTML =
269
- '<div class="alert alert-danger"><i class="fas fa-exclamation-triangle"></i> Network error occurred</div>'
280
+ mainContent.innerHTML
281
+ = "<div class=\"alert alert-danger\"><i class=\"fas fa-exclamation-triangle\"></i> Network error occurred</div>"
270
282
  }
271
283
  }
272
284
 
@@ -276,12 +288,12 @@ function renderConfiguredView(basicData, settings, torReachable) {
276
288
  const mainContent = document.getElementById("main-content")
277
289
 
278
290
  // Extract Node ID (Nostr PubKey)
279
- const nodeId =
280
- settings.officialNostrPubKey || basicData.officialNostrPubKey || "Unknown"
291
+ const nodeId
292
+ = settings.officialNostrPubKey || basicData.officialNostrPubKey || "Unknown"
281
293
 
282
294
  // Get Tor status from basicData
283
- const enableTor =
284
- basicData.enableTor !== undefined ? basicData.enableTor : true
295
+ const enableTor
296
+ = basicData.enableTor !== undefined ? basicData.enableTor : true
285
297
 
286
298
  // Determine Service Status
287
299
  // We check basicData for status indicators or default to design mocks if not present
@@ -289,10 +301,10 @@ function renderConfiguredView(basicData, settings, torReachable) {
289
301
  const rgbStatus = basicData.rgb || "Stopped" // Mock/Default based on design
290
302
  const litdStatus = basicData.litd || "Stopped" // Mock/Default based on design
291
303
 
292
- const isRgbRunning =
293
- rgbStatus.toLowerCase() === "running" || rgbStatus === "true"
294
- const isLitdRunning =
295
- litdStatus.toLowerCase() === "running" || litdStatus === "true"
304
+ const isRgbRunning
305
+ = rgbStatus.toLowerCase() === "running" || rgbStatus === "true"
306
+ const isLitdRunning
307
+ = litdStatus.toLowerCase() === "running" || litdStatus === "true"
296
308
 
297
309
  const rgbClass = isRgbRunning ? "running" : "stopped"
298
310
  const litdClass = isLitdRunning ? "running" : "stopped"
@@ -446,13 +458,15 @@ function updateManageButtonState(anyRunning, allRunning) {
446
458
  // All services running - enable button
447
459
  manageBtn.disabled = false
448
460
  manageBtn.classList.remove("loading-state")
449
- manageBtn.innerHTML = 'Manage My Node <i class="fas fa-arrow-right"></i>'
450
- } else if (anyRunning) {
461
+ manageBtn.innerHTML = "Manage My Node <i class=\"fas fa-arrow-right\"></i>"
462
+ }
463
+ else if (anyRunning) {
451
464
  // Some services starting - show loading
452
465
  manageBtn.disabled = true
453
466
  manageBtn.classList.add("loading-state")
454
- manageBtn.innerHTML = '<span class="loading"></span> Starting Services...'
455
- } else {
467
+ manageBtn.innerHTML = "<span class=\"loading\"></span> Starting Services..."
468
+ }
469
+ else {
456
470
  // No services running - show normal but disabled
457
471
  manageBtn.disabled = true
458
472
  manageBtn.classList.remove("loading-state")
@@ -488,7 +502,8 @@ async function pollServiceStatus() {
488
502
  if (nameEl && nameEl.textContent.includes("RGB")) {
489
503
  rgbStatusEl = box.querySelector(".status-value")
490
504
  rgbDotEl = box.querySelector(".status-dot")
491
- } else if (nameEl && nameEl.textContent.includes("LITD")) {
505
+ }
506
+ else if (nameEl && nameEl.textContent.includes("LITD")) {
492
507
  litdStatusEl = box.querySelector(".status-value")
493
508
  litdDotEl = box.querySelector(".status-dot")
494
509
  }
@@ -528,14 +543,16 @@ async function pollServiceStatus() {
528
543
  attempts++
529
544
  if (attempts < maxAttempts) {
530
545
  setTimeout(checkStatus, 1000)
531
- } else {
546
+ }
547
+ else {
532
548
  console.log("Service status polling timed out")
533
549
  // Re-enable button even if services didn't start
534
550
  updateManageButtonState(false, false)
535
551
  const manageBtn = document.querySelector(".manage-btn")
536
552
  manageBtn.disabled = false
537
553
  }
538
- } catch (error) {
554
+ }
555
+ catch (error) {
539
556
  console.error("Error polling service status:", error)
540
557
  attempts++
541
558
  if (attempts < maxAttempts) {
@@ -576,8 +593,8 @@ window.navigateToManage = function navigateToManage(url, button) {
576
593
  window.openManageUrl = function openManageUrl(url, linkEl) {
577
594
  if (!url) return
578
595
  if (linkEl) {
579
- linkEl.innerHTML =
580
- '<i class="fas fa-spinner fa-spin status-icon"></i>Loading...'
596
+ linkEl.innerHTML
597
+ = "<i class=\"fas fa-spinner fa-spin status-icon\"></i>Loading..."
581
598
  }
582
599
  setTimeout(() => {
583
600
  window.location.href = url
@@ -680,7 +697,8 @@ function togglePasswordVisibility(icon) {
680
697
  input.type = "text"
681
698
  icon.classList.remove("fa-eye")
682
699
  icon.classList.add("fa-eye-slash")
683
- } else {
700
+ }
701
+ else {
684
702
  input.type = "password"
685
703
  icon.classList.remove("fa-eye-slash")
686
704
  icon.classList.add("fa-eye")
@@ -712,7 +730,8 @@ function copyToClipboard(text, triggerElement) {
712
730
  console.error("Could not copy text: ", err)
713
731
  },
714
732
  )
715
- } else {
733
+ }
734
+ else {
716
735
  const textArea = document.createElement("textarea")
717
736
  textArea.value = text
718
737
  textArea.style.position = "fixed"
@@ -723,7 +742,8 @@ function copyToClipboard(text, triggerElement) {
723
742
  try {
724
743
  document.execCommand("copy")
725
744
  showFeedback()
726
- } catch (err) {
745
+ }
746
+ catch (err) {
727
747
  console.error("Fallback: Oops, unable to copy", err)
728
748
  }
729
749
  document.body.removeChild(textArea)
@@ -829,7 +849,8 @@ window.toggleAdvanced = function () {
829
849
  container.style.display = "block"
830
850
  icon.classList.remove("fa-chevron-down")
831
851
  icon.classList.add("fa-chevron-up")
832
- } else {
852
+ }
853
+ else {
833
854
  container.style.display = "none"
834
855
  icon.classList.remove("fa-chevron-up")
835
856
  icon.classList.add("fa-chevron-down")
@@ -848,7 +869,8 @@ window.selectNetwork = function (network) {
848
869
  document.querySelectorAll(".btn-network").forEach((btn) => {
849
870
  if (btn.dataset.value === network) {
850
871
  btn.classList.add("active")
851
- } else {
872
+ }
873
+ else {
852
874
  btn.classList.remove("active")
853
875
  }
854
876
  })
@@ -868,7 +890,8 @@ window.togglePassword = function (id) {
868
890
  const input = document.getElementById(id)
869
891
  if (input.type === "password") {
870
892
  input.type = "text"
871
- } else {
893
+ }
894
+ else {
872
895
  input.type = "password"
873
896
  }
874
897
  }
@@ -970,7 +993,8 @@ function updateConfigFields() {
970
993
  let editableFields = []
971
994
  if (selectedNetwork === "regtest") {
972
995
  editableFields = ["bitcoindPass"]
973
- } else if (selectedNetwork === "mainnet") {
996
+ }
997
+ else if (selectedNetwork === "mainnet") {
974
998
  editableFields = [
975
999
  "bitcoindRpcHost",
976
1000
  "bitcoindRpcPort",
@@ -981,7 +1005,8 @@ function updateConfigFields() {
981
1005
  "rgbProxy",
982
1006
  "bitcoindIndex",
983
1007
  ]
984
- } else if (selectedNetwork === "testnet") {
1008
+ }
1009
+ else if (selectedNetwork === "testnet") {
985
1010
  editableFields = ["bitcoindPass"]
986
1011
  }
987
1012
 
@@ -1052,9 +1077,9 @@ async function handleInitTorToggle(checkbox, torReachable) {
1052
1077
 
1053
1078
  if (!checkbox.checked) {
1054
1079
  label.classList.add("disabled-state")
1055
- label.innerHTML =
1056
- "Disabled - Enable Tor to ensure all features work properly" +
1057
- torTooltipShort
1080
+ label.innerHTML
1081
+ = `Disabled - Enable Tor to ensure all features work properly${
1082
+ torTooltipShort}`
1058
1083
  return
1059
1084
  }
1060
1085
 
@@ -1069,17 +1094,18 @@ async function handleInitTorToggle(checkbox, torReachable) {
1069
1094
  label.classList.remove("disabled-state")
1070
1095
  label.textContent = "Enabled-Enhanced privacy"
1071
1096
  // label.style.color = "#10b981";
1072
- } else {
1097
+ }
1098
+ else {
1073
1099
  checkbox.checked = false
1074
1100
  label.classList.add("disabled-state")
1075
- label.innerHTML =
1076
- "Disabled - Enable Tor to ensure all features work properly" +
1077
- torTooltipLong
1101
+ label.innerHTML
1102
+ = `Disabled - Enable Tor to ensure all features work properly${
1103
+ torTooltipLong}`
1078
1104
  label.style.color = ""
1079
1105
  showErrorModal(
1080
- "<div>Your current network environment does not support Tor. Check your network or proxy (TUN mode required).</div>" +
1081
- "<div style='margin-top: 10px;'>If Tor is disabled or fails to enable, your Taproot Assets node will only be able to initiate outbound connections to other nodes.</div>" +
1082
- "<div style='margin-top: 5px;'>Other nodes will not be able to connect to your node, and your node cannot be shared for inbound connections.</div>",
1106
+ "<div>Your current network environment does not support Tor. Check your network or proxy (TUN mode required).</div>"
1107
+ + "<div style='margin-top: 10px;'>If Tor is disabled or fails to enable, your Taproot Assets node will only be able to initiate outbound connections to other nodes.</div>"
1108
+ + "<div style='margin-top: 5px;'>Other nodes will not be able to connect to your node, and your node cannot be shared for inbound connections.</div>",
1083
1109
  )
1084
1110
  }
1085
1111
  }
@@ -1091,7 +1117,8 @@ async function checkTorReachability() {
1091
1117
  const response = await fetch("/api/lnd/tor/check")
1092
1118
  const result = await response.json()
1093
1119
  return result.data?.reachable === true
1094
- } catch {
1120
+ }
1121
+ catch {
1095
1122
  return false
1096
1123
  }
1097
1124
  }
@@ -1111,7 +1138,7 @@ async function handleConfigFormSubmit(event) {
1111
1138
  form.classList.add("was-validated")
1112
1139
  submitBtn.setAttribute("disabled", "disabled")
1113
1140
  // Use the new loading spinner style
1114
- submitBtn.innerHTML = '<div class="loading"></div>Save and Continue'
1141
+ submitBtn.innerHTML = "<div class=\"loading\"></div>Save and Continue"
1115
1142
  const formData = new FormData(form)
1116
1143
  const myHeaders = new Headers()
1117
1144
  myHeaders.append("Content-Type", "application/json")
@@ -1127,9 +1154,10 @@ async function handleConfigFormSubmit(event) {
1127
1154
  // Handle comma-separated array
1128
1155
  settings[key] = value
1129
1156
  .split(",")
1130
- .map((item) => item.trim())
1131
- .filter((item) => item)
1132
- } else {
1157
+ .map(item => item.trim())
1158
+ .filter(item => item)
1159
+ }
1160
+ else {
1133
1161
  settings[key] = value
1134
1162
  }
1135
1163
  }
@@ -1140,15 +1168,15 @@ async function handleConfigFormSubmit(event) {
1140
1168
 
1141
1169
  // Check Tor network reachability if Tor is enabled
1142
1170
  if (enableTor) {
1143
- submitBtn.innerHTML = '<div class="loading"></div>Checking Tor network...'
1171
+ submitBtn.innerHTML = "<div class=\"loading\"></div>Checking Tor network..."
1144
1172
  const torReachable = await checkTorReachability()
1145
1173
  if (!torReachable) {
1146
1174
  submitBtn.removeAttribute("disabled")
1147
1175
  submitBtn.innerHTML = "Save and Continue"
1148
1176
  showErrorModal(
1149
- "<div>Your current network environment does not support Tor. Check your network or proxy (TUN mode required).</div>" +
1150
- "<div style='margin-top: 10px;'>If Tor is disabled or fails to enable, your Taproot Assets node will only be able to initiate outbound connections to other nodes.</div>" +
1151
- "<div style='margin-top: 5px;'>Other nodes will not be able to connect to your node, and your node cannot be shared for inbound connections.</div>",
1177
+ "<div>Your current network environment does not support Tor. Check your network or proxy (TUN mode required).</div>"
1178
+ + "<div style='margin-top: 10px;'>If Tor is disabled or fails to enable, your Taproot Assets node will only be able to initiate outbound connections to other nodes.</div>"
1179
+ + "<div style='margin-top: 5px;'>Other nodes will not be able to connect to your node, and your node cannot be shared for inbound connections.</div>",
1152
1180
  )
1153
1181
  return
1154
1182
  }
@@ -1176,16 +1204,19 @@ async function handleConfigFormSubmit(event) {
1176
1204
 
1177
1205
  // Refresh page data to show running services
1178
1206
  await getInfo(false)
1179
- } else {
1207
+ }
1208
+ else {
1180
1209
  showErrorModal(result.message || "Configuration failed")
1181
1210
  }
1182
- } catch (error) {
1211
+ }
1212
+ catch (error) {
1183
1213
  console.error("Network error:", error)
1184
1214
  showErrorModal("Network error occurred")
1185
- } finally {
1215
+ }
1216
+ finally {
1186
1217
  submitBtn.removeAttribute("disabled")
1187
- submitBtn.innerHTML =
1188
- '<i class="fas fa-save"></i> Save Complete Configuration'
1218
+ submitBtn.innerHTML
1219
+ = "<i class=\"fas fa-save\"></i> Save Complete Configuration"
1189
1220
  }
1190
1221
  }
1191
1222
 
@@ -1215,9 +1246,9 @@ async function handleTorToggle(checkbox, torReachable) {
1215
1246
  if (enable && !torReachable) {
1216
1247
  checkbox.checked = false
1217
1248
  showErrorModal(
1218
- "<div>Your current network environment does not support Tor. Check your network or proxy (TUN mode required).</div>" +
1219
- "<div style='margin-top: 10px;'>If Tor is disabled or fails to enable, your Taproot Assets node will only be able to initiate outbound connections to other nodes.</div>" +
1220
- "<div style='margin-top: 5px;'>Other nodes will not be able to connect to your node, and your node cannot be shared for inbound connections.</div>",
1249
+ "<div>Your current network environment does not support Tor. Check your network or proxy (TUN mode required).</div>"
1250
+ + "<div style='margin-top: 10px;'>If Tor is disabled or fails to enable, your Taproot Assets node will only be able to initiate outbound connections to other nodes.</div>"
1251
+ + "<div style='margin-top: 5px;'>Other nodes will not be able to connect to your node, and your node cannot be shared for inbound connections.</div>",
1221
1252
  )
1222
1253
  return
1223
1254
  }
@@ -1246,8 +1277,8 @@ async function handleTorToggle(checkbox, torReachable) {
1246
1277
  label.innerHTML = enable
1247
1278
  ? `Enabled - Enhanced privacy`
1248
1279
  : `Disabled - Enable Tor to ensure all features work properly${
1249
- torReachable ? torTooltipShort : torTooltipLong
1250
- }`
1280
+ torReachable ? torTooltipShort : torTooltipLong
1281
+ }`
1251
1282
 
1252
1283
  // Show success message
1253
1284
  showToast(
@@ -1257,30 +1288,34 @@ async function handleTorToggle(checkbox, torReachable) {
1257
1288
 
1258
1289
  // Poll service status to update UI
1259
1290
  await pollServiceStatus()
1260
- } else {
1291
+ }
1292
+ else {
1261
1293
  throw new Error(result.message || "Failed to toggle Tor")
1262
1294
  }
1263
- } catch (error) {
1295
+ }
1296
+ catch (error) {
1264
1297
  console.error("Error toggling Tor:", error)
1265
1298
  // Revert checkbox state on error
1266
1299
  checkbox.checked = !enable
1267
1300
  label.textContent = originalText
1268
1301
  showToast(`Failed to toggle Tor: ${error.message}`, "error")
1269
- } finally {
1302
+ }
1303
+ finally {
1270
1304
  checkbox.disabled = false
1271
1305
  }
1272
1306
  }
1273
1307
 
1274
1308
  if (!enable) {
1275
1309
  showConfirmModal(
1276
- "<div>If Tor is disabled or fails to enable, your Taproot Assets node will only be able to initiate outbound connections to other nodes.</div>" +
1277
- "<div style='margin-top: 5px;'>Other nodes will not be able to connect to your node, and your node cannot be shared for inbound connections.</div>",
1310
+ "<div>If Tor is disabled or fails to enable, your Taproot Assets node will only be able to initiate outbound connections to other nodes.</div>"
1311
+ + "<div style='margin-top: 5px;'>Other nodes will not be able to connect to your node, and your node cannot be shared for inbound connections.</div>",
1278
1312
  executeToggle,
1279
1313
  () => {
1280
1314
  checkbox.checked = true
1281
1315
  },
1282
1316
  )
1283
- } else {
1317
+ }
1318
+ else {
1284
1319
  await executeToggle()
1285
1320
  }
1286
1321
  }
@@ -18,5 +18,6 @@
18
18
  "officialRgbPeerHost": "CHANGE_ME_MAINNET_RGB_HOST:9736",
19
19
  "officialUniverseServer": "CHANGE_ME_MAINNET_UNIVERSE_HOST:10009",
20
20
  "priceOracle": "grpc-oracle.lnfi.network",
21
- "rgbProxy": "rpc://CHANGE_ME_MAINNET_RGB_PROXY_HOST:5000/json-rpc"
21
+ "rgbProxy": "rpc://CHANGE_ME_MAINNET_RGB_PROXY_HOST:5000/json-rpc",
22
+ "rgbPriceServer": "https://api-oracle.lnfi.network"
22
23
  }
@@ -8,15 +8,15 @@
8
8
  "bitcoindZmqRawTx": "tcp://regtest.lnfi.network:28335",
9
9
  "network": "regtest",
10
10
  "nostrRelays": [
11
- "wss://relay.snort.social",
12
- "wss://relay01.lnfi.network"
11
+ "wss://relay01.lnfi.network","wss://vault.iris.to"
13
12
  ],
14
13
  "officialLndPeer": "03b24a4bf911ffd26ac1d5e5f2440a3c2f6974e4cc85d2ef54e17ee6d3717433d3",
15
- "officialLndPeerHost": "34.84.66.29:7739",
14
+ "officialLndPeerHost": "34.84.69.164:7739",
16
15
  "officialNostrPubKey": "npub1me48869w43j30cfry9ayz9dsdl4gj54xppgk9krrv7g6hsq7psuqp3yusn",
17
16
  "officialRgbPeer": "03b7153e278882e48e690acd0743305cbada86b131ab3388ccd782b45b02f064ef",
18
17
  "officialRgbPeerHost": "regtest.lnfi.network:9736",
19
18
  "officialUniverseServer": "regtest.lnfi.network:10009",
20
19
  "priceOracle": "grpc-oracle.lnfi.network",
21
- "rgbProxy": "rpc://regtest.lnfi.network:5000/json-rpc"
20
+ "rgbProxy": "rpc://regtest.lnfi.network:5000/json-rpc",
21
+ "rgbPriceServer": "https://api-oracle.lnfi.network"
22
22
  }
@@ -18,5 +18,6 @@
18
18
  "officialRgbPeerHost": "CHANGE_ME_TESTNET_RGB_HOST:9736",
19
19
  "officialUniverseServer": "CHANGE_ME_TESTNET_UNIVERSE_HOST:10009",
20
20
  "priceOracle": "grpc-oracle.lnfi.network",
21
- "rgbProxy": "rpc://CHANGE_ME_TESTNET_RGB_PROXY_HOST:5000/json-rpc"
21
+ "rgbProxy": "rpc://CHANGE_ME_TESTNET_RGB_PROXY_HOST:5000/json-rpc",
22
+ "rgbPriceServer": "https://api-oracle.lnfi.network"
22
23
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lnlink-server",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -12,7 +12,7 @@
12
12
  "build": "node build.js && node build.js --mode development --external all --entry electron",
13
13
  "start:bin": "node scripts/start-bin.js",
14
14
  "start:docker:dev": "dotenv -e .env.dev -- docker compose -f ./docker-compose.dev.yml up --build",
15
- "start:dev": "dotenv -e .env.dev -- sh -c \"prisma generate && (prisma migrate dev --name auto_update || prisma db push) && clinic heapprof -- node ./app.js\"",
15
+ "start:dev": "dotenv -e .env.dev -- sh -c \"prisma generate && (prisma migrate dev --name auto_update || prisma db push) && node ./app.js\"",
16
16
  "start:regtest": "docker compose --env-file ./.env.regtest -f ./docker-compose-lnlink.yml up --build",
17
17
  "start:testnet": "docker compose --env-file ./.env.testnet -f ./docker-compose-lnlink.yml up --build",
18
18
  "start:mainnet": "docker compose --env-file ./.env.mainnet -f ./docker-compose-lnlink.yml up --build",