Skip to content

Commit

Permalink
feat: todos refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
limpbrains committed Oct 9, 2023
1 parent fa0c170 commit 8eb8006
Show file tree
Hide file tree
Showing 51 changed files with 593 additions and 413 deletions.
200 changes: 200 additions & 0 deletions __tests__/todos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import assert from 'node:assert';
import cloneDeep from 'lodash/cloneDeep';

import '../src/utils/i18n';
import { todosFullSelector } from '../src/store/reselect/todos';
import store from '../src/store';
import Store from '../src/store/types';
import { createNewWallet } from '../src/utils/startup';
import { updateWallet } from '../src/store/actions/wallet';
import {
backupSeedPhraseTodo,
buyBitcoinTodo,
lightningConnectingTodo,
lightningReadyTodo,
lightningSettingUpTodo,
lightningTodo,
pinTodo,
slashtagsProfileTodo,
transferClosingChannel,
transferToSavingsTodo,
transferToSpendingTodo,
} from '../src/store/shapes/todos';
import { IBtOrder } from '@synonymdev/blocktank-lsp-http-client';
import { TChannel } from '@synonymdev/react-native-ldk';

describe('Todos selector', () => {
let s: Store;

beforeAll(async () => {
require('../nodejs-assets/nodejs-project/main.js');
let res = await createNewWallet();
if (res.isErr()) {
throw res.error;
}
updateWallet({ selectedNetwork: 'bitcoinRegtest' });
s = store.getState();
});

it('should return default set of todos', () => {
assert.deepEqual(todosFullSelector(s), [
backupSeedPhraseTodo,
lightningTodo,
pinTodo,
slashtagsProfileTodo,
buyBitcoinTodo,
]);
});

it('should not return pinTodo if PIN is set', () => {
const state = cloneDeep(s);
state.settings.pin = true;

expect(todosFullSelector(state)).not.toEqual(
expect.arrayContaining([pinTodo]),
);
});

it('should not return backupSeedPhraseTodo if backup is verified', () => {
const state = cloneDeep(s);
state.user.backupVerified = true;

expect(todosFullSelector(state)).not.toEqual(
expect.arrayContaining([backupSeedPhraseTodo]),
);
});

it('should not return slashtagsProfileTodo if profile is set', () => {
const state = cloneDeep(s);
state.slashtags.onboardingProfileStep = 'Done';

expect(todosFullSelector(state)).not.toEqual(
expect.arrayContaining([slashtagsProfileTodo]),
);
});

it('should not return hidden todos', () => {
const state = cloneDeep(s);
state.todos.hide = {
backupSeedPhrase: +new Date(),
pin: +new Date(),
slashtagsProfile: +new Date(),
buyBitcoin: +new Date(),
lightning: +new Date(),
};

assert.deepEqual(todosFullSelector(state), []);
});

it('should return lightningSettingUpTodo if there is a pending BT order', () => {
const state = cloneDeep(s);
state.blocktank.orders.push({
id: 'order1',
state: 'created',
} as IBtOrder);
state.blocktank.paidOrders = { order1: 'txid' };

expect(todosFullSelector(state)).toEqual(
expect.arrayContaining([lightningSettingUpTodo]),
);
});

it('should return lightningConnectingTodo if there is a pending channel', () => {
const state = cloneDeep(s);

const channel1 = {
channel_id: 'channel1',
is_channel_ready: false,
} as TChannel;
state.lightning.nodes.wallet0.channels.bitcoinRegtest = { channel1 };
state.lightning.nodes.wallet0.openChannelIds.bitcoinRegtest = ['channel1'];

expect(todosFullSelector(state)).toEqual(
expect.arrayContaining([lightningConnectingTodo]),
);
});

it('should return transferClosingChannel if there are gracefully closing channels', () => {
const state = cloneDeep(s);

const channel1 = {
channel_id: 'channel1',
is_channel_ready: true,
} as TChannel;
state.lightning.nodes.wallet0.channels.bitcoinRegtest = { channel1 };
state.lightning.nodes.wallet0.openChannelIds.bitcoinRegtest = ['channel1'];
state.user.startCoopCloseTimestamp = 123;

expect(todosFullSelector(state)).toEqual(
expect.arrayContaining([transferClosingChannel]),
);
});

it('should return transferToSpendingTodo if there are new pending BT orders', () => {
const state = cloneDeep(s);

const channel1 = {
channel_id: 'channel1',
is_channel_ready: true,
} as TChannel;
state.lightning.nodes.wallet0.channels.bitcoinRegtest = { channel1 };
state.lightning.nodes.wallet0.openChannelIds.bitcoinRegtest = ['channel1'];
state.blocktank.orders.push({ id: 'order1', state: 'created' } as IBtOrder);
state.blocktank.paidOrders = { order1: 'txid' };

expect(todosFullSelector(state)).toEqual(
expect.arrayContaining([transferToSpendingTodo]),
);
});

it('should return transferToSavingsTodo if there is a new claimable balance', () => {
const state = cloneDeep(s);

const channel1 = {
channel_id: 'channel1',
is_channel_ready: true,
} as TChannel;
state.lightning.nodes.wallet0.channels.bitcoinRegtest = { channel1 };
state.lightning.nodes.wallet0.openChannelIds.bitcoinRegtest = ['channel1'];
state.lightning.nodes.wallet0.claimableBalance.bitcoinRegtest = 123;

expect(todosFullSelector(state)).toEqual(
expect.arrayContaining([transferToSavingsTodo]),
);
});

it('should return lightningReadyTodo if there is a new open channel', () => {
const state = cloneDeep(s);

const channel1 = {
channel_id: 'channel1',
is_channel_ready: true,
confirmations: 1,
confirmations_required: 1,
} as TChannel;
state.lightning.nodes.wallet0.channels.bitcoinRegtest = { channel1 };
state.lightning.nodes.wallet0.openChannelIds.bitcoinRegtest = ['channel1'];

expect(todosFullSelector(state)).toEqual(
expect.arrayContaining([lightningReadyTodo]),
);
});

it('should return not lightningReadyTodo if notification has already been shown', () => {
const state = cloneDeep(s);

const channel1 = {
channel_id: 'channel1',
is_channel_ready: true,
confirmations: 1,
confirmations_required: 1,
} as TChannel;
state.lightning.nodes.wallet0.channels.bitcoinRegtest = { channel1 };
state.lightning.nodes.wallet0.openChannelIds.bitcoinRegtest = ['channel1'];
state.todos.newChannelsNotifications = { channel1: +new Date() };

expect(todosFullSelector(state)).not.toEqual(
expect.arrayContaining([lightningReadyTodo]),
);
});
});
2 changes: 1 addition & 1 deletion __tests__/wallet-send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe('Wallet - new wallet, send and receive', () => {
expect(res.value).toEqual('Wallet created');

// switch to regtest
await updateWallet({ selectedNetwork: 'bitcoinRegtest' });
updateWallet({ selectedNetwork: 'bitcoinRegtest' });
expect(store.getState().wallet.selectedNetwork).toEqual('bitcoinRegtest');

res = await addElectrumPeer({
Expand Down
9 changes: 2 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,7 @@
"immer": "^9.0.19",
"intl-messageformat": "^10.5.0",
"jdenticon": "^3.2.0",
"lodash.clonedeep": "^4.5.0",
"lodash.debounce": "^4.0.8",
"lodash.isequal": "^4.5.0",
"lodash.throttle": "^4.1.1",
"lodash": "^4.17.21",
"lottie-react-native": "^5.1.5",
"mime": "3.0.0",
"nodejs-mobile-react-native": "github:Shopify/nodejs-mobile-react-native#a74b13a8f92b39805611c3458e453e57e5abe98f",
Expand Down Expand Up @@ -172,9 +169,7 @@
"@types/b4a": "^1.6.0",
"@types/bip21": "^2.0.0",
"@types/jest": "^29.5.1",
"@types/lodash.debounce": "^4.0.7",
"@types/lodash.isequal": "^4.5.6",
"@types/lodash.throttle": "^4.1.7",
"@types/lodash": "^4.14.199",
"@types/mime": "^3.0.1",
"@types/react": "^18.2.7",
"@types/react-native": "0.72.2",
Expand Down
14 changes: 3 additions & 11 deletions src/components/AssetCard.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import React, { memo, ReactElement } from 'react';
import { useSelector } from 'react-redux';
import { View, GestureResponderEvent, StyleSheet } from 'react-native';

import { ClockIcon } from '../styles/icons';
import { Text01M, Caption13M } from '../styles/text';
import { TouchableOpacity } from '../styles/components';
import Money from '../components/Money';
import { useSelector } from 'react-redux';
import Store from '../store/types';
import {
selectedNetworkSelector,
selectedWalletSelector,
} from '../store/reselect/wallet';
import { openChannelIdsSelector } from '../store/reselect/lightning';

const AssetCard = ({
Expand All @@ -29,11 +25,7 @@ const AssetCard = ({
testID?: string;
onPress: (event: GestureResponderEvent) => void;
}): ReactElement => {
const selectedWallet = useSelector(selectedWalletSelector);
const selectedNetwork = useSelector(selectedNetworkSelector);
const openChannelIds = useSelector((state: Store) => {
return openChannelIdsSelector(state, selectedWallet, selectedNetwork);
});
const openChannelIds = useSelector(openChannelIdsSelector);

const isTransferToSavings = openChannelIds.length === 0;

Expand Down
2 changes: 1 addition & 1 deletion src/components/FancySlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React, {
useState,
} from 'react';
import { Animated, PanResponder, StyleSheet, View } from 'react-native';
import throttle from 'lodash.throttle';
import throttle from 'lodash/throttle';

import { View as ThemedView } from '../styles/components';
import useColors from '../hooks/colors';
Expand Down
2 changes: 1 addition & 1 deletion src/components/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
TouchableOpacity,
} from 'react-native';
import { SvgProps } from 'react-native-svg';
import isEqual from 'lodash.isequal';
import isEqual from 'lodash/isEqual';

import { Switch } from '../styles/components';
import {
Expand Down
15 changes: 1 addition & 14 deletions src/components/SuggestionCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { memo, ReactElement, useEffect, useMemo, useRef } from 'react';
import React, { memo, ReactElement, useEffect, useMemo } from 'react';
import { StyleSheet, Image, View } from 'react-native';
import Animated, {
useSharedValue,
Expand All @@ -20,7 +20,6 @@ import { Pressable } from '../styles/components';
import { Caption13M, Text01M } from '../styles/text';
import { XIcon } from '../styles/icons';
import { ITodo, TTodoType } from '../store/types/todos';
import { removeTodo } from '../store/actions/todos';
import useColors from '../hooks/colors';
import Card from './Card';

Expand Down Expand Up @@ -88,12 +87,10 @@ const SuggestionCard = ({
title,
description,
dismissable,
temporary,
onPress,
onClose,
}: CardProps): ReactElement => {
const colors = useColors();
const timeout = useRef<NodeJS.Timeout>();
const glowOpacity = useSharedValue(0);

const containerStyle = useMemo(
Expand All @@ -111,16 +108,6 @@ const SuggestionCard = ({
glowOpacity.value = withRepeat(withTiming(1, { duration: 1100 }), -1, true);
}, [glowOpacity]);

useEffect(() => {
if (temporary) {
timeout.current = setTimeout(() => removeTodo(id), 4000);
}

return (): void => {
clearTimeout(timeout.current);
};
}, [id, temporary]);

return (
<Card style={containerStyle} testID={`Suggestion-${id}`}>
{dismissable ? (
Expand Down
Loading

0 comments on commit 8eb8006

Please sign in to comment.