mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-13 19:16:52 +01:00
FIX: Lndhub lacked timeouts
This commit is contained in:
parent
ec027a12df
commit
a6306c53d8
3 changed files with 376 additions and 268 deletions
|
@ -1,6 +1,7 @@
|
|||
import bolt11 from 'bolt11';
|
||||
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
||||
import { LegacyWallet } from './legacy-wallet';
|
||||
import loc from '../../loc';
|
||||
|
||||
export class LightningCustodianWallet extends LegacyWallet {
|
||||
static readonly type = 'lightningCustodianWallet';
|
||||
|
@ -95,48 +96,64 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
}
|
||||
|
||||
async createAccount(isTest: boolean = false) {
|
||||
const response = await fetch(this.baseURI + '/create', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ partnerid: 'bluewallet', accounttype: (isTest && 'test') || 'common' }),
|
||||
headers: { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' },
|
||||
});
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
}
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/create', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ partnerid: 'bluewallet', accounttype: (isTest && 'test') || 'common' }),
|
||||
headers: { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' },
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + (json.message ? json.message : json.error) + ' (code ' + json.code + ')');
|
||||
}
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + (json.message ? json.message : json.error) + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.login || !json.password) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
if (!json.login || !json.password) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
this.secret = 'lndhub://' + json.login + ':' + json.password;
|
||||
this.secret = 'lndhub://' + json.login + ':' + json.password;
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
}
|
||||
|
||||
async payInvoice(invoice: string, freeAmount: number = 0) {
|
||||
const response = await fetch(this.baseURI + '/payinvoice', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ invoice, amount: freeAmount }),
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/payinvoice', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ invoice, amount: freeAmount }),
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
this.last_paid_invoice_result = json;
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
this.last_paid_invoice_result = json;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,47 +164,56 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
async getUserInvoices(limit: number | false = false) {
|
||||
let limitString = '';
|
||||
if (limit) limitString = '?limit=' + parseInt(limit as unknown as string, 10);
|
||||
const response = await fetch(this.baseURI + '/getuserinvoices' + limitString, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
}
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/getuserinvoices' + limitString, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (limit) {
|
||||
// need to merge existing invoices with the ones that arrived
|
||||
// but the ones received later should overwrite older ones
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
for (const oldInvoice of this.user_invoices_raw) {
|
||||
// iterate all OLD invoices
|
||||
let found = false;
|
||||
for (const newInvoice of json) {
|
||||
// iterate all NEW invoices
|
||||
if (newInvoice.payment_request === oldInvoice.payment_request) found = true;
|
||||
}
|
||||
if (limit) {
|
||||
// need to merge existing invoices with the ones that arrived
|
||||
// but the ones received later should overwrite older ones
|
||||
|
||||
if (!found) {
|
||||
// if old invoice is not found in NEW array, we simply add it:
|
||||
json.push(oldInvoice);
|
||||
for (const oldInvoice of this.user_invoices_raw) {
|
||||
// iterate all OLD invoices
|
||||
let found = false;
|
||||
for (const newInvoice of json) {
|
||||
// iterate all NEW invoices
|
||||
if (newInvoice.payment_request === oldInvoice.payment_request) found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// if old invoice is not found in NEW array, we simply add it:
|
||||
json.push(oldInvoice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.user_invoices_raw = json.sort(function (a: { timestamp: number }, b: { timestamp: number }) {
|
||||
return a.timestamp - b.timestamp;
|
||||
});
|
||||
|
||||
return this.user_invoices_raw;
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
this.user_invoices_raw = json.sort(function (a: { timestamp: number }, b: { timestamp: number }) {
|
||||
return a.timestamp - b.timestamp;
|
||||
});
|
||||
|
||||
return this.user_invoices_raw;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,29 +235,38 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
}
|
||||
|
||||
async addInvoice(amt: number, memo: string) {
|
||||
const response = await fetch(this.baseURI + '/addinvoice', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ amt: amt + '', memo }),
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
}
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/addinvoice', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ amt: amt + '', memo }),
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (!json.r_hash || !json.pay_req) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
return json.pay_req;
|
||||
if (!json.r_hash || !json.pay_req) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
return json.pay_req;
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,29 +284,37 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
login = this.secret.replace('lndhub://', '').split(':')[0];
|
||||
password = this.secret.replace('lndhub://', '').split(':')[1];
|
||||
}
|
||||
const response = await fetch(this.baseURI + '/auth?type=auth', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ login, password }),
|
||||
headers: { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' },
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/auth?type=auth', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ login, password }),
|
||||
headers: { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' },
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.access_token || !json.refresh_token) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
this.refresh_token = json.refresh_token;
|
||||
this.access_token = json.access_token;
|
||||
this._refresh_token_created_ts = +new Date();
|
||||
this._access_token_created_ts = +new Date();
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.access_token || !json.refresh_token) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
this.refresh_token = json.refresh_token;
|
||||
this.access_token = json.access_token;
|
||||
this._refresh_token_created_ts = +new Date();
|
||||
this._access_token_created_ts = +new Date();
|
||||
}
|
||||
|
||||
async checkLogin() {
|
||||
|
@ -297,54 +340,70 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
}
|
||||
|
||||
async refreshAcessToken() {
|
||||
const response = await fetch(this.baseURI + '/auth?type=refresh_token', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ refresh_token: this.refresh_token }),
|
||||
headers: { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' },
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/auth?type=refresh_token', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ refresh_token: this.refresh_token }),
|
||||
headers: { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' },
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.access_token || !json.refresh_token) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
this.refresh_token = json.refresh_token;
|
||||
this.access_token = json.access_token;
|
||||
this._refresh_token_created_ts = +new Date();
|
||||
this._access_token_created_ts = +new Date();
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.access_token || !json.refresh_token) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
this.refresh_token = json.refresh_token;
|
||||
this.access_token = json.access_token;
|
||||
this._refresh_token_created_ts = +new Date();
|
||||
this._access_token_created_ts = +new Date();
|
||||
}
|
||||
|
||||
async fetchBtcAddress() {
|
||||
const response = await fetch(this.baseURI + '/getbtc', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/getbtc', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
}
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
this.refill_addressess = [];
|
||||
this.refill_addressess = [];
|
||||
|
||||
for (const arr of json) {
|
||||
this.refill_addressess.push(arr.address);
|
||||
for (const arr of json) {
|
||||
this.refill_addressess.push(arr.address);
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,25 +464,33 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
}
|
||||
|
||||
async fetchPendingTransactions() {
|
||||
const response = await fetch(this.baseURI + '/getpending', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/getpending', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
this.pending_transactions_raw = json;
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
this.pending_transactions_raw = json;
|
||||
}
|
||||
|
||||
async fetchTransactions() {
|
||||
|
@ -434,30 +501,38 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
queryRes += '?limit=' + limit;
|
||||
queryRes += '&offset=' + offset;
|
||||
|
||||
const response = await fetch(this.baseURI + '/gettxs' + queryRes, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/gettxs' + queryRes, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!Array.isArray(json)) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
this._lastTxFetch = +new Date();
|
||||
this.transactions_raw = json;
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!Array.isArray(json)) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
this._lastTxFetch = +new Date();
|
||||
this.transactions_raw = json;
|
||||
}
|
||||
|
||||
getBalance() {
|
||||
|
@ -467,34 +542,42 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
async fetchBalance(noRetry?: boolean): Promise<void> {
|
||||
await this.checkLogin();
|
||||
|
||||
const response = await fetch(this.baseURI + '/balance', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/balance', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
if (json.code * 1 === 1 && !noRetry) {
|
||||
await this.authorize();
|
||||
return this.fetchBalance(true);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.BTC || typeof json.BTC.AvailableBalance === 'undefined') {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
if (json.error) {
|
||||
if (json.code * 1 === 1 && !noRetry) {
|
||||
await this.authorize();
|
||||
return this.fetchBalance(true);
|
||||
}
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
this.balance = json.BTC.AvailableBalance;
|
||||
this._lastBalanceFetch = +new Date();
|
||||
if (!json.BTC || typeof json.BTC.AvailableBalance === 'undefined') {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
this.balance = json.BTC.AvailableBalance;
|
||||
this._lastBalanceFetch = +new Date();
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -556,50 +639,66 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
}
|
||||
|
||||
async fetchInfo() {
|
||||
const response = await fetch(this.baseURI + '/getinfo', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/getinfo', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
}
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.identity_pubkey) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
if (!json.identity_pubkey) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
}
|
||||
|
||||
static async isValidNodeAddress(address: string): Promise<boolean> {
|
||||
const normalizedAddress = new URL('/getinfo', address.replace(/([^:]\/)\/+/g, '$1'));
|
||||
|
||||
const response = await fetch(normalizedAddress.toString(), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(normalizedAddress.toString(), {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.code && json.code !== 1) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.code && json.code !== 1) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
allowReceive() {
|
||||
|
@ -629,29 +728,37 @@ export class LightningCustodianWallet extends LegacyWallet {
|
|||
async decodeInvoiceRemote(invoice: string) {
|
||||
await this.checkLogin();
|
||||
|
||||
const response = await fetch(this.baseURI + '/decodeinvoice?invoice=' + invoice, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
});
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(() => controller.abort(), 10000);
|
||||
try {
|
||||
const response = await fetch(this.baseURI + '/decodeinvoice?invoice=' + invoice, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer' + ' ' + this.access_token,
|
||||
},
|
||||
signal: controller.signal,
|
||||
});
|
||||
clearTimeout(id);
|
||||
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error('API failure: ' + response.statusText);
|
||||
const json = await response.json();
|
||||
if (!json) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.payment_hash) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
return (this.decoded_invoice_raw = json);
|
||||
} catch (err) {
|
||||
throw new Error(loc.lnd.errorServerUnreachable);
|
||||
}
|
||||
|
||||
if (json.error) {
|
||||
throw new Error('API error: ' + json.message + ' (code ' + json.code + ')');
|
||||
}
|
||||
|
||||
if (!json.payment_hash) {
|
||||
throw new Error('API unexpected response: ' + JSON.stringify(json));
|
||||
}
|
||||
|
||||
return (this.decoded_invoice_raw = json);
|
||||
}
|
||||
|
||||
weOwnTransaction(txid: string) {
|
||||
|
|
|
@ -3,13 +3,13 @@ import DefaultPreference from 'react-native-default-preference';
|
|||
import { BlueApp } from '../class';
|
||||
import { GROUP_IO_BLUEWALLET } from '../blue_modules/currency';
|
||||
|
||||
// Function to get the value from DefaultPreference first, then fallback to AsyncStorage
|
||||
// Function to get the value from DefaultPreference first, then fallback to AsyncStorage
|
||||
// as DefaultPreference uses truly native storage.
|
||||
// If found in AsyncStorage, migrate it to DefaultPreference and remove it from AsyncStorage.
|
||||
export const getLNDHub = async (): Promise<string | undefined> => {
|
||||
try {
|
||||
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
|
||||
let value = await DefaultPreference.get(BlueApp.LNDHUB) as string | null;
|
||||
let value = (await DefaultPreference.get(BlueApp.LNDHUB)) as string | null;
|
||||
|
||||
// If not found, check AsyncStorage and migrate it to DefaultPreference
|
||||
if (!value) {
|
||||
|
@ -46,4 +46,4 @@ export const clearLNDHub = async (): Promise<void> => {
|
|||
} catch (error) {
|
||||
console.error('Error clearing LNDHub preference:', error);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
},
|
||||
"lnd": {
|
||||
"errorInvoiceExpired": "Invoice expired.",
|
||||
"errorServerUnreachable": "Unable to connect to the server. Please check your internet connection or try again.",
|
||||
"expired": "Expired",
|
||||
"expiresIn": "Expires in {time} minutes",
|
||||
"payButton": "Pay",
|
||||
|
|
Loading…
Add table
Reference in a new issue