Browse Source

ADD: Created BlueAddressInput (#270)

REF: Created BlueAddressInput
FIX: Invalid bip21
REF: Change Blue Wallet strings to BlueWallet
FIX: Many layout bug fixes.
ADD: Autofocus on number inputs
OPS: Upgraded to React Native 0.58
FIX: Fixes for LND view
pulltorefresh
Marcos Rodriguez Vélez 6 years ago
committed by Igor Korsakov
parent
commit
0c32dfb55b
  1. 2
      .flowconfig
  2. 2
      App.js
  3. 163
      BlueComponents.js
  4. 21
      NavigationService.js
  5. 18
      android/app/BUCK
  6. 9
      android/app/app.iml
  7. 31
      android/app/build.gradle
  8. 19
      android/app/build_defs.bzl
  9. 2
      android/app/src/main/AndroidManifest.xml
  10. BIN
      android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf
  11. BIN
      android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf
  12. BIN
      android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf
  13. 20
      android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java
  14. 10
      android/build.gradle
  15. 3
      android/gradle/wrapper/gradle-wrapper.properties
  16. 2
      android/metadata/en-US/full_description.txt
  17. 8
      android/settings.gradle
  18. 3
      babel.config.js
  19. 4
      class/lightning-custodian-wallet.js
  20. 79
      class/walletGradient.js
  21. 4
      events.js
  22. 922
      ios/BlueWallet.xcodeproj/project.pbxproj
  23. 2
      ios/BlueWallet/AppDelegate.h
  24. 12
      ios/BlueWallet/AppDelegate.m
  25. 2
      ios/BlueWallet/Info.plist
  26. 2
      ios/BlueWallet/main.m
  27. 2
      ios/BlueWalletTests/BlueWalletTests.m
  28. 2
      ios/fastlane/metadata/en-US/description.txt
  29. 2
      ios/fastlane/metadata/es-ES/description.txt
  30. 2
      ios/fastlane/metadata/pt-BR/description.txt
  31. 2
      ios/fastlane/metadata/pt-PT/description.txt
  32. 2
      loc/cs_CZ.js
  33. 2
      loc/da_DK.js
  34. 2
      loc/de_DE.js
  35. 2
      loc/en.js
  36. 2
      loc/es.js
  37. 2
      loc/fr_FR.js
  38. 2
      loc/hr_HR.js
  39. 7
      loc/index.js
  40. 2
      loc/nl_NL.js
  41. 2
      loc/pt_BR.js
  42. 2
      loc/pt_PT.js
  43. 4509
      package-lock.json
  44. 16
      package.json
  45. 6
      screen/lnd/lndCreateInvoice.js
  46. 2
      screen/lnd/lndViewAdditionalInvoiceInformation.js
  47. 8
      screen/lnd/lndViewInvoice.js
  48. 120
      screen/lnd/scanLndInvoice.js
  49. 2
      screen/receive/details.js
  50. 64
      screen/receive/receiveAmount.js
  51. 100
      screen/send/details.js
  52. 21
      screen/send/scanQrAddress.js
  53. 122
      screen/settings/about.js
  54. 2
      screen/settings/language.js
  55. 6
      screen/settings/lightningSettings.js
  56. 2
      screen/transactions/details.js
  57. 3
      screen/wallets/add.js
  58. 144
      screen/wallets/details.js
  59. 9
      screen/wallets/list.js
  60. 40
      screen/wallets/reorderWallets.js
  61. 40
      screen/wallets/selectWallet.js
  62. 22
      screen/wallets/transactions.js
  63. 2
      screen/wallets/walletMigrate.js

2
.flowconfig

@ -67,4 +67,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
[version]
^0.78.0
^0.85.0

2
App.js

@ -2,6 +2,7 @@ import React from 'react';
import { Linking } from 'react-native';
import { NavigationActions } from 'react-navigation';
import MainBottomTabs from './MainBottomTabs';
import NavigationService from './NavigationService';
export default class App extends React.Component {
navigator = null;
@ -53,6 +54,7 @@ export default class App extends React.Component {
<MainBottomTabs
ref={nav => {
this.navigator = nav;
NavigationService.setTopLevelNavigator(nav);
}}
/>
);

163
BlueComponents.js

@ -21,14 +21,12 @@ import {
TextInput,
} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { WatchOnlyWallet, LegacyWallet } from './class';
import { LightningCustodianWallet } from './class';
import Carousel from 'react-native-snap-carousel';
import DeviceInfo from 'react-native-device-info';
import { HDLegacyP2PKHWallet } from './class/hd-legacy-p2pkh-wallet';
import { HDLegacyBreadwalletWallet } from './class/hd-legacy-breadwallet-wallet';
import { HDSegwitP2SHWallet } from './class/hd-segwit-p2sh-wallet';
import { LightningCustodianWallet } from './class/lightning-custodian-wallet';
import { BitcoinUnit } from './models/bitcoinUnits';
import NavigationService from './NavigationService';
import WalletGradient from './class/walletGradient';
let loc = require('./loc/');
/** @type {AppStorage} */
let BlueApp = require('./BlueApp');
@ -43,30 +41,29 @@ if (aspectRatio > 1.6) {
export class BlueButton extends Component {
render() {
// eslint-disable-next-line
this.props.buttonStyle = this.props.buttonStyle || {};
const backgroundColor = this.props.disabled ? '#99a0ab' : '#ccddf9';
return (
<Button
activeOpacity={0.1}
delayPressIn={0}
{...this.props}
<TouchableOpacity
style={{
flex: 1,
borderWidth: 0.7,
borderColor: 'transparent',
backgroundColor: this.props.hasOwnProperty('backgroundColor') ? this.props.backgroundColor : backgroundColor,
minHeight: 45,
height: 45,
maxHeight: 45,
borderRadius: 25,
minWidth: width / 1.5,
justifyContent: 'center',
alignItems: 'center',
}}
buttonStyle={Object.assign(
{
backgroundColor: '#ccddf9',
minHeight: 45,
height: 45,
borderWidth: 0,
borderRadius: 25,
},
this.props.buttonStyle,
)}
color="#0c2550"
/>
{...this.props}
>
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
{this.props.icon && <Icon name={this.props.icon.name} type={this.props.icon.type} color={this.props.icon.color} />}
{this.props.title && <Text style={{ marginHorizontal: 8, fontSize: 16, color: '#0c2550' }}>{this.props.title}</Text>}
</View>
</TouchableOpacity>
);
}
}
@ -208,7 +205,7 @@ export class BlueCopyTextToClipboard extends Component {
constructor() {
super();
UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
if (Platform.OS === 'android') UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
}
copyToClipboard = () => {
@ -271,13 +268,12 @@ export class BlueText extends Component {
render() {
return (
<Text
style={Object.assign(
{
color: BlueApp.settings.foregroundColor,
},
style={{
color: BlueApp.settings.foregroundColor,
// eslint-disable-next-line
this.props.style,
)}
...this.props.style,
}}
{...this.props}
/>
);
@ -939,7 +935,7 @@ export class NewWalletPanel extends Component {
style={{ marginVertical: 17 }}
>
<LinearGradient
colors={['#eef0f4', '#eef0f4']}
colors={WalletGradient.createWallet}
style={{
padding: 15,
borderRadius: 10,
@ -1020,39 +1016,6 @@ export class WalletsCarousel extends Component {
);
}
let gradient1 = '#65ceef';
let gradient2 = '#68bbe1';
if (WatchOnlyWallet.type === item.type) {
gradient1 = '#7d7d7d';
gradient2 = '#4a4a4a';
}
if (LegacyWallet.type === item.type) {
gradient1 = '#40fad1';
gradient2 = '#15be98';
}
if (HDLegacyP2PKHWallet.type === item.type) {
gradient1 = '#e36dfa';
gradient2 = '#bd10e0';
}
if (HDLegacyBreadwalletWallet.type === item.type) {
gradient1 = '#fe6381';
gradient2 = '#f99c42';
}
if (HDSegwitP2SHWallet.type === item.type) {
gradient1 = '#c65afb';
gradient2 = '#9053fe';
}
if (LightningCustodianWallet.type === item.type) {
gradient1 = '#f1be07';
gradient2 = '#f79056';
}
return (
<Animated.View
style={{ paddingRight: 10, marginVertical: 17, transform: [{ scale: scaleValue }] }}
@ -1066,13 +1029,13 @@ export class WalletsCarousel extends Component {
onLongPress={WalletsCarousel.handleLongPress}
onPress={() => {
if (WalletsCarousel.handleClick) {
WalletsCarousel.handleClick(index, [gradient1, gradient2]);
WalletsCarousel.handleClick(index);
}
}}
>
<LinearGradient
shadowColor="#000000"
colors={[gradient1, gradient2]}
colors={WalletGradient.gradientsFor(item.type)}
style={{
padding: 15,
borderRadius: 10,
@ -1167,6 +1130,71 @@ export class WalletsCarousel extends Component {
}
}
export class BlueAddressInput extends Component {
static propTypes = {
isLoading: PropTypes.bool,
onChangeText: PropTypes.func,
onBarScanned: PropTypes.func,
address: PropTypes.string,
};
static defaultProps = {
isLoading: false,
address: '',
};
render() {
return (
<View
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
}}
>
<TextInput
onChangeText={text => {
this.props.onChangeText(text);
}}
placeholder={loc.send.details.address}
numberOfLines={1}
value={this.props.address}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }}
editable={!this.props.isLoading}
/>
<TouchableOpacity
disabled={this.props.isLoading}
onPress={() => NavigationService.navigate('ScanQrAddress', { onBarScanned: this.props.onBarScanned })}
style={{
width: 75,
height: 36,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#bebebe',
borderRadius: 4,
paddingVertical: 4,
paddingHorizontal: 8,
marginHorizontal: 4,
}}
>
<Icon name="qrcode" size={22} type="font-awesome" color="#FFFFFF" />
<Text style={{ color: '#FFFFFF' }}>{loc.send.details.scan}</Text>
</TouchableOpacity>
</View>
);
}
}
export class BlueBitcoinAmount extends Component {
static propTypes = {
isLoading: PropTypes.bool,
@ -1204,6 +1232,7 @@ export class BlueBitcoinAmount extends Component {
ref={textInput => (this.textInput = textInput)}
editable={!this.props.isLoading && !this.props.disabled}
value={amount}
autoFocus={this.props.pointerEvents !== 'none'}
placeholderTextColor={this.props.disabled ? '#99a0ab' : '#0f5cc0'}
style={{
color: this.props.disabled ? '#99a0ab' : '#0f5cc0',

21
NavigationService.js

@ -0,0 +1,21 @@
import { NavigationActions } from 'react-navigation';
let _navigator;
function setTopLevelNavigator(navigatorRef) {
_navigator = navigatorRef;
}
function navigate(routeName, params) {
_navigator.dispatch(
NavigationActions.navigate({
routeName,
params,
}),
);
}
export default {
navigate,
setTopLevelNavigator,
};

18
android/app/BUCK

@ -8,23 +8,13 @@
# - `buck install -r android/app` - compile, install and run application
#
load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
lib_deps = []
for jarfile in glob(['libs/*.jar']):
name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')]
lib_deps.append(':' + name)
prebuilt_jar(
name = name,
binary_jar = jarfile,
)
create_aar_targets(glob(["libs/*.aar"]))
for aarfile in glob(['libs/*.aar']):
name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')]
lib_deps.append(':' + name)
android_prebuilt_aar(
name = name,
aar = aarfile,
)
create_jar_targets(glob(["libs/*.jar"]))
android_library(
name = "all-libs",

9
android/app/app.iml

@ -133,7 +133,6 @@
<orderEntry type="jdk" jdkName="Android API 27 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: org.webkit:android-jsc:r174650@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-ads-identifier:16.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable:27.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:fresco:1.10.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.react:react-native:0.57.8@aar" level="project" />
@ -147,26 +146,21 @@
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp:3.11.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.parse.bolts:bolts-tasks:1.4.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:exifinterface:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-analytics-impl:16.0.6@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-v4:27.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.core:runtime:1.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-urlconnection:3.11.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable:27.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-okhttp3:1.10.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-tagmanager-v4-impl:16.0.6@aar" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-base:1.10.0@aar" level="project" />
<orderEntry type="library" name="Gradle: io.sentry:sentry:1.7.5@jar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-stats:16.0.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.14.0@jar" level="project" />
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-base:16.0.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui:27.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-compat:27.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.infer.annotation:infer-annotation:0.11.2@jar" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline:1.10.0@aar" level="project" />
<orderEntry type="library" name="Gradle: org.slf4j:slf4j-api:1.7.24@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-media-compat:27.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-basement:16.0.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.code.findbugs:jsr305:3.0.2@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-fragment:27.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: io.sentry:sentry-android:1.7.5@jar" level="project" />
@ -174,10 +168,7 @@
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7:27.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.fasterxml.jackson.core:jackson-core:2.8.7@jar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-measurement-base:16.0.5@aar" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.soloader:soloader:0.5.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-tasks:16.0.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-analytics:16.0.6@aar" level="project" />
<orderEntry type="module" module-name="react-native-webview" />
<orderEntry type="module" module-name="react-native-linear-gradient" />
<orderEntry type="module" module-name="react-native-svg" />

31
android/app/build.gradle

@ -126,7 +126,7 @@ android {
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2]
def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
@ -137,22 +137,19 @@ android {
}
dependencies {
compile project(':react-native-webview')
compile project(':react-native-vector-icons')
compile project(':react-native-svg')
compile project(':react-native-camera')
compile project(':react-native-sentry')
compile project(':react-native-randombytes')
compile project(':react-native-prompt-android')
compile project(':react-native-linear-gradient')
compile project(':react-native-haptic-feedback')
compile project(':react-native-google-analytics-bridge')
compile project(':react-native-gesture-handler')
compile project(':react-native-fs')
compile project(':react-native-device-info')
implementation "com.android.support:exifinterface:+"
implementation "com.android.support:support-annotations:+"
implementation "com.android.support:support-v4:27.1.1"
implementation project(':react-native-webview')
implementation project(':react-native-svg')
implementation project(':react-native-vector-icons')
implementation project(':react-native-sentry')
implementation project(':react-native-randombytes')
implementation project(':react-native-prompt-android')
implementation project(':react-native-linear-gradient')
implementation project(':react-native-haptic-feedback')
implementation project(':react-native-google-analytics-bridge')
implementation project(':react-native-gesture-handler')
implementation project(':react-native-fs')
implementation project(':react-native-device-info')
implementation project(':react-native-camera')
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "com.facebook.react:react-native:+" // From node_modules

19
android/app/build_defs.bzl

@ -0,0 +1,19 @@
"""Helper definitions to glob .aar and .jar targets"""
def create_aar_targets(aarfiles):
for aarfile in aarfiles:
name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
lib_deps.append(":" + name)
android_prebuilt_aar(
name = name,
aar = aarfile,
)
def create_jar_targets(jarfiles):
for jarfile in jarfiles:
name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
lib_deps.append(":" + name)
prebuilt_jar(
name = name,
binary_jar = jarfile,
)

2
android/app/src/main/AndroidManifest.xml

@ -4,11 +4,11 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<activity

BIN
android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf

Binary file not shown.

BIN
android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf

Binary file not shown.

BIN
android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf

Binary file not shown.

20
android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java

@ -3,6 +3,17 @@ package io.bluewallet.bluewallet;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.reactnativecommunity.webview.RNCWebViewPackage;
import io.sentry.RNSentryPackage;
import com.bitgo.randombytes.RandomBytesPackage;
import im.shimo.react.prompt.RNPromptPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.mkuczera.RNReactNativeHapticFeedbackPackage;
import com.idehub.GoogleAnalyticsBridge.GoogleAnalyticsBridgePackage;
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import com.rnfs.RNFSPackage;
import com.learnium.RNDeviceInfo.RNDeviceInfo;
import org.reactnative.camera.RNCameraPackage;
import io.sentry.RNSentryPackage;
import com.bitgo.randombytes.RandomBytesPackage;
import im.shimo.react.prompt.RNPromptPackage;
@ -42,19 +53,18 @@ public class MainApplication extends Application implements ReactApplication {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNCWebViewPackage(),
new RNSentryPackage(),
new RandomBytesPackage(),
new RNPromptPackage(),
new LinearGradientPackage(),
new RNReactNativeHapticFeedbackPackage(),
new GoogleAnalyticsBridgePackage(),
new RNCWebViewPackage(),
new RNDeviceInfo(),
new LinearGradientPackage(),
new RNFSPackage() ,
new VectorIconsPackage(),
new SvgPackage(),
new LinearGradientPackage(),
new RNDeviceInfo(),
new RNCameraPackage(),
new RNCameraPackage(),
new RNGestureHandlerPackage()
);
}

10
android/build.gradle

@ -2,11 +2,11 @@
buildscript {
ext {
buildToolsVersion = "28.0.3"
buildToolsVersion = "28.0.2"
minSdkVersion = 16
compileSdkVersion = 27
targetSdkVersion = 26
supportLibVersion = "27.1.1"
compileSdkVersion = 28
targetSdkVersion = 27
supportLibVersion = "28.0.0"
}
repositories {
google()
@ -34,6 +34,6 @@ allprojects {
task wrapper(type: Wrapper) {
gradleVersion = '4.4'
gradleVersion = '4.7'
distributionUrl = distributionUrl.replace("bin", "all")
}

3
android/gradle/wrapper/gradle-wrapper.properties

@ -1,6 +1,5 @@
#Sat Jan 19 02:29:20 GMT 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-all.zip

2
android/metadata/en-US/full_description.txt

@ -1,6 +1,6 @@
Store, send and receive bitcoin with the wallet focus on security and simplicity.
On Blue Wallet you own you private keys.
On BlueWallet you own you private keys.
You can instantly transact with anyone in the world and transform the financial system right from your pocket.

8
android/settings.gradle

@ -3,10 +3,6 @@ include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
include ':react-native-svg'
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':react-native-sentry'
@ -21,6 +17,10 @@ include ':react-native-haptic-feedback'
project(':react-native-haptic-feedback').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-haptic-feedback/android')
include ':react-native-google-analytics-bridge'
project(':react-native-google-analytics-bridge').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-analytics-bridge/android')
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
include ':react-native-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
include ':react-native-camera'

3
babel.config.js

@ -0,0 +1,3 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
};

4
class/lightning-custodian-wallet.js

@ -7,8 +7,8 @@ export class LightningCustodianWallet extends LegacyWallet {
static type = 'lightningCustodianWallet';
static typeReadable = 'Lightning';
constructor() {
super();
constructor(props) {
super(props);
this.setBaseURI(); // no args to init with default value
this.init();
this.refresh_token = '';

79
class/walletGradient.js

@ -0,0 +1,79 @@
import { LegacyWallet } from './legacy-wallet';
import { HDSegwitP2SHWallet } from './hd-segwit-p2sh-wallet';
import { LightningCustodianWallet } from './lightning-custodian-wallet';
import { HDLegacyBreadwalletWallet } from './hd-legacy-breadwallet-wallet';
import { HDLegacyP2PKHWallet } from './hd-legacy-p2pkh-wallet';
import { WatchOnlyWallet } from './watch-only-wallet';
export default class WalletGradient {
static defaultGradients = ['#65ceef', '#68bbe1'];
static watchOnlyWallet = ['#7d7d7d', '#4a4a4a'];
static legacyWallet = ['#40fad1', '#15be98'];
static hdLegacyP2PKHWallet = ['#e36dfa', '#bd10e0'];
static hdLegacyBreadWallet = ['#fe6381', '#f99c42'];
static hdSegwitP2SHWallet = ['#c65afb', '#9053fe'];
static lightningCustodianWallet = ['#f1be07', '#f79056'];
static createWallet = ['#eef0f4', '#eef0f4'];
static gradientsFor(type) {
let gradient;
switch (type) {
case WatchOnlyWallet.type:
gradient = WalletGradient.watchOnlyWallet;
break;
case LegacyWallet.type:
gradient = WalletGradient.legacyWallet;
break;
case HDLegacyP2PKHWallet.type:
gradient = WalletGradient.hdLegacyP2PKHWallet;
break;
case HDLegacyBreadwalletWallet.type:
gradient = WalletGradient.hdLegacyBreadWallet;
break;
case HDSegwitP2SHWallet.type:
gradient = WalletGradient.hdSegwitP2SHWallet;
break;
case LightningCustodianWallet.type:
gradient = WalletGradient.lightningCustodianWallet;
break;
case 'CreateWallet':
gradient = WalletGradient.createWallet;
break;
default:
gradient = WalletGradient.defaultGradients;
break;
}
return gradient;
}
static headerColorFor(type) {
let gradient;
switch (type) {
case WatchOnlyWallet.type:
gradient = WalletGradient.watchOnlyWallet;
break;
case LegacyWallet.type:
gradient = WalletGradient.legacyWallet;
break;
case HDLegacyP2PKHWallet.type:
gradient = WalletGradient.hdLegacyP2PKHWallet;
break;
case HDLegacyBreadwalletWallet.type:
gradient = WalletGradient.hdLegacyBreadWallet;
break;
case HDSegwitP2SHWallet.type:
gradient = WalletGradient.hdSegwitP2SHWallet;
break;
case LightningCustodianWallet.type:
gradient = WalletGradient.lightningCustodianWallet;
break;
case 'CreateWallet':
gradient = WalletGradient.createWallet;
break;
default:
gradient = WalletGradient.defaultGradients;
break;
}
return gradient[0];
}
}

4
events.js

@ -36,10 +36,6 @@ EV.enum = {
// changed (usually for current wallet)
REMOTE_TRANSACTIONS_COUNT_CHANGED: 'REMOTE_TRANSACTIONS_COUNT_CHANGED',
// emitted when QR scanner scanned address that should be used in CREATE TRANSACTION screen
// thus, previous screen (CREATE TRANSACTION screen) will update it's input content
CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS: 'CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS',
// RECEIVE_ADDRESS_CHANGED: 'RECEIVE_ADDRESS_CHANGED',
};

922
ios/BlueWallet.xcodeproj/project.pbxproj

File diff suppressed because it is too large

2
ios/BlueWallet/AppDelegate.h

@ -1,5 +1,5 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.

12
ios/BlueWallet/AppDelegate.m

@ -1,5 +1,5 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
@ -22,18 +22,14 @@
{
NSURL *jsCodeLocation;
#ifdef DEBUG
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"BlueWallet"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
[RNSentry installWithRootView:rootView];
rootView.backgroundColor = [UIColor blackColor];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;

2
ios/BlueWallet/Info.plist

@ -56,7 +56,7 @@
<key>NSCalendarsUsageDescription</key>
<string>This alert should not show up as we do not require this data</string>
<key>NSCameraUsageDescription</key>
<string>In order to quickly scan the recipient&apos;s address, we need your permission to use the camera to scan their QR Code.</string>
<string>In order to quickly scan the recipient's address, we need your permission to use the camera to scan their QR Code.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This alert should not show up as we do not require this data</string>
<key>NSMotionUsageDescription</key>

2
ios/BlueWallet/main.m

@ -1,5 +1,5 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.

2
ios/BlueWalletTests/BlueWalletTests.m

@ -1,5 +1,5 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.

2
ios/fastlane/metadata/en-US/description.txt

@ -1,6 +1,6 @@
Store, send and receive bitcoin with the wallet focus on security and simplicity.
On Blue Wallet you own you private keys. A Bitcoin wallet focused on us the users.
On BlueWallet you own you private keys. A Bitcoin wallet focused on us the users.
You can instantly transact with anyone in the world and transform the financial system right from your pocket.

2
ios/fastlane/metadata/es-ES/description.txt

@ -1,6 +1,6 @@
Store, send and receive bitcoin with the wallet focus on security and simplicity.
On Blue Wallet you own you private keys. A Bitcoin wallet focused on us the users.
On BlueWallet you own you private keys. A Bitcoin wallet focused on us the users.
You can instantly transact with anyone in the world and transform the financial system right from your pocket.

2
ios/fastlane/metadata/pt-BR/description.txt

@ -1,6 +1,6 @@
Guardar, enviar e receber bitcoin com uma carteira focada na segurança e simplicidade.
Na Blue Wallet você possui as suas chaves privadas. Uma carteira Bitcoin focada nos usuários.
Na BlueWallet você possui as suas chaves privadas. Uma carteira Bitcoin focada nos usuários.
Você pode instantaneamente transacionar com qualquer pessoa no mundo e transformar o sistema financeiro diretamente do seu bolso.

2
ios/fastlane/metadata/pt-PT/description.txt

@ -1,6 +1,6 @@
Guardar, enviar e receber bitcoin com uma carteira focada na segurança e simplicidade.
Na Blue Wallet você possui as suas chaves privadas. Uma carteira Bitcoin focada nos usuários.
Na BlueWallet você possui as suas chaves privadas. Uma carteira Bitcoin focada nos usuários.
Você pode instantaneamente transacionar com qualquer pessoa no mundo e transformar o sistema financeiro diretamente do seu bolso.

2
loc/cs_CZ.js

@ -12,7 +12,7 @@ module.exports = {
options: 'možnosti',
createBitcoinWallet: 'In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'peněženky',
header: 'Peněženka reprezentuje pár tajného (privátního) klíče a adresy' + 'kterou můžete sdílet, abyste získali mince',
add: 'Přidat peněženku',

2
loc/da_DK.js

@ -12,7 +12,7 @@ module.exports = {
options: 'valgmuligheder',
createBitcoinWallet: 'In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'wallets',
header: 'En wallet består af par af hemmelige (private nøgler) og en adresse' + 'som du kan dele med andre for at modtage coins.',
add: 'Tilføj Wallet',

2
loc/de_DE.js

@ -13,7 +13,7 @@ module.exports = {
createBitcoinWallet:
'In order to use a Lightning wallet, a Bitcoin wallet is needed in order to fund it. Please, create or import a Bitcoin wallet.',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'Wallets',
header:
'Eine Wallet (Brieftasche) spiegelt ein Paar von kryptographischen Schlüssel wider. Einen geheimen und eine Adresse als öffentlichen Schlüssel. Letztern kann man zum Erhalt von Bitcoin teilen.',

2
loc/en.js

@ -13,7 +13,7 @@ module.exports = {
createBitcoinWallet:
'You currently do not have a Bitcoin wallet. In order to fund a Lightning wallet, a Bitcoin wallet needs to be created or imported. Would you like to continue anyway?',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'wallets',
header: 'A wallet represents a pair of a secret (private key) and an address' + 'you can share to receive coins.',
add: 'Add Wallet',

2
loc/es.js

@ -13,7 +13,7 @@ module.exports = {
createBitcoinWallet:
'In order to use a Lightning wallet, a Bitcoin wallet is needed in order to fund it. Would you like to continue anyway?',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'billeteras',
header: 'Un Monedero esta representado con secreto (clave privada) y una dirección' + 'que puedes compartir para recibir monedas.',
add: 'Añadir Carterqa',

2
loc/fr_FR.js

@ -13,7 +13,7 @@ module.exports = {
createBitcoinWallet: 'In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'portefeuilles',
header:
'Un portefeuille represente une paire de clées (publique/privée) et une adresse que vous pouvez partager pour recevoir des transactions.',

2
loc/hr_HR.js

@ -11,7 +11,7 @@ module.exports = {
select_wallet: 'Odaberi volet',
options: 'opcije',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'Voleti',
header: 'Volet je par privatnog ključa (tajna!) i javne adrese ' + 'koju slobodno možete dijeliti kada primate novce.',
add: 'Dodaj volet',

7
loc/index.js

@ -156,6 +156,13 @@ strings.transactionTimeToReadable = time => {
return dayjs(time).fromNow();
};
strings.transactionTimeToReadableToFuture = time => {
if (time === 0) {
return strings._.never;
}
return dayjs(time).toNow();
};
function removeTrailingZeros(value) {
value = value.toString();

2
loc/nl_NL.js

@ -13,7 +13,7 @@ module.exports = {
createBitcoinWallet:
'Om een Lightning-portemonnee te kunnen gebruiken, is een Bitcoin-portemonnee nodig om deze te financieren. Wil je toch doorgaan?',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'portemonnees',
header: 'Een portemonnee vertegenwoordigt een geheime (privésleutel) en een adres' + 'dat u kunt delen om munten te ontvangen.',
add: 'Portemonnee toevoegen',

2
loc/pt_BR.js

@ -14,7 +14,7 @@ module.exports = {
list: {
tabBarLabel: 'Carteiras',
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'carteiras',
header: 'Uma carteira representa um par composto de uma chave privada e um endereço que você pode .',
add: 'adicionar wallet',

2
loc/pt_PT.js

@ -13,7 +13,7 @@ module.exports = {
createBitcoinWallet: 'In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?',
list: {
app_name: 'Blue Wallet',
app_name: 'BlueWallet',
title: 'wallets',
header: 'Uma wallet representa um par entre um segredo (chave privada) e um endereço' + 'que pode partilhar para receber Bitcoin.',
add: 'adicionar wallet',

4509
package-lock.json

File diff suppressed because it is too large

16
package.json

@ -3,14 +3,14 @@
"version": "3.7.0",
"devDependencies": {
"babel-eslint": "^10.0.1",
"babel-jest": "23.6.0",
"babel-jest": "^24.0.0",
"eslint": "^5.12.1",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "^2.15.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-react": "^7.12.3",
"jest": "23.6.0",
"jest": "^24.0.0",
"metro-react-native-babel-preset": "^0.51.1",
"prettier-eslint-cli": "^4.7.1",
"react-test-renderer": "^16.7.0",
@ -59,14 +59,14 @@
"prop-types": "^15.6.2",
"react": "^16.7.0",
"react-localization": "^1.0.10",
"react-native": "^0.57.8",
"react-native-camera": "^1.9.1",
"react-native": "^0.58.1",
"react-native-camera": "^1.9.2",
"react-native-custom-qr-codes": "^2.0.0",
"react-native-device-info": "^0.25.1",
"react-native-elements": "^0.19.0",
"react-native-flexi-radio-button": "^0.2.2",
"react-native-fs": "^2.13.3",
"react-native-gesture-handler": "^1.0.12",
"react-native-gesture-handler": "^1.0.15",
"react-native-google-analytics-bridge": "^7.0.0",
"react-native-haptic-feedback": "^1.4.2",
"react-native-level-fs": "^3.0.1",
@ -78,11 +78,11 @@
"react-native-randombytes": "^3.5.2",
"react-native-rate": "^1.1.6",
"react-native-sentry": "^0.40.2",
"react-native-snap-carousel": "^3.7.4",
"react-native-snap-carousel": "^3.7.5",
"react-native-sortable-list": "0.0.22",
"react-native-svg": "^9.0.2",
"react-native-svg": "^9.0.4",
"react-native-vector-icons": "^6.2.0",
"react-native-webview": "2.8.0",
"react-native-webview": "^3.2.1",
"react-native-wkwebview-reborn": "^2.0.0",
"react-navigation": "^3.0.9",
"react-test-render": "^1.1.1",

6
screen/lnd/lndCreateInvoice.js

@ -51,11 +51,7 @@ export default class LNDCreateInvoice extends Component {
{this.state.isLoading ? (
<ActivityIndicator />
) : (
<BlueButton
disabled={!(this.state.description.length > 0 && this.state.amount > 0)}
onPress={() => this.createInvoice()}
title={loc.send.details.create}
/>
<BlueButton disabled={!this.state.amount > 0} onPress={() => this.createInvoice()} title={loc.send.details.create} />
)}
</View>
);

2
screen/lnd/lndViewAdditionalInvoiceInformation.js

@ -59,7 +59,7 @@ export default class LNDViewAdditionalInvoiceInformation extends Component {
<BlueText>Open direct channel with this node:</BlueText>
<BlueCopyTextToClipboard text={this.state.walletInfo.uris[0]} />
</View>
<View style={{ marginBottom: 24 }}>
<View style={{ marginBottom: 25 }}>
<BlueButton
icon={{
name: 'share-alternative',

8
screen/lnd/lndViewInvoice.js

@ -173,7 +173,6 @@ export default class LNDViewInvoice extends Component {
}
}
}
// Invoice has not expired, nor has it been paid for.
return (
<SafeBlueArea>
@ -198,7 +197,9 @@ export default class LNDViewInvoice extends Component {
<BlueSpacing20 />
{invoice && invoice.amt && <BlueText>Please pay {invoice.amt} sats</BlueText>}
{invoice && invoice.description && <BlueText>For: {invoice.description}</BlueText>}
{invoice && invoice.hasOwnProperty('description') && invoice.description.length > 0 && (
<BlueText>For: {invoice.description}</BlueText>
)}
<BlueCopyTextToClipboard text={this.state.invoice.payment_request} />
<BlueButton
@ -214,8 +215,9 @@ export default class LNDViewInvoice extends Component {
}}
title={loc.receive.details.share}
/>
<BlueSpacing20 />
<BlueButton
buttonStyle={{ backgroundColor: 'white' }}
backgroundColor="#FFFFFF"
icon={{
name: 'info',
type: 'entypo',

120
screen/lnd/scanLndInvoice.js

@ -1,16 +1,22 @@
/* global alert */
import React from 'react';
import { Text, Dimensions, ActivityIndicator, View, TouchableOpacity, TouchableWithoutFeedback, TextInput, Keyboard } from 'react-native';
import { Icon } from 'react-native-elements';
import { Text, ActivityIndicator, View, TouchableWithoutFeedback, Keyboard } from 'react-native';
import PropTypes from 'prop-types';
import { BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueBitcoinAmount } from '../../BlueComponents';
import {
BlueSpacing20,
BlueButton,
SafeBlueArea,
BlueCard,
BlueNavigationStyle,
BlueAddressInput,
BlueBitcoinAmount,
} from '../../BlueComponents';
import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet';
import { BitcoinUnit } from '../../models/bitcoinUnits';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let EV = require('../../events');
let loc = require('../../loc');
const { width } = Dimensions.get('window');
export default class ScanLndInvoice extends React.Component {
static navigationOptions = ({ navigation }) => ({
@ -59,20 +65,12 @@ export default class ScanLndInvoice extends React.Component {
}
async componentDidMount() {
EV(
EV.enum.CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS,
data => {
this.processInvoice(data);
},
true,
);
if (this.props.navigation.state.params.uri) {
this.processTextForInvoice(this.props.navigation.getParam('uri'));
}
}
processInvoice(data) {
processInvoice = data => {
this.setState({ isLoading: true }, async () => {
if (this.ignoreRead) return;
this.ignoreRead = true;
@ -122,7 +120,7 @@ export default class ScanLndInvoice extends React.Component {
alert(Err.message);
}
});
}
};
async pay() {
if (!this.state.hasOwnProperty('decoded')) {
@ -212,53 +210,15 @@ export default class ScanLndInvoice extends React.Component {
/>
<BlueSpacing20 />
<BlueCard>
<View
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
<BlueAddressInput
onChangeText={text => {
this.setState({ destination: text });
this.processTextForInvoice(text);
}}
>
<TextInput
onChangeText={text => {
this.setState({ destination: text });
this.processTextForInvoice(text);
}}
placeholder={loc.wallets.details.destination}
numberOfLines={1}
value={this.state.destination}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33, height: 33 }}
editable={!this.state.isLoading}
/>
<TouchableOpacity
disabled={this.state.isLoading}
onPress={() => this.props.navigation.navigate('ScanQrAddress')}
style={{
width: 75,
height: 36,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#bebebe',
borderRadius: 4,
paddingVertical: 4,
paddingHorizontal: 8,
marginHorizontal: 4,
}}
>
<Icon name="qrcode" size={22} type="font-awesome" color="#FFFFFF" />
<Text style={{ color: '#FFFFFF' }}>{loc.send.details.scan}</Text>
</TouchableOpacity>
</View>
onBarScanned={this.processInvoice}
address={this.state.destination}
isLoading={this.state.isLoading}
/>
<View
style={{
flexDirection: 'row',
@ -275,27 +235,27 @@ export default class ScanLndInvoice extends React.Component {
{this.state.expiresIn !== undefined && (
<Text style={{ color: '#81868e', fontSize: 12, left: 20, top: 10 }}>Expires in: {this.state.expiresIn}</Text>
)}
<BlueSpacing20 />
<BlueSpacing20 />
{this.state.isLoading ? (
<View>
<ActivityIndicator />
</View>
) : (
<BlueButton
icon={{
name: 'bolt',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
title={'Pay'}
onPress={() => {
this.pay();
}}
disabled={this.shouldDisablePayButton()}
/>
)}
</BlueCard>
<BlueSpacing20 />
{this.state.isLoading ? (
<View>
<ActivityIndicator />
</View>
) : (
<BlueButton
icon={{
name: 'bolt',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
title={'Pay'}
buttonStyle={{ width: 150, left: (width - 150) / 2 - 20 }}
onPress={() => {
this.pay();
}}
disabled={this.shouldDisablePayButton()}
/>
)}
</SafeBlueArea>
</TouchableWithoutFeedback>
);

2
screen/receive/details.js

@ -97,7 +97,7 @@ export default class ReceiveDetails extends Component {
/>
<BlueCopyTextToClipboard text={this.state.addressText} />
</View>
<View style={{ marginBottom: 24, alignItems: 'center' }}>
<View style={{ flex: 0.2, marginBottom: 24, alignItems: 'center' }}>
<BlueButtonLink
title={loc.receive.details.setAmount}
onPress={() => {

64
screen/receive/receiveAmount.js

@ -3,7 +3,15 @@ import { View, Share, TextInput, KeyboardAvoidingView, Platform, Dimensions, Scr
import { QRCode as QRSlow } from 'react-native-custom-qr-codes';
import QRFast from 'react-native-qrcode';
import bip21 from 'bip21';
import { SafeBlueArea, BlueButton, BlueNavigationStyle, BlueBitcoinAmount, BlueText, BlueCopyTextToClipboard } from '../../BlueComponents';
import {
SafeBlueArea,
BlueCard,
BlueButton,
BlueNavigationStyle,
BlueBitcoinAmount,
BlueText,
BlueCopyTextToClipboard,
} from '../../BlueComponents';
import PropTypes from 'prop-types';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
@ -75,15 +83,17 @@ export default class ReceiveAmount extends Component {
editable={!this.state.isLoading}
/>
</View>
<BlueButton
title={loc.receive.create}
onPress={() => {
this.setState({
amountSet: true,
bip21: bip21.encode(this.state.address, { amount: this.state.amount, label: this.state.label }),
});
}}
/>
<BlueCard>
<BlueButton
title={loc.receive.details.create}
onPress={() => {
this.setState({
amountSet: true,
bip21: bip21.encode(this.state.address, { amount: this.state.amount, label: this.state.label }),
});
}}
/>
</BlueCard>
</View>
);
}
@ -113,7 +123,7 @@ export default class ReceiveAmount extends Component {
/>
)}
</View>
<View style={{ marginBottom: 24, alignItems: 'center', justifyContent: 'space-between' }}>
<View style={{ alignItems: 'center', justifyContent: 'space-between' }}>
<BlueCopyTextToClipboard text={this.state.bip21} />
</View>
</View>
@ -134,23 +144,21 @@ export default class ReceiveAmount extends Component {
{this.state.amountSet ? this.renderWithSetAmount() : this.renderDefault()}
</KeyboardAvoidingView>
{this.state.amountSet && (
<BlueButton
buttonStyle={{
alignSelf: 'center',
marginBottom: 24,
}}
icon={{
name: 'share-alternative',
type: 'entypo',
color: BlueApp.settings.buttonTextColor,
}}
onPress={async () => {
Share.share({
message: this.state.bip21,
});
}}
title={loc.receive.details.share}
/>
<BlueCard>
<BlueButton
icon={{
name: 'share-alternative',
type: 'entypo',
color: BlueApp.settings.buttonTextColor,
}}
onPress={async () => {
Share.share({
message: this.state.bip21,
});
}}
title={loc.receive.details.share}
/>
</BlueCard>
)}
</View>
</ScrollView>

100
screen/send/details.js

@ -14,7 +14,7 @@ import {
Text,
} from 'react-native';
import { Icon } from 'react-native-elements';
import { BlueNavigationStyle, BlueButton, BlueBitcoinAmount } from '../../BlueComponents';
import { BlueNavigationStyle, BlueButton, BlueBitcoinAmount, BlueAddressInput } from '../../BlueComponents';
import PropTypes from 'prop-types';
import Modal from 'react-native-modal';
import NetworkTransactionFees, { NetworkTransactionFee } from '../../models/networkTransactionFees';
@ -23,7 +23,6 @@ import { BitcoinUnit } from '../../models/bitcoinUnits';
import { HDLegacyP2PKHWallet, HDSegwitP2SHWallet } from '../../class';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
const bip21 = require('bip21');
let EV = require('../../events');
let BigNumber = require('bignumber.js');
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
@ -82,13 +81,15 @@ export default class SendDetails extends Component {
};
}
async componentDidMount() {
EV(EV.enum.CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS, data => {
this.setState(
{ isLoading: false },
() => {
data = data.replace('bitcoin:', '');
if (btcAddressRx.test(data) || data.indexOf('bc1') === 0) {
processAddressData = data => {
this.setState(
{ isLoading: true },
() => {
if (BitcoinBIP70TransactionDecode.matchesPaymentURL(data)) {
this.processBIP70Invoice(data);
} else {
const dataWithoutSchema = data.replace('bitcoin:', '');
if (btcAddressRx.test(dataWithoutSchema) || dataWithoutSchema.indexOf('bc1') === 0) {
this.setState({
address: data,
bip70TransactionExpiration: null,
@ -97,11 +98,15 @@ export default class SendDetails extends Component {
} else {
let address, options;
try {
if (!data.toLowerCase().startsWith('bitcoin:')) {
data = `bitcoin:${data}`;
}
const decoded = bip21.decode(data);
address = decoded.address;
options = decoded.options;
} catch (Err) {
console.log(Err);
} catch (error) {
console.log(error);
this.setState({ isLoading: false });
}
console.log(options);
if (btcAddressRx.test(address)) {
@ -112,14 +117,15 @@ export default class SendDetails extends Component {
bip70TransactionExpiration: null,
isLoading: false,
});
} else if (BitcoinBIP70TransactionDecode.matchesPaymentURL(data)) {
this.processBIP70Invoice(data);
}
}
},
true,
);
});
}
},
true,
);
};
async componentDidMount() {
let recommendedFees = await NetworkTransactionFees.recommendedFees().catch(response => {
this.setState({
fee: response.halfHourFee,
@ -497,56 +503,18 @@ export default class SendDetails extends Component {
amount={this.state.amount}
onChangeText={text => this.setState({ amount: text })}
/>
<View
style={{
flexDirection: 'row',
borderColor: '#d2d2d2',
borderBottomColor: '#d2d2d2',
borderWidth: 1.0,
borderBottomWidth: 0.5,
backgroundColor: '#f5f5f5',
minHeight: 44,
height: 44,
marginHorizontal: 20,
alignItems: 'center',
marginVertical: 8,
borderRadius: 4,
<BlueAddressInput
onChangeText={text => {
if (!this.processBIP70Invoice(text)) {
this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null });
} else {
this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null });
}
}}
>
<TextInput
onChangeText={text => {
if (!this.processBIP70Invoice(text)) {
this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null });
} else {
this.setState({ address: text.replace(' ', ''), isLoading: false, bip70TransactionExpiration: null });
}
}}
placeholder={loc.send.details.address}
numberOfLines={1}
value={this.state.address}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33 }}
editable={!this.state.isLoading}
/>
<TouchableOpacity
disabled={this.state.isLoading}
onPress={() => this.props.navigation.navigate('ScanQrAddress')}
style={{
width: 75,
height: 36,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#bebebe',
borderRadius: 4,
paddingVertical: 4,
paddingHorizontal: 8,
marginHorizontal: 4,
}}
>
<Icon name="qrcode" size={22} type="font-awesome" color="#FFFFFF" />
<Text style={{ color: '#FFFFFF' }}>{loc.send.details.scan}</Text>
</TouchableOpacity>
</View>
onBarScanned={this.processAddressData}
address={this.state.address}
isLoading={this.state.isLoading}
/>
<View
hide={!this.state.showMemoRow}
style={{

21
screen/send/scanQrAddress.js

@ -5,7 +5,6 @@ import PropTypes from 'prop-types';
import Camera from 'react-native-camera';
import Permissions from 'react-native-permissions';
import { SafeBlueArea } from '../../BlueComponents';
let EV = require('../../events');
export default class CameraExample extends React.Component {
static navigationOptions = {
@ -17,21 +16,26 @@ export default class CameraExample extends React.Component {
hasCameraPermission: null,
};
async onBarCodeScanned(ret) {
onBarCodeScanned(ret) {
if (this.ignoreRead) return;
this.ignoreRead = true;
setTimeout(() => {
this.ignoreRead = false;
}, 2000);
this.props.navigation.goBack();
EV(EV.enum.CREATE_TRANSACTION_NEW_DESTINATION_ADDRESS, ret.data);
const onBarScanned = this.props.navigation.getParam('onBarScanned');
onBarScanned(ret.data);
this.props.navigation.goBack(null);
} // end
async componentDidMount() {
componentDidMount() {
Permissions.request('camera').then(response => {
// Response is one of: 'authorized', 'denied', 'restricted', or 'undetermined'
this.setState({ hasCameraPermission: response === 'authorized' });
if (response !== 'authorized') {
alert('BlueWallet does not have permission to use your camera.');
this.props.navigation.goBack(null);
}
});
}
@ -48,8 +52,6 @@ export default class CameraExample extends React.Component {
if (hasCameraPermission === null) {
return <View />;
} else if (hasCameraPermission === false) {
alert('BlueWallet does not have permission to use your camera.');
this.props.navigation.goBack(null);
return <View />;
} else {
return (
@ -70,7 +72,8 @@ export default class CameraExample extends React.Component {
CameraExample.propTypes = {
navigation: PropTypes.shape({
goBack: PropTypes.function,
dismiss: PropTypes.function,
goBack: PropTypes.func,
dismiss: PropTypes.func,
getParam: PropTypes.func,
}),
};

122
screen/settings/about.js

@ -51,73 +51,71 @@ export default class About extends Component {
<BlueTextCentered h4>Always backup your keys</BlueTextCentered>
<BlueSpacing20 />
</BlueCard>
<BlueButton
icon={{
name: 'mark-github',
type: 'octicon',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://github.com/BlueWallet/BlueWallet');
}}
title="github.com/BlueWallet/BlueWallet"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'mark-github',
type: 'octicon',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://github.com/BlueWallet/BlueWallet');
}}
title="github.com/BlueWallet/BlueWallet"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'twitter',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://twitter.com/bluewalletio');
}}
title="Follow us on Twitter"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'twitter',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://twitter.com/bluewalletio');
}}
title="Follow us on Twitter"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'telegram',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://t.me/bluewallet');
}}
title="Join Telegram chat"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'telegram',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
Linking.openURL('https://t.me/bluewallet');
}}
title="Join Telegram chat"
/>
<BlueSpacing20 />
<BlueButton
icon={{
name: 'thumbsup',
type: 'octicon',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
let options = {
AppleAppID: '1376878040',
GooglePackageName: 'io.bluewallet.bluewallet',
preferredAndroidMarket: AndroidMarket.Google,
preferInApp: true,
openAppStoreIfInAppFails: true,
fallbackPlatformURL: 'https://bluewallet.io',
};
Rate.rate(options, success => {
if (success) {
console.log('User Rated.');
}
});
}}
title="Rate Blue Wallet"
/>
<BlueButton
icon={{
name: 'thumbsup',
type: 'octicon',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() => {
let options = {
AppleAppID: '1376878040',
GooglePackageName: 'io.bluewallet.bluewallet',
preferredAndroidMarket: AndroidMarket.Google,
preferInApp: true,
openAppStoreIfInAppFails: true,
fallbackPlatformURL: 'https://bluewallet.io',
};
Rate.rate(options, success => {
if (success) {
console.log('User Rated.');
}
});
}}
title="Rate BlueWallet"
/>
<BlueSpacing20 />
<BlueCard>
<BlueSpacing20 />
<BlueText h3>Built with awesome:</BlueText>
<BlueSpacing20 />
<BlueText h4>* React Native</BlueText>

2
screen/settings/language.js

@ -78,7 +78,7 @@ export default class Language extends Component {
renderItem={this.renderItem}
/>
<BlueCard>
<BlueText>When selecting a new language, restarting Blue Wallet may be required for the change to take effect.</BlueText>
<BlueText>When selecting a new language, restarting BlueWallet may be required for the change to take effect.</BlueText>
</BlueCard>
</SafeBlueArea>
);

6
screen/settings/lightningSettings.js

@ -3,6 +3,7 @@ import { AsyncStorage, View, TextInput, Linking } from 'react-native';
import { AppStorage } from '../../class';
import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueText } from '../../BlueComponents';
import PropTypes from 'prop-types';
import { Button } from 'react-native-elements';
import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
@ -56,7 +57,7 @@ export default class LightningSettings extends Component {
<BlueText>{loc.settings.lightning_settings_explain}</BlueText>
</BlueCard>
<BlueButton
<Button
icon={{
name: 'mark-github',
type: 'octicon',
@ -67,6 +68,7 @@ export default class LightningSettings extends Component {
Linking.openURL('https://github.com/BlueWallet/LndHub');
}}
title="github.com/BlueWallet/LndHub"
color={BlueApp.settings.buttonTextColor}
buttonStyle={{
backgroundColor: '#FFFFFF',
}}
@ -92,7 +94,7 @@ export default class LightningSettings extends Component {
value={this.state.URI}
onChangeText={text => this.setState({ URI: text })}
numberOfLines={1}
style={{ flex: 1, marginHorizontal: 8, minHeight: 33, height: 33 }}
style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36 }}
editable={!this.state.isLoading}
underlineColorAndroid="transparent"
/>

2
screen/transactions/details.js

@ -176,7 +176,7 @@ export default class TransactionsDetails extends Component {
</React.Fragment>
)}
{this.state.tx.hasOwnProperty('block_height') && (
{this.state.tx.hasOwnProperty('block_height') && this.state.block_height > 0 && (
<React.Fragment>
<BlueText style={{ fontSize: 16, fontWeight: '500', marginBottom: 4 }}>Block Height</BlueText>
<BlueText style={{ marginBottom: 26, color: 'grey' }}>{this.state.tx.block_height}</BlueText>

3
screen/wallets/add.js

@ -182,9 +182,6 @@ export default class WalletsAdd extends Component {
{!this.state.isLoading ? (
<BlueButton
title={loc.wallets.add.create}
buttonStyle={{
width: width / 1.5,
}}
onPress={() => {
this.setState(
{ isLoading: true },

144
screen/wallets/details.js

@ -120,88 +120,88 @@ export default class WalletDetails extends Component {
{loc.wallets.details.type.toLowerCase()}
</Text>
<Text style={{ color: '#81868e', fontWeight: '500', fontSize: 14 }}>{this.state.wallet.typeReadable}</Text>
</BlueCard>
<View>
<BlueSpacing20 />
<BlueButton
onPress={() =>
this.props.navigation.navigate('WalletExport', {
address: this.state.wallet.getAddress(),
secret: this.state.wallet.getSecret(),
})
}
title={loc.wallets.details.export_backup}
/>
<View>
<BlueSpacing20 />
<BlueButton
onPress={() =>
this.props.navigation.navigate('WalletExport', {
address: this.state.wallet.getAddress(),
secret: this.state.wallet.getSecret(),
})
}
title={loc.wallets.details.export_backup}
/>
<BlueSpacing20 />
{(this.state.wallet.type === HDLegacyBreadwalletWallet.type ||
this.state.wallet.type === HDLegacyP2PKHWallet.type ||
this.state.wallet.type === HDSegwitP2SHWallet.type) && (
<React.Fragment>
<BlueButton
onPress={() =>
this.props.navigation.navigate('WalletXpub', {
secret: this.state.wallet.getSecret(),
})
}
title={loc.wallets.details.show_xpub}
/>
<BlueSpacing20 />
<BlueSpacing20 />
</React.Fragment>
)}
{(this.state.wallet.type === HDLegacyBreadwalletWallet.type ||
this.state.wallet.type === HDLegacyP2PKHWallet.type ||
this.state.wallet.type === HDSegwitP2SHWallet.type) && (
<React.Fragment>
{this.state.wallet.type !== LightningCustodianWallet.type && (
<BlueButton
icon={{
name: 'shopping-cart',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() =>
this.props.navigation.navigate('WalletXpub', {
this.props.navigation.navigate('BuyBitcoin', {
address: this.state.wallet.getAddress(),
secret: this.state.wallet.getSecret(),
})
}
title={loc.wallets.details.show_xpub}
title={loc.wallets.details.buy_bitcoin}
/>
)}
<BlueSpacing20 />
<BlueSpacing20 />
</React.Fragment>
)}
{this.state.wallet.type !== LightningCustodianWallet.type && (
<BlueButton
icon={{
name: 'shopping-cart',
type: 'font-awesome',
color: BlueApp.settings.buttonTextColor,
}}
onPress={() =>
this.props.navigation.navigate('BuyBitcoin', {
address: this.state.wallet.getAddress(),
secret: this.state.wallet.getSecret(),
})
}
title={loc.wallets.details.buy_bitcoin}
/>
)}
<BlueSpacing20 />
<TouchableOpacity
style={{ alignItems: 'center' }}
onPress={() => {
ReactNativeHapticFeedback.trigger('notificationWarning', false);
Alert.alert(
loc.wallets.details.delete + ' ' + loc.wallets.details.title,
loc.wallets.details.are_you_sure,
[
{
text: loc.wallets.details.yes_delete,
onPress: async () => {
this.props.navigation.setParams({ isLoading: true });
this.setState({ isLoading: true }, async () => {
BlueApp.deleteWallet(this.state.wallet);
ReactNativeHapticFeedback.trigger('notificationSuccess', false);
await BlueApp.saveToDisk();
EV(EV.enum.TRANSACTIONS_COUNT_CHANGED);
EV(EV.enum.WALLETS_COUNT_CHANGED);
this.props.navigation.navigate('Wallets');
});
<TouchableOpacity
style={{ alignItems: 'center' }}
onPress={() => {
ReactNativeHapticFeedback.trigger('notificationWarning', false);
Alert.alert(
loc.wallets.details.delete + ' ' + loc.wallets.details.title,
loc.wallets.details.are_you_sure,
[
{
text: loc.wallets.details.yes_delete,
onPress: async () => {
this.props.navigation.setParams({ isLoading: true });
this.setState({ isLoading: true }, async () => {
BlueApp.deleteWallet(this.state.wallet);
ReactNativeHapticFeedback.trigger('notificationSuccess', false);
await BlueApp.saveToDisk();
EV(EV.enum.TRANSACTIONS_COUNT_CHANGED);
EV(EV.enum.WALLETS_COUNT_CHANGED);
this.props.navigation.navigate('Wallets');
});
},
style: 'destructive',
},
style: 'destructive',
},
{ text: loc.wallets.details.no_cancel, onPress: () => {}, style: 'cancel' },
],
{ cancelable: false },
);
}}
>
<Text style={{ color: '#d0021b', fontSize: 15, fontWeight: '500' }}>{loc.wallets.details.delete}</Text>
</TouchableOpacity>
</View>
{ text: loc.wallets.details.no_cancel, onPress: () => {}, style: 'cancel' },
],
{ cancelable: false },
);
}}
>
<Text style={{ color: '#d0021b', fontSize: 15, fontWeight: '500' }}>{loc.wallets.details.delete}</Text>
</TouchableOpacity>
</View>
</BlueCard>
</View>
</TouchableWithoutFeedback>
</SafeBlueArea>

9
screen/wallets/list.js

@ -19,6 +19,7 @@ import { Icon } from 'react-native-elements';
import { NavigationEvents } from 'react-navigation';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import PropTypes from 'prop-types';
import WalletGradient from '../../class/walletGradient';
let EV = require('../../events');
let A = require('../../analytics');
/** @type {AppStorage} */
@ -121,13 +122,13 @@ export default class WalletsList extends Component {
return '';
}
handleClick(index, gradients) {
handleClick(index) {
console.log('click', index);
let wallet = BlueApp.wallets[index];
if (wallet) {
this.props.navigation.navigate('WalletTransactions', {
wallet: wallet,
gradients: gradients,
headerColor: WalletGradient.headerColorFor(wallet.type),
});
} else {
// if its out of index - this must be last card with incentive to create wallet
@ -298,8 +299,8 @@ export default class WalletsList extends Component {
<BlueHeaderDefaultMain leftText={loc.wallets.list.title} onNewWalletPress={() => this.props.navigation.navigate('AddWallet')} />
<WalletsCarousel
data={this.state.wallets}
handleClick={(index, headerColor) => {
this.handleClick(index, headerColor);
handleClick={index => {
this.handleClick(index);
}}
handleLongPress={this.handleLongPress}
onSnapToItem={index => {

40
screen/wallets/reorderWallets.js

@ -4,12 +4,9 @@ import { SafeBlueArea, BlueNavigationStyle } from '../../BlueComponents';
import SortableList from 'react-native-sortable-list';
import LinearGradient from 'react-native-linear-gradient';
import PropTypes from 'prop-types';
import { WatchOnlyWallet, LegacyWallet } from '../../class';
import { HDLegacyP2PKHWallet } from '../../class/hd-legacy-p2pkh-wallet';
import { HDLegacyBreadwalletWallet } from '../../class/hd-legacy-breadwallet-wallet';
import { HDSegwitP2SHWallet } from '../../class/hd-segwit-p2sh-wallet';
import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import WalletGradient from '../../class/walletGradient';
let EV = require('../../events');
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
@ -67,39 +64,6 @@ export default class ReorderWallets extends Component {
}
item = item.data;
let gradient1 = '#65ceef';
let gradient2 = '#68bbe1';
if (WatchOnlyWallet.type === item.type) {
gradient1 = '#7d7d7d';
gradient2 = '#4a4a4a';
}
if (LegacyWallet.type === item.type) {
gradient1 = '#40fad1';
gradient2 = '#15be98';
}
if (HDLegacyP2PKHWallet.type === item.type) {
gradient1 = '#e36dfa';
gradient2 = '#bd10e0';
}
if (HDLegacyBreadwalletWallet.type === item.type) {
gradient1 = '#fe6381';
gradient2 = '#f99c42';
}
if (HDSegwitP2SHWallet.type === item.type) {
gradient1 = '#c65afb';
gradient2 = '#9053fe';
}
if (LightningCustodianWallet.type === item.type) {
gradient1 = '#f1be07';
gradient2 = '#f79056';
}
return (
<View
shadowOpacity={40 / 100}
@ -109,7 +73,7 @@ export default class ReorderWallets extends Component {
>
<LinearGradient
shadowColor="#000000"
colors={[gradient1, gradient2]}
colors={WalletGradient.gradientsFor(item.type)}
style={{
padding: 15,
borderRadius: 10,

40
screen/wallets/selectWallet.js

@ -3,12 +3,9 @@ import { View, ActivityIndicator, Image, Text, TouchableOpacity, FlatList } from
import { SafeBlueArea, BlueNavigationStyle, BlueText, BlueSpacing20 } from '../../BlueComponents';
import LinearGradient from 'react-native-linear-gradient';
import PropTypes from 'prop-types';
import { WatchOnlyWallet, LegacyWallet } from '../../class';
import { HDLegacyP2PKHWallet } from '../../class/hd-legacy-p2pkh-wallet';
import { HDLegacyBreadwalletWallet } from '../../class/hd-legacy-breadwallet-wallet';
import { HDSegwitP2SHWallet } from '../../class/hd-segwit-p2sh-wallet';
import { LightningCustodianWallet } from '../../class/lightning-custodian-wallet';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import WalletGradient from '../../class/walletGradient';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let loc = require('../../loc');
@ -36,39 +33,6 @@ export default class SelectWallet extends Component {
}
_renderItem = ({ item }) => {
let gradient1 = '#65ceef';
let gradient2 = '#68bbe1';
if (WatchOnlyWallet.type === item.type) {
gradient1 = '#7d7d7d';
gradient2 = '#4a4a4a';
}
if (LegacyWallet.type === item.type) {
gradient1 = '#40fad1';
gradient2 = '#15be98';
}
if (HDLegacyP2PKHWallet.type === item.type) {
gradient1 = '#e36dfa';
gradient2 = '#bd10e0';
}
if (HDLegacyBreadwalletWallet.type === item.type) {
gradient1 = '#fe6381';
gradient2 = '#f99c42';
}
if (HDSegwitP2SHWallet.type === item.type) {
gradient1 = '#c65afb';
gradient2 = '#9053fe';
}
if (LightningCustodianWallet.type === item.type) {
gradient1 = '#f1be07';
gradient2 = '#f79056';
}
return (
<TouchableOpacity
onPress={() => {
@ -84,7 +48,7 @@ export default class SelectWallet extends Component {
>
<LinearGradient
shadowColor="#000000"
colors={[gradient1, gradient2]}
colors={WalletGradient.gradientsFor(item.type)}
style={{
padding: 15,
borderRadius: 10,

22
screen/wallets/transactions.js

@ -20,6 +20,7 @@ import {
import { Icon } from 'react-native-elements';
import { BitcoinUnit } from '../../models/bitcoinUnits';
import { LightningCustodianWallet } from '../../class';
import WalletGradient from '../../class/walletGradient';
/** @type {AppStorage} */
let BlueApp = require('../../BlueApp');
let loc = require('../../loc');
@ -41,7 +42,7 @@ export default class WalletTransactions extends Component {
</TouchableOpacity>
),
headerStyle: {
backgroundColor: navigation.getParam('gradients')[0] || '#65ceef',
backgroundColor: navigation.getParam('headerColor'),
borderBottomWidth: 0,
elevation: 0,
shadowRadius: 0,
@ -201,9 +202,8 @@ export default class WalletTransactions extends Component {
}
renderWalletHeader = () => {
const gradients = this.props.navigation.getParam('gradients') || ['#65ceef', '#68bbe1'];
return (
<LinearGradient colors={[gradients[0], gradients[1]]} style={{ padding: 15, minHeight: 164 }}>
<LinearGradient colors={WalletGradient.gradientsFor(this.state.wallet.type)} style={{ padding: 15, minHeight: 164 }}>
<Image
source={
(LightningCustodianWallet.type === this.state.wallet.type && require('../../img/lnd-shape.png')) ||
@ -372,27 +372,26 @@ export default class WalletTransactions extends Component {
{(() => {
if (this.state.showManageFundsSmallButton) {
return (
<React.Fragment>
<View style={{ justifyContent: 'space-between', alignContent: 'center', flexDirection: 'row', marginVertical: 8 }}>
<TouchableOpacity
style={{ alignSelf: 'flex-start', left: 10, top: 15, flexDirection: 'row' }}
style={{ left: 10, flexDirection: 'row', flex: 1, alignItems: 'center' }}
onPress={() => {
console.log('navigating to LappBrowser');
navigate('LappBrowser', { fromSecret: this.state.wallet.getSecret(), fromWallet: this.state.wallet });
}}
>
<BlueText style={{ fontWeight: '600', fontSize: 16 }}>{'marketplace'}</BlueText>
<BlueText style={{ fontWeight: '600', fontSize: 16 }}>marketplace</BlueText>
<Icon
style={{ position: 'relative' }}
name="shopping-cart"
type="font-awesome"
size={14}
color={BlueApp.settings.foregroundColor}
iconStyle={{ left: 5 }}
iconStyle={{ left: 5, top: 2 }}
/>
</TouchableOpacity>
<TouchableOpacity
style={{ alignSelf: 'flex-end', right: 10, top: -5, flexDirection: 'row' }}
style={{ marginRight: 10, flexDirection: 'row', alignItems: 'center' }}
onPress={() => {
console.log('navigating to', this.state.wallet.getLabel());
navigate('ManageFunds', { fromWallet: this.state.wallet });
@ -400,15 +399,14 @@ export default class WalletTransactions extends Component {
>
<BlueText style={{ fontWeight: '600', fontSize: 16 }}>{loc.lnd.title}</BlueText>
<Icon
style={{ position: 'relative' }}
name="link"
type="font-awesome"
size={14}
color={BlueApp.settings.foregroundColor}
iconStyle={{ left: 5, transform: [{ rotate: '90deg' }] }}
iconStyle={{ left: 5, top: 2, transform: [{ rotate: '90deg' }] }}
/>
</TouchableOpacity>
</React.Fragment>
</View>
);
}
})()}

2
screen/wallets/walletMigrate.js

@ -82,7 +82,7 @@ export default class WalletMigrate extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignContent: 'center' }}>
<View style={{ flex: 1, justifyContent: 'center', alignContent: 'center', backgroundColor: '#ffffff' }}>
<ActivityIndicator />
</View>
);

Loading…
Cancel
Save