Browse Source

ADD: Today Extension and Quick Actions.

Update MainInterface.storyboard

ADD: Cache fetched data

ADD: Add "Up from/Down from" data

OPS: Add Provision Profile

Update project.pbxproj

ADD: Synchronize user selected currency with Today extension

Update Info.plist

ADD: quick actions

Update App.js

Update App.js

Update App.js

Update App.js

Update App.js

FIX: Fix currency bugs

FIX: Hide balance from quick actions

ADD: cqc

Update currency.js

Update TodayViewController.swift

Update App.js

REF: headercolor

Update App.js

FIX: carousel would not show

FIX: Fix

FIX

FIX

Update API.swift

FIX: Fixed alerts

TST

Revert "TST"

This reverts commit bcdf62e9b2.

ADD: Tests mocks

REF: Device Quick Actions ref

FIX: Fixed crash

Update quickActions.ios.js

ADD: QuickActions for Android

D

FIX: Tests

OP
acinqstrike
Marcos Rodriguez 5 years ago
committed by Overtorment
parent
commit
00bb9fe28b
  1. 74
      App.js
  2. 2
      BlueApp.js
  3. 2
      MainBottomTabs.js
  4. 2
      WatchConnectivity.ios.js
  5. BIN
      android/app/src/main/res/drawable/quickactions.png
  6. 9
      class/app-storage.js
  7. 46
      class/quickActions.js
  8. 17
      currency.js
  9. 1
      edit-version-number.sh
  10. 223
      ios/BlueWallet.xcodeproj/project.pbxproj
  11. 5
      ios/BlueWallet/AppDelegate.m
  12. 7
      ios/BlueWallet/BlueWallet.entitlements
  13. 15
      ios/BlueWallet/Info.plist
  14. 34
      ios/Podfile.lock
  15. 125
      ios/TodayExtension/Base.lproj/MainInterface.storyboard
  16. 10
      ios/TodayExtension/BlueWallet - Bitcoin Price.entitlements
  17. 31
      ios/TodayExtension/Info.plist
  18. 65
      ios/TodayExtension/New Group/API.swift
  19. 89
      ios/TodayExtension/TodayDataStore.swift
  20. 130
      ios/TodayExtension/TodayViewController.swift
  21. 16
      package-lock.json
  22. 4
      package.json
  23. 12
      screen/wallets/list.js
  24. 32
      screen/wallets/transactions.js
  25. 15
      tests/setup.js

74
App.js

