Skip to content

Commit 7ee0152

Browse files
committed
feat: implement auto coin select
Implement and enable auto coin select functionality in Advanced Settings.
1 parent 4da383e commit 7ee0152

File tree

12 files changed

+138
-400
lines changed

12 files changed

+138
-400
lines changed

.env.development.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ ELECTRUM_BITCOIN_SSL_PORT=8900
3232
ELECTRUM_BITCOIN_TCP_PORT=8911
3333
ELECTRUM_BITCOIN_PROTO=ssl
3434

35-
ELECTRUM_REGTEST_HOST=34.65.86.104
35+
ELECTRUM_REGTEST_HOST=35.233.47.252
3636
ELECTRUM_REGTEST_SSL_PORT=18484
3737
ELECTRUM_REGTEST_TCP_PORT=18483
3838
ELECTRUM_REGTEST_PROTO=tcp

ios/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2308,7 +2308,7 @@ SPEC CHECKSUMS:
23082308
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
23092309
sodium-react-native-direct: 8feb9a6d0d88ce65efa305d6cc774c11c62d9a15
23102310
SSZipArchive: c69881e8ac5521f0e622291387add5f60f30f3c4
2311-
Yoga: a1d7895431387402a674fd0d1c04ec85e87909b8
2311+
Yoga: 2a45d7e59592db061217551fd3bbe2dd993817ae
23122312
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
23132313

23142314
PODFILE CHECKSUM: cb153cb4a39e6c92c8b869eafab65a4bba7b869f

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"@synonymdev/slashtags-widget-news-feed": "1.1.0",
6161
"@synonymdev/slashtags-widget-price-feed": "1.1.0",
6262
"@synonymdev/web-relay": "1.0.7",
63-
"beignet": "0.0.51",
63+
"beignet": "0.0.52",
6464
"bip21": "2.0.3",
6565
"bip32": "4.0.0",
6666
"bitcoin-address-validation": "2.2.3",

src/screens/Settings/CoinSelectPreference/index.tsx

Lines changed: 71 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1-
import React, { memo, ReactElement, useMemo } from 'react';
1+
import React, { memo, ReactElement, useCallback, useMemo } from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { useAppDispatch, useAppSelector } from '../../../hooks/redux';
44

55
import { EItemType, IListData } from '../../../components/List';
6-
import { coinSelectAutoSelector } from '../../../store/reselect/settings';
76
import { updateSettings } from '../../../store/slices/settings';
7+
import {
8+
coinSelectAutoSelector,
9+
coinSelectPreferenceSelector,
10+
} from '../../../store/reselect/settings';
11+
import { ECoinSelectPreference } from "beignet";
12+
import { updateCoinSelectPreference } from "../../../utils/settings";
813
import SettingsView from '../SettingsView';
14+
import { getOnChainWalletAsync } from "../../../utils/wallet";
915

