Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion components/WalletHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,15 @@ export default class WalletHeader extends React.Component<
const nodeAddress = SettingsStore!.host || SettingsStore!.url;

let infoValue: string;
if (NodeInfoStore!.nodeInfo.isTestNet) {
// Check Testnet4 first (more specific), then fall back to generic Testnet
// For embedded LND, also check embeddedLndNetwork setting
const isTestNet4 =
NodeInfoStore!.nodeInfo.isTestNet4 ||
(implementation === 'embedded-lnd' &&
SettingsStore!.embeddedLndNetwork === 'Testnet4');
if (isTestNet4) {
infoValue = localeString('network.testnet4');
} else if (NodeInfoStore!.nodeInfo.isTestNet) {
infoValue = localeString('views.Wallet.MainPane.testnet');
} else if (NodeInfoStore!.nodeInfo.isRegTest) {
infoValue = localeString('views.Wallet.MainPane.regnet');
Expand Down
3 changes: 2 additions & 1 deletion locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@
"views.Settings.SocialMedia.twitter": "X / Twitter",
"views.Settings.Support.store": "ZEUS merch store",
"network.mainnet": "Mainnet",
"network.testnet": "Testnet",
"network.testnet3": "Testnet3",
"network.testnet4": "Testnet4",
"nostr.nostr": "Nostr",
"nostr.keys": "Nostr keys",
"nostr.pubkey": "Nostr pubkey",
Expand Down
13 changes: 12 additions & 1 deletion models/NodeInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,24 @@ export default class NodeInfo extends BaseModel {
return this.id || this.pubkey || this.identity_pubkey || '';
}

@computed public get isTestNet4(): boolean {
return (
this.network === 'testnet4' ||
(this.chains &&
this.chains[0] &&
this.chains[0].network === 'testnet4')
);
}

@computed public get isTestNet(): boolean {
return (
this.testnet ||
this.network === 'testnet' ||
this.network === 'testnet4' ||
(this.chains &&
this.chains[0] &&
this.chains[0].network === 'testnet')
(this.chains[0].network === 'testnet' ||
this.chains[0].network === 'testnet4'))
);
}
Comment on lines 41 to 51
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for isTestNet can be simplified for better readability and to reduce redundancy, especially now that isTestNet4 is available.

Suggested change
@computed public get isTestNet(): boolean {
return (
this.testnet ||
this.network === 'testnet' ||
this.network === 'testnet4' ||
(this.chains &&
this.chains[0] &&
this.chains[0].network === 'testnet')
(this.chains[0].network === 'testnet' ||
this.chains[0].network === 'testnet4'))
);
}
@computed public get isTestNet(): boolean {
const networks = ['testnet', 'testnet4'];
return (
this.testnet ||
(this.network && networks.includes(this.network)) ||
(this.chains &&
this.chains[0] &&
this.chains[0].network &&
networks.includes(this.chains[0].network))
);
}