@ -1,5 +1,5 @@
import React from 'react';
import { Linking, AppState, Clipboard, StyleSheet, KeyboardAvoidingView, Platform, View } from 'react-native';
import { Linking, DeviceEventEmitter, AppState, Clipboard, StyleSheet, KeyboardAvoidingView, Platform, View } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import Modal from 'react-native-modal';
import { NavigationActions } from 'react-navigation';
@ -10,8 +10,9 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import url from 'url';
import { AppStorage, LightningCustodianWallet } from './class';
import { Chain } from './models/bitcoinUnits';
import QuickActions from 'react-native-quick-actions';
import * as Sentry from '@sentry/react-native';
import OnAppLaunch from './class/onAppLaunch';
if (process.env.NODE_ENV !== 'development') {
Sentry.init({
@ -36,18 +37,71 @@ export default class App extends React.Component {
clipboardContent: '',
};
componentDidMount() {
Linking.getInitialURL()
.then(url => {
if (this.hasSchema(url)) {
this.handleOpenURL({ url });
}
})
.catch(console.error);
async componentDidMount() {
Linking.addEventListener('url', this.handleOpenURL);
AppState.addEventListener('change', this._handleAppStateChange);
QuickActions.popInitialAction().then(this.popInitialAction);
DeviceEventEmitter.addListener('quickActionShortcut', this.walletQuickActions);
}
popInitialAction = async data => {
if (data) {
// eslint-disable-next-line no-unused-expressions
this.navigator.dismiss;
const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === data.userInfo.url.split('wallet/')[1]);
this.navigator.dispatch(
NavigationActions.navigate({
key: `WalletTransactions-${wallet.getID()}`,
routeName: 'WalletTransactions',
params: {
wallet,
},
}),
);
} else {
const url = await Linking.getInitialURL();
if (url) {
if (this.hasSchema(url)) {
this.handleOpenURL({ url });
}
} else {
const isViewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
if (!isViewAllWalletsEnabled) {
// eslint-disable-next-line no-unused-expressions
this.navigator.dismiss;
const selectedDefaultWallet = await OnAppLaunch.getSelectedDefaultWallet();
const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === selectedDefaultWallet.getID());
if (wallet) {
this.navigator.dispatch(
NavigationActions.navigate({
routeName: 'WalletTransactions',
key: `WalletTransactions-${wallet.getID()}`,
params: {
wallet,
},
}),
);
}
}
}
}
};
walletQuickActions = data => {
const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === data.userInfo.url.split('wallet/')[1]);
// eslint-disable-next-line no-unused-expressions
this.navigator.dismiss;
this.navigator.dispatch(
NavigationActions.navigate({
routeName: 'WalletTransactions',
key: `WalletTransactions-${wallet.getID()}`,
params: {
wallet,
},
}),
);
};
componentWillUnmount() {
Linking.removeEventListener('url', this.handleOpenURL);
AppState.removeEventListener('change', this._handleAppStateChange);

2
BlueApp.js

@ -2,6 +2,7 @@
* @exports {AppStorage}
*/
import { AppStorage } from './class';
import DeviceQuickActions from './class/quickActions';
let prompt = require('./prompt');
let EV = require('./events');
let currency = require('./currency');
@ -19,6 +20,7 @@ async function startAndDecrypt(retry) {
}
let password = false;
if (await BlueApp.storageIsEncrypted()) {
DeviceQuickActions.clearShortcutItems();
do {
password = await prompt((retry && loc._.bad_password) || loc._.enter_password, loc._.storage_is_encrypted, false);
} while (!password);

2
MainBottomTabs.js

@ -64,6 +64,8 @@ const WalletsStackNavigator = createStackNavigator(
},
WalletTransactions: {
screen: WalletTransactions,
path: 'WalletTransactions',
routeName: 'WalletTransactions',
},
TransactionStatus: {
screen: TransactionStatus,

2
WatchConnectivity.ios.js

@ -65,8 +65,6 @@ export default class WatchConnectivity {
}
return InteractionManager.runAfterInteractions(async () => {
console.warn(WatchConnectivity.shared.isAppInstalled);
if (WatchConnectivity.shared.isAppInstalled) {
let wallets = [];

BIN
android/app/src/main/res/drawable/quickactions.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

9
class/app-storage.js

@ -12,6 +12,7 @@ import {
} from './';
import { LightningCustodianWallet } from './lightning-custodian-wallet';
import WatchConnectivity from '../WatchConnectivity';
import DeviceQuickActions from './quickActions';
const encryption = require('../encryption');
export class AppStorage {
@ -137,6 +138,8 @@ export class AppStorage {
this.cachedPassword = password;
await this.setItem('data', data);
await this.setItem(AppStorage.FLAG_ENCRYPTED, '1');
DeviceQuickActions.clearShortcutItems();
DeviceQuickActions.removeAllWallets();
}
/**
@ -251,6 +254,8 @@ export class AppStorage {
await this.saveToDisk();
};
await WatchConnectivity.shared.sendWalletsToWatch(this.wallets);
DeviceQuickActions.setWallets(this.wallets);
DeviceQuickActions.setQuickActions();
return true;
} else {
return false; // failed loading data or loading/decryptin data
@ -326,7 +331,9 @@ export class AppStorage {
}
WatchConnectivity.shared.wallets = this.wallets;
WatchConnectivity.shared.tx_metadata = this.tx_metadata;
await WatchConnectivity.shared.sendWalletsToWatch();
WatchConnectivity.shared.sendWalletsToWatch();
DeviceQuickActions.setWallets(this.wallets);
DeviceQuickActions.setQuickActions();
return this.setItem('data', JSON.stringify(data));
}

46
class/quickActions.js

@ -0,0 +1,46 @@
import QuickActions from 'react-native-quick-actions';
import { Platform } from 'react-native';
export default class DeviceQuickActions {
static shared = new DeviceQuickActions();
wallets;
static setWallets(wallets) {
DeviceQuickActions.shared.wallets = wallets;
}
static removeAllWallets() {
DeviceQuickActions.shared.wallets = undefined;
}
static setQuickActions() {
if (DeviceQuickActions.shared.wallets === undefined) {
return;
}
QuickActions.isSupported((error, supported) => {
if (supported && error === null) {
let shortcutItems = [];
const loc = require('../loc/');
for (const wallet of DeviceQuickActions.shared.wallets) {
shortcutItems.push({
type: 'Wallets', // Required
title: wallet.getLabel(), // Optional, if empty, `type` will be used instead
subtitle:
wallet.hideBalance || wallet.getBalance() <= 0
? ''
: loc.formatBalance(Number(wallet.getBalance()), wallet.getPreferredBalanceUnit(), true),
userInfo: {
url: `bluewallet://wallet/${wallet.getID()}`, // Provide any custom data like deep linking URL
},
icon: Platform.select({ android: 'quickactions', ios: 'bookmark' }),
});
}
QuickActions.setShortcutItems(shortcutItems);
}
});
}
static clearShortcutItems() {
QuickActions.clearShortcutItems();
}
}

17
currency.js

@ -2,6 +2,8 @@ import Frisbee from 'frisbee';
import AsyncStorage from '@react-native-community/async-storage';
import { AppStorage } from './class';
import { FiatUnit } from './models/fiatUnit';
import DefaultPreference from 'react-native-default-preference';
import DeviceQuickActions from './class/quickActions';
let BigNumber = require('bignumber.js');
let preferredFiatCurrency = FiatUnit.USD;
let exchangeRates = {};
@ -19,10 +21,17 @@ const STRUCT = {
*/
async function setPrefferedCurrency(item) {
await AsyncStorage.setItem(AppStorage.PREFERRED_CURRENCY, JSON.stringify(item));
await DefaultPreference.setName('group.io.bluewallet.bluewallet');
await DefaultPreference.set('preferredCurrency', item.endPointKey);
await DefaultPreference.set('preferredCurrencyLocale', item.locale.replace('-', '_'));
DeviceQuickActions.setQuickActions();
}
async function getPreferredCurrency() {
return JSON.parse(await AsyncStorage.getItem(AppStorage.PREFERRED_CURRENCY));
let preferredCurrency = await JSON.parse(await AsyncStorage.getItem(AppStorage.PREFERRED_CURRENCY));
await DefaultPreference.set('preferredCurrency', preferredCurrency.endPointKey);
await DefaultPreference.set('preferredCurrencyLocale', preferredCurrency.locale.replace('-', '_'));
return preferredCurrency;
}
async function updateExchangeRate() {
@ -57,6 +66,7 @@ async function updateExchangeRate() {
exchangeRates['BTC_' + preferredFiatCurrency.endPointKey] = json.bpi[preferredFiatCurrency.endPointKey].rate_float * 1;
await AsyncStorage.setItem(AppStorage.EXCHANGE_RATES, JSON.stringify(exchangeRates));
await AsyncStorage.setItem(AppStorage.PREFERRED_CURRENCY, JSON.stringify(preferredFiatCurrency));
DeviceQuickActions.setQuickActions();
}
let interval = false;
@ -71,7 +81,10 @@ async function startUpdater() {
}
function satoshiToLocalCurrency(satoshi) {
if (!exchangeRates['BTC_' + preferredFiatCurrency.endPointKey]) return '...';
if (!exchangeRates['BTC_' + preferredFiatCurrency.endPointKey]) {
startUpdater();
return '...';
}
let b = new BigNumber(satoshi);
b = b

1
edit-version-number.sh

@ -1,6 +1,7 @@
vim ios/BlueWallet/Info.plist
vim ios/BlueWalletWatch/Info.plist
vim "ios/BlueWalletWatch Extension/Info.plist"
vim "ios/TodayExtension/Info.plist"
vim android/app/build.gradle
vim package.json
vim package-lock.json

223
ios/BlueWallet.xcodeproj/project.pbxproj

@ -19,7 +19,13 @@
2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
2D16E6881FA4F8E400B85C8A /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D16E6891FA4F8E400B85C8A /* libReact.a */; };
2DCD954D1E0B4F2C00145EB5 /* BlueWalletTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* BlueWalletTests.m */; };
32002D9D236FAA9F00B93396 /* TodayDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32002D9C236FAA9F00B93396 /* TodayDataStore.swift */; };
3208E93922F63279007F5A27 /* AppCenter-Config.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3208E93822F63279007F5A27 /* AppCenter-Config.plist */; };
3271B0AB236E2E0700DA766F /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3271B0AA236E2E0700DA766F /* NotificationCenter.framework */; };
3271B0AE236E2E0700DA766F /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3271B0AD236E2E0700DA766F /* TodayViewController.swift */; };
3271B0B1236E2E0700DA766F /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3271B0AF236E2E0700DA766F /* MainInterface.storyboard */; };
3271B0B5236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 3271B0A9236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3271B0BB236E329400DA766F /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3271B0BA236E329400DA766F /* API.swift */; };
32B5A32A2334450100F8D608 /* Bridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B5A3292334450100F8D608 /* Bridge.swift */; };
32F0A29A2311DBB20095C559 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F0A2992311DBB20095C559 /* ComplicationController.swift */; };
398DED6337DF58F0ECFD8F2E /* libPods-BlueWalletTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 70089FECE936F9A0AC45B7CE /* libPods-BlueWalletTests.a */; };
@ -68,6 +74,13 @@
remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7;
remoteInfo = "BlueWallet-tvOS";
};
3271B0B3236E2E0700DA766F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 3271B0A8236E2E0700DA766F;
remoteInfo = TodayExtension;
};
B40D4E3E225841ED00428FCC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
@ -85,6 +98,17 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
3271B0B6236E2E0700DA766F /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
3271B0B5236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
B40D4E2D225841C300428FCC /* Embed Watch Content */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@ -131,7 +155,15 @@
2D02E4901E0B4A5D006451C7 /* BlueWallet-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "BlueWallet-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; };
2FCC2CD6FF4448229D0CE0F3 /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = "<group>"; };
32002D9C236FAA9F00B93396 /* TodayDataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayDataStore.swift; sourceTree = "<group>"; };
3208E93822F63279007F5A27 /* AppCenter-Config.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "AppCenter-Config.plist"; sourceTree = "<group>"; };
32475F792370F6D30070E6CF /* BlueWallet - Bitcoin Price.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "BlueWallet - Bitcoin Price.entitlements"; sourceTree = "<group>"; };
3271B0A9236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "BlueWallet - Bitcoin Price.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
3271B0AA236E2E0700DA766F /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; };
3271B0AD236E2E0700DA766F /* TodayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewController.swift; sourceTree = "<group>"; };
3271B0B0236E2E0700DA766F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
3271B0B2236E2E0700DA766F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3271B0BA236E329400DA766F /* API.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = API.swift; sourceTree = "<group>"; };
32B5A3282334450100F8D608 /* BlueWallet-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BlueWallet-Bridging-Header.h"; sourceTree = "<group>"; };
32B5A3292334450100F8D608 /* Bridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bridge.swift; sourceTree = "<group>"; };
32F0A24F2310B0700095C559 /* BlueWalletWatch Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "BlueWalletWatch Extension.entitlements"; sourceTree = "<group>"; };
@ -255,6 +287,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
3271B0A6236E2E0700DA766F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3271B0AB236E2E0700DA766F /* NotificationCenter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
421830728822A20A50D8A07C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -326,10 +366,33 @@
154B05BEF3C3512F67A08374 /* libPods-BlueWalletWatch Extension.a */,
70089FECE936F9A0AC45B7CE /* libPods-BlueWalletTests.a */,
731973BA0AC6EA78962CE5B6 /* libPods-BlueWallet.a */,
3271B0AA236E2E0700DA766F /* NotificationCenter.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
3271B0AC236E2E0700DA766F /* TodayExtension */ = {
isa = PBXGroup;
children = (
32475F792370F6D30070E6CF /* BlueWallet - Bitcoin Price.entitlements */,
32A5F95E236E4A2A00443927 /* API */,
3271B0AD236E2E0700DA766F /* TodayViewController.swift */,
3271B0AF236E2E0700DA766F /* MainInterface.storyboard */,
3271B0B2236E2E0700DA766F /* Info.plist */,
32002D9C236FAA9F00B93396 /* TodayDataStore.swift */,
);
path = TodayExtension;
sourceTree = "<group>";
};
32A5F95E236E4A2A00443927 /* API */ = {
isa = PBXGroup;
children = (
3271B0BA236E329400DA766F /* API.swift */,
);
name = API;
path = "New Group";
sourceTree = "<group>";
};
4B0CACE36C3348E1BCEA92C8 /* Resources */ = {
isa = PBXGroup;
children = (
@ -359,6 +422,7 @@
00E356EF1AD99517003FC87E /* BlueWalletTests */,
B40D4E31225841EC00428FCC /* BlueWalletWatch */,
B40D4E40225841ED00428FCC /* BlueWalletWatch Extension */,
3271B0AC236E2E0700DA766F /* TodayExtension */,
83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */,
B40FE50A21FAD228005D5578 /* Recovered References */,
@ -379,6 +443,7 @@
2D02E4901E0B4A5D006451C7 /* BlueWallet-tvOSTests.xctest */,
B40D4E30225841EC00428FCC /* BlueWalletWatch.app */,
B40D4E3C225841ED00428FCC /* BlueWalletWatch Extension.appex */,
3271B0A9236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex */,
);
name = Products;
sourceTree = "<group>";
@ -508,11 +573,13 @@
B40D4E2D225841C300428FCC /* Embed Watch Content */,
791C03B6EF06B63A39F55115 /* [CP] Copy Pods Resources */,
2130DE983D1D45AC8FC45F7E /* Upload Debug Symbols to Sentry */,
3271B0B6236E2E0700DA766F /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
B40D4E4C225841ED00428FCC /* PBXTargetDependency */,
3271B0B4236E2E0700DA766F /* PBXTargetDependency */,
);
name = BlueWallet;
productName = "Hello World";
@ -555,6 +622,23 @@
productReference = 2D02E4901E0B4A5D006451C7 /* BlueWallet-tvOSTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
3271B0A8236E2E0700DA766F /* TodayExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3271B0B9236E2E0700DA766F /* Build configuration list for PBXNativeTarget "TodayExtension" */;
buildPhases = (
3271B0A5236E2E0700DA766F /* Sources */,
3271B0A6236E2E0700DA766F /* Frameworks */,
3271B0A7236E2E0700DA766F /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = TodayExtension;
productName = TodayExtension;
productReference = 3271B0A9236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex */;
productType = "com.apple.product-type.app-extension";
};
B40D4E2F225841EC00428FCC /* BlueWalletWatch */ = {
isa = PBXNativeTarget;
buildConfigurationList = B40D4E52225841ED00428FCC /* Build configuration list for PBXNativeTarget "BlueWalletWatch" */;
@ -598,7 +682,7 @@
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1020;
LastSwiftUpdateCheck = 1120;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
@ -610,7 +694,7 @@
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = A7W54YZ4WU;
LastSwiftMigration = 1030;
ProvisioningStyle = Manual;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Keychain = {
enabled = 0;
@ -628,6 +712,11 @@
ProvisioningStyle = Automatic;
TestTargetID = 2D02E47A1E0B4A5D006451C7;
};
3271B0A8236E2E0700DA766F = {
CreatedOnToolsVersion = 11.2;
DevelopmentTeam = A7W54YZ4WU;
ProvisioningStyle = Automatic;
};
B40D4E2F225841EC00428FCC = {
CreatedOnToolsVersion = 10.2;
DevelopmentTeam = A7W54YZ4WU;
@ -665,6 +754,7 @@
2D02E48F1E0B4A5D006451C7 /* BlueWallet-tvOSTests */,
B40D4E2F225841EC00428FCC /* BlueWalletWatch */,
B40D4E3B225841ED00428FCC /* BlueWalletWatch Extension */,
3271B0A8236E2E0700DA766F /* TodayExtension */,
);
};
/* End PBXProject section */
@ -702,6 +792,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
3271B0A7236E2E0700DA766F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3271B0B1236E2E0700DA766F /* MainInterface.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B40D4E2E225841EC00428FCC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -938,6 +1036,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
3271B0A5236E2E0700DA766F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3271B0BB236E329400DA766F /* API.swift in Sources */,
3271B0AE236E2E0700DA766F /* TodayViewController.swift in Sources */,
32002D9D236FAA9F00B93396 /* TodayDataStore.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
B40D4E38225841ED00428FCC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -973,6 +1081,11 @@
target = 2D02E47A1E0B4A5D006451C7 /* BlueWallet-tvOS */;
targetProxy = 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */;
};
3271B0B4236E2E0700DA766F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 3271B0A8236E2E0700DA766F /* TodayExtension */;
targetProxy = 3271B0B3236E2E0700DA766F /* PBXContainerItemProxy */;
};
B40D4E3F225841ED00428FCC /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = B40D4E3B225841ED00428FCC /* BlueWalletWatch Extension */;
@ -995,6 +1108,14 @@
path = BlueWallet;
sourceTree = "<group>";
};
3271B0AF236E2E0700DA766F /* MainInterface.storyboard */ = {
isa = PBXVariantGroup;
children = (
3271B0B0236E2E0700DA766F /* Base */,
);
name = MainInterface.storyboard;
sourceTree = "<group>";
};
B40D4E32225841EC00428FCC /* Interface.storyboard */ = {
isa = PBXVariantGroup;
children = (
@ -1109,16 +1230,18 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 9B3A324B70BC8C6D9314FD4F /* Pods-BlueWallet.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CODE_SIGN_ENTITLEMENTS = BlueWallet/BlueWallet.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = A7W54YZ4WU;
DEVELOPMENT_TEAM = "";
HEADER_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = BlueWallet/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@ -1131,7 +1254,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet;
PRODUCT_NAME = BlueWallet;
PROVISIONING_PROFILE_SPECIFIER = "io.bluewallet.bluewallet AppStore";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "BlueWallet-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
@ -1144,15 +1267,17 @@
isa = XCBuildConfiguration;
baseConfigurationReference = B459EE96941AE09BCB547DC0 /* Pods-BlueWallet.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_ENTITLEMENTS = BlueWallet/BlueWallet.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
HEADER_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = BlueWallet/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
@ -1387,6 +1512,67 @@
};
name = Release;
};
3271B0B7236E2E0700DA766F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "TodayExtension/BlueWallet - Bitcoin Price.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = TodayExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
PRODUCT_NAME = "BlueWallet - Bitcoin Price";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
3271B0B8236E2E0700DA766F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "TodayExtension/BlueWallet - Bitcoin Price.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = TodayExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
PRODUCT_NAME = "BlueWallet - Bitcoin Price";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1438,7 +1624,7 @@
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@ -1486,7 +1672,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 4.2;
VALIDATE_PRODUCT = YES;
};
name = Release;
@ -1502,6 +1688,7 @@
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "BlueWalletWatch Extension/BlueWalletWatch Extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
DEBUG_INFORMATION_FORMAT = dwarf;
@ -1535,6 +1722,7 @@
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "BlueWalletWatch Extension/BlueWalletWatch Extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
@ -1584,7 +1772,7 @@
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 5.0;
};
@ -1617,7 +1805,7 @@
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 5.0;
};
@ -1662,6 +1850,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3271B0B9236E2E0700DA766F /* Build configuration list for PBXNativeTarget "TodayExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3271B0B7236E2E0700DA766F /* Debug */,
3271B0B8236E2E0700DA766F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "BlueWallet" */ = {
isa = XCConfigurationList;
buildConfigurations = (

5
ios/BlueWallet/AppDelegate.m

@ -10,6 +10,7 @@
#import <React/RCTLinkingManager.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "RNQuickActionManager.h"
#import <AppCenterReactNativeShared/AppCenterReactNativeShared.h>
#import <AppCenterReactNative.h>
#import <AppCenterReactNativeAnalytics.h>
@ -49,4 +50,8 @@
return NO;
}
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded)) completionHandler {
[RNQuickActionManager onQuickActionPress:shortcutItem completionHandler:completionHandler];
}
@end

7
ios/BlueWallet/BlueWallet.entitlements

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.io.bluewallet.bluewallet</string>
</array>
</dict>
</plist>

15
ios/BlueWallet/Info.plist

@ -47,21 +47,6 @@
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>electrum3.bluewallet.io</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>electrum2.bluewallet.io</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>electrum1.bluewallet.io</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>

34
ios/Podfile.lock

@ -10,13 +10,13 @@ PODS:
- AppCenter/Crashes
- AppCenterReactNativeShared
- React
- AppCenter/Analytics (2.5.0):
- AppCenter/Analytics (2.5.1):
- AppCenter/Core
- AppCenter/Core (2.5.0)
- AppCenter/Crashes (2.5.0):
- AppCenter/Core (2.5.1)
- AppCenter/Crashes (2.5.1):
- AppCenter/Core
- AppCenterReactNativeShared (2.5.0):
- AppCenter/Core (= 2.5.0)
- AppCenterReactNativeShared (2.6.0):
- AppCenter/Core (= 2.5.1)
- boost-for-react-native (1.63.0)
- BVLinearGradient (2.5.4):
- React
@ -133,6 +133,8 @@ PODS:
- React
- RNCAsyncStorage (1.6.2):
- React
- RNDefaultPreference (1.4.1):
- React
- RNDeviceInfo (4.0.1):
- React
- RNFS (2.13.3):
@ -141,6 +143,8 @@ PODS:
- React
- RNHandoff (0.0.3):
- React
- RNQuickAction (0.3.12):
- React
- RNRate (1.0.1):
- React
- RNSecureKeyStore (1.0.0):
@ -156,9 +160,9 @@ PODS:
- React
- RNWatch (0.4.1):
- React
- Sentry (4.4.1):
- Sentry/Core (= 4.4.1)
- Sentry/Core (4.4.1)
- Sentry (4.4.2):
- Sentry/Core (= 4.4.2)
- Sentry/Core (4.4.2)
- swift_qrcodejs (1.1.2)
- TcpSockets (3.3.2):
- React
@ -204,10 +208,12 @@ DEPENDENCIES:
- ReactNativePrivacySnapshot (from `../node_modules/react-native-privacy-snapshot`)
- "RemobileReactNativeQrcodeLocalImage (from `../node_modules/@remobile/react-native-qrcode-local-image`)"
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNFS (from `../node_modules/react-native-fs`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNHandoff (from `../node_modules/react-native-handoff`)
- RNQuickAction (from `../node_modules/react-native-quick-actions`)
- RNRate (from `../node_modules/react-native-rate/ios`)
- RNSecureKeyStore (from `../node_modules/react-native-secure-key-store/ios`)
- "RNSentry (from `../node_modules/@sentry/react-native`)"
@ -302,6 +308,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/@remobile/react-native-qrcode-local-image"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNDefaultPreference:
:path: "../node_modules/react-native-default-preference"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNFS:
@ -310,6 +318,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-gesture-handler"
RNHandoff:
:path: "../node_modules/react-native-handoff"
RNQuickAction:
:path: "../node_modules/react-native-quick-actions"
RNRate:
:path: "../node_modules/react-native-rate/ios"
RNSecureKeyStore:
@ -332,11 +342,11 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
AppCenter: 637f180deefc61e8ab3f94223869ee50f61dabea
AppCenter: fddcbac6e4baae3d93a196ceb0bfe0e4ce407dec
appcenter: bde9923b687332a25607fc1aa9577c9361cfed85
appcenter-analytics: 0ee7a35def715d4bce58ec435f54161770195166
appcenter-crashes: 9f9c5647dba19026ff09509576fb7233f69697ff
AppCenterReactNativeShared: 99e7f662ec66b1cb41306ecf357aabac35931c08
AppCenterReactNativeShared: d5e360f8a4cb5126d29e31ab98051d2f070ba631
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: 8cbc5155c978f2e43098818c91d206d07aae6d30
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
@ -373,10 +383,12 @@ SPEC CHECKSUMS:
ReactNativePrivacySnapshot: cc295e45dc22810e9ff2c93380d643de20a77015
RemobileReactNativeQrcodeLocalImage: 57aadc12896b148fb5e04bc7c6805f3565f5c3fa
RNCAsyncStorage: 5ae4d57458804e99f73d427214442a6b10a53856
RNDefaultPreference: 12d246dd2222e66dadcd76cc1250560663befc3a
RNDeviceInfo: 12faae605ba42a1a5041c3c41a77834bc23f049d
RNFS: c9bbde46b0d59619f8e7b735991c60e0f73d22c1
RNGestureHandler: 5329a942fce3d41c68b84c2c2276ce06a696d8b0
RNHandoff: d3b0754cca3a6bcd9b25f544f733f7f033ccf5fa
RNQuickAction: eca9a5dd04b5cdf8a0dd32d8be8844dc33aba2bd
RNRate: 29be49c24b314c4e8ec09d848c3965f61cb0be47
RNSecureKeyStore: f1ad870e53806453039f650720d2845c678d89c8
RNSentry: 2803ba8c8129dcf26b79e9b4d8c80168be6e4390
@ -384,7 +396,7 @@ SPEC CHECKSUMS:
RNSVG: 0eb087cfb5d7937be93c45b163b26352a647e681
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
RNWatch: a14e378448e187cc12f307f61d41fe8a65400e86
Sentry: 5d312a04e369154aeac616214f4dfc3cbcc8b296
Sentry: bba998b0fb157fdd6596aa73290a9d67ae47be79
swift_qrcodejs: 4d024fc98b0778b804ec6a5c810880fd092aec9d
TcpSockets: 8d839b9b14f6f344d98e4642ded13ab3112b462d
ToolTipMenu: bdcaa0e888bcf44778a67fe34639b094352e904e

125
ios/TodayExtension/Base.lproj/MainInterface.storyboard

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="M4Y-Lb-cyx">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15509"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Today View Controller-->
<scene sceneID="cwh-vc-ff4">
<objects>
<viewController id="M4Y-Lb-cyx" customClass="TodayViewController" customModule="BlueWallet___Bitcoin_Price" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" simulatedAppContext="notificationCenter" id="S3S-Oj-5AN">
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Bitcoin Price" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aaf-Pc-Y9i">
<rect key="frame" x="16" y="8" width="288" height="21"/>
<constraints>
<constraint firstAttribute="height" constant="21" id="fON-Nf-oBQ"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bcB-MD-aJf">
<rect key="frame" x="104" y="73" width="200" height="15"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Last Updated:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vU4-uK-6ow">
<rect key="frame" x="16" y="73" width="80" height="15"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="USD" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lkL-gv-1a1">
<rect key="frame" x="16" y="40" width="35" height="33"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="35" id="4Nq-zK-gi3"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bEQ-e6-Puo">
<rect key="frame" x="59" y="46.5" width="14" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrow.up" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="eST-DU-WIK">
<rect key="frame" x="221" y="47.5" width="17" height="18"/>
<constraints>
<constraint firstAttribute="width" constant="17" id="gkK-pz-TDJ"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="..." textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gm7-vT-KrH" userLabel="...">
<rect key="frame" x="290" y="40" width="14" height="33"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="14" id="KoT-51-551"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="from" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aqr-Mt-cor">
<rect key="frame" x="246" y="40" width="36" height="33"/>
<constraints>
<constraint firstAttribute="height" constant="33" id="u9N-WC-Os2"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="aqr-Mt-cor" firstAttribute="top" secondItem="aaf-Pc-Y9i" secondAttribute="bottom" constant="11" id="0ca-1C-JqG"/>
<constraint firstItem="ssy-KU-ocm" firstAttribute="trailing" secondItem="aaf-Pc-Y9i" secondAttribute="trailing" constant="16" id="197-jr-Kn5"/>
<constraint firstItem="eST-DU-WIK" firstAttribute="centerY" secondItem="aqr-Mt-cor" secondAttribute="centerY" id="2yd-pY-y1Y"/>
<constraint firstItem="bcB-MD-aJf" firstAttribute="leading" secondItem="vU4-uK-6ow" secondAttribute="trailing" constant="8" id="5bB-Zv-Yeq"/>
<constraint firstItem="lkL-gv-1a1" firstAttribute="leading" secondItem="ssy-KU-ocm" secondAttribute="leading" constant="16" id="Bgx-xM-CSS"/>
<constraint firstItem="ssy-KU-ocm" firstAttribute="bottom" secondItem="bcB-MD-aJf" secondAttribute="bottom" constant="12" id="EPP-OS-3b6"/>
<constraint firstItem="vU4-uK-6ow" firstAttribute="leading" secondItem="ssy-KU-ocm" secondAttribute="leading" constant="16" id="EkD-jp-arv"/>
<constraint firstItem="gm7-vT-KrH" firstAttribute="centerY" secondItem="aqr-Mt-cor" secondAttribute="centerY" id="Eo2-n1-zbi"/>
<constraint firstItem="ssy-KU-ocm" firstAttribute="bottom" secondItem="vU4-uK-6ow" secondAttribute="bottom" constant="12" id="JSh-ZE-k1H"/>
<constraint firstItem="bcB-MD-aJf" firstAttribute="centerY" secondItem="vU4-uK-6ow" secondAttribute="centerY" id="MUL-tE-LmX"/>
<constraint firstItem="bEQ-e6-Puo" firstAttribute="leading" secondItem="lkL-gv-1a1" secondAttribute="trailing" constant="8" id="Ml2-4o-Yqk"/>
<constraint firstItem="ssy-KU-ocm" firstAttribute="trailing" secondItem="gm7-vT-KrH" secondAttribute="trailing" constant="16" id="OLV-lQ-T8a"/>
<constraint firstItem="gm7-vT-KrH" firstAttribute="centerY" secondItem="bEQ-e6-Puo" secondAttribute="centerY" id="Rle-PT-j9m"/>
<constraint firstItem="gm7-vT-KrH" firstAttribute="leading" secondItem="aqr-Mt-cor" secondAttribute="trailing" constant="8" id="Rtu-ah-AvP"/>
<constraint firstItem="gm7-vT-KrH" firstAttribute="firstBaseline" secondItem="aqr-Mt-cor" secondAttribute="firstBaseline" id="YIV-xq-qlw"/>
<constraint firstItem="bEQ-e6-Puo" firstAttribute="centerY" secondItem="lkL-gv-1a1" secondAttribute="centerY" id="Ys3-7f-RIc"/>
<constraint firstItem="aaf-Pc-Y9i" firstAttribute="leading" secondItem="S3S-Oj-5AN" secondAttribute="leading" constant="16" id="a1b-Yq-aZb"/>
<constraint firstItem="aaf-Pc-Y9i" firstAttribute="top" secondItem="S3S-Oj-5AN" secondAttribute="top" constant="8" id="aIo-h1-w4F"/>
<constraint firstItem="lkL-gv-1a1" firstAttribute="top" secondItem="aaf-Pc-Y9i" secondAttribute="bottom" constant="11" id="dET-8J-W4K"/>
<constraint firstItem="ssy-KU-ocm" firstAttribute="trailing" secondItem="bcB-MD-aJf" secondAttribute="trailing" constant="16" id="kkD-VZ-BAt"/>
<constraint firstItem="vU4-uK-6ow" firstAttribute="firstBaseline" secondItem="lkL-gv-1a1" secondAttribute="baseline" constant="16" symbolType="layoutAnchor" id="lml-Hc-8Sv"/>
<constraint firstItem="aqr-Mt-cor" firstAttribute="leading" secondItem="eST-DU-WIK" secondAttribute="trailing" constant="8" id="t4j-U9-sOm"/>
</constraints>
<viewLayoutGuide key="safeArea" id="ssy-KU-ocm"/>
</view>
<extendedEdge key="edgesForExtendedLayout"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<size key="freeformSize" width="320" height="100"/>
<connections>
<outlet property="currencyLabel" destination="lkL-gv-1a1" id="Gzb-TF-E6W"/>
<outlet property="lastPrice" destination="gm7-vT-KrH" id="YIE-KJ-0qW"/>
<outlet property="lastPriceArrowImage" destination="eST-DU-WIK" id="VWH-ED-VL1"/>
<outlet property="lastPriceFromLabel" destination="aqr-Mt-cor" id="p17-Aq-ufa"/>
<outlet property="lastUpdatedDate" destination="bcB-MD-aJf" id="A9U-MB-qJq"/>
<outlet property="priceLabel" destination="bEQ-e6-Puo" id="0IP-Yg-dWr"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="vXp-U4-Rya" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="137.68115942028987" y="96.428571428571431"/>
</scene>
</scenes>
<resources>
<image name="arrow.up" catalog="system" width="60" height="64"/>
</resources>
</document>

10
ios/TodayExtension/BlueWallet - Bitcoin Price.entitlements

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.io.bluewallet.bluewallet</string>
</array>
</dict>
</plist>

31
ios/TodayExtension/Info.plist

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>4.7.3</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widget-extension</string>
</dict>
</dict>
</plist>

65
ios/TodayExtension/New Group/API.swift

@ -0,0 +1,65 @@
//
// API.swift
// TodayExtension
//
// Created by Marcos Rodriguez on 11/2/19.
// Copyright © 2019 Facebook. All rights reserved.
//
import Foundation
class API {
static func fetchPrice(currency: String, completion: @escaping ((Dictionary<String, Any>?, Error?) -> Void)) {
guard let url = URL(string: "https://api.coindesk.com/v1/bpi/currentPrice/\(currency).json") else {return}
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
let json = try? JSONSerialization.jsonObject(with: dataResponse, options: .mutableContainers) as? Dictionary<String, Any>,
error == nil else {
print(error?.localizedDescription ?? "Response Error")
completion(nil, error)
return }
completion(json, nil)
}.resume()
}
static func getUserPreferredCurrency() -> String {
guard let userDefaults = UserDefaults(suiteName: "group.io.bluewallet.bluewallet"),
let preferredCurrency = userDefaults.string(forKey: "preferredCurrency")
else {
return "USD"
}
if preferredCurrency != API.getLastSelectedCurrency() {
UserDefaults.standard.removeObject(forKey: TodayData.TodayCachedDataStoreKey)
UserDefaults.standard.removeObject(forKey: TodayData.TodayDataStoreKey)
UserDefaults.standard.synchronize()
}
return preferredCurrency
}
static func getUserPreferredCurrencyLocale() -> String {
guard let userDefaults = UserDefaults(suiteName: "group.io.bluewallet.bluewallet"),
let preferredCurrency = userDefaults.string(forKey: "preferredCurrencyLocale")
else {
return "en_US"
}
return preferredCurrency
}
static func getLastSelectedCurrency() -> String {
guard let dataStore = UserDefaults.standard.string(forKey: "currency") else {
return "USD"
}
return dataStore
}
static func saveNewSelectedCurrency() {
UserDefaults.standard.setValue(API.getUserPreferredCurrency(), forKey: "currency")
}
}

89
ios/TodayExtension/TodayDataStore.swift

@ -0,0 +1,89 @@
//
// TodayDataStore.swift
// TodayExtension
//
// Created by Marcos Rodriguez on 11/3/19.
// Copyright © 2019 Facebook. All rights reserved.
//
import Foundation
struct TodayDataStore {
let rate: String
let lastUpdate: String
var formattedDate: String? {
let isoDateFormatter = ISO8601DateFormatter()
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short
dateFormatter.dateStyle = .short
if let date = isoDateFormatter.date(from: lastUpdate) {
return dateFormatter.string(from: date)
}
return nil
}
var rateDoubleValue: Double? {
let rateDigits = rate.replacingOccurrences(of: ",", with: "");
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 2
numberFormatter.minimumFractionDigits = 2
if let rateDoubleValue = numberFormatter.number(from: rateDigits) {
return rateDoubleValue.doubleValue
}
return nil
}
var formattedRate: String? {
let rateDigits = rate.replacingOccurrences(of: ",", with: "");
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 2
numberFormatter.minimumFractionDigits = 2
if let rateNumber = numberFormatter.number(from: rateDigits) {
numberFormatter.numberStyle = .currency
numberFormatter.locale = Locale(identifier: API.getUserPreferredCurrencyLocale())
return numberFormatter.string(from: rateNumber);
}
return nil
}
}
class TodayData {
static let TodayDataStoreKey = "TodayDataStoreKey"
static let TodayCachedDataStoreKey = "TodayCachedDataStoreKey"
static func savePriceRateAndLastUpdate(rate: String, lastUpdate: String) {
UserDefaults.standard.setValue(["rate": rate, "lastUpdate": lastUpdate], forKey: TodayDataStoreKey)
UserDefaults.standard.synchronize()
}
static func getPriceRateAndLastUpdate() -> TodayDataStore? {
guard let dataStore = UserDefaults.standard.value(forKey: TodayDataStoreKey) as? [String: String], let rate = dataStore["rate"], let lastUpdate = dataStore["lastUpdate"] else {
return nil
}
return TodayDataStore(rate: rate, lastUpdate: lastUpdate)
}
static func saveCachePriceRateAndLastUpdate(rate: String, lastUpdate: String) {
UserDefaults.standard.setValue(["rate": rate, "lastUpdate": lastUpdate], forKey: TodayCachedDataStoreKey)
UserDefaults.standard.synchronize()
}
static func getCachedPriceRateAndLastUpdate() -> TodayDataStore? {
guard let dataStore = UserDefaults.standard.value(forKey: TodayCachedDataStoreKey) as? [String: String], var rate = dataStore["rate"], let lastUpdate = dataStore["lastUpdate"] else {
return nil
}
rate = rate.replacingOccurrences(of: ",", with: "");
return TodayDataStore(rate: rate, lastUpdate: lastUpdate)
}
}

130
ios/TodayExtension/TodayViewController.swift

@ -0,0 +1,130 @@
//
// TodayViewController.swift
// TodayExtension
//
// Created by Marcos Rodriguez on 11/2/19.
// Copyright © 2019 Facebook. All rights reserved.
//
import UIKit
import NotificationCenter
class TodayViewController: UIViewController, NCWidgetProviding {
@IBOutlet weak var currencyLabel: UILabel!
@IBOutlet weak var lastUpdatedDate: UILabel!
@IBOutlet weak var priceLabel: UILabel!
@IBOutlet weak var lastPriceArrowImage: UIImageView!
@IBOutlet weak var lastPrice: UILabel!
@IBOutlet weak var lastPriceFromLabel: UILabel!
private var lastPriceNumber: NSNumber?
override func viewDidLoad() {
super.viewDidLoad()
setLastPriceOutletsHidden(isHidden: true)
if let lastStoredTodayStore = TodayData.getPriceRateAndLastUpdate() {
processRateAndLastUpdate(todayStore: lastStoredTodayStore)
} else {
setLastPriceOutletsHidden(isHidden: true)
}
}
func setLastPriceOutletsHidden(isHidden: Bool) {
lastPrice.isHidden = isHidden
lastPriceFromLabel.isHidden = isHidden
lastPriceArrowImage.isHidden = isHidden
}
func processRateAndLastUpdate(todayStore: TodayDataStore) {
guard let rateString = todayStore.formattedRate, let dateFormatted = todayStore.formattedDate else { return }
priceLabel.text = rateString
lastUpdatedDate.text = dateFormatted
}
func processStoredRateAndLastUpdate(todayStore: TodayDataStore) {
guard let lastPriceNumber = todayStore.formattedRate else { return }
lastPrice.text = lastPriceNumber
}
func processCachedStoredRateAndLastUpdate(new: TodayDataStore, cached: TodayDataStore) {
guard let newPriceDoubleValue = new.rateDoubleValue, let cachedPriceNumber = cached.formattedRate, let cachedPriceNumberDoubleValue = cached.rateDoubleValue else { return }
lastPrice.text = cachedPriceNumber
if newPriceDoubleValue > cachedPriceNumberDoubleValue {
self.lastPriceArrowImage.image = UIImage(systemName: "arrow.up")
self.setLastPriceOutletsHidden(isHidden: false)
} else {
self.lastPriceArrowImage.image = UIImage(systemName: "arrow.down")
self.setLastPriceOutletsHidden(isHidden: false)
}
}
func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResult.Failed
// If there's no update required, use NCUpdateResult.NoData
// If there's an update, use NCUpdateResult.NewData
let userPreferredCurrency = API.getUserPreferredCurrency();
self.currencyLabel.text = userPreferredCurrency
API.fetchPrice(currency: userPreferredCurrency, completion: { (result, error) in
DispatchQueue.main.async { [unowned self] in
guard let result = result else {
completionHandler(.failed)
return
}
guard let bpi = result["bpi"] as? Dictionary<String, Any>, let preferredCurrency = bpi[userPreferredCurrency] as? Dictionary<String, Any>, let rateString = preferredCurrency["rate"] as? String,
let time = result["time"] as? Dictionary<String, Any>, let lastUpdatedString = time["updatedISO"] as? String
else {
return
}
let latestRateDataStore = TodayDataStore(rate: rateString, lastUpdate: lastUpdatedString)
if let lastStoredTodayStore = TodayData.getPriceRateAndLastUpdate(), lastStoredTodayStore.lastUpdate == latestRateDataStore.lastUpdate, rateString == lastStoredTodayStore.rate, API.getLastSelectedCurrency() == userPreferredCurrency {
if let cached = TodayData.getCachedPriceRateAndLastUpdate() {
self.processCachedStoredRateAndLastUpdate(new: lastStoredTodayStore, cached: cached)
} else {
self.setLastPriceOutletsHidden(isHidden: true)
}
completionHandler(.noData)
} else {
self.processRateAndLastUpdate(todayStore: latestRateDataStore)
let priceRiceAndLastUpdate = TodayData.getPriceRateAndLastUpdate()
if let rate = priceRiceAndLastUpdate?.rate, let lastUpdate = priceRiceAndLastUpdate?.lastUpdate {
TodayData.saveCachePriceRateAndLastUpdate(rate: rate, lastUpdate: lastUpdate);
}
if let latestRateDataStore = latestRateDataStore.rateDoubleValue, let lastStoredPriceNumber = priceRiceAndLastUpdate?.rateDoubleValue, API.getLastSelectedCurrency() == userPreferredCurrency {
if latestRateDataStore > lastStoredPriceNumber {
self.lastPriceArrowImage.image = UIImage(systemName: "arrow.up")
self.setLastPriceOutletsHidden(isHidden: false)
} else {
self.lastPriceArrowImage.image = UIImage(systemName: "arrow.down")
self.setLastPriceOutletsHidden(isHidden: false)
}
self.lastPrice.text = priceRiceAndLastUpdate?.formattedRate
} else {
self.setLastPriceOutletsHidden(isHidden: true)
}
TodayData.savePriceRateAndLastUpdate(rate: latestRateDataStore.rate, lastUpdate: latestRateDataStore.lastUpdate)
API.saveNewSelectedCurrency()
completionHandler(.newData)
}
}
})
}
}

