fix: enable @react-native-community eslint plugin and fix all the errors

This commit is contained in:
Ivan Vershigora 2023-07-25 14:50:04 +01:00
parent 4b48bb5a00
commit 7a6aa679fe
No known key found for this signature in database
GPG Key ID: DCCF7FB5ED2CEBD7
85 changed files with 386 additions and 370 deletions

View File

@ -11,7 +11,7 @@
"plugin:react-hooks/recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
// "@react-native-community", // TODO: try to enable
"@react-native-community",
"plugin:prettier/recommended" // removes all eslint rules that can mess up with prettier
],
"rules": {

9
App.js
View File

@ -16,9 +16,10 @@ import {
} from 'react-native';
import { NavigationContainer, CommonActions } from '@react-navigation/native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { navigationRef } from './NavigationService';
import * as NavigationService from './NavigationService';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { Chain } from './models/bitcoinUnits';
import OnAppLaunch from './class/on-app-launch';
import DeeplinkSchemaMatch from './class/deeplink-schema-match';
@ -153,7 +154,7 @@ const App = () => {
const popInitialAction = async data => {
if (data) {
const wallet = wallets.find(wallet => wallet.getID() === data.userInfo.url.split('wallet/')[1]);
const wallet = wallets.find(w => w.getID() === data.userInfo.url.split('wallet/')[1]);
NavigationService.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',
@ -174,7 +175,7 @@ const App = () => {
const isViewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
if (!isViewAllWalletsEnabled) {
const selectedDefaultWallet = await OnAppLaunch.getSelectedDefaultWallet();
const wallet = wallets.find(wallet => wallet.getID() === selectedDefaultWallet.getID());
const wallet = wallets.find(w => w.getID() === selectedDefaultWallet.getID());
if (wallet) {
NavigationService.dispatch(
CommonActions.navigate({
@ -193,7 +194,7 @@ const App = () => {
};
const walletQuickActions = data => {
const wallet = wallets.find(wallet => wallet.getID() === data.userInfo.url.split('wallet/')[1]);
const wallet = wallets.find(w => w.getID() === data.userInfo.url.split('wallet/')[1]);
NavigationService.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',

View File

@ -33,7 +33,7 @@ let usedBucketNum = false;
let savingInProgress = 0; // its both a flag and a counter of attempts to write to disk
const prompt = require('./helpers/prompt');
const currency = require('./blue_modules/currency');
const BlueElectrum = require('./blue_modules/BlueElectrum'); // eslint-disable-line @typescript-eslint/no-unused-vars
const BlueElectrum = require('./blue_modules/BlueElectrum');
BlueElectrum.connectMain();
class AppStorage {
@ -399,8 +399,8 @@ class AppStorage {
let lndhub = false;
try {
lndhub = await AsyncStorage.getItem(AppStorage.LNDHUB);
} catch (Error) {
console.warn(Error);
} catch (error) {
console.warn(error);
}
if (unserializedWallet.baseURI) {
@ -543,7 +543,7 @@ class AppStorage {
{
walletid: id,
internal: false,
index: parseInt(index),
index: parseInt(index, 10),
tx: JSON.stringify(tx),
},
Realm.UpdateMode.Modified,
@ -559,7 +559,7 @@ class AppStorage {
{
walletid: id,
internal: true,
index: parseInt(index),
index: parseInt(index, 10),
tx: JSON.stringify(tx),
},
Realm.UpdateMode.Modified,

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useCallback, useMemo } from 'react';
import { createNativeStackNavigator } from 'react-native-screens/native-stack';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { Platform, useWindowDimensions, Dimensions, I18nManager } from 'react-native';
@ -340,23 +340,25 @@ const ReorderWalletsStackRoot = () => {
};
const Drawer = createDrawerNavigator();
function DrawerRoot() {
const DrawerRoot = () => {
const dimensions = useWindowDimensions();
const isLargeScreen =
Platform.OS === 'android' ? isTablet() : (dimensions.width >= Dimensions.get('screen').width / 2 && isTablet()) || isDesktop;
const drawerStyle = { width: isLargeScreen ? 320 : '0%' };
const isLargeScreen = useMemo(() => {
return Platform.OS === 'android' ? isTablet() : (dimensions.width >= Dimensions.get('screen').width / 2 && isTablet()) || isDesktop;
}, [dimensions.width]);
const drawerStyle = useMemo(() => ({ width: isLargeScreen ? 320 : '0%' }), [isLargeScreen]);
const drawerContent = useCallback(props => (isLargeScreen ? <DrawerList {...props} /> : null), [isLargeScreen]);
return (
<Drawer.Navigator
drawerStyle={drawerStyle}
drawerType={isLargeScreen ? 'permanent' : null}
drawerContent={props => (isLargeScreen ? <DrawerList {...props} /> : null)}
drawerContent={drawerContent}
drawerPosition={I18nManager.isRTL ? 'right' : 'left'}
>
<Drawer.Screen name="Navigation" component={Navigation} options={{ headerShown: false, gestureEnabled: false }} />
</Drawer.Navigator>
);
}
};
const ReceiveDetailsStack = createNativeStackNavigator();
const ReceiveDetailsStackRoot = () => {

View File

@ -1,4 +1,3 @@
/* eslint-disable no-unused-expressions */
import * as React from 'react';
export const navigationRef = React.createRef();

View File

@ -44,17 +44,16 @@ const UnlockWith = () => {
const colorScheme = useColorScheme();
const initialRender = async () => {
let biometricType = false;
let bt = false;
if (await Biometric.isBiometricUseCapableAndEnabled()) {
biometricType = await Biometric.biometricType();
bt = await Biometric.biometricType();
}
setBiometricType(biometricType);
setBiometricType(bt);
};
useEffect(() => {
initialRender();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const successfullyAuthenticated = () => {

View File

@ -67,7 +67,6 @@ function WatchConnectivity() {
console.log(e);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [preferredFiatCurrency, walletsInitialized, isReachable, isInstalled]);
const handleMessages = (message, reply) => {
@ -159,7 +158,7 @@ function WatchConnectivity() {
type = 'pendingConfirmation';
} else if (transaction.type === 'user_invoice' || transaction.type === 'payment_request') {
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const now = (currentDate.getTime() / 1000) | 0; // eslint-disable-line no-bitwise
const invoiceExpiration = transaction.timestamp + transaction.expire_time;
if (invoiceExpiration > now) {
@ -179,7 +178,7 @@ function WatchConnectivity() {
if (transaction.type === 'user_invoice' || transaction.type === 'payment_request') {
amount = isNaN(transaction.value) ? '0' : amount;
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const now = (currentDate.getTime() / 1000) | 0; // eslint-disable-line no-bitwise
const invoiceExpiration = transaction.timestamp + transaction.expire_time;
if (invoiceExpiration > now) {

View File

@ -43,7 +43,7 @@ export type ElectrumTransaction = {
type MempoolTransaction = {
height: 0;
tx_hash: string; // eslint-disable-line camelcase
tx_hash: string;
fee: number;
};
@ -67,7 +67,7 @@ export function multiGetTransactionByTxid(txIds: string[], batchsize: number, ve
export type MultiGetBalanceResponse = {
balance: number;
unconfirmed_balance: number; // eslint-disable-line camelcase
unconfirmed_balance: number;
addresses: Record<string, { confirmed: number; unconfirmed: number }>;
};
@ -80,7 +80,7 @@ export function getMempoolTransactionsByAddress(address: string): Promise<Mempoo
export function estimateCurrentBlockheight(): number;
export type ElectrumHistory = {
tx_hash: string; // eslint-disable-line camelcase
tx_hash: string;
height: number;
address: string;
};

View File

@ -72,18 +72,18 @@ let latestBlockheightTimestamp = false;
const txhashHeightCache = {};
async function isDisabled() {
let isDisabled;
let result;
try {
const savedValue = await AsyncStorage.getItem(ELECTRUM_CONNECTION_DISABLED);
if (savedValue === null) {
isDisabled = false;
result = false;
} else {
isDisabled = savedValue;
result = savedValue;
}
} catch {
isDisabled = false;
result = false;
}
return !!isDisabled;
return !!result;
}
async function setDisabled(disabled = true) {
@ -306,7 +306,7 @@ async function getSavedPeer() {
*
* @returns {Promise<{tcp: number, host: string}>}
*/
// eslint-disable-next-line
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async function getRandomDynamicPeer() {
try {
let peers = JSON.parse(await AsyncStorage.getItem(storageKey));
@ -676,8 +676,8 @@ module.exports.multiGetTransactionByTxid = async function (txids, batchsize, ver
let tx = await mainClient.blockchainTransaction_get(txid, false);
tx = txhexToElectrumTransaction(tx);
results.push({ result: tx, param: txid });
} catch (_) {
console.log(_);
} catch (error) {
console.log(error);
}
}
} else {
@ -692,8 +692,8 @@ module.exports.multiGetTransactionByTxid = async function (txids, batchsize, ver
tx = txhexToElectrumTransaction(tx);
}
results.push({ result: tx, param: txid });
} catch (_) {
console.log(_);
} catch (error) {
console.log(error);
}
}
}

View File

@ -97,7 +97,7 @@ async function updateExchangeRate() {
} catch (Err) {
console.log('Error encountered when attempting to update exchange rate...');
console.warn(Err.message);
const rate = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
rate = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
rate.LAST_UPDATED_ERROR = true;
exchangeRates.LAST_UPDATED_ERROR = true;
await AsyncStorage.setItem(EXCHANGE_RATES_STORAGE_KEY, JSON.stringify(rate));

View File

@ -21,19 +21,19 @@ export async function setIsTorDaemonDisabled(disabled: boolean = true): Promise<
}
export async function isTorDaemonDisabled(): Promise<boolean> {
let isTorDaemonDisabled: boolean;
let result: boolean;
try {
const savedValue = await AsyncStorage.getItem(IS_TOR_DAEMON_DISABLED);
if (savedValue === null) {
isTorDaemonDisabled = false;
result = false;
} else {
isTorDaemonDisabled = savedValue === '1';
result = savedValue === '1';
}
} catch {
isTorDaemonDisabled = true;
result = true;
}
return isTorDaemonDisabled;
return result;
}
export const isHandset: boolean = getDeviceType() === 'Handset';

View File

@ -185,8 +185,8 @@ const showFilePickerAndReadFile = async function () {
if (res?.type === DocumentPicker.types.images || res?.type?.startsWith('image/')) {
return new Promise(resolve => {
const uri = res.uri.toString().replace('file://', '');
LocalQRCode.decode(decodeURI(uri), (error, result) => {
const uri2 = res.uri.toString().replace('file://', '');
LocalQRCode.decode(decodeURI(uri2), (error, result) => {
if (!error) {
resolve({ data: result, uri: decodeURI(res.uri) });
} else {

View File

@ -69,7 +69,7 @@ function Notifications(props) {
// if user is staring at the app when he receives the notification we process it instantly
// so app refetches related wallet
if (payload.foreground) props.onProcessNotifications(); // eslint-disable-line react/prop-types
if (payload.foreground) props.onProcessNotifications();
},
// (optional) Called when Registered Action is pressed and invokeApp is false, if true onNotification will be called (Android)

View File

@ -1,4 +1,3 @@
/* eslint-disable react/prop-types */
import React, { createContext, useEffect, useState } from 'react';
import { Alert } from 'react-native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
@ -108,8 +107,8 @@ export const BlueStorageProvider = ({ children }) => {
setWallets(BlueApp.getWallets());
};
const setWalletsWithNewOrder = wallets => {
BlueApp.wallets = wallets;
const setWalletsWithNewOrder = wlts => {
BlueApp.wallets = wlts;
saveToDisk();
};

View File

@ -1,5 +1,5 @@
import Frisbee from 'frisbee';
import url from 'url';
import URL from 'url';
export default class Azteco {
/**
@ -29,7 +29,7 @@ export default class Azteco {
}
static getParamsFromUrl(u) {
const urlObject = url.parse(u, true); // eslint-disable-line n/no-deprecated-api
const urlObject = URL.parse(u, true); // eslint-disable-line n/no-deprecated-api
return {
uri: u,
c1: urlObject.query.c1,

View File

@ -1,7 +1,7 @@
import { LightningCustodianWallet, WatchOnlyWallet } from './';
import AsyncStorage from '@react-native-async-storage/async-storage';
import RNFS from 'react-native-fs';
import url from 'url';
import URL from 'url';
import { Chain } from '../models/bitcoinUnits';
import Lnurl from './lnurl';
import Azteco from './azteco';
@ -186,7 +186,7 @@ class DeeplinkSchemaMatch {
},
]);
} else {
const urlObject = url.parse(event.url, true); // eslint-disable-line n/no-deprecated-api
const urlObject = URL.parse(event.url, true); // eslint-disable-line n/no-deprecated-api
(async () => {
if (urlObject.protocol === 'bluewallet:' || urlObject.protocol === 'lapp:' || urlObject.protocol === 'blue:') {
switch (urlObject.host) {
@ -380,15 +380,15 @@ class DeeplinkSchemaMatch {
static isBothBitcoinAndLightning(url) {
if (url.includes('lightning') && (url.includes('bitcoin') || url.includes('BITCOIN'))) {
const txInfo = url.split(/(bitcoin:\/\/|BITCOIN:\/\/|bitcoin:|BITCOIN:|lightning:|lightning=|bitcoin=)+/);
let bitcoin;
let btc;
let lndInvoice;
for (const [index, value] of txInfo.entries()) {
try {
// Inside try-catch. We dont wan't to crash in case of an out-of-bounds error.
if (value.startsWith('bitcoin') || value.startsWith('BITCOIN')) {
bitcoin = `bitcoin:${txInfo[index + 1]}`;
if (!DeeplinkSchemaMatch.isBitcoinAddress(bitcoin)) {
bitcoin = false;
btc = `bitcoin:${txInfo[index + 1]}`;
if (!DeeplinkSchemaMatch.isBitcoinAddress(btc)) {
btc = false;
break;
}
} else if (value.startsWith('lightning')) {
@ -402,10 +402,10 @@ class DeeplinkSchemaMatch {
} catch (e) {
console.log(e);
}
if (bitcoin && lndInvoice) break;
if (btc && lndInvoice) break;
}
if (bitcoin && lndInvoice) {
return { bitcoin, lndInvoice };
if (btc && lndInvoice) {
return { bitcoin: btc, lndInvoice };
} else {
return undefined;
}

View File

@ -117,7 +117,7 @@ export default class Lnurl {
if (!decoded.expiry) decoded.expiry = '3600'; // default
if (parseInt(decoded.num_satoshis) === 0 && decoded.num_millisatoshis > 0) {
if (parseInt(decoded.num_satoshis, 10) === 0 && decoded.num_millisatoshis > 0) {
decoded.num_satoshis = (decoded.num_millisatoshis / 1000).toString();
}
@ -154,7 +154,7 @@ export default class Lnurl {
if (metadataHash !== decoded.description_hash) {
throw new Error(`Invoice description_hash doesn't match metadata.`);
}
if (parseInt(decoded.num_satoshis) !== Math.round(amountSat)) {
if (parseInt(decoded.num_satoshis, 10) !== Math.round(amountSat)) {
throw new Error(`Invoice doesn't match specified amount, got ${decoded.num_satoshis}, expected ${Math.round(amountSat)}`);
}
@ -286,15 +286,15 @@ export default class Lnurl {
}
getCommentAllowed() {
return this?._lnurlPayServicePayload?.commentAllowed ? parseInt(this._lnurlPayServicePayload.commentAllowed) : false;
return this?._lnurlPayServicePayload?.commentAllowed ? parseInt(this._lnurlPayServicePayload.commentAllowed, 10) : false;
}
getMin() {
return this?._lnurlPayServicePayload?.min ? parseInt(this._lnurlPayServicePayload.min) : false;
return this?._lnurlPayServicePayload?.min ? parseInt(this._lnurlPayServicePayload.min, 10) : false;
}
getMax() {
return this?._lnurlPayServicePayload?.max ? parseInt(this._lnurlPayServicePayload.max) : false;
return this?._lnurlPayServicePayload?.max ? parseInt(this._lnurlPayServicePayload.max, 10) : false;
}
getAmount() {

View File

@ -29,7 +29,6 @@ export default class WalletGradient {
static ldkWallet = ['#8584FF', '#5351FB'];
static createWallet = () => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const { colors } = useTheme();
return colors.lightButton;
};

View File

@ -188,8 +188,8 @@ const startImport = (importTextOrig, askPassphrase = false, searchAccounts = fal
if (hd2.validateMnemonic()) {
let walletFound = false;
// by default we don't try all the paths and options
const paths = searchAccounts ? bip39WalletFormats : bip39WalletFormatsBlueWallet;
for (const i of paths) {
const searchPaths = searchAccounts ? bip39WalletFormats : bip39WalletFormatsBlueWallet;
for (const i of searchPaths) {
// we need to skip m/0' p2pkh from default scan list. It could be a BRD wallet and will be handled later
if (i.derivation_path === "m/0'" && i.script_type === 'p2pkh') continue;
let paths;

View File

@ -1482,8 +1482,8 @@ export class AbstractHDElectrumWallet extends AbstractHDWallet {
}
getBIP47NotificationAddress(): string {
const bip47 = this.getBIP47FromSeed();
return bip47.getNotificationAddress();
const bip47Local = this.getBIP47FromSeed();
return bip47Local.getNotificationAddress();
}
async fetchBIP47SenderPaymentCodes(): Promise<void> {

View File

@ -16,14 +16,14 @@ export class AbstractHDWallet extends LegacyWallet {
static type = 'abstract';
static typeReadable = 'abstract';
next_free_address_index: number; // eslint-disable-line camelcase
next_free_change_address_index: number; // eslint-disable-line camelcase
internal_addresses_cache: Record<number, string>; // eslint-disable-line camelcase
external_addresses_cache: Record<number, string>; // eslint-disable-line camelcase
next_free_address_index: number;
next_free_change_address_index: number;
internal_addresses_cache: Record<number, string>;
external_addresses_cache: Record<number, string>;
_xpub: string;
usedAddresses: string[];
_address_to_wif_cache: Record<string, string>; // eslint-disable-line camelcase
gap_limit: number; // eslint-disable-line camelcase
_address_to_wif_cache: Record<string, string>;
gap_limit: number;
passphrase?: string;
_node0?: BIP32Interface;
_node1?: BIP32Interface;
@ -90,7 +90,7 @@ export class AbstractHDWallet extends LegacyWallet {
const words = newSecret.match(/[\d]{4}/g);
if (words) {
newSecret = words.map(num => wordlist[parseInt(num)]).join(' ');
newSecret = words.map(num => wordlist[parseInt(num, 10)]).join(' ');
}
}
} catch (e) {}
@ -264,14 +264,14 @@ export class AbstractHDWallet extends LegacyWallet {
// fast approach, first lets iterate over all addressess we have in cache
for (const indexStr of Object.keys(this.internal_addresses_cache)) {
const index = parseInt(indexStr);
const index = parseInt(indexStr, 10);
if (this._getInternalAddressByIndex(index) === address) {
return (this._address_to_wif_cache[address] = <string>this._getInternalWIFByIndex(index));
}
}
for (const indexStr of Object.keys(this.external_addresses_cache)) {
const index = parseInt(indexStr);
const index = parseInt(indexStr, 10);
if (this._getExternalAddressByIndex(index) === address) {
return (this._address_to_wif_cache[address] = <string>this._getExternalWIFByIndex(index));
}

View File

@ -38,7 +38,7 @@ export class AbstractWallet {
label: string;
secret: string;
balance: number;
unconfirmed_balance: number; // eslint-disable-line camelcase
unconfirmed_balance: number;
_address: string | false;
utxo: Utxo[];
_lastTxFetch: number;
@ -49,7 +49,7 @@ export class AbstractWallet {
userHasSavedExport: boolean;
_hideTransactionsInWalletsList: boolean;
_utxoMetadata: Record<string, UtxoMetadata>;
use_with_hardware_wallet: boolean; // eslint-disable-line camelcase
use_with_hardware_wallet: boolean;
masterFingerprint: number | false;
constructor() {
@ -323,7 +323,7 @@ export class AbstractWallet {
* @deprecated
* TODO: be more precise on the type
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createTx(): any {
throw Error('not implemented');
}

View File

@ -17,8 +17,8 @@ export class HDLegacyBreadwalletWallet extends HDLegacyP2PKHWallet {
static derivationPath = "m/0'";
// track address index at which wallet switched to segwit
_external_segwit_index = null; // eslint-disable-line camelcase
_internal_segwit_index = null; // eslint-disable-line camelcase
_external_segwit_index = null;
_internal_segwit_index = null;
// we need a separate function without external_addresses_cache to use in binarySearch
_calcNodeAddressByIndex(node, index, p2wpkh = false) {

View File

@ -22,8 +22,8 @@ export class LegacyWallet extends AbstractWallet {
static type = 'legacy';
static typeReadable = 'Legacy (P2PKH)';
_txs_by_external_index: Transaction[] = []; // eslint-disable-line camelcase
_txs_by_internal_index: Transaction[] = []; // eslint-disable-line camelcase
_txs_by_external_index: Transaction[] = [];
_txs_by_internal_index: Transaction[] = [];
/**
* Simple function which says that we havent tried to fetch balance
@ -116,8 +116,8 @@ export class LegacyWallet extends AbstractWallet {
this.balance = Number(balance.confirmed);
this.unconfirmed_balance = Number(balance.unconfirmed);
this._lastBalanceFetch = +new Date();
} catch (Error) {
console.warn(Error);
} catch (error) {
console.warn(error);
}
}
@ -151,8 +151,8 @@ export class LegacyWallet extends AbstractWallet {
}
this.utxo = newUtxos;
} catch (Error) {
console.warn(Error);
} catch (error) {
console.warn(error);
}
}
@ -193,8 +193,8 @@ export class LegacyWallet extends AbstractWallet {
const utxos: Utxo[] = [];
const ownedAddressesHashmap: Record<string, boolean> = {};
const address = this.getAddress();
if (address) ownedAddressesHashmap[address] = true;
const addrs = this.getAddress();
if (addrs) ownedAddressesHashmap[addrs] = true;
/**
* below copypasted from
@ -263,7 +263,7 @@ export class LegacyWallet extends AbstractWallet {
const txs: Record<
string,
{
tx_hash: string; // eslint-disable-line camelcase
tx_hash: string;
height: number;
address: string;
}
@ -322,10 +322,10 @@ export class LegacyWallet extends AbstractWallet {
for (const vin of tx.vin) {
if ('addresses' in vin && vin.addresses && vin.addresses.indexOf(address || '') !== -1) {
// this TX is related to our address
const { vin, vout, ...txRest } = tx;
const { vin: vin2, vout, ...txRest } = tx;
const clonedTx: Transaction = {
...txRest,
inputs: [...vin],
inputs: [...vin2],
outputs: [...vout],
};
@ -335,11 +335,11 @@ export class LegacyWallet extends AbstractWallet {
for (const vout of tx.vout) {
if (vout.scriptPubKey.addresses && vout.scriptPubKey.addresses.indexOf(address || '') !== -1) {
// this TX is related to our address
const { vin, vout, ...txRest } = tx;
const { vin, vout: vout2, ...txRest } = tx;
const clonedTx: Transaction = {
...txRest,
inputs: [...vin],
outputs: [...vout],
outputs: [...vout2],
};
_txsByExternalIndex.push(clonedTx);

View File

@ -156,7 +156,7 @@ export class LightningCustodianWallet extends LegacyWallet {
*/
async getUserInvoices(limit = false) {
let limitString = '';
if (limit) limitString = '?limit=' + parseInt(limit);
if (limit) limitString = '?limit=' + parseInt(limit, 10);
const response = await this._api.get('/getuserinvoices' + limitString, {
headers: {
'Access-Control-Allow-Origin': '*',
@ -386,7 +386,7 @@ export class LightningCustodianWallet extends LegacyWallet {
if (typeof tx.amt !== 'undefined' && typeof tx.fee !== 'undefined') {
// lnd tx outgoing
tx.value = parseInt((tx.amt * 1 + tx.fee * 1) * -1);
tx.value = parseInt((tx.amt * 1 + tx.fee * 1) * -1, 10);
}
if (tx.type === 'paid_invoice') {
@ -401,7 +401,7 @@ export class LightningCustodianWallet extends LegacyWallet {
if (tx.type === 'user_invoice') {
// incoming ln tx
tx.value = parseInt(tx.amt);
tx.value = parseInt(tx.amt, 10);
tx.memo = tx.description || 'Lightning invoice';
}
@ -554,7 +554,7 @@ export class LightningCustodianWallet extends LegacyWallet {
if (!decoded.expiry) decoded.expiry = '3600'; // default
if (parseInt(decoded.num_satoshis) === 0 && decoded.num_millisatoshis > 0) {
if (parseInt(decoded.num_satoshis, 10) === 0 && decoded.num_millisatoshis > 0) {
decoded.num_satoshis = (decoded.num_millisatoshis / 1000).toString();
}

View File

@ -191,7 +191,7 @@ export class LightningLdkWallet extends LightningCustodianWallet {
const ret = {
pubkey,
host: address.addr.split(':')[0],
port: parseInt(address.addr.split(':')[1]),
port: parseInt(address.addr.split(':')[1], 10),
};
this._nodeConnectionDetailsCache[pubkey] = Object.assign({}, ret, { ts: +new Date() });
@ -302,7 +302,7 @@ export class LightningLdkWallet extends LightningCustodianWallet {
// if its NOT zero amount invoice, we forcefully reset passed amount argument so underlying LDK code
// would extract amount from bolt11
if (decoded.num_satoshis && parseInt(decoded.num_satoshis) > 0) freeAmount = 0;
if (decoded.num_satoshis && parseInt(decoded.num_satoshis, 10) > 0) freeAmount = 0;
if (await this.channelsNeedReestablish()) {
await this.reestablishChannels();
@ -382,7 +382,7 @@ export class LightningLdkWallet extends LightningCustodianWallet {
if (receivedPayment.payment_hash === invoice.payment_hash) {
// match! this particular payment was paid
newInvoice.ispaid = true;
newInvoice.value = Math.floor(parseInt(receivedPayment.amt) / 1000);
newInvoice.value = Math.floor(parseInt(receivedPayment.amt, 10) / 1000);
found = true;
}
}
@ -412,14 +412,14 @@ export class LightningLdkWallet extends LightningCustodianWallet {
if (this.getReceivableBalance() < amtSat) throw new Error('You dont have enough inbound capacity');
const bolt11 = await RnLdk.addInvoice(amtSat * 1000, memo);
if (!bolt11) return false;
const paymentRequest = await RnLdk.addInvoice(amtSat * 1000, memo);
if (!paymentRequest) return false;
const decoded = this.decodeInvoice(bolt11);
const decoded = this.decodeInvoice(paymentRequest);
this._listInvoices = this._listInvoices || [];
const tx = {
payment_request: bolt11,
payment_request: paymentRequest,
ispaid: false,
timestamp: +new Date(),
expire_time: 3600 * 1000,
@ -430,7 +430,7 @@ export class LightningLdkWallet extends LightningCustodianWallet {
};
this._listInvoices.push(tx);
return bolt11;
return paymentRequest;
}
async getAddressAsync() {
@ -508,7 +508,7 @@ export class LightningLdkWallet extends LightningCustodianWallet {
if (this._listChannels) {
for (const channel of this._listChannels) {
if (!channel.is_funding_locked) continue; // pending channel
sum += Math.floor(parseInt(channel.outbound_capacity_msat) / 1000);
sum += Math.floor(parseInt(channel.outbound_capacity_msat, 10) / 1000);
}
}
@ -520,7 +520,7 @@ export class LightningLdkWallet extends LightningCustodianWallet {
if (this._listChannels) {
for (const channel of this._listChannels) {
if (!channel.is_funding_locked) continue; // pending channel
sum += Math.floor(parseInt(channel.inbound_capacity_msat) / 1000);
sum += Math.floor(parseInt(channel.inbound_capacity_msat, 10) / 1000);
}
}
return sum;
@ -542,7 +542,7 @@ export class LightningLdkWallet extends LightningCustodianWallet {
if (json && Array.isArray(json)) {
for (const utxo of json) {
if (utxo?.status?.confirmed) {
confirmedSat += parseInt(utxo.value);
confirmedSat += parseInt(utxo.value, 10);
}
}
}

View File

@ -488,8 +488,8 @@ export class MultisigHDWallet extends AbstractHDElectrumWallet {
// is it electrum json?
if (json && json.wallet_type && json.wallet_type !== 'standard') {
const mofn = json.wallet_type.split('of');
this.setM(parseInt(mofn[0].trim()));
const n = parseInt(mofn[1].trim());
this.setM(parseInt(mofn[0].trim(), 10));
const n = parseInt(mofn[1].trim(), 10);
for (let c = 1; c <= n; c++) {
const cosignerData = json['x' + c + '/'];
if (cosignerData) {
@ -523,7 +523,7 @@ export class MultisigHDWallet extends AbstractHDElectrumWallet {
break;
case 'Policy':
this.setM(parseInt(value.trim().split('of')[0].trim()));
this.setM(parseInt(value.trim().split('of')[0].trim(), 10));
break;
case 'Derivation':
@ -577,8 +577,8 @@ export class MultisigHDWallet extends AbstractHDElectrumWallet {
const s2 = json.descriptor.substr(json.descriptor.indexOf('sortedmulti(') + 12);
const s3 = s2.split(',');
const m = parseInt(s3[0]);
if (m) this.setM(m);
const M = parseInt(s3[0], 10);
if (M) this.setM(M);
for (let c = 1; c < s3.length; c++) {
const re = /\[([^\]]+)\](.*)/;

View File

@ -39,9 +39,9 @@ export const FContainer = forwardRef((props, ref) => {
const { width } = event.nativeEvent.layout;
const withPaddings = Math.ceil(width + PADDINGS * 2);
const len = React.Children.toArray(props.children).filter(Boolean).length;
let newWidth = withPaddings * len > maxWidth ? Math.floor(maxWidth / len) : withPaddings;
if (len === 1 && newWidth < 90) newWidth = 90; // to add Paddings for lonely small button, like Scan on main screen
setNewWidth(newWidth);
let newW = withPaddings * len > maxWidth ? Math.floor(maxWidth / len) : withPaddings;
if (len === 1 && newW < 90) newW = 90; // to add Paddings for lonely small button, like Scan on main screen
setNewWidth(newW);
layoutCalculated.current = true;
};

View File

@ -7,7 +7,7 @@ const ToolTipMenu = (props, ref) => {
const menuRef = useRef();
const disabled = props.disabled ?? false;
const isMenuPrimaryAction = props.isMenuPrimaryAction ?? false;
// eslint-disable-next-line react/prop-types
const buttonStyle = props.buttonStyle ?? {};
const handleToolTipSelection = selection => {
props.onPressMenuItem(selection.id);

View File

@ -43,7 +43,7 @@ const ToolTipMenu = (props, ref) => {
const previewQRCode = props.previewQRCode ?? false;
const previewValue = props.previewValue;
const disabled = props.disabled ?? false;
// eslint-disable-next-line react/prop-types
const buttonStyle = props.buttonStyle;
return isButton ? (
<ContextMenuButton

View File

@ -60,7 +60,7 @@ export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUn
item.value = '0';
}
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const now = (currentDate.getTime() / 1000) | 0; // eslint-disable-line no-bitwise
const invoiceExpiration = item.timestamp + item.expire_time;
if (invoiceExpiration > now) {
@ -83,7 +83,7 @@ export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUn
if (item.type === 'user_invoice' || item.type === 'payment_request') {
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const now = (currentDate.getTime() / 1000) | 0; // eslint-disable-line no-bitwise
const invoiceExpiration = item.timestamp + item.expire_time;
if (invoiceExpiration > now) {
@ -137,7 +137,7 @@ export const TransactionListItem = React.memo(({ item, itemPriceUnit = BitcoinUn
if (item.type === 'user_invoice' || item.type === 'payment_request') {
if (!item.ispaid) {
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const now = (currentDate.getTime() / 1000) | 0; // eslint-disable-line no-bitwise
const invoiceExpiration = item.timestamp + item.expire_time;
if (invoiceExpiration < now) {
return (

View File

@ -63,9 +63,9 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
Clipboard.setString(formatBalance(wallet.getBalance(), wallet.getPreferredBalanceUnit()).toString());
};
const updateWalletVisibility = (wallet: AbstractWallet, newHideBalance: boolean) => {
wallet.hideBalance = newHideBalance;
return wallet;
const updateWalletVisibility = (w: AbstractWallet, newHideBalance: boolean) => {
w.hideBalance = newHideBalance;
return w;
};
const handleBalanceVisibility = async () => {
@ -84,9 +84,9 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
context.saveToDisk();
};
const updateWalletWithNewUnit = (wallet: AbstractWallet, newPreferredUnit: BitcoinUnit) => {
wallet.preferredBalanceUnit = newPreferredUnit;
return wallet;
const updateWalletWithNewUnit = (w: AbstractWallet, newPreferredUnit: BitcoinUnit) => {
w.preferredBalanceUnit = newPreferredUnit;
return w;
};
const changeWalletBalanceUnit = () => {

View File

@ -257,6 +257,8 @@ const cStyles = StyleSheet.create({
},
});
const ListHeaderComponent = () => <View style={cStyles.separatorStyle} />;
const WalletsCarousel = forwardRef((props, ref) => {
const { preferredFiatCurrency, language } = useContext(BlueStorageContext);
const renderItem = useCallback(
@ -276,7 +278,6 @@ const WalletsCarousel = forwardRef((props, ref) => {
[props.horizontal, props.selectedWallet, props.handleLongPress, props.onPress, preferredFiatCurrency, language],
);
const flatListRef = useRef();
const ListHeaderComponent = () => <View style={cStyles.separatorStyle} />;
useImperativeHandle(ref, () => ({
scrollToItem: ({ item }) => {

View File

@ -29,7 +29,6 @@ const AddressTypeBadge = ({ isInternal, hasTransactions }) => {
usedText: { color: colors.alternativeTextColor },
});
// eslint-disable-next-line prettier/prettier
const badgeLabel = hasTransactions
? loc.addresses.type_used
: isInternal

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import React from 'react';
import { Image, Keyboard, TouchableOpacity, StyleSheet } from 'react-native';
import { Theme } from './themes';

View File

@ -19,7 +19,7 @@ const RateExtractors = {
} catch (e: any) {
throw new Error(`Could not update rate for ${ticker}: ${e.message}`);
}
let rate = json?.bpi?.[ticker]?.rate_float; // eslint-disable-line
let rate = json?.bpi?.[ticker]?.rate_float;
if (!rate) throw new Error(`Could not update rate for ${ticker}: data is wrong`);
rate = Number(rate);
@ -34,7 +34,7 @@ const RateExtractors = {
} catch (e: any) {
throw new Error(`Could not update rate for ${ticker}: ${e.message}`);
}
let rate = json?.bitcoin?.[ticker] || json?.bitcoin?.[ticker.toLowerCase()]; // eslint-disable-line
const rate = json?.bitcoin?.[ticker] || json?.bitcoin?.[ticker.toLowerCase()];
if (!rate) throw new Error(`Could not update rate for ${ticker}: data is wrong`);
return rate;
},
@ -115,7 +115,7 @@ const RateExtractors = {
} catch (e: any) {
throw new Error(`Could not update rate for ${ticker}: ${e.message}`);
}
let rate = json?.ticker?.buy; // eslint-disable-line
let rate = json?.ticker?.buy;
if (!rate) throw new Error(`Could not update rate for ${ticker}: data is wrong`);
rate = Number(rate);

View File

@ -64,7 +64,7 @@
"e2e:release-build": "detox build -c android.release",
"e2e:release-test": "detox test -c android.release --record-videos all --record-logs all --take-screenshots all --headless -d 200000 -R 3",
"tslint": "tsc",
"lint": "eslint --ext .js,.ts,.tsx '*.@(js|ts|tsx)' screen 'blue_modules/*.@(js|ts|tsx)' class models loc tests components && npm run tslint && node scripts/find-unused-loc.js",
"lint": " npm run tslint && node scripts/find-unused-loc.js && eslint --ext .js,.ts,.tsx '*.@(js|ts|tsx)' screen 'blue_modules/*.@(js|ts|tsx)' class models loc tests components",
"lint:fix": "npm run lint -- --fix",
"lint:quickfix": "git status --porcelain | grep -v '\\.json' | grep -E '\\.js|\\.ts' --color=never | awk '{print $2}' | xargs eslint --fix; exit 0",
"unit": "jest -b -i tests/unit/*",

View File

@ -29,7 +29,7 @@ let lastTimeTriedToPay = 0;
// this code has no use in RN, it gets copypasted in webview injected code
//
const bluewalletResponses = {};
// eslint-disable-next-line
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-var
var webln = {
enable: function () {
window.ReactNativeWebView.postMessage(JSON.stringify({ enable: true }));
@ -53,10 +53,11 @@ var webln = {
});
},
makeInvoice: function (RequestInvoiceArgs) {
var id = Math.random(); // eslint-disable-line
var id = Math.random(); // eslint-disable-line no-var
window.ReactNativeWebView.postMessage(JSON.stringify({ makeInvoice: RequestInvoiceArgs, id }));
return new Promise(function (resolve, reject) {
var interval = setInterval(function () { // eslint-disable-line
// eslint-disable-next-line no-var
var interval = setInterval(function () {
if (bluewalletResponses[id]) {
clearInterval(interval);
resolve(bluewalletResponses[id]);

View File

@ -81,8 +81,8 @@ const LdkInfo = () => {
setChannels([]);
}
if (listChannels && Array.isArray(listChannels)) {
const inactiveChannels = listChannels.filter(channel => !channel.is_usable && channel.is_funding_locked);
setInactiveChannels(inactiveChannels);
const inactive = listChannels.filter(channel => !channel.is_usable && channel.is_funding_locked);
setInactiveChannels(inactive);
} else {
setInactiveChannels([]);
}

View File

@ -71,7 +71,6 @@ const LdkOpenChannel = (props: any) => {
setVerified(true);
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [psbt]);
useEffect(() => {
@ -215,7 +214,7 @@ const LdkOpenChannel = (props: any) => {
let amountSats = fundingAmount.amountSats;
switch (newUnit) {
case BitcoinUnit.SATS:
amountSats = parseInt(fundingAmount.amount);
amountSats = parseInt(fundingAmount.amount, 10);
break;
case BitcoinUnit.BTC:
amountSats = currency.btcToSatoshi(fundingAmount.amount);
@ -238,7 +237,7 @@ const LdkOpenChannel = (props: any) => {
amountSats = currency.btcToSatoshi(currency.fiatToBTC(text));
break;
case BitcoinUnit.SATS:
amountSats = parseInt(text);
amountSats = parseInt(text, 10);
break;
}
setFundingAmount({ amount: text, amountSats });

View File

@ -152,7 +152,7 @@ const LNDCreateInvoice = () => {
let invoiceAmount = amount;
switch (unit) {
case BitcoinUnit.SATS:
invoiceAmount = parseInt(invoiceAmount); // basically nop
invoiceAmount = parseInt(invoiceAmount, 10); // basically nop
break;
case BitcoinUnit.BTC:
invoiceAmount = currency.btcToSatoshi(invoiceAmount);
@ -293,18 +293,18 @@ const LNDCreateInvoice = () => {
}
// amount that comes from lnurl is always in sats
let amount = (reply.maxWithdrawable / 1000).toString();
const sats = amount;
let newAmount = (reply.maxWithdrawable / 1000).toString();
const sats = newAmount;
switch (unit) {
case BitcoinUnit.SATS:
// nop
break;
case BitcoinUnit.BTC:
amount = currency.satoshiToBTC(amount);
newAmount = currency.satoshiToBTC(newAmount);
break;
case BitcoinUnit.LOCAL_CURRENCY:
amount = formatBalancePlain(amount, BitcoinUnit.LOCAL_CURRENCY);
AmountInput.setCachedSatoshis(amount, sats);
newAmount = formatBalancePlain(newAmount, BitcoinUnit.LOCAL_CURRENCY);
AmountInput.setCachedSatoshis(newAmount, sats);
break;
}
@ -316,7 +316,7 @@ const LNDCreateInvoice = () => {
min: (reply.minWithdrawable || 0) / 1000,
max: reply.maxWithdrawable / 1000,
});
setAmount(amount);
setAmount(newAmount);
setDescription(reply.defaultDescription);
setIsLoading(false);
} catch (Err) {

View File

@ -74,6 +74,7 @@ const LNDViewInvoice = () => {
gestureEnabled: false,
headerHideBackButton: true,
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<TouchableOpacity
accessibilityRole="button"
@ -128,7 +129,7 @@ const LNDViewInvoice = () => {
fetchAndSaveWalletTransactions(walletID);
} else {
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const now = (currentDate.getTime() / 1000) | 0; // eslint-disable-line no-bitwise
const invoiceExpiration = updatedUserInvoice.timestamp + updatedUserInvoice.expire_time;
if (invoiceExpiration < now && !updatedUserInvoice.ispaid) {
// invoice expired :-(
@ -202,7 +203,7 @@ const LNDViewInvoice = () => {
if (typeof invoice === 'object') {
const currentDate = new Date();
const now = (currentDate.getTime() / 1000) | 0;
const now = (currentDate.getTime() / 1000) | 0; // eslint-disable-line no-bitwise
const invoiceExpiration = invoice.timestamp + invoice.expire_time;
if (invoice.ispaid || invoice.type === 'paid_invoice') {
let amount = 0;

View File

@ -11,7 +11,7 @@ import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
import selectWallet from '../../helpers/select-wallet';
import url from 'url';
import URL from 'url';
import { SuccessView } from '../send/success';
const AuthState = {
@ -28,7 +28,7 @@ const LnurlAuth = () => {
const wallet = useMemo(() => wallets.find(w => w.getID() === walletID), [wallets, walletID]);
const LN = useMemo(() => new Lnurl(lnurl), [lnurl]);
const parsedLnurl = useMemo(
() => (lnurl ? url.parse(Lnurl.getUrlFromLnurl(lnurl), true) : {}), // eslint-disable-line n/no-deprecated-api
() => (lnurl ? URL.parse(Lnurl.getUrlFromLnurl(lnurl), true) : {}), // eslint-disable-line n/no-deprecated-api
[lnurl],
);
const [authState, setAuthState] = useState(AuthState.USER_PROMPT);
@ -45,7 +45,7 @@ const LnurlAuth = () => {
});
const showSelectWalletScreen = useCallback(() => {
selectWallet(navigate, name, Chain.OFFCHAIN).then(wallet => setParams({ walletID: wallet.getID() }));
selectWallet(navigate, name, Chain.OFFCHAIN).then(w => setParams({ walletID: w.getID() }));
}, [navigate, name, setParams]);
const authenticate = useCallback(() => {

View File

@ -102,8 +102,8 @@ const LnurlPay = () => {
}
}, [payload]); // eslint-disable-line react-hooks/exhaustive-deps
const onWalletSelect = wallet => {
setParams({ walletID: wallet.getID() });
const onWalletSelect = w => {
setParams({ walletID: w.getID() });
pop();
};
@ -122,7 +122,7 @@ const LnurlPay = () => {
let amountSats = amount;
switch (unit) {
case BitcoinUnit.SATS:
amountSats = parseInt(amountSats); // nop
amountSats = parseInt(amountSats, 10); // nop
break;
case BitcoinUnit.BTC:
amountSats = currency.btcToSatoshi(amountSats);

View File

@ -68,7 +68,6 @@ const ScanLndInvoice = () => {
Keyboard.removeAllListeners('keyboardDidShow');
Keyboard.removeAllListeners('keyboardDidHide');
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
@ -104,25 +103,25 @@ const ScanLndInvoice = () => {
data = data.replace('LIGHTNING:', '').replace('lightning:', '');
console.log(data);
let decoded;
let newDecoded;
try {
decoded = wallet.decodeInvoice(data);
newDecoded = wallet.decodeInvoice(data);
let expiresIn = (decoded.timestamp * 1 + decoded.expiry * 1) * 1000; // ms
if (+new Date() > expiresIn) {
expiresIn = loc.lnd.expired;
let newExpiresIn = (newDecoded.timestamp * 1 + newDecoded.expiry * 1) * 1000; // ms
if (+new Date() > newExpiresIn) {
newExpiresIn = loc.lnd.expired;
} else {
const time = Math.round((expiresIn - +new Date()) / (60 * 1000));
expiresIn = loc.formatString(loc.lnd.expiresIn, { time });
const time = Math.round((newExpiresIn - +new Date()) / (60 * 1000));
newExpiresIn = loc.formatString(loc.lnd.expiresIn, { time });
}
Keyboard.dismiss();
setParams({ uri: undefined, invoice: data });
setIsAmountInitiallyEmpty(decoded.num_satoshis === '0');
setIsAmountInitiallyEmpty(newDecoded.num_satoshis === '0');
setDestination(data);
setIsLoading(false);
setAmount(decoded.num_satoshis);
setExpiresIn(expiresIn);
setDecoded(decoded);
setAmount(newDecoded.num_satoshis);
setExpiresIn(newExpiresIn);
setDecoded(newDecoded);
} catch (Err) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
Keyboard.dismiss();
@ -178,7 +177,7 @@ const ScanLndInvoice = () => {
let amountSats = amount;
switch (unit) {
case BitcoinUnit.SATS:
amountSats = parseInt(amountSats); // nop
amountSats = parseInt(amountSats, 10); // nop
break;
case BitcoinUnit.BTC:
amountSats = currency.btcToSatoshi(amountSats);
@ -189,15 +188,15 @@ const ScanLndInvoice = () => {
}
setIsLoading(true);
const expiresIn = (decoded.timestamp * 1 + decoded.expiry * 1) * 1000; // ms
if (+new Date() > expiresIn) {
const newExpiresIn = (decoded.timestamp * 1 + decoded.expiry * 1) * 1000; // ms
if (+new Date() > newExpiresIn) {
setIsLoading(false);
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
return alert(loc.lnd.errorInvoiceExpired);
}
const currentUserInvoices = wallet.user_invoices_raw; // not fetching invoices, as we assume they were loaded previously
if (currentUserInvoices.some(invoice => invoice.payment_hash === decoded.payment_hash)) {
if (currentUserInvoices.some(i => i.payment_hash === decoded.payment_hash)) {
setIsLoading(false);
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
return alert(loc.lnd.sameWalletAsInvoiceError);

View File

@ -329,10 +329,10 @@ const ReceiveDetails = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const setAddressBIP21Encoded = address => {
const bip21encoded = DeeplinkSchemaMatch.bip21encode(address);
setParams({ address });
setBip21encoded(bip21encoded);
const setAddressBIP21Encoded = addr => {
const newBip21encoded = DeeplinkSchemaMatch.bip21encode(addr);
setParams({ address: addr });
setBip21encoded(newBip21encoded);
setShowAddress(true);
};

View File

@ -58,8 +58,8 @@ const Broadcast = () => {
const walletObj = new HDSegwitBech32Wallet();
const result = await walletObj.broadcastTx(txHex);
if (result) {
const tx = bitcoin.Transaction.fromHex(txHex);
const txid = tx.getId();
const newTx = bitcoin.Transaction.fromHex(txHex);
const txid = newTx.getId();
setTx(txid);
setBroadcastResult(BROADCAST_RESULT.success);
@ -86,8 +86,8 @@ const Broadcast = () => {
try {
// sould be base64 encoded PSBT
const tx = bitcoin.Psbt.fromBase64(scannedData).extractTransaction();
return handleUpdateTxHex(tx.toHex());
const validTx = bitcoin.Psbt.fromBase64(scannedData).extractTransaction();
return handleUpdateTxHex(validTx.toHex());
} catch (e) {}
};

View File

@ -202,8 +202,8 @@ const OutputModalContent = ({ output, wallet, onUseCoin, frozen, setFrozen }) =>
// save on form change. Because effect called on each event, debounce it.
const debouncedSaveMemo = useRef(
debounce(async memo => {
wallet.setUTXOMetadata(output.txid, output.vout, { memo });
debounce(async m => {
wallet.setUTXOMetadata(output.txid, output.vout, { memo: m });
await saveToDisk();
}, 500),
);
@ -261,14 +261,14 @@ const CoinControl = () => {
const [loading, setLoading] = useState(true);
const [selected, setSelected] = useState([]);
const [frozen, setFrozen] = useState(
utxo.filter(output => wallet.getUTXOMetadata(output.txid, output.vout).frozen).map(({ txid, vout }) => `${txid}:${vout}`),
utxo.filter(out => wallet.getUTXOMetadata(out.txid, out.vout).frozen).map(({ txid, vout }) => `${txid}:${vout}`),
);
// save frozen status. Because effect called on each event, debounce it.
const debouncedSaveFronen = useRef(
debounce(async frozen => {
debounce(async frzn => {
utxo.forEach(({ txid, vout }) => {
wallet.setUTXOMetadata(txid, vout, { frozen: frozen.includes(`${txid}:${vout}`) });
wallet.setUTXOMetadata(txid, vout, { frozen: frzn.includes(`${txid}:${vout}`) });
});
await saveToDisk();
}, 500),
@ -285,9 +285,7 @@ const CoinControl = () => {
console.log('coincontrol wallet.fetchUtxo() failed'); // either sleep expired or fetchUtxo threw an exception
}
const freshUtxo = wallet.getUtxo(true);
setFrozen(
freshUtxo.filter(output => wallet.getUTXOMetadata(output.txid, output.vout).frozen).map(({ txid, vout }) => `${txid}:${vout}`),
);
setFrozen(freshUtxo.filter(out => wallet.getUTXOMetadata(out.txid, out.vout).frozen).map(({ txid, vout }) => `${txid}:${vout}`));
setLoading(false);
})();
}, [wallet, setLoading, sleep]);
@ -321,10 +319,10 @@ const CoinControl = () => {
const handleChoose = item => setOutput(item);
const handleUseCoin = utxo => {
const handleUseCoin = u => {
setOutput(null);
navigation.pop();
onUTXOChoose(utxo);
onUTXOChoose(u);
};
const handleMassFreeze = () => {
@ -362,11 +360,11 @@ const CoinControl = () => {
selectionStarted={selectionStarted}
onSelect={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); // animate buttons show
setSelected(selected => [...selected, `${p.item.txid}:${p.item.vout}`]);
setSelected(s => [...s, `${p.item.txid}:${p.item.vout}`]);
}}
onDeSelect={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); // animate buttons show
setSelected(selected => selected.filter(i => i !== `${p.item.txid}:${p.item.vout}`));
setSelected(s => s.filter(i => i !== `${p.item.txid}:${p.item.vout}`));
}}
/>
);

View File

@ -29,7 +29,7 @@ const Confirm = () => {
const { recipients = [], walletID, fee, memo, tx, satoshiPerByte, psbt } = params;
const [isLoading, setIsLoading] = useState(false);
const [isPayjoinEnabled, setIsPayjoinEnabled] = useState(false);
const wallet = wallets.find(wallet => wallet.getID() === walletID);
const wallet = wallets.find(w => w.getID() === walletID);
const payjoinUrl = wallet.allowPayJoin() ? params.payjoinUrl : false;
const feeSatoshi = new Bignumber(fee).multipliedBy(100000000).toNumber();
const { navigate, setOptions } = useNavigation();
@ -70,6 +70,7 @@ const Confirm = () => {
useEffect(() => {
setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<TouchableOpacity
accessibilityRole="button"
@ -124,14 +125,14 @@ const Confirm = () => {
console.warn('trying TOR....');
// working through TOR - crafting custom requester that will handle TOR http request
const customPayjoinRequester = {
requestPayjoin: async function (psbt) {
console.warn('requesting payjoin with psbt:', psbt.toBase64());
requestPayjoin: async function (psbt2) {
console.warn('requesting payjoin with psbt:', psbt2.toBase64());
const api = new torrific.Torsbee();
const torResponse = await api.post(payjoinUrl, {
headers: {
'Content-Type': 'text/plain',
},
body: psbt.toBase64(),
body: psbt2.toBase64(),
});
console.warn('got torResponse.body');
if (!torResponse.body) throw new Error('TOR failure, got ' + JSON.stringify(torResponse));
@ -153,8 +154,8 @@ const Confirm = () => {
await payjoinClient.run();
const payjoinPsbt = payJoinWallet.getPayjoinPsbt();
if (payjoinPsbt) {
const tx = payjoinPsbt.extractTransaction();
txids2watch.push(tx.getId());
const tx2watch = payjoinPsbt.extractTransaction();
txids2watch.push(tx2watch.getId());
}
}
@ -186,7 +187,7 @@ const Confirm = () => {
}
};
const broadcast = async tx => {
const broadcast = async transaction => {
await BlueElectrum.ping();
await BlueElectrum.waitTillConnected();
@ -196,7 +197,7 @@ const Confirm = () => {
}
}
const result = await wallet.broadcastTx(tx);
const result = await wallet.broadcastTx(transaction);
if (!result) {
throw new Error(loc.errors.broadcast);
}

View File

@ -104,6 +104,7 @@ const SendCreate = () => {
useEffect(() => {
setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<TouchableOpacity accessibilityRole="button" onPress={exportTXN}>
<Icon size={22} name="share-alternative" type="entypo" color={colors.foregroundColor} />

View File

@ -124,31 +124,31 @@ const SendDetails = () => {
Keyboard.removeAllListeners('keyboardDidShow');
Keyboard.removeAllListeners('keyboardDidHide');
};
}, []); // eslint-disable-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
// decode route params
const currentAddress = addresses[scrollIndex.current];
if (routeParams.uri) {
try {
const { address, amount, memo, payjoinUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(routeParams.uri);
const { address, amount, memo, payjoinUrl: pjUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(routeParams.uri);
setUnits(units => {
units[scrollIndex.current] = BitcoinUnit.BTC; // also resetting current unit to BTC
return [...units];
setUnits(u => {
u[scrollIndex.current] = BitcoinUnit.BTC; // also resetting current unit to BTC
return [...u];
});
setAddresses(addresses => {
setAddresses(addrs => {
if (currentAddress) {
currentAddress.address = address;
if (Number(amount) > 0) {
currentAddress.amount = amount;
currentAddress.amountSats = currency.btcToSatoshi(amount);
}
addresses[scrollIndex.current] = currentAddress;
return [...addresses];
addrs[scrollIndex.current] = currentAddress;
return [...addrs];
} else {
return [...addresses, { address, amount, amountSats: currency.btcToSatoshi(amount), key: String(Math.random()) }];
return [...addrs, { address, amount, amountSats: currency.btcToSatoshi(amount), key: String(Math.random()) }];
}
});
@ -156,28 +156,28 @@ const SendDetails = () => {
setTransactionMemo(memo);
}
setAmountUnit(BitcoinUnit.BTC);
setPayjoinUrl(payjoinUrl);
setPayjoinUrl(pjUrl);
} catch (error) {
console.log(error);
Alert.alert(loc.errors.error, loc.send.details_error_decode);
}
} else if (routeParams.address) {
const { amount, amountSats, unit = BitcoinUnit.BTC } = routeParams;
setAddresses(addresses => {
setAddresses(addrs => {
if (currentAddress) {
currentAddress.address = routeParams.address;
addresses[scrollIndex.current] = currentAddress;
return [...addresses];
addrs[scrollIndex.current] = currentAddress;
return [...addrs];
} else {
return [...addresses, { address: routeParams.address, key: String(Math.random()), amount, amountSats }];
return [...addrs, { address: routeParams.address, key: String(Math.random()), amount, amountSats }];
}
});
if (routeParams.memo?.trim().length > 0) {
setTransactionMemo(routeParams.memo);
}
setUnits(units => {
units[scrollIndex.current] = unit;
return [...units];
setUnits(u => {
u[scrollIndex.current] = unit;
return [...u];
});
} else {
setAddresses([{ address: '', key: String(Math.random()) }]); // key is for the FlatList
@ -187,16 +187,16 @@ const SendDetails = () => {
useEffect(() => {
// check if we have a suitable wallet
const suitable = wallets.filter(wallet => wallet.chain === Chain.ONCHAIN && wallet.allowSend());
const suitable = wallets.filter(w => w.chain === Chain.ONCHAIN && w.allowSend());
if (suitable.length === 0) {
Alert.alert(loc.errors.error, loc.send.details_wallet_before_tx);
navigation.goBack();
return;
}
const wallet = (routeParams.walletID && wallets.find(w => w.getID() === routeParams.walletID)) || suitable[0];
setWallet(wallet);
setFeeUnit(wallet.getPreferredBalanceUnit());
setAmountUnit(wallet.preferredBalanceUnit); // default for whole screen
const newWallet = (routeParams.walletID && wallets.find(w => w.getID() === routeParams.walletID)) || suitable[0];
setWallet(newWallet);
setFeeUnit(newWallet.getPreferredBalanceUnit());
setAmountUnit(newWallet.preferredBalanceUnit); // default for whole screen
// we are ready!
setIsLoading(false);
@ -250,7 +250,7 @@ const SendDetails = () => {
useEffect(() => {
if (!wallet) return; // wait for it
const fees = networkTransactionFees;
const changeAddress = getChangeAddressFast();
const change = getChangeAddressFast();
const requestedSatPerByte = Number(feeRate);
const lutxo = utxo || wallet.getUtxo();
let frozen = 0;
@ -279,7 +279,7 @@ const SendDetails = () => {
targets = [{ address: transaction.address }];
break;
}
const value = parseInt(transaction.amountSats);
const value = parseInt(transaction.amountSats, 10);
if (value > 0) {
targets.push({ address: transaction.address, value });
} else if (transaction.amount) {
@ -306,7 +306,7 @@ const SendDetails = () => {
let flag = false;
while (true) {
try {
const { fee } = wallet.coinselect(lutxo, targets, opt.fee, changeAddress);
const { fee } = wallet.coinselect(lutxo, targets, opt.fee, change);
newFeePrecalc[opt.key] = fee;
break;
@ -398,9 +398,9 @@ const SendDetails = () => {
const dataWithoutSchema = data.replace('bitcoin:', '').replace('BITCOIN:', '');
if (wallet.isAddressValid(dataWithoutSchema)) {
setAddresses(addresses => {
addresses[scrollIndex.current].address = dataWithoutSchema;
return [...addresses];
setAddresses(addrs => {
addrs[scrollIndex.current].address = dataWithoutSchema;
return [...addrs];
});
setIsLoading(false);
return;
@ -423,15 +423,15 @@ const SendDetails = () => {
console.log('options', options);
if (btcAddressRx.test(address) || address.startsWith('bc1') || address.startsWith('BC1')) {
setAddresses(addresses => {
addresses[scrollIndex.current].address = address;
addresses[scrollIndex.current].amount = options.amount;
addresses[scrollIndex.current].amountSats = new BigNumber(options.amount).multipliedBy(100000000).toNumber();
return [...addresses];
setAddresses(addrs => {
addrs[scrollIndex.current].address = address;
addrs[scrollIndex.current].amount = options.amount;
addrs[scrollIndex.current].amountSats = new BigNumber(options.amount).multipliedBy(100000000).toNumber();
return [...addrs];
});
setUnits(units => {
units[scrollIndex.current] = BitcoinUnit.BTC; // also resetting current unit to BTC
return [...units];
setUnits(u => {
u[scrollIndex.current] = BitcoinUnit.BTC; // also resetting current unit to BTC
return [...u];
});
setTransactionMemo(options.label || options.message);
setAmountUnit(BitcoinUnit.BTC);
@ -499,7 +499,7 @@ const SendDetails = () => {
};
const createPsbtTransaction = async () => {
const changeAddress = await getChangeAddressAsync();
const change = await getChangeAddressAsync();
const requestedSatPerByte = Number(feeRate);
const lutxo = utxo || wallet.getUtxo();
console.log({ requestedSatPerByte, lutxo: lutxo.length });
@ -511,7 +511,7 @@ const SendDetails = () => {
targets.push({ address: transaction.address });
continue;
}
const value = parseInt(transaction.amountSats);
const value = parseInt(transaction.amountSats, 10);
if (value > 0) {
targets.push({ address: transaction.address, value });
} else if (transaction.amount) {
@ -525,7 +525,7 @@ const SendDetails = () => {
lutxo,
targets,
requestedSatPerByte,
changeAddress,
change,
isTransactionReplaceable ? HDSegwitBech32Wallet.defaultRBFSequence : HDSegwitBech32Wallet.finalRBFSequence,
);
@ -565,7 +565,7 @@ const SendDetails = () => {
};
await saveToDisk();
let recipients = outputs.filter(({ address }) => address !== changeAddress);
let recipients = outputs.filter(({ address }) => address !== change);
if (recipients.length === 0) {
// special case. maybe the only destination in this transaction is our own change address..?
@ -586,8 +586,8 @@ const SendDetails = () => {
setIsLoading(false);
};
const onWalletSelect = wallet => {
setWallet(wallet);
const onWalletSelect = w => {
setWallet(w);
navigation.pop();
};
@ -775,7 +775,7 @@ const SendDetails = () => {
};
const handleAddRecipient = async () => {
setAddresses(addresses => [...addresses, { address: '', key: String(Math.random()) }]);
setAddresses(addrs => [...addrs, { address: '', key: String(Math.random()) }]);
setOptionsVisible(false);
await sleep(200); // wait for animation
scrollView.current.scrollToEnd();
@ -786,9 +786,9 @@ const SendDetails = () => {
const handleRemoveRecipient = async () => {
const last = scrollIndex.current === addresses.length - 1;
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setAddresses(addresses => {
addresses.splice(scrollIndex.current, 1);
return [...addresses];
setAddresses(addrs => {
addrs.splice(scrollIndex.current, 1);
return [...addrs];
});
setOptionsVisible(false);
if (addresses.length === 0) return;
@ -801,7 +801,7 @@ const SendDetails = () => {
setOptionsVisible(false);
navigation.navigate('CoinControl', {
walletID: wallet.getID(),
onUTXOChoose: utxo => setUtxo(utxo),
onUTXOChoose: u => setUtxo(u),
});
};
@ -939,6 +939,7 @@ const SendDetails = () => {
const setHeaderRightOptions = () => {
navigation.setOptions({
headerRight: Platform.select({
// eslint-disable-next-line react/no-unstable-nested-components
ios: () => (
<ToolTipMenu
disabled={isLoading}
@ -950,6 +951,7 @@ const SendDetails = () => {
<Icon size={22} name="more-horiz" type="material" color={colors.foregroundColor} style={styles.advancedOptions} />
</ToolTipMenu>
),
// eslint-disable-next-line react/no-unstable-nested-components
default: () => (
<TouchableOpacity
accessibilityRole="button"
@ -1004,14 +1006,14 @@ const SendDetails = () => {
text: loc._.ok,
onPress: () => {
Keyboard.dismiss();
setAddresses(addresses => {
addresses[scrollIndex.current].amount = BitcoinUnit.MAX;
addresses[scrollIndex.current].amountSats = BitcoinUnit.MAX;
return [...addresses];
setAddresses(addrs => {
addrs[scrollIndex.current].amount = BitcoinUnit.MAX;
addrs[scrollIndex.current].amountSats = BitcoinUnit.MAX;
return [...addrs];
});
setUnits(units => {
units[scrollIndex.current] = BitcoinUnit.BTC;
return [...units];
setUnits(u => {
u[scrollIndex.current] = BitcoinUnit.BTC;
return [...u];
});
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setOptionsVisible(false);
@ -1339,32 +1341,32 @@ const SendDetails = () => {
isLoading={isLoading}
amount={item.amount ? item.amount.toString() : null}
onAmountUnitChange={unit => {
setAddresses(addresses => {
const item = addresses[index];
setAddresses(addrs => {
const addr = addrs[index];
switch (unit) {
case BitcoinUnit.SATS:
item.amountSats = parseInt(item.amount);
addr.amountSats = parseInt(addr.amount, 10);
break;
case BitcoinUnit.BTC:
item.amountSats = currency.btcToSatoshi(item.amount);
addr.amountSats = currency.btcToSatoshi(addr.amount);
break;
case BitcoinUnit.LOCAL_CURRENCY:
// also accounting for cached fiat->sat conversion to avoid rounding error
item.amountSats = AmountInput.getCachedSatoshis(item.amount) || currency.btcToSatoshi(currency.fiatToBTC(item.amount));
addr.amountSats = AmountInput.getCachedSatoshis(addr.amount) || currency.btcToSatoshi(currency.fiatToBTC(addr.amount));
break;
}
addresses[index] = item;
return [...addresses];
addrs[index] = addr;
return [...addrs];
});
setUnits(units => {
units[index] = unit;
return [...units];
setUnits(u => {
u[index] = unit;
return [...u];
});
}}
onChangeText={text => {
setAddresses(addresses => {
setAddresses(addrs => {
item.amount = text;
switch (units[index] || amountUnit) {
case BitcoinUnit.BTC:
@ -1375,11 +1377,11 @@ const SendDetails = () => {
break;
case BitcoinUnit.SATS:
default:
item.amountSats = parseInt(text);
item.amountSats = parseInt(text, 10);
break;
}
addresses[index] = item;
return [...addresses];
addrs[index] = item;
return [...addrs];
});
}}
unit={units[index] || amountUnit}
@ -1399,16 +1401,16 @@ const SendDetails = () => {
<AddressInput
onChangeText={text => {
text = text.trim();
const { address, amount, memo, payjoinUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(text);
setAddresses(addresses => {
const { address, amount, memo, payjoinUrl: pjUrl } = DeeplinkSchemaMatch.decodeBitcoinUri(text);
setAddresses(addrs => {
item.address = address || text;
item.amount = amount || item.amount;
addresses[index] = item;
return [...addresses];
addrs[index] = item;
return [...addrs];
});
setTransactionMemo(memo || transactionMemo);
setIsLoading(false);
setPayjoinUrl(payjoinUrl);
setPayjoinUrl(pjUrl);
}}
onBarScanned={processAddressData}
address={item.address}

View File

@ -141,7 +141,6 @@ const PsbtMultisig = () => {
);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => {
if (receivedPSBTBase64) {
_combinePSBT();

View File

@ -98,9 +98,9 @@ const PsbtWithHardwareWallet = () => {
}
if (deepLinkPSBT) {
const psbt = bitcoin.Psbt.fromBase64(deepLinkPSBT);
const newPsbt = bitcoin.Psbt.fromBase64(deepLinkPSBT);
try {
const Tx = fromWallet.combinePsbt(routeParamsPSBT.current, psbt);
const Tx = fromWallet.combinePsbt(routeParamsPSBT.current, newPsbt);
setTxHex(Tx.toHex());
} catch (Err) {
alert(Err);

View File

@ -30,7 +30,6 @@ const Success = () => {
});
useEffect(() => {
console.log('send/success - useEffect');
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (

View File

@ -16,14 +16,14 @@ const DefaultView = () => {
useEffect(() => {
(async () => {
const viewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
let defaultWalletLabel = '';
const newViewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
let newDefaultWalletLabel = '';
const wallet = await OnAppLaunch.getSelectedDefaultWallet();
if (wallet) {
defaultWalletLabel = wallet.getLabel();
newDefaultWalletLabel = wallet.getLabel();
}
setDefaultWalletLabel(defaultWalletLabel);
setViewAllWalletsEnabled(viewAllWalletsEnabled);
setDefaultWalletLabel(newDefaultWalletLabel);
setViewAllWalletsEnabled(newViewAllWalletsEnabled);
})();
});

View File

@ -57,7 +57,6 @@ const EncryptStorage = () => {
setIsLoading(false);
setStorageIsEncryptedSwitchEnabled(await isStorageEncrypted());
}
// eslint-disable-next-line react-hooks/exhaustive-deps
};
const onEncryptStorageSwitch = async value => {
@ -102,7 +101,6 @@ const EncryptStorage = () => {
{ cancelable: false },
);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
};
const onUseBiometricSwitch = async value => {
@ -116,7 +114,6 @@ const EncryptStorage = () => {
await Biometric.setBiometricUseEnabled(value);
setBiometrics(isBiometricsEnabled);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
};
const navigateToPlausibleDeniability = () => {

View File

@ -35,7 +35,7 @@ const Language = () => {
return (
<BlueListItem
onPress={() => {
const currentLanguage = AvailableLanguages.find(language => language.value === selectedLanguage);
const currentLanguage = AvailableLanguages.find(l => l.value === selectedLanguage);
saveLanguage(item.item.value).then(() => {
setSelectedLanguage(item.item.value);
setLanguage();

View File

@ -60,7 +60,6 @@ const TorSettings = () => {
return () => {
clearInterval(interval);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {

View File

@ -141,7 +141,7 @@ export default class CPFP extends Component {
}
async createTransaction() {
const newFeeRate = parseInt(this.state.newFeeRate);
const newFeeRate = parseInt(this.state.newFeeRate, 10);
if (newFeeRate > this.state.feeRate) {
/** @type {HDSegwitBech32Transaction} */
const tx = this.state.tx;

View File

@ -45,7 +45,7 @@ export default class RBFBumpFee extends CPFP {
}
async createTransaction() {
const newFeeRate = parseInt(this.state.newFeeRate);
const newFeeRate = parseInt(this.state.newFeeRate, 10);
if (newFeeRate > this.state.feeRate) {
/** @type {HDSegwitBech32Transaction} */
const tx = this.state.tx;

View File

@ -43,7 +43,7 @@ export default class RBFCancel extends CPFP {
}
async createTransaction() {
const newFeeRate = parseInt(this.state.newFeeRate);
const newFeeRate = parseInt(this.state.newFeeRate, 10);
if (newFeeRate > this.state.feeRate) {
/** @type {HDSegwitBech32Transaction} */
const tx = this.state.tx;

View File

@ -1,12 +1,12 @@
import React, { useContext, useEffect, useLayoutEffect, useState } from 'react';
import { View, ScrollView, TouchableOpacity, Text, TextInput, Linking, StatusBar, StyleSheet, Keyboard } from 'react-native';
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
import Clipboard from '@react-native-clipboard/clipboard';
import { BlueCard, BlueCopyToClipboardButton, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
import navigationStyle from '../../components/navigationStyle';
import HandoffComponent from '../../components/handoff';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import Clipboard from '@react-native-clipboard/clipboard';
import ToolTipMenu from '../../components/TooltipMenu';
import alert from '../../components/Alert';
const dayjs = require('dayjs');
@ -57,6 +57,7 @@ const TransactionsDetails = () => {
useLayoutEffect(() => {
setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<TouchableOpacity
accessibilityRole="button"
@ -73,17 +74,17 @@ const TransactionsDetails = () => {
useEffect(() => {
let foundTx = {};
let from = [];
let to = [];
for (const tx of getTransactions(null, Infinity, true)) {
if (tx.hash === hash) {
foundTx = tx;
let newFrom = [];
let newTo = [];
for (const transaction of getTransactions(null, Infinity, true)) {
if (transaction.hash === hash) {
foundTx = transaction;
for (const input of foundTx.inputs) {
from = from.concat(input.addresses);
newFrom = newFrom.concat(input.addresses);
}
for (const output of foundTx.outputs) {
if (output.addresses) to = to.concat(output.addresses);
if (output.scriptPubKey && output.scriptPubKey.addresses) to = to.concat(output.scriptPubKey.addresses);
if (output.addresses) newTo = newTo.concat(output.addresses);
if (output.scriptPubKey && output.scriptPubKey.addresses) newTo = newTo.concat(output.scriptPubKey.addresses);
}
}
}
@ -102,8 +103,8 @@ const TransactionsDetails = () => {
}
setTX(foundTx);
setFrom(from);
setTo(to);
setFrom(newFrom);
setTo(newTo);
setIsLoading(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hash, wallets]);

View File

@ -62,6 +62,7 @@ const TransactionsStatus = () => {
useLayoutEffect(() => {
setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<TouchableOpacity
accessibilityRole="button"
@ -77,9 +78,9 @@ const TransactionsStatus = () => {
}, [colors, tx]);
useEffect(() => {
for (const tx of wallet.current.getTransactions()) {
if (tx.hash === hash) {
setTX(tx);
for (const newTx of wallet.current.getTransactions()) {
if (newTx.hash === hash) {
setTX(newTx);
break;
}
}
@ -191,8 +192,8 @@ const TransactionsStatus = () => {
}, [tx, wallets]);
useEffect(() => {
const walletID = wallet.current?.getID();
if (walletID) {
const wID = wallet.current?.getID();
if (wID) {
setSelectedWallet(wallet.current?.getID());
}
// eslint-disable-next-line react-hooks/exhaustive-deps

View File

@ -105,21 +105,21 @@ const WalletAddresses = () => {
}, [setOptions]);
const getAddresses = () => {
const addressList = [];
const newAddresses = [];
for (let index = 0; index <= walletInstance.next_free_change_address_index; index++) {
const address = getAddress(walletInstance, index, true);
addressList.push(address);
newAddresses.push(address);
}
for (let index = 0; index < walletInstance.next_free_address_index + walletInstance.gap_limit; index++) {
const address = getAddress(walletInstance, index, false);
addressList.push(address);
newAddresses.push(address);
}
setAddresses(addressList);
setAddresses(newAddresses);
setShowAddresses(true);
};

View File

@ -206,8 +206,9 @@ const WalletDetails = () => {
useLayoutEffect(() => {
isAdvancedModeEnabled().then(setIsAdvancedModeEnabledRender);
// eslint-disable-next-line react-hooks/exhaustive-deps
setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<TouchableOpacity
accessibilityRole="button"
@ -224,7 +225,7 @@ const WalletDetails = () => {
}, [isLoading, colors, walletName, useWithHardwareWallet, hideTransactionsInWalletsList, isBIP47Enabled]);
useEffect(() => {
if (wallets.some(wallet => wallet.getID() === walletID)) {
if (wallets.some(w => w.getID() === walletID)) {
setSelectedWallet(walletID);
}
// eslint-disable-next-line react-hooks/exhaustive-deps

View File

@ -81,8 +81,8 @@ const WalletsImport = () => {
importMnemonic(textToImport);
};
const importMnemonic = importText => {
navigation.navigate('ImportWalletDiscovery', { importText, askPassphrase, searchAccounts });
const importMnemonic = text => {
navigation.navigate('ImportWalletDiscovery', { importText: text, askPassphrase, searchAccounts });
};
const onBarScanned = value => {

View File

@ -16,6 +16,8 @@ const WALLET_FOUND = 'WALLET_FOUND';
const WALLET_NOTFOUND = 'WALLET_NOTFOUND';
const WALLET_UNKNOWN = 'WALLET_UNKNOWN';
const ListEmptyComponent = () => <BlueTextCentered>{loc.wallets.import_wrong_path}</BlueTextCentered>;
const ImportCustomDerivationPath = () => {
const navigation = useNavigation();
const { colors } = useTheme();
@ -30,32 +32,32 @@ const ImportCustomDerivationPath = () => {
const importing = useRef(false);
const debouncedSavePath = useRef(
debounce(async path => {
if (!validateBip32(path)) {
setWallets(ws => ({ ...ws, [path]: WRONG_PATH }));
debounce(async newPath => {
if (!validateBip32(newPath)) {
setWallets(ws => ({ ...ws, [newPath]: WRONG_PATH }));
return;
}
// create wallets
const wallets = {};
const newWallets = {};
for (const Wallet of [HDLegacyP2PKHWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet]) {
const wallet = new Wallet();
wallet.setSecret(importText);
wallet.setPassphrase(password);
wallet.setDerivationPath(path);
wallets[Wallet.type] = wallet;
wallet.setDerivationPath(newPath);
newWallets[Wallet.type] = wallet;
}
setWallets(ws => ({ ...ws, [path]: wallets }));
setWallets(ws => ({ ...ws, [newPath]: newWallets }));
// discover was they ever used
const res = {};
const promises = Object.values(wallets).map(w => w.wasEverUsed().then(v => (res[w.type] = v ? WALLET_FOUND : WALLET_NOTFOUND)));
const promises = Object.values(newWallets).map(w => w.wasEverUsed().then(v => (res[w.type] = v ? WALLET_FOUND : WALLET_NOTFOUND)));
try {
await Promise.all(promises); // wait for all promises to be resolved
} catch (e) {
Object.values(wallets).forEach(w => (res[w.type] = WALLET_UNKNOWN));
Object.values(newWallets).forEach(w => (res[w.type] = WALLET_UNKNOWN));
}
setUsed(u => ({ ...u, [path]: res }));
setUsed(u => ({ ...u, [newPath]: res }));
}, 500),
);
useEffect(() => {
@ -133,7 +135,7 @@ const ImportCustomDerivationPath = () => {
keyExtractor={w => path + w[0]}
renderItem={renderItem}
contentContainerStyle={styles.flatListContainer}
ListEmptyComponent={() => <BlueTextCentered>{loc.wallets.import_wrong_path}</BlueTextCentered>}
ListEmptyComponent={ListEmptyComponent}
/>
<View style={[styles.center, stylesHook.center]}>

View File

@ -57,7 +57,7 @@ const ImportWalletDiscovery = () => {
try {
subtitle = wallet.getDerivationPath?.();
} catch (e) {}
setWallets(wallets => [...wallets, { wallet, subtitle, id }]);
setWallets(w => [...w, { wallet, subtitle, id }]);
};
const onPassword = async (title, subtitle) => {
@ -78,10 +78,10 @@ const ImportWalletDiscovery = () => {
task.current = startImport(importText, askPassphrase, searchAccounts, onProgress, onWallet, onPassword);
task.current.promise
.then(({ cancelled, wallets }) => {
.then(({ cancelled, wallets: w }) => {
if (cancelled) return;
if (wallets.length === 1) saveWallet(wallets[0]); // instantly save wallet if only one has been discovered
if (wallets.length === 0) {
if (w.length === 1) saveWallet(w[0]); // instantly save wallet if only one has been discovered
if (w.length === 0) {
ReactNativeHapticFeedback.trigger('impactLight', { ignoreAndroidSystemSettings: false });
}
})

View File

@ -38,6 +38,7 @@ const LdkViewLogs = () => {
})
.finally(() => {
setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<TouchableOpacity
accessibilityRole="button"
@ -81,8 +82,8 @@ const LdkViewLogs = () => {
getLogs();
await wallet
.getInfo()
.then(async info => {
setGetInfo(info);
.then(async newInfo => {
setGetInfo(newInfo);
const peers = await wallet.listPeers();
const listChannels = await wallet.listChannels();
const version = await LightningLdkWallet.getVersion();

View File

@ -101,6 +101,7 @@ const WalletsList = () => {
shadowOpacity: 0,
shadowOffset: { height: 0, width: 0 },
},
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () =>
I18nManager.isRTL ? null : (
<TouchableOpacity
@ -113,6 +114,7 @@ const WalletsList = () => {
<Icon size={22} name="more-horiz" type="material" color={colors.foregroundColor} />
</TouchableOpacity>
),
// eslint-disable-next-line react/no-unstable-nested-components
headerLeft: () =>
I18nManager.isRTL ? (
<TouchableOpacity

View File

@ -247,12 +247,15 @@ const Entropy = () => {
active={tab}
onSwitch={setTab}
tabs={[
// eslint-disable-next-line react/no-unstable-nested-components
({ active }) => (
<Icon name="toll" type="material" color={active ? colors.buttonAlternativeTextColor : colors.buttonBackgroundColor} />
),
// eslint-disable-next-line react/no-unstable-nested-components
({ active }) => (
<Icon name="dice" type="font-awesome-5" color={active ? colors.buttonAlternativeTextColor : colors.buttonBackgroundColor} />
),
// eslint-disable-next-line react/no-unstable-nested-components
({ active }) => (
<Icon name="dice-d20" type="font-awesome-5" color={active ? colors.buttonAlternativeTextColor : colors.buttonBackgroundColor} />
),

View File

@ -1,4 +1,3 @@
/* eslint-disable react/prop-types */
import React, { useContext, useEffect, useState } from 'react';
import { View, ActivityIndicator, Image, Text, TouchableOpacity, I18nManager, FlatList, StyleSheet, StatusBar } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
@ -105,6 +104,7 @@ const SelectWallet = () => {
setOptions(
isModal
? {
// eslint-disable-next-line react/no-unstable-nested-components
headerLeft: () => (
<TouchableOpacity
accessibilityRole="button"

View File

@ -78,10 +78,10 @@ const WalletTransactions = ({ navigation }) => {
* Simple wrapper for `wallet.getTransactions()`, where `wallet` is current wallet.
* Sorts. Provides limiting.
*
* @param limit {Integer} How many txs return, starting from the earliest. Default: all of them.
* @param lmt {Integer} How many txs return, starting from the earliest. Default: all of them.
* @returns {Array}
*/
const getTransactionsSliced = (limit = Infinity) => {
const getTransactionsSliced = (lmt = Infinity) => {
let txs = wallet.getTransactions();
for (const tx of txs) {
tx.sort_ts = +new Date(tx.received);
@ -89,7 +89,7 @@ const WalletTransactions = ({ navigation }) => {
txs = txs.sort(function (a, b) {
return b.sort_ts - a.sort_ts;
});
return txs.slice(0, limit);
return txs.slice(0, lmt);
};
useEffect(() => {
@ -97,7 +97,6 @@ const WalletTransactions = ({ navigation }) => {
return () => {
clearInterval(interval);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {

View File

@ -125,8 +125,8 @@ const ViewEditMultisigCosigners = () => {
}
// eslint-disable-next-line prefer-const
let newWallets = wallets.filter(w => {
return w.getID() !== walletId;
let newWallets = wallets.filter(newWallet => {
return newWallet.getID() !== walletId;
});
if (!isElectrumDisabled) {
await wallet.fetchBalance();

View File

@ -16,6 +16,7 @@ it('BlueHeaderDefaultSub works', () => {
expect(rendered).toBeTruthy();
});
// eslint-disable-next-line jest/no-disabled-tests
it.skip('Settings work', () => {
const rendered = TestRenderer.create(<Settings />).toJSON();
expect(rendered).toBeTruthy();

File diff suppressed because one or more lines are too long

View File

@ -98,6 +98,7 @@ describe('Bech32 Segwit HD (BIP84)', () => {
// skpped because its a very specific testcase, and slow
// unskip and test manually
// eslint-disable-next-line jest/no-disabled-tests
it.skip('can catch up with externally modified wallet', async () => {
if (!process.env.HD_MNEMONIC_BIP84) {
console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped');
@ -133,6 +134,7 @@ describe('Bech32 Segwit HD (BIP84)', () => {
assert.strictEqual(hd.getTransactions().length, oldTransactions.length);
});
// eslint-disable-next-line jest/no-disabled-tests
it.skip('can work with faulty zpub', async () => {
// takes too much time, skipped
if (!process.env.FAULTY_ZPUB) {

View File

@ -400,7 +400,7 @@ describe('import procedure', () => {
assert.strictEqual(store.state.wallets[0].getMasterFingerprintHex(), '7d2f0272');
});
it('can import watch-only Cobo vault export', async () => {
it('can import watch-only Cobo vault export 2', async () => {
const store = createStore();
const { promise } = startImport(
`[{"ExtPubKey":"zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs","MasterFingerprint":"73C5DA0A","AccountKeyPath":"m/84'/0'/0'"},{"ExtPubKey":"ypub6Ww3ibxVfGzLrAH1PNcjyAWenMTbbAosGNB6VvmSEgytSER9azLDWCxoJwW7Ke7icmizBMXrzBx9979FfaHxHcrArf3zbeJJJUZPf663zsP","MasterFingerprint":"73C5DA0A","AccountKeyPath":"m/49'/0'/0'"},{"ExtPubKey":"xpub6BosfCnifzxcFwrSzQiqu2DBVTshkCXacvNsWGYJVVhhawA7d4R5WSWGFNbi8Aw6ZRc1brxMyWMzG3DSSSSoekkudhUd9yLb6qx39T9nMdj","MasterFingerprint":"73C5DA0A","AccountKeyPath":"m/44'/0'/0'"}]`,

View File

@ -149,7 +149,7 @@ describe('SegwitBech32Wallet', function () {
assert.strictEqual(l1, l2);
});
it('can fetch TXs', async () => {
it('can fetch TXs LegacyWallet', async () => {
const w = new LegacyWallet();
w._address = 'bc1quhnve8q4tk3unhmjts7ymxv8cd6w9xv8wy29uv';
await w.fetchTransactions();
@ -166,7 +166,7 @@ describe('SegwitBech32Wallet', function () {
assert.strictEqual(w.getTransactions()[1].value, 892111);
});
it('can fetch TXs', async () => {
it('can fetch TXs SegwitBech32Wallet', async () => {
const w = new SegwitBech32Wallet();
w._address = 'bc1qn887fmetaytw4vj68vsh529ft408q8j9x3dndc';
assert.ok(w.weOwnAddress('bc1qn887fmetaytw4vj68vsh529ft408q8j9x3dndc'));

View File

@ -5,11 +5,13 @@ import { LightningCustodianWallet } from '../../class';
jest.setTimeout(200 * 1000);
const baseUri = 'https://lndhub-staging.herokuapp.com';
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('LightningCustodianWallet', () => {
const l1 = new LightningCustodianWallet();
l1.setBaseURI(baseUri);
l1.init();
// eslint-disable-next-line jest/no-disabled-tests
it.skip('issue credentials', async () => {
assert.ok(l1.refill_addressess.length === 0);
assert.ok(l1._refresh_token_created_ts === 0);
@ -108,7 +110,7 @@ describe.skip('LightningCustodianWallet', () => {
assert.ok(decoded.payment_hash);
assert.ok(decoded.description);
assert.ok(decoded.num_satoshis);
assert.strictEqual(parseInt(decoded.num_satoshis) * 1000, parseInt(decoded.num_millisatoshis));
assert.strictEqual(parseInt(decoded.num_satoshis, 10) * 1000, parseInt(decoded.num_millisatoshis, 10));
// checking that bad invoice cant be decoded
invoice = 'gsom';
@ -202,6 +204,7 @@ describe.skip('LightningCustodianWallet', () => {
});
// turned off because acinq strike is shutting down
// eslint-disable-next-line jest/no-disabled-tests
it.skip('can pay invoice (acinq)', async () => {
if (!process.env.BLITZHUB) {
console.error('process.env.BLITZHUB not set, skipped');
@ -524,27 +527,27 @@ describe.skip('LightningCustodianWallet', () => {
});
it('cant create zemo amt invoices yet', async () => {
const l1 = new LightningCustodianWallet();
l1.setBaseURI(baseUri);
l1.init();
assert.ok(l1.refill_addressess.length === 0);
assert.ok(l1._refresh_token_created_ts === 0);
assert.ok(l1._access_token_created_ts === 0);
l1.balance = 'FAKE';
const l = new LightningCustodianWallet();
l.setBaseURI(baseUri);
l.init();
assert.ok(l.refill_addressess.length === 0);
assert.ok(l._refresh_token_created_ts === 0);
assert.ok(l._access_token_created_ts === 0);
l.balance = 'FAKE';
await l1.createAccount(true);
await l1.authorize();
await l1.fetchBalance();
await l.createAccount(true);
await l.authorize();
await l.fetchBalance();
assert.ok(l1.access_token);
assert.ok(l1.refresh_token);
assert.ok(l1._refresh_token_created_ts > 0);
assert.ok(l1._access_token_created_ts > 0);
assert.ok(l1.balance === 0);
assert.ok(l.access_token);
assert.ok(l.refresh_token);
assert.ok(l._refresh_token_created_ts > 0);
assert.ok(l._access_token_created_ts > 0);
assert.ok(l.balance === 0);
let err = false;
try {
await l1.addInvoice(0, 'zero amt inv');
await l.addInvoice(0, 'zero amt inv');
} catch (_) {
err = true;
}
@ -552,7 +555,7 @@ describe.skip('LightningCustodianWallet', () => {
err = false;
try {
await l1.addInvoice(NaN, 'zero amt inv');
await l.addInvoice(NaN, 'zero amt inv');
} catch (_) {
err = true;
}

View File

@ -3,6 +3,7 @@ import SyncedAsyncStorage from '../../class/synced-async-storage';
const assert = require('assert');
describe('', () => {
// eslint-disable-next-line jest/no-disabled-tests
it.skip('can import & dump LDK bytes from network storage ', async () => {
const ldk = new LightningLdkWallet();
ldk.setSecret('');

View File

@ -5,6 +5,7 @@ import Notifications from '../../blue_modules/notifications';
describe('notifications', () => {
// yeah, lets rely less on external services...
// eslint-disable-next-line jest/no-disabled-tests
it.skip('can check groundcontrol server uri validity', async () => {
assert.ok(await Notifications.isGroundControlUriValid('https://groundcontrol-bluewallet.herokuapp.com'));
assert.ok(!(await Notifications.isGroundControlUriValid('https://www.google.com')));
@ -12,6 +13,7 @@ describe('notifications', () => {
});
// muted because it causes jest to hang waiting indefinitely
// eslint-disable-next-line jest/no-disabled-tests
it.skip('can check non-responding url', async () => {
assert.ok(!(await Notifications.isGroundControlUriValid('https://localhost.com')));
});

View File

@ -41,6 +41,7 @@ describe('Watch only wallet', () => {
assert.strictEqual(w.getTransactions().length, 2);
});
// eslint-disable-next-line jest/no-disabled-tests
it.skip('can fetch tx from huge wallet', async () => {
const w = new WatchOnlyWallet();
w.setSecret('1NDyJtNTjmwk5xPNhjgAMu4HDHigtobu1s'); // binance wallet

View File

@ -20,6 +20,7 @@ it('bip38 decodes', async () => {
});
// too slow, even on CI. unskip and manually run it if you need it
// eslint-disable-next-line jest/no-disabled-tests
it.skip('bip38 decodes slow', async () => {
if (!(process.env.CI || process.env.TRAVIS)) {
// run only on CI

View File

@ -1328,7 +1328,7 @@ describe('multisig-wallet (native segwit)', () => {
});
it('can import incomplete wallet from Coldcard', async () => {
const Zpub2 = 'Zpub75mAE8EjyxSzoyPmGnd5E6MyD7ALGNndruWv52xpzimZQKukwvEfXTHqmH8nbbc6ccP5t2aM3mws3pKYSnKpKMMytdbNEZFUxKzztYFM8Pn';
const Zpub = 'Zpub75mAE8EjyxSzoyPmGnd5E6MyD7ALGNndruWv52xpzimZQKukwvEfXTHqmH8nbbc6ccP5t2aM3mws3pKYSnKpKMMytdbNEZFUxKzztYFM8Pn';
const w = new MultisigHDWallet();
w.setSecret(coldcardExport);
@ -1338,8 +1338,8 @@ describe('multisig-wallet (native segwit)', () => {
assert.strictEqual(w.getM(), 0); // zero means unknown
assert.strictEqual(w.getN(), 1); // added only one cosigner
assert.strictEqual(w.getCosigner(1), Zpub2);
assert.strictEqual(w.getCosignerForFingerprint(fp2coldcard), Zpub2);
assert.strictEqual(w.getCosigner(1), Zpub);
assert.strictEqual(w.getCosignerForFingerprint(fp2coldcard), Zpub);
assert.strictEqual(w.getDerivationPath(), ''); // unknown
});