1016
const CoinSelectSettings = (): ReactElement => {
1117
const { t } = useTranslation('settings');
1218
const dispatch = useAppDispatch();
1319
const selectedAutoPilot = useAppSelector(coinSelectAutoSelector);
14-
//const coinSelectPreference = useAppSelector(coinSelectPreferenceSelector);
20+
const coinSelectPreference = useAppSelector(coinSelectPreferenceSelector);
1521

1622
const settingsListData: IListData[] = useMemo(
1723
() => [
@@ -22,73 +28,84 @@ const CoinSelectSettings = (): ReactElement => {
2228
title: t('adv.cs_manual'),
2329
value: !selectedAutoPilot,
2430
type: EItemType.button,
25-
onPress: (): void => {
31+
onPress: async (): Promise<void> => {
32+
// Update the coin selection preference in beignet.
33+
const wallet = await getOnChainWalletAsync();
34+
// Set beignet to consolidate if manual coin control is enabled in Bitkit.
35+
wallet.updateCoinSelectPreference(ECoinSelectPreference.consolidate);
2636
dispatch(updateSettings({ coinSelectAuto: false }));
2737
},
2838
},
2939
{
3040
title: t('adv.cs_auto'),
3141
value: selectedAutoPilot,
3242
type: EItemType.button,
33-
onPress: (): void => {
43+
onPress: async (): Promise<void> => {
44+
// Update the coin selection preference in beignet.
45+
const wallet = await getOnChainWalletAsync();
46+
wallet.updateCoinSelectPreference(coinSelectPreference);
3447
dispatch(updateSettings({ coinSelectAuto: true }));
3548
},
3649
},
3750
],
3851
},
39-
/*{
40-
// TODO: Re-Add and enable this feature once thoroughly tested in Beignet.
41-
title: selectedAutoPilot ? t('adv.cs_auto_mode') : '',
42-
data: [
43-
{
44-
title: t('adv.cs_max'),
45-
description: t('adv.cs_max_description'),
46-
value: coinSelectPreference === 'large',
47-
type: EItemType.button,
48-
hide: !selectedAutoPilot,
49-
onPress: (): void => {
50-
dispatch(
51-
updateSettings({
52-
coinSelectAuto: true,
53-
coinSelectPreference: 'large',
54-
}),
55-
);
52+
{
53+
title: selectedAutoPilot ? t('adv.cs_auto_mode') : '',
54+
data: [
55+
{
56+
title: t('adv.cs_max'),
57+
description: t('adv.cs_max_description'),
58+
value: coinSelectPreference === ECoinSelectPreference.small,
59+
type: EItemType.button,
60+
hide: !selectedAutoPilot,
61+
onPress: (): void => {
62+
updateCoinSelectPreference(ECoinSelectPreference.small);
63+
},
64+
},
65+
{
66+
title: t('adv.cs_min'),
67+
description: t('adv.cs_min_description'),
68+
value: coinSelectPreference === ECoinSelectPreference.large,
69+
type: EItemType.button,
70+
hide: !selectedAutoPilot,
71+
onPress: (): void => {
72+
updateCoinSelectPreference(ECoinSelectPreference.large);
73+
},
74+
},
75+
{
76+
title: t('adv.cs_consolidate'),
77+
description: t('adv.cs_consolidate_description'),
78+
value: coinSelectPreference === ECoinSelectPreference.consolidate,
79+
type: EItemType.button,
80+
hide: !selectedAutoPilot,
81+
onPress: (): void => {
82+
updateCoinSelectPreference(ECoinSelectPreference.consolidate);
83+
},
5684
},
57-
},
58-
{
59-
title: t('adv.cs_min'),
60-
description: t('adv.cs_min_description'),
61-
value: coinSelectPreference === 'small',
62-
type: EItemType.button,
63-
hide: !selectedAutoPilot,
64-
onPress: (): void => {
65-
dispatch(
66-
updateSettings({
67-
coinSelectAuto: true,
68-
coinSelectPreference: 'small',
69-
}),
70-
);
85+
{
86+
title: t('adv.cs_first_in_first_out'),
87+
description: t('adv.cs_first_in_first_out_description'),
88+
value: coinSelectPreference === ECoinSelectPreference.firstInFirstOut,
89+
type: EItemType.button,
90+
hide: !selectedAutoPilot,
91+
onPress: (): void => {
92+
updateCoinSelectPreference(ECoinSelectPreference.firstInFirstOut);
93+
},
7194
},
72-
},
73-
{
74-
title: t('adv.cs_consolidate'),
75-
description: t('adv.cs_consolidate_description'),
76-
value: coinSelectPreference === 'consolidate',
77-
type: EItemType.button,
78-
hide: !selectedAutoPilot,
79-
onPress: (): void => {
80-
dispatch(
81-
updateSettings({
82-
coinSelectAuto: true,
83-
coinSelectPreference: 'consolidate',
84-
}),
85-
);
95+
{
96+
title: t('adv.cs_last_in_last_out'),
97+
description: t('adv.cs_last_in_last_out_description'),
98+
value: coinSelectPreference === ECoinSelectPreference.lastInFirstOut,
99+
type: EItemType.button,
100+
hide: !selectedAutoPilot,
101+
onPress: (): void => {
102+
updateCoinSelectPreference(ECoinSelectPreference.lastInFirstOut);
103+
},
86104
},
87-
},
88-
],
89-
},*/
105+
],
106+
},
90107
],
91-
[selectedAutoPilot, t, dispatch],
108+
[selectedAutoPilot, coinSelectPreference, t, dispatch],
92109
);
93110

94111
return (

src/store/shapes/settings.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EProtocol, TServer } from 'beignet';
1+
import { ECoinSelectPreference, EProtocol, TServer } from 'beignet';
22
import cloneDeep from 'lodash/cloneDeep';
33