16
package-lock.json

@ -12227,6 +12227,11 @@
}
}
},
"react-native-default-preference": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/react-native-default-preference/-/react-native-default-preference-1.4.1.tgz",
"integrity": "sha512-UHX8Hsgq2AwEI8SA1IkjU+u6y+Uroht0sCP70UVLhEZWyqRnn8elrcEjRSInWFNUwxSeFF/c7Tnf17fWFHZEcw=="
},
"react-native-device-info": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-4.0.1.tgz",
@ -12331,6 +12336,11 @@
"qrcode": "^1.2.0"
}
},
"react-native-quick-actions": {
"version": "0.3.12",
"resolved": "https://registry.npmjs.org/react-native-quick-actions/-/react-native-quick-actions-0.3.12.tgz",
"integrity": "sha512-jQkzbA6L1/+FIqvHnPenHUe2IrBihh48KOMTOa0QbOaxWzsejSB8kkWpSQOjYxjGu7k+3DVgosQ8wGJTB/l4JA=="
},
"react-native-randombytes": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/react-native-randombytes/-/react-native-randombytes-3.5.3.tgz",
@ -12391,9 +12401,9 @@
"integrity": "sha512-J8Xl3mq0L9KDFtSYtKsQDAnZWw/niZIpAD1PRiNfZFHo44Rc+oS2bEIhskNnoQXKEgBNdPzCl/DenMXYAHXRYg=="
},
"react-native-snap-carousel": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/react-native-snap-carousel/-/react-native-snap-carousel-3.8.0.tgz",
"integrity": "sha512-YtDZLv2Di77HfnH4yf+NyyYyISPNjrnjXDQLrzOkG9kkSlho/BROgHLQKGRLg3C2YSUMArFOePrb9CH3yeV5FA==",
"version": "3.8.4",
"resolved": "https://registry.npmjs.org/react-native-snap-carousel/-/react-native-snap-carousel-3.8.4.tgz",
"integrity": "sha512-KMxLl75Tyf12DzeTCtV7xU0KuPZQQs/2+2iM90cgxcm3lrg4+hLXff5/61ynasBkzzJ5v4bTRq5CEy/qGUJVQw==",
"requires": {
"prop-types": "^15.6.1",
"react-addons-shallow-compare": "15.6.2"

4
package.json

@ -90,6 +90,7 @@
"react-native": "0.60.5",
"react-native-biometrics": "git+https://github.com/BlueWallet/react-native-biometrics.git",
"react-native-camera": "3.4.0",
"react-native-default-preference": "1.4.1",
"react-native-device-info": "4.0.1",
"react-native-elements": "0.19.0",
"react-native-flexi-radio-button": "0.2.2",
@ -106,11 +107,12 @@
"react-native-privacy-snapshot": "git+https://github.com/BlueWallet/react-native-privacy-snapshot.git",
"react-native-prompt-android": "git+https://github.com/marcosrdz/react-native-prompt-android.git",
"react-native-qrcode-svg": "5.1.2",
"react-native-quick-actions": "0.3.12",
"react-native-randombytes": "3.5.3",
"react-native-rate": "1.1.7",
"react-native-secure-key-store": "git+https://github.com/marcosrdz/react-native-secure-key-store.git",
"react-native-share": "2.0.0",
"react-native-snap-carousel": "3.8.0",
"react-native-snap-carousel": "3.8.4",
"react-native-sortable-list": "0.0.23",
"react-native-svg": "9.5.1",
"react-native-tcp": "git+https://github.com/aprock/react-native-tcp.git",

12
screen/wallets/list.js

@ -5,8 +5,6 @@ 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';
import OnAppLaunch from '../../class/onAppLaunch';
let EV = require('../../events');
let A = require('../../analytics');
/** @type {AppStorage} */
@ -51,13 +49,6 @@ export default class WalletsList extends Component {
// the idea is that upon wallet launch we will refresh
// all balances and all transactions here:
InteractionManager.runAfterInteractions(async () => {
const isViewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled();
if (!isViewAllWalletsEnabled) {
const selectedDefaultWallet = await OnAppLaunch.getSelectedDefaultWallet();
const walletIndex = this.state.wallets.findIndex(wallet => wallet.getID() === selectedDefaultWallet.getID());
this.handleClick(walletIndex);
}
let noErr = true;
try {
await BlueElectrum.waitTillConnected();
@ -143,7 +134,7 @@ export default class WalletsList extends Component {
if (wallet) {
this.props.navigation.navigate('WalletTransactions', {
wallet: wallet,
headerColor: WalletGradient.headerColorFor(wallet.type),
key: `WalletTransactions-${wallet.getID()}`,
});
} else {
// if its out of index - this must be last card with incentive to create wallet
@ -266,6 +257,7 @@ export default class WalletsList extends Component {
>
<BlueHeaderDefaultMain leftText={loc.wallets.list.title} onNewWalletPress={() => this.props.navigation.navigate('AddWallet')} />
<WalletsCarousel
removeClippedSubviews={false}
data={this.state.wallets}
handleClick={index => {
this.handleClick(index);

32
screen/wallets/transactions.js

@ -26,6 +26,7 @@ import {
BlueTransactionListItem,
BlueWalletNavigationHeader,
} from '../../BlueComponents';
import WalletGradient from '../../class/walletGradient';
import { Icon } from 'react-native-elements';
import { LightningCustodianWallet } from '../../class';
import Handoff from 'react-native-handoff';
@ -54,7 +55,7 @@ export default class WalletTransactions extends Component {
</TouchableOpacity>
),
headerStyle: {
backgroundColor: navigation.getParam('headerColor'),
backgroundColor: WalletGradient.headerColorFor(navigation.state.params.wallet.type),
borderBottomWidth: 0,
elevation: 0,
shadowRadius: 0,
@ -354,29 +355,28 @@ export default class WalletTransactions extends Component {
};
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();
if (wallet) {
NavigationService.navigate('WalletTransactions', {
key: `WalletTransactions-${wallet.getID()}`,
});
/** @type {LightningCustodianWallet} */
let toAddress = false;
if (this.state.wallet.refill_addressess.length > 0) {
toAddress = this.state.wallet.refill_addressess[0];
} catch (Err) {
return alert(Err.message);
} 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');
}
};

15
tests/setup.js

@ -5,3 +5,18 @@ jest.mock('react-native-watch-connectivity', () => {
updateApplicationContext: jest.fn(),
}
})
jest.mock('react-native-quick-actions', () => {
return {
clearShortcutItems: jest.fn(),
setQuickActions: jest.fn(),
isSupported: jest.fn(),
}
})
jest.mock('react-native-default-preference', () => {
return {
setName: jest.fn(),
set: jest.fn(),
}
})
Loading…
Cancel
Save