Browse Source

ADD: Refill with external wallet

walletselecttest
Overtorment 5 years ago
committed by GitHub
parent
commit
ae8dac8ba9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      BlueComponents.js
  2. 28
      MainBottomTabs.js
  3. 10
      class/lightning-custodian-wallet.js
  4. 98
      screen/lnd/manageFunds.js
  5. 96
      screen/receive/details.js
  6. 2
      screen/send/details.js
  7. 126
      screen/wallets/transactions.js

6
BlueComponents.js

@ -234,6 +234,10 @@ export class BlueWalletNavigationHeader extends Component {
});
}
manageFundsPressed = () => {
this.props.onManageFundsPressed();
};
render() {
return (
<LinearGradient
@ -300,7 +304,7 @@ export class BlueWalletNavigationHeader extends Component {
)}
</TouchableOpacity>
{this.state.wallet.type === LightningCustodianWallet.type && (
<TouchableOpacity onPress={() => NavigationService.navigate('ManageFunds', { fromWallet: this.state.wallet })}>
<TouchableOpacity onPress={this.manageFundsPressed}>
<View
style={{
marginTop: 14,

28
MainBottomTabs.js

@ -41,7 +41,6 @@ import sendCreate from './screen/send/create';
import Confirm from './screen/send/confirm';
import Success from './screen/send/success';
import ManageFunds from './screen/lnd/manageFunds';
import ScanLndInvoice from './screen/lnd/scanLndInvoice';
import LappBrowser from './screen/lnd/browser';
import LNDCreateInvoice from './screen/lnd/lndCreateInvoice';
@ -170,21 +169,6 @@ const CreateTransactionStackNavigator = createStackNavigator({
},
});
const ManageFundsStackNavigator = createStackNavigator({
ManageFunds: {
screen: ManageFunds,
},
SelectWallet: {
screen: SelectWallet,
},
SendDetails: {
screen: CreateTransactionStackNavigator,
navigationOptions: {
header: null,
},
},
});
const LNDCreateInvoiceStackNavigator = createStackNavigator({
LNDCreateInvoice: {
screen: LNDCreateInvoice,
@ -260,6 +244,12 @@ const MainBottomTabs = createStackNavigator(
header: null,
},
},
SelectWallet: {
screen: SelectWallet,
navigationOptions: {
headerLeft: null,
}
},
//
@ -275,12 +265,6 @@ const MainBottomTabs = createStackNavigator(
// LND:
ManageFunds: {
screen: ManageFundsStackNavigator,
navigationOptions: {
header: null,
},
},
ScanLndInvoice: {
screen: LightningScanInvoiceStackNavigator,
navigationOptions: {

10
class/lightning-custodian-wallet.js

@ -44,7 +44,11 @@ export class LightningCustodianWallet extends LegacyWallet {
}
getAddress() {
return '';
if (this.refill_addressess.length > 0) {
return this.refill_addressess[0];
} else {
return undefined;
}
}
getSecret() {
@ -358,6 +362,10 @@ export class LightningCustodianWallet extends LegacyWallet {
}
}
async getAddressAsync() {
return this.fetchBtcAddress();
}
getTransactions() {
let txs = [];
this.pending_transactions_raw = this.pending_transactions_raw || [];

98
screen/lnd/manageFunds.js

@ -1,98 +0,0 @@
/* global alert */
import React, { Component } from 'react';
import { TouchableOpacity, Linking, View } from 'react-native';
import { BlueSpacingVariable, BlueNavigationStyle, SafeBlueArea, BlueCard } from '../../BlueComponents';
import { ListItem } from 'react-native-elements';
import PropTypes from 'prop-types';
import { Chain } from '../../models/bitcoinUnits';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let loc = require('../../loc');
export default class ManageFunds extends Component {
static navigationOptions = ({ navigation }) => ({
...BlueNavigationStyle(navigation, true),
title: loc.lnd.title,
headerLeft: null,
});
constructor(props) {
super(props);
this.onWalletSelect = this.onWalletSelect.bind(this);
if (!props.navigation.getParam('fromWallet')) throw new Error('Invalid param');
this.state = { fromWallet: props.navigation.getParam('fromWallet') };
}
async onWalletSelect(wallet) {
this.props.navigation.dismiss();
/** @type {LightningCustodianWallet} */
let toAddress = false;
if (this.state.fromWallet.refill_addressess.length > 0) {
toAddress = this.state.fromWallet.refill_addressess[0];
} else {
try {
await this.state.fromWallet.fetchBtcAddress();
toAddress = this.state.fromWallet.refill_addressess[0];
} catch (Err) {
return alert(Err.message);
}
}
if (wallet) {
setTimeout(() => {
this.props.navigation.navigate('SendDetails', {
memo: loc.lnd.refill_lnd_balance,
fromSecret: wallet.getSecret(),
address: toAddress,
fromWallet: wallet,
});
}, 100);
} else {
return alert('Internal error');
}
}
render() {
return (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
<BlueSpacingVariable />
<BlueCard>
<ListItem
titleStyle={{ color: BlueApp.settings.foregroundColor }}
component={TouchableOpacity}
onPress={a => {
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.ONCHAIN });
}}
title={loc.lnd.refill}
/>
<ListItem
titleStyle={{ color: BlueApp.settings.foregroundColor }}
component={TouchableOpacity}
onPress={a => {
Linking.openURL('https://zigzag.io/?utm_source=integration&utm_medium=bluewallet&utm_campaign=withdrawLink');
}}
title={loc.lnd.withdraw}
/>
<View />
</BlueCard>
</SafeBlueArea>
);
}
}
ManageFunds.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.func,
dismiss: PropTypes.func,
navigate: PropTypes.func,
getParam: PropTypes.func,
state: PropTypes.shape({
params: PropTypes.shape({
fromSecret: PropTypes.string,
}),
}),
}),
};

96
screen/receive/details.js

@ -1,4 +1,3 @@
/* global alert */
import React, { Component } from 'react';
import { View, InteractionManager } from 'react-native';
import QRCode from 'react-native-qrcode-svg';
@ -17,6 +16,7 @@ import Privacy from '../../Privacy';
import Share from 'react-native-share';
import { ScrollView } from 'react-native-gesture-handler';
import SystemSetting from 'react-native-system-setting';
import { Chain } from '../../models/bitcoinUnits';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let loc = require('../../loc');
@ -30,65 +30,83 @@ export default class ReceiveDetails extends Component {
constructor(props) {
super(props);
let address = props.navigation.state.params.address;
let secret = props.navigation.state.params.secret;
let address = props.navigation.state.params.address || '';
let secret = props.navigation.state.params.secret || '';
this.state = {
address: address,
secret: secret,
addressText: '',
addressText: address,
bip21encoded: undefined,
};
}
async componentDidMount() {
Privacy.enableBlur();
await SystemSetting.saveBrightness();
await SystemSetting.setAppBrightness(1.0);
console.log('receive/details - componentDidMount');
/** @type {AbstractWallet} */
let wallet;
let address = this.state.address;
for (let w of BlueApp.getWallets()) {
if ((address && w.getAddress() === this.state.address) || w.getSecret() === this.state.secret) {
// found our wallet
wallet = w;
if (address.trim().length === 0) {
let wallet;
for (let w of BlueApp.getWallets()) {
if ((address && w.getAddress() === this.state.address) || w.getSecret() === this.state.secret) {
// found our wallet
wallet = w;
}
}
}
if (wallet) {
if (wallet.getAddressAsync) {
try {
address = await Promise.race([wallet.getAddressAsync(), BlueApp.sleep(1000)]);
} catch (_) {}
if (!address) {
// either sleep expired or getAddressAsync threw an exception
console.warn('either sleep expired or getAddressAsync threw an exception');
address = wallet._getExternalAddressByIndex(wallet.next_free_address_index);
if (wallet) {
if (wallet.getAddressAsync) {
if (wallet.chain === Chain.ONCHAIN) {
try {
address = await Promise.race([wallet.getAddressAsync(), BlueApp.sleep(1000)]);
} catch (_) {}
if (!address) {
// either sleep expired or getAddressAsync threw an exception
console.warn('either sleep expired or getAddressAsync threw an exception');
address = wallet._getExternalAddressByIndex(wallet.next_free_address_index);
} else {
BlueApp.saveToDisk(); // caching whatever getAddressAsync() generated internally
}
this.setState({
address: address,
addressText: address,
});
} else if (wallet.chain === Chain.OFFCHAIN) {
try {
await Promise.race([wallet.getAddressAsync(), BlueApp.sleep(1000)]);
address = wallet.getAddress();
} catch (_) {}
if (!address) {
// either sleep expired or getAddressAsync threw an exception
console.warn('either sleep expired or getAddressAsync threw an exception');
address = wallet.getAddress();
} else {
BlueApp.saveToDisk(); // caching whatever getAddressAsync() generated internally
}
}
this.setState({
address: address,
addressText: address,
});
} else if (wallet.getAddress) {
this.setState({
address: address,
addressText: address,
});
} else {
BlueApp.saveToDisk(); // caching whatever getAddressAsync() generated internally
this.setState({
address,
addressText: address,
});
}
this.setState({
address: address,
addressText: address,
});
} else if (wallet.getAddress) {
address = wallet.getAddress();
this.setState({
address: address,
addressText: address,
});
} else {
alert('There was a problem obtaining your receive address. Please, try again.');
this.props.navigation.goBack();
this.setState({
address,
addressText: address,
});
}
}
InteractionManager.runAfterInteractions(async () => {
await SystemSetting.saveBrightness();
await SystemSetting.setAppBrightness(1.0);
const bip21encoded = bip21.encode(this.state.address);
this.setState({ bip21encoded });
});

2
screen/send/details.js

@ -37,8 +37,8 @@ import BitcoinBIP70TransactionDecode from '../../bip70/bip70';
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
import { HDLegacyP2PKHWallet, HDSegwitBech32Wallet, HDSegwitP2SHWallet, LightningCustodianWallet } from '../../class';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
const bitcoin = require('bitcoinjs-lib');
import { BitcoinTransaction } from '../../models/bitcoinTransactionInfo';
const bitcoin = require('bitcoinjs-lib');
const bip21 = require('bip21');
let BigNumber = require('bignumber.js');
const { width } = Dimensions.get('window');

126
screen/wallets/transactions.js

@ -4,21 +4,33 @@ import { Chain } from '../../models/bitcoinUnits';
import {
Text,
Platform,
StyleSheet,
View,
Keyboard,
ActivityIndicator,
InteractionManager,
FlatList,
RefreshControl,
TouchableOpacity,
StatusBar,
Linking,
KeyboardAvoidingView,
} from 'react-native';
import PropTypes from 'prop-types';
import { NavigationEvents } from 'react-navigation';
import { BlueSendButtonIcon, BlueReceiveButtonIcon, BlueTransactionListItem, BlueWalletNavigationHeader } from '../../BlueComponents';
import {
BlueSendButtonIcon,
BlueListItem,
BlueReceiveButtonIcon,
BlueTransactionListItem,
BlueWalletNavigationHeader,
} from '../../BlueComponents';
import { Icon } from 'react-native-elements';
import { LightningCustodianWallet } from '../../class';
import Handoff from 'react-native-handoff';
import { ScrollView } from 'react-native-gesture-handler';
import Modal from 'react-native-modal';
import NavigationService from '../../NavigationService';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let loc = require('../../loc');
@ -63,6 +75,7 @@ export default class WalletTransactions extends Component {
this.state = {
showMarketplace: Platform.OS !== 'ios',
isLoading: true,
isManageFundsModalVisible: false,
showShowFlatListRefreshControl: false,
wallet: wallet,
dataSource: this.getTransactions(15),
@ -206,7 +219,88 @@ export default class WalletTransactions extends Component {
</View>
);
};
renderManageFundsModal = () => {
return (
<Modal
isVisible={this.state.isManageFundsModalVisible}
style={styles.bottomModal}
onBackdropPress={() => {
Keyboard.dismiss();
this.setState({ isManageFundsModalVisible: false });
}}
>
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'position' : null}>
<View style={styles.advancedTransactionOptionsModalContent}>
<BlueListItem
hideChevron
component={TouchableOpacity}
onPress={a => {
const wallets = [...BlueApp.getWallets().filter(item => item.chain === Chain.ONCHAIN && item.allowSend())];
if (wallets.length === 0) {
alert('In order to proceed, please create a Bitcoin wallet to refill with.');
} else {
this.setState({ isManageFundsModalVisible: false });
this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.ONCHAIN });
}
}}
title={loc.lnd.refill}
/>
<BlueListItem
hideChevron
component={TouchableOpacity}
onPress={a => {
this.setState({ isManageFundsModalVisible: false }, () =>
this.props.navigation.navigate('ReceiveDetails', {
secret: this.state.wallet.getSecret(),
}),
);
}}
title={'Refill with External Wallet'}
/>
<BlueListItem
title={loc.lnd.withdraw}
hideChevron
component={TouchableOpacity}
onPress={a => {
this.setState({ isManageFundsModalVisible: false });
Linking.openURL('https://zigzag.io/?utm_source=integration&utm_medium=bluewallet&utm_campaign=withdrawLink');
}}
/>
</View>
</KeyboardAvoidingView>
</Modal>
);
};
onWalletSelect = async wallet => {
NavigationService.navigate('WalletTransactions');
/** @type {LightningCustodianWallet} */
let toAddress = false;
if (this.state.wallet.refill_addressess.length > 0) {
toAddress = this.state.wallet.refill_addressess[0];
} else {
try {
await this.state.wallet.fetchBtcAddress();
toAddress = this.state.wallet.refill_addressess[0];
} catch (Err) {
return alert(Err.message);
}
}
if (wallet) {
this.props.navigation.navigate('SendDetails', {
memo: loc.lnd.refill_lnd_balance,
fromSecret: wallet.getSecret(),
address: toAddress,
fromWallet: wallet,
});
} else {
return alert('Internal error');
}
};
async onWillBlur() {
StatusBar.setBarStyle('dark-content');
}
@ -245,6 +339,7 @@ export default class WalletTransactions extends Component {
this.setState({ wallet }, () => InteractionManager.runAfterInteractions(() => BlueApp.saveToDisk()));
})
}
onManageFundsPressed={() => this.setState({ isManageFundsModalVisible: true })}
/>
<View style={{ flex: 1, backgroundColor: '#FFFFFF' }}>
{this.state.showMarketplace && (
@ -343,6 +438,7 @@ export default class WalletTransactions extends Component {
renderItem={this.renderItem}
contentInset={{ top: 0, left: 0, bottom: 90, right: 0 }}
/>
{this.renderManageFundsModal()}
</View>
<View
style={{
@ -397,6 +493,32 @@ export default class WalletTransactions extends Component {
}
}
const styles = StyleSheet.create({
modalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
justifyContent: 'center',
alignItems: 'center',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 200,
height: 200,
},
advancedTransactionOptionsModalContent: {
backgroundColor: '#FFFFFF',
padding: 22,
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
borderColor: 'rgba(0, 0, 0, 0.1)',
minHeight: 130,
},
bottomModal: {
justifyContent: 'flex-end',
margin: 0,
},
});
WalletTransactions.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func,

Loading…
Cancel
Save