44
import {
@@ -91,7 +91,7 @@ export const initialSettingsState: TSettings = {
9191
customElectrumPeers: defaultElectrumPeer,
9292
rapidGossipSyncUrl: 'https://rgs.blocktank.to/snapshot/',
9393
coinSelectAuto: true,
94-
coinSelectPreference: 'small',
94+
coinSelectPreference: ECoinSelectPreference.small,
9595
receivePreference: defaultReceivePreference,
9696
enableDevOptions: __DEV__,
9797
enableOfflinePayments: false,

src/store/slices/settings.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
2-
import { TServer } from 'beignet';
2+
import { ECoinSelectPreference, TServer } from 'beignet';
33

44
import { EAvailableNetwork } from '../../utils/networks';
55
import { initialSettingsState } from '../shapes/settings';
66
import {
77
ETransactionSpeed,
88
ICustomElectrumPeer,
99
TChest,
10-
TCoinSelectPreference,
1110
TReceiveOption,
1211
TTheme,
1312
} from '../types/settings';
@@ -31,7 +30,7 @@ export type TSettings = {
3130
selectedCurrency: string;
3231
selectedLanguage: string;
3332
coinSelectAuto: boolean;
34-
coinSelectPreference: TCoinSelectPreference;
33+
coinSelectPreference: ECoinSelectPreference;
3534
receivePreference: TReceiveOption[];
3635
enableDevOptions: boolean;
3736
enableOfflinePayments: boolean;

src/store/types/settings.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@ export enum ETransactionSpeed {
1717
custom = 'custom',
1818
}
1919

20-
/**
21-
* large = Sort by and use largest UTXO first. Lowest fee, but reveals your largest UTXO's.
22-
* small = Sort by and use smallest UTXO first. Higher fee, but hides your largest UTXO's.
23-
* consolidate = Use all available UTXO's regardless of the amount being sent. Preferable to use this method when fees are low in order to reduce fees in future transactions.
24-
*/
25-
export type TCoinSelectPreference = 'small' | 'large' | 'consolidate';
2620

2721
export interface ICustomElectrumPeer {
2822
host: string;

src/utils/i18n/locales/en/settings.json

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -427,23 +427,35 @@
427427
"string": "Autopilot Mode"
428428
},
429429
"cs_max": {
430-
"string": "More Private"
430+
"string": "Smallest First"
431431
},
432432
"cs_max_description": {
433-
"string": "Sort by and use smallest UTXO first. Higher fee, but hides your largest UTXO's."
433+
"string": "Sort by and use smallest UTXO first. Potentially higher fee, but hides your largest UTXO's."
434434
},
435435
"cs_min": {
436-
"string": "Lowest Fee"
436+
"string": "Largest First"
437437
},
438438
"cs_min_description": {
439-
"string": "Sort by and use largest UTXO first. Lowest fee, but reveals your largest UTXO's."
439+
"string": "Sort by and use largest UTXO first. Potentially lower fee, but reveals your largest UTXO's."
440440
},
441441
"cs_consolidate": {
442442
"string": "Consolidate"
443443
},
444444
"cs_consolidate_description": {
445445
"string": "Use all available UTXO's regardless of the amount being sent. Use this method when fees are low in order to reduce fees in future transactions."
446446
},
447+
"cs_first_in_first_out": {
448+
"string": "First-In First-Out"
449+
},
450+
"cs_first_in_first_out_description": {
451+
"string": "Use older UTXO's first (by block height)."
452+
},
453+
"cs_last_in_last_out": {
454+
"string": "Last-In Last-Out"
455+
},
456+
"cs_last_in_last_out_description": {
457+
"string": "Use newer UTXO's first (by block height)."
458+
},
447459
"payment_preference": {
448460
"string": "Payment Preference"
449461
},

src/utils/settings/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { PIN_ATTEMPTS } from '../../constants/app';
22
import { dispatch } from '../../store/helpers';
33
import { updateSettings } from '../../store/slices/settings';
44
import { resetKeychainValue, setKeychainValue } from '../keychain';
5+
import { ECoinSelectPreference } from "beignet";
6+
import { getOnChainWalletAsync } from "../wallet";
57

68
/**
79
* @async
@@ -46,3 +48,11 @@ export const removePin = async (): Promise<void> => {
4648
resetKeychainValue('pin'),
4749
]);
4850
};
51+
52+
export const updateCoinSelectPreference = async (
53+
preference: ECoinSelectPreference
54+
): Promise<void> => {
55+
const wallet = await getOnChainWalletAsync();
56+
wallet.updateCoinSelectPreference(preference);
57+
dispatch(updateSettings({ coinSelectAuto: true, coinSelectPreference: preference }));
58+
}

0 commit comments

Comments
 (0)