Expand Down
4 changes: 3 additions & 1 deletion stores/AlertStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ export default class AlertStore {
@action
public checkNeutrinoPeers = async () => {
const peers =
this.settingsStore.embeddedLndNetwork === 'Testnet'
this.settingsStore.embeddedLndNetwork === 'Testnet3'
? this.settingsStore.settings.neutrinoPeersTestnet
: this.settingsStore.embeddedLndNetwork === 'Testnet4'
? this.settingsStore.settings.neutrinoPeersTestnet4
: this.settingsStore.settings.neutrinoPeersMainnet;

const results: any = [];
Expand Down
23 changes: 22 additions & 1 deletion stores/SettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ export interface Settings {
dontAllowOtherPeers: boolean;
neutrinoPeersMainnet: Array<string>;
neutrinoPeersTestnet: Array<string>;
neutrinoPeersTestnet4: Array<string>;
zeroConfPeers: Array<string>;
rescan: boolean;
compactDb: boolean;
Expand Down Expand Up @@ -376,9 +377,23 @@ export type Implementations =

export const EMBEDDED_NODE_NETWORK_KEYS = [
{ key: 'Mainnet', translateKey: 'network.mainnet', value: 'mainnet' },
{ key: 'Testnet', translateKey: 'network.testnet', value: 'testnet' }
{ key: 'Testnet3', translateKey: 'network.testnet3', value: 'testnet' },
{ key: 'Testnet4', translateKey: 'network.testnet4', value: 'testnet4' }
];
Comment on lines 378 to 382
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There seems to be an inconsistency in how embeddedLndNetwork is used across the codebase. This constant defines the internal values as mainnet, testnet, and testnet4. However, some parts of the code are checking for Testnet3 or testnet3 (e.g., stores/AlertStore.ts, views/Settings/EmbeddedNode/LNDLogs.tsx, utils/LndMobileUtils.ts). This can lead to bugs where conditions are not met as expected. Please ensure consistent use of the internal values (mainnet, testnet, testnet4) throughout the application.

References
  1. This rule clarifies the expected string value for 'Mainnet' when checking the network type from settingsStore.embeddedLndNetwork and emphasizes consistency in network naming and checks across the codebase.


// Helper to get display name for embedded LND network
export const getNetworkDisplayName = (network: string): string => {
const networkDisplayMap: { [key: string]: string } = {
mainnet: 'Mainnet',
Mainnet: 'Mainnet',
testnet: 'Testnet3',
Testnet3: 'Testnet3',
testnet4: 'Testnet4',
Testnet4: 'Testnet4'
};
return networkDisplayMap[network] || network;
};
Comment on lines +385 to +395
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The networkDisplayMap contains redundant entries for capitalized and lowercased keys. You can simplify this function by converting the input network string to lowercase before the lookup. This will make the map more concise and easier to maintain.

export const getNetworkDisplayName = (network: string): string => {
    const lowercasedNetwork = network.toLowerCase();
    const networkDisplayMap: { [key: string]: string } = {
        mainnet: 'Mainnet',
        testnet: 'Testnet3',
        testnet4: 'Testnet4'
    };
    return networkDisplayMap[lowercasedNetwork] || network;
};


export const LNC_MAILBOX_KEYS = [
{
key: 'mailbox.terminal.lightning.today:443',
Expand Down Expand Up @@ -1346,6 +1361,11 @@ export const DEFAULT_NEUTRINO_PEERS_TESTNET = [
'testnet.blixtwallet.com'
];

export const DEFAULT_NEUTRINO_PEERS_TESTNET4 = [
'testnet4.lnolymp.us',
'testnet4.blixtwallet.com'
];

export const DEFAULT_SLIDE_TO_PAY_THRESHOLD = 10000;

export default class SettingsStore {
Expand Down Expand Up @@ -1427,6 +1447,7 @@ export default class SettingsStore {
dontAllowOtherPeers: false,
neutrinoPeersMainnet: DEFAULT_NEUTRINO_PEERS_MAINNET,
neutrinoPeersTestnet: DEFAULT_NEUTRINO_PEERS_TESTNET,
neutrinoPeersTestnet4: DEFAULT_NEUTRINO_PEERS_TESTNET4,
zeroConfPeers: [],
rescan: false,
compactDb: false,
Expand Down
12 changes: 7 additions & 5 deletions stores/SyncStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,15 @@ export default class SyncStore {

private getBestBlockHeight = async () => {
await new Promise((resolve, reject) => {
const networkPath =
this.settingsStore.embeddedLndNetwork === 'Testnet3'
? 'testnet/'
: this.settingsStore.embeddedLndNetwork === 'Testnet4'
? 'testnet4/'
: '';
ReactNativeBlobUtil.fetch(
'get',
`https://mempool.space/${
this.settingsStore.embeddedLndNetwork === 'Testnet'
? 'testnet/'
: ''
}api/blocks/tip/height`
`https://mempool.space/${networkPath}api/blocks/tip/height`
)
.then(async (response: any) => {
const status = response.info().status;
Expand Down
2 changes: 1 addition & 1 deletion utils/GraphSyncUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ describe('GraphSyncUtils', () => {

it('should return true and not show prompt on testnet', () => {
// Temporarily set to testnet
(mockSettingsStore as any).embeddedLndNetwork = 'Testnet';
(mockSettingsStore as any).embeddedLndNetwork = 'Testnet3';

const result = checkGraphSyncBeforePayment(
mockSettings,
Expand Down
130 changes: 76 additions & 54 deletions utils/LndMobileUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
DEFAULT_NEUTRINO_PEERS_MAINNET,
SECONDARY_NEUTRINO_PEERS_MAINNET,
DEFAULT_NEUTRINO_PEERS_TESTNET,
DEFAULT_NEUTRINO_PEERS_TESTNET4,
DEFAULT_FEE_ESTIMATOR,
DEFAULT_SPEEDLOADER
} from '../stores/SettingsStore';
Expand Down Expand Up @@ -90,15 +91,18 @@ export function checkLndStreamErrorResponse(

const writeLndConfig = async ({
lndDir = 'lnd',
isTestnet,
network,
rescan,
compactDb
}: {
lndDir: string;
isTestnet?: boolean;
network?: string;
rescan?: boolean;
compactDb?: boolean;
}) => {
const isMainnet = !network || network === 'mainnet';
const isTestnet = network === 'testnet' || network === 'testnet3';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The check network === 'testnet3' will always be false because the network value for Testnet3 is 'testnet'. This is confusing and should be removed to avoid potential bugs.

    const isTestnet = network === 'testnet';
References
  1. This rule clarifies the expected string value for 'Mainnet' when checking the network type from settingsStore.embeddedLndNetwork and emphasizes consistency in network naming and checks across the codebase.

const isTestnet4 = network === 'testnet4';
const { writeConfig } = lndMobile.index;

const peerMode = settingsStore?.settings?.dontAllowOtherPeers
Expand All @@ -112,6 +116,41 @@ const writeLndConfig = async ({

console.log('persistFilters', persistFilters);

// Get neutrino peers based on network
const getNeutrinoPeers = () => {
if (isMainnet) {
return settingsStore?.settings?.neutrinoPeersMainnet || [];
} else if (isTestnet4) {
return settingsStore?.settings?.neutrinoPeersTestnet4 || [];
} else {
return settingsStore?.settings?.neutrinoPeersTestnet || [];
}
};

const dbConfig = `[db]
db.no-graph-cache=false

[bolt]
db.bolt.auto-compact=${compactDb ? 'true' : 'false'}
${compactDb ? 'db.bolt.auto-compact-min-age=0' : ''}`;

const neutrinoConfig = `[Neutrino]
${getNeutrinoPeers()
.map((peer: string) => `neutrino.${peerMode}=${peer}\n `)
.join('')}
${
isMainnet
? 'neutrino.assertfilterheader=230000:1308d5cfc6462f877a5587fd77d7c1ab029d45e58d5175aaf8c264cee9bde760'
: ''
}
${
isMainnet
? 'neutrino.assertfilterheader=660000:08312375fabc082b17fa8ee88443feb350c19a34bb7483f94f7478fa4ad33032'
: ''
}
neutrino.broadcasttimeout=11s
neutrino.persistfilters=${persistFilters}`;

const config = `[Application Options]
debuglevel=info
maxbackoff=2s
Expand All @@ -124,46 +163,21 @@ const writeLndConfig = async ({
payments-expiration-grace-period=168h
${rescan ? 'reset-wallet-transactions=true' : ''}

[db]
db.no-graph-cache=false

[bolt]
db.bolt.auto-compact=${compactDb ? 'true' : 'false'}
${compactDb ? 'db.bolt.auto-compact-min-age=0' : ''}
${dbConfig}

[Routing]
routing.assumechanvalid=1
routing.strictgraphpruning=false

[Bitcoin]
bitcoin.active=1
bitcoin.mainnet=${isTestnet ? 0 : 1}
bitcoin.testnet=${isTestnet ? 1 : 0}
bitcoin.mainnet=${isMainnet ? true : false}
bitcoin.testnet=${isTestnet ? true : false}
bitcoin.testnet4=${isTestnet4 ? true : false}
bitcoin.node=neutrino
bitcoin.defaultchanconfs=1

[Neutrino]
${
!isTestnet
? settingsStore?.settings?.neutrinoPeersMainnet
.map((peer) => `neutrino.${peerMode}=${peer}\n `)
.join('')
: settingsStore?.settings?.neutrinoPeersTestnet
.map((peer) => `neutrino.${peerMode}=${peer}\n `)
.join('')
}
${
!isTestnet
? 'neutrino.assertfilterheader=230000:1308d5cfc6462f877a5587fd77d7c1ab029d45e58d5175aaf8c264cee9bde760'
: ''
}
${
!isTestnet
? 'neutrino.assertfilterheader=660000:08312375fabc082b17fa8ee88443feb350c19a34bb7483f94f7478fa4ad33032'
: ''
}
neutrino.broadcasttimeout=11s
neutrino.persistfilters=${persistFilters}
${neutrinoConfig}

[fee]
fee.url=${
Expand Down Expand Up @@ -251,17 +265,17 @@ export async function expressGraphSync() {

export async function initializeLnd({
lndDir = 'lnd',
isTestnet,
network,
rescan,
compactDb
}: {
lndDir: string;
isTestnet?: boolean;
network?: string;
rescan?: boolean;
compactDb?: boolean;
}) {
const { initialize } = lndMobile.index;
await writeLndConfig({ lndDir, isTestnet, rescan, compactDb });
await writeLndConfig({ lndDir, network, rescan, compactDb });
await initialize();
}

Expand Down Expand Up @@ -402,13 +416,19 @@ export async function startLnd({
}

export async function optimizeNeutrinoPeers(
isTestnet?: boolean,
network?: string,
peerTargetCount: number = 3
) {
console.log('Optimizing Neutrino peers');
let peers = isTestnet
? DEFAULT_NEUTRINO_PEERS_TESTNET
: DEFAULT_NEUTRINO_PEERS_MAINNET;
const isMainnet = !network || network === 'mainnet';
const isTestnet = network === 'testnet' || network === 'testnet3';
const isTestnet4 = network === 'testnet4';

let peers = isMainnet
? DEFAULT_NEUTRINO_PEERS_MAINNET
: isTestnet4
? DEFAULT_NEUTRINO_PEERS_TESTNET4
: DEFAULT_NEUTRINO_PEERS_TESTNET;

const results: any = [];
for (let i = 0; i < peers.length; i++) {
Expand Down Expand Up @@ -506,8 +526,8 @@ export async function optimizeNeutrinoPeers(
console.log('Peers count:', selectedPeers.length);
}

// Extra external peers
if (selectedPeers.length < peerTargetCount && !isTestnet) {
// Extra external peers (mainnet only)
if (selectedPeers.length < peerTargetCount && isMainnet) {
console.log(
`Selecting Neutrino peers with ping times <${NEUTRINO_PING_THRESHOLD_MS}ms from alternate set`
);
Expand Down Expand Up @@ -562,17 +582,17 @@ export async function optimizeNeutrinoPeers(
}

if (selectedPeers.length > 0) {
if (isTestnet) {
await settingsStore.updateSettings({
neutrinoPeersTestnet: selectedPeers,
dontAllowOtherPeers: selectedPeers.length > 2 ? true : false
});
const settingsUpdate: any = {
dontAllowOtherPeers: selectedPeers.length > 2 ? true : false
};
if (isTestnet4) {
settingsUpdate.neutrinoPeersTestnet4 = selectedPeers;
} else if (isTestnet) {
settingsUpdate.neutrinoPeersTestnet = selectedPeers;
} else {
await settingsStore.updateSettings({
neutrinoPeersMainnet: selectedPeers,
dontAllowOtherPeers: selectedPeers.length > 2 ? true : false
});
settingsUpdate.neutrinoPeersMainnet = selectedPeers;
}
await settingsStore.updateSettings(settingsUpdate);

console.log('Selected the following Neutrino peers:', selectedPeers);
} else {
Expand All @@ -588,13 +608,13 @@ export async function createLndWallet({
lndDir,
seedMnemonic,
walletPassphrase,
isTestnet,
network,
channelBackupsBase64
}: {
lndDir: string;
seedMnemonic?: string;
walletPassphrase?: string;
isTestnet?: boolean;
network?: string;
channelBackupsBase64?: string;
}) {
const {
Expand All @@ -610,19 +630,21 @@ export async function createLndWallet({
await excludeLndICloudBackup(lndDir);
}

await writeLndConfig({ lndDir, isTestnet });
await writeLndConfig({ lndDir, network });
await initialize();

let status = await checkStatus();
if (
(status & ELndMobileStatusCodes.STATUS_PROCESS_STARTED) !==
ELndMobileStatusCodes.STATUS_PROCESS_STARTED
) {
// Native code expects isTestnet boolean - true for any non-mainnet network
const isTestnet = network === 'testnet' || network === 'testnet4';
await startLnd({
lndDir,
walletPassword: '',
isTorEnabled: false,
isTestnet: isTestnet || false
isTestnet
});
}

Expand Down
Loading