mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2024-11-19 09:50:15 +01:00
ADD: push notifications
This commit is contained in:
parent
f58653bdb7
commit
545c8891f6
1
App.js
1
App.js
@ -30,6 +30,7 @@ const lightningModalString = 'Lightning Invoice';
|
||||
const loc = require('./loc');
|
||||
const BlueApp = require('./BlueApp');
|
||||
const EV = require('./blue_modules/events');
|
||||
const notifications = require('./blue_modules/notifications'); // eslint-disable-line no-unused-vars
|
||||
|
||||
export default class App extends React.Component {
|
||||
state = {
|
||||
|
@ -2,6 +2,8 @@ import * as Watch from 'react-native-watch-connectivity';
|
||||
import { InteractionManager } from 'react-native';
|
||||
import { Chain } from './models/bitcoinUnits';
|
||||
const loc = require('./loc');
|
||||
const notifications = require('./blue_modules/notifications');
|
||||
|
||||
export default class WatchConnectivity {
|
||||
isAppInstalled = false;
|
||||
static shared = new WatchConnectivity();
|
||||
@ -50,6 +52,11 @@ export default class WatchConnectivity {
|
||||
if (wallet.allowReceive() && amount > 0 && description.trim().length > 0) {
|
||||
try {
|
||||
const invoiceRequest = await wallet.addInvoice(amount, description);
|
||||
|
||||
// lets decode payreq and subscribe groundcontrol so we can receive push notification when our invoice is paid
|
||||
const decoded = await wallet.decodeInvoice(invoiceRequest);
|
||||
await notifications.tryToObtainPermissions();
|
||||
notifications.majorTomToGroundControl([], [decoded.payment_hash]);
|
||||
return invoiceRequest;
|
||||
} catch (error) {
|
||||
return error;
|
||||
|
@ -219,4 +219,5 @@ task copyDownloadableDepsToLibs(type: Copy) {
|
||||
into 'libs'
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services' // Google Services plugin
|
||||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
||||
|
40
android/app/google-services.json
Normal file
40
android/app/google-services.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "993804676679",
|
||||
"firebase_url": "https://bluewallet-d7cd5.firebaseio.com",
|
||||
"project_id": "bluewallet-d7cd5",
|
||||
"storage_bucket": "bluewallet-d7cd5.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:993804676679:android:3e611cf30d58bac8b5cb62",
|
||||
"android_client_info": {
|
||||
"package_name": "io.bluewallet.bluewallet"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "993804676679-cntmqmnbkrm9c89lcr1cq6rhaq8tfi0u.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCzJxNtavou1G10ZLIjzC-b2mX6TrVF3Ew"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "993804676679-cntmqmnbkrm9c89lcr1cq6rhaq8tfi0u.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
@ -13,6 +13,38 @@
|
||||
android:allowBackup="false"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name"
|
||||
android:value="BlueWallet notifications"/> <!-- YOUR NOTIFICATION CHANNEL NAME -->
|
||||
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_description"
|
||||
android:value="Notifications about incoming payments"/> <!-- YOUR NOTIFICATION CHANNEL DESCRIPTION -->
|
||||
|
||||
<!-- Change the value to true to enable pop-up for in foreground (remote-only, for local use ignoreInForeground) -->
|
||||
<meta-data android:name="com.dieam.reactnativepushnotification.notification_foreground"
|
||||
android:value="true"/>
|
||||
<!-- Change the value to false if you don't want the creation of the default channel -->
|
||||
<meta-data android:name="com.dieam.reactnativepushnotification.channel_create_default"
|
||||
android:value="true"/>
|
||||
<!-- Change the resource name to your App's accent color - or any other color you want -->
|
||||
<meta-data android:name="com.dieam.reactnativepushnotification.notification_color"
|
||||
android:resource="@color/white"/> <!-- or @android:color/{name} to use a standard color -->
|
||||
|
||||
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationActions" />
|
||||
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
|
||||
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
|
||||
android:exported="false" >
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
|
3
android/app/src/main/res/values/colors.xml
Normal file
3
android/app/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<color name="white">#FFF</color>
|
||||
</resources>
|
@ -9,6 +9,7 @@ buildscript {
|
||||
supportLibVersion = "28.0.0"
|
||||
googlePlayServicesVersion = "16.+"
|
||||
firebaseVersion = "17.3.4"
|
||||
firebaseMessagingVersion = "20.2.1"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
@ -18,6 +19,8 @@ buildscript {
|
||||
dependencies {
|
||||
classpath('com.android.tools.build:gradle:3.6.3')
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
classpath 'com.google.gms:google-services:4.3.3' // Google Services plugin
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
5
blue_modules/constants.js
Normal file
5
blue_modules/constants.js
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Let's keep config vars, constants and definitions here
|
||||
*/
|
||||
|
||||
export const groundControlUri = 'https://groundcontrol-bluewallet.herokuapp.com/';
|
180
blue_modules/notifications.js
Normal file
180
blue_modules/notifications.js
Normal file
@ -0,0 +1,180 @@
|
||||
import PushNotificationIOS from '@react-native-community/push-notification-ios';
|
||||
import { Alert } from 'react-native';
|
||||
import Frisbee from 'frisbee';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
const PushNotification = require('react-native-push-notification');
|
||||
const constants = require('./constants');
|
||||
const PUSH_TOKEN = 'PUSH_TOKEN';
|
||||
const loc = require('../loc');
|
||||
let alreadyConfigured = false;
|
||||
|
||||
async function _setPushToken(token) {
|
||||
token = JSON.stringify(token);
|
||||
return AsyncStorage.setItem(PUSH_TOKEN, token);
|
||||
}
|
||||
|
||||
async function _getPushToken() {
|
||||
try {
|
||||
let token = await AsyncStorage.getItem(PUSH_TOKEN);
|
||||
token = JSON.parse(token);
|
||||
return token;
|
||||
} catch (_) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls `configure`, which tries to obtain push token, save it, and registers all associated with
|
||||
* notifications callbacks
|
||||
*
|
||||
* @returns {Promise<boolean>} TRUE if acquired token, FALSE if not
|
||||
*/
|
||||
const configureNotifications = async function () {
|
||||
return new Promise(function (resolve) {
|
||||
PushNotification.configure({
|
||||
// (optional) Called when Token is generated (iOS and Android)
|
||||
onRegister: async function (token) {
|
||||
console.log('TOKEN:', token);
|
||||
alreadyConfigured = true;
|
||||
await _setPushToken(token);
|
||||
resolve(true);
|
||||
},
|
||||
|
||||
// (required) Called when a remote is received or opened, or local notification is opened
|
||||
onNotification: function (notification) {
|
||||
console.log('NOTIFICATION:', notification);
|
||||
|
||||
// process the notification
|
||||
PushNotification.setApplicationIconBadgeNumber(0); // always reset badges to zero
|
||||
|
||||
// (required) Called when a remote is received or opened, or local notification is opened
|
||||
notification.finish(PushNotificationIOS.FetchResult.NoData);
|
||||
},
|
||||
|
||||
// (optional) Called when Registered Action is pressed and invokeApp is false, if true onNotification will be called (Android)
|
||||
onAction: function (notification) {
|
||||
console.log('ACTION:', notification.action);
|
||||
console.log('NOTIFICATION:', notification);
|
||||
|
||||
// process the action
|
||||
},
|
||||
|
||||
// (optional) Called when the user fails to register for remote notifications. Typically occurs when APNS is having issues, or the device is a simulator. (iOS)
|
||||
onRegistrationError: function (err) {
|
||||
console.error(err.message, err);
|
||||
resolve(false);
|
||||
},
|
||||
|
||||
// IOS ONLY (optional): default: all - Permissions to register.
|
||||
permissions: {
|
||||
alert: true,
|
||||
badge: true,
|
||||
sound: true,
|
||||
},
|
||||
|
||||
// Should the initial notification be popped automatically
|
||||
// default: true
|
||||
popInitialNotification: true,
|
||||
|
||||
/**
|
||||
* (optional) default: true
|
||||
* - Specified if permissions (ios) and token (android and ios) will requested or not,
|
||||
* - if not, you must call PushNotificationsHandler.requestPermissions() later
|
||||
* - if you are not using remote notification or do not have Firebase installed, use this:
|
||||
* requestPermissions: Platform.OS === 'ios'
|
||||
*/
|
||||
requestPermissions: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Should be called when user is most interested in receiving push notifications.
|
||||
* If we dont have a token it will show alert asking whether
|
||||
* user wants to receive notifications, and if yes - will configure push notifications.
|
||||
* FYI, on Android permissions are acquired when app is installed, so basically we dont need to ask,
|
||||
* we can just call `configure`. On iOS its different, and calling `configure` triggers system's dialog box.
|
||||
*
|
||||
* @returns {Promise<boolean>} TRUE if permissions were obtained, FALSE otherwise
|
||||
*/
|
||||
const tryToObtainPermissions = async function () {
|
||||
if (await _getPushToken()) {
|
||||
// we already have a token, no sense asking again, just configure pushes to register callbacks and we are done
|
||||
if (!alreadyConfigured) configureNotifications(); // no await so it executes in background while we return TRUE and use token
|
||||
return true;
|
||||
}
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
Alert.alert(
|
||||
'Would you like to receive notifications when you get incoming payments?',
|
||||
'',
|
||||
[
|
||||
{
|
||||
text: 'Ask Me Later',
|
||||
onPress: () => {
|
||||
resolve(false);
|
||||
},
|
||||
style: 'cancel',
|
||||
},
|
||||
{
|
||||
text: loc._.ok,
|
||||
onPress: async () => {
|
||||
resolve(await configureNotifications());
|
||||
},
|
||||
style: 'default',
|
||||
},
|
||||
],
|
||||
{ cancelable: false },
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
function _getHeaders() {
|
||||
return {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits onchain bitcoin addresses and ln invoice preimage hashes to GroundControl server, so later we could
|
||||
* be notified if they were paid
|
||||
*
|
||||
* @param addresses {string[]}
|
||||
* @param hashes {string[]}
|
||||
* @returns {Promise<object>} Response object from API rest call
|
||||
*/
|
||||
const majorTomToGroundControl = async function (addresses, hashes) {
|
||||
if (!Array.isArray(addresses) || !Array.isArray(hashes)) throw new Error('no addresses or hashes provided');
|
||||
const pushToken = await _getPushToken();
|
||||
if (!pushToken || !pushToken.token || !pushToken.os) return;
|
||||
|
||||
const api = new Frisbee({ baseURI: constants.groundControlUri });
|
||||
|
||||
return await api.post(
|
||||
'/majorTomToGroundControl',
|
||||
Object.assign({}, _getHeaders(), {
|
||||
body: {
|
||||
addresses,
|
||||
hashes,
|
||||
token: pushToken.token,
|
||||
os: pushToken.os,
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
// on app launch (load module):
|
||||
(async () => {
|
||||
if (!(await _getPushToken())) return;
|
||||
// if we previously had token that means we already acquired permission from the user and it is safe to call
|
||||
// `configure` to register callbacks etc
|
||||
await configureNotifications();
|
||||
})();
|
||||
|
||||
// every launch should clear badges:
|
||||
PushNotification.setApplicationIconBadgeNumber(0);
|
||||
|
||||
module.exports.tryToObtainPermissions = tryToObtainPermissions;
|
||||
module.exports.majorTomToGroundControl = majorTomToGroundControl;
|
@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Let's keep config vars, constants and definitions here
|
||||
*/
|
||||
|
||||
export const useBlockcypherTokens = false;
|
@ -1,6 +1,5 @@
|
||||
export * from './wallets/abstract-wallet';
|
||||
export * from './app-storage';
|
||||
export * from './constants';
|
||||
export * from './wallets/legacy-wallet';
|
||||
export * from './wallets/segwit-bech32-wallet';
|
||||
export * from './wallets/segwit-p2sh-wallet';
|
||||
|
@ -5,9 +5,10 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UserNotifications/UNUserNotificationCenter.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate, UNUserNotificationCenterDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
#import <React/RCTBundleURLProvider.h>
|
||||
#import <React/RCTRootView.h>
|
||||
#import "RNQuickActionManager.h"
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
#import <RNCPushNotificationIOS.h>
|
||||
#if DEBUG
|
||||
#import <FlipperKit/FlipperClient.h>
|
||||
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
|
||||
@ -18,6 +20,7 @@
|
||||
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
|
||||
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
|
||||
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
|
||||
|
||||
static void InitializeFlipper(UIApplication *application) {
|
||||
FlipperClient *client = [FlipperClient sharedClient];
|
||||
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
|
||||
@ -57,6 +60,11 @@ static void InitializeFlipper(UIApplication *application) {
|
||||
UIView* launchScreenView = [[UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil] instantiateInitialViewController].view;
|
||||
launchScreenView.frame = self.window.bounds;
|
||||
rootView.loadingView = launchScreenView;
|
||||
|
||||
// Define UNUserNotificationCenter
|
||||
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
|
||||
center.delegate = self;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -82,4 +90,69 @@ static void InitializeFlipper(UIApplication *application) {
|
||||
[RNQuickActionManager onQuickActionPress:shortcutItem completionHandler:completionHandler];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Called when a notification is delivered to a foreground app.
|
||||
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
|
||||
{
|
||||
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Required to register for notifications
|
||||
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
|
||||
{
|
||||
[RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
|
||||
}
|
||||
// Required for the register event.
|
||||
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
||||
{
|
||||
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
|
||||
}
|
||||
// Required for the notification event. You must call the completion handler after handling the remote notification.
|
||||
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
|
||||
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
|
||||
{
|
||||
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
|
||||
}
|
||||
// Required for the registrationError event.
|
||||
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
|
||||
{
|
||||
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
|
||||
}
|
||||
// IOS 10+ Required for localNotification event
|
||||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
||||
didReceiveNotificationResponse:(UNNotificationResponse *)response
|
||||
withCompletionHandler:(void (^)(void))completionHandler
|
||||
{
|
||||
[RNCPushNotificationIOS didReceiveNotificationResponse:response];
|
||||
completionHandler();
|
||||
}
|
||||
// IOS 4-10 Required for the localNotification event.
|
||||
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
|
||||
{
|
||||
[RNCPushNotificationIOS didReceiveLocalNotification:notification];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -2,6 +2,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>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.io.bluewallet.bluewallet</string>
|
||||
|
@ -2,6 +2,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>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.icloud-container-identifiers</key>
|
||||
<array/>
|
||||
<key>com.apple.developer.icloud-services</key>
|
||||
|
@ -339,6 +339,8 @@ PODS:
|
||||
- React
|
||||
- RNCMaskedView (0.1.10):
|
||||
- React
|
||||
- RNCPushNotificationIOS (1.3.0):
|
||||
- React
|
||||
- RNDefaultPreference (1.4.3):
|
||||
- React
|
||||
- RNDeviceInfo (5.6.1):
|
||||
@ -372,9 +374,9 @@ PODS:
|
||||
- React
|
||||
- RNWatch (0.5.0):
|
||||
- React
|
||||
- Sentry (5.1.6):
|
||||
- Sentry/Core (= 5.1.6)
|
||||
- Sentry/Core (5.1.6)
|
||||
- Sentry (5.1.9):
|
||||
- Sentry/Core (= 5.1.9)
|
||||
- Sentry/Core (5.1.9)
|
||||
- swift_qrcodejs (1.1.2)
|
||||
- ToolTipMenu (5.2.0):
|
||||
- React
|
||||
@ -449,6 +451,7 @@ DEPENDENCIES:
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
|
||||
- "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)"
|
||||
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
|
||||
- "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)"
|
||||
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
|
||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
@ -573,6 +576,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/@react-native-community/clipboard"
|
||||
RNCMaskedView:
|
||||
:path: "../node_modules/@react-native-community/masked-view"
|
||||
RNCPushNotificationIOS:
|
||||
:path: "../node_modules/@react-native-community/push-notification-ios"
|
||||
RNDefaultPreference:
|
||||
:path: "../node_modules/react-native-default-preference"
|
||||
RNDeviceInfo:
|
||||
@ -666,6 +671,7 @@ SPEC CHECKSUMS:
|
||||
RNCAsyncStorage: db711e29e5e0500d9bd21aa0c2e397efa45302b1
|
||||
RNCClipboard: a254f6e568bc713b7ef49646e216661369882030
|
||||
RNCMaskedView: f5c7d14d6847b7b44853f7acb6284c1da30a3459
|
||||
RNCPushNotificationIOS: 23c5b5fdae79f105c63236de5ca306a70c00c444
|
||||
RNDefaultPreference: 21816c0a6f61a2829ccc0cef034392e9b509ee5f
|
||||
RNDeviceInfo: ab2ab4ca9e7f2bc4f35d62ab6ce2b66f2cbf1e7a
|
||||
RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df
|
||||
@ -682,7 +688,7 @@ SPEC CHECKSUMS:
|
||||
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
|
||||
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
|
||||
RNWatch: 4de37878bbf071847e438b089c01d4ad8d4eddae
|
||||
Sentry: e5796ec31a481474d2f94553213278470f9e302d
|
||||
Sentry: 81f7f2bd3cb041137ea7efcde3aa5ad0d5a67632
|
||||
swift_qrcodejs: 4d024fc98b0778b804ec6a5c810880fd092aec9d
|
||||
ToolTipMenu: 4d89d95ddffd7539230bdbe02ee51bbde362e37e
|
||||
Yoga: 3ebccbdd559724312790e7742142d062476b698e
|
||||
|
16
package-lock.json
generated
16
package-lock.json
generated
@ -4650,6 +4650,14 @@
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/masked-view/-/masked-view-0.1.10.tgz",
|
||||
"integrity": "sha512-rk4sWFsmtOw8oyx8SD3KSvawwaK7gRBSEIy2TAwURyGt+3TizssXP1r8nx3zY+R7v2vYYHXZ+k2/GULAT/bcaQ=="
|
||||
},
|
||||
"@react-native-community/push-notification-ios": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/push-notification-ios/-/push-notification-ios-1.3.0.tgz",
|
||||
"integrity": "sha512-fXLtDYsDv8CZIF/1pnrLyKv68X1VVgsWQTVdxA4UeYPAGP9OU4XdShD1TsPFWIF5VgabNrnmKl1uEDLw3X+6jA==",
|
||||
"requires": {
|
||||
"invariant": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"@react-native-community/slider": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/slider/-/slider-3.0.0.tgz",
|
||||
@ -14968,6 +14976,14 @@
|
||||
"version": "git+https://github.com/BlueWallet/react-native-prompt-android.git#2073b07f64bf5dc95807f64d79f37bdb111e6951",
|
||||
"from": "git+https://github.com/BlueWallet/react-native-prompt-android.git#2073b07f64bf5dc95807f64d79f37bdb111e6951"
|
||||
},
|
||||
"react-native-push-notification": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-push-notification/-/react-native-push-notification-4.0.0.tgz",
|
||||
"integrity": "sha512-PwFxGupwlAKc8qz8nMhX9U+/En/kiEH/1cyuKvUQdMa+tx96xZ/t81RTyOkkehkx4lbsI+Tv2F+D+fJV9IQb+A==",
|
||||
"requires": {
|
||||
"@react-native-community/push-notification-ios": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"react-native-qrcode-svg": {
|
||||
"version": "6.0.6",
|
||||
"resolved": "https://registry.npmjs.org/react-native-qrcode-svg/-/react-native-qrcode-svg-6.0.6.tgz",
|
||||
|
@ -42,7 +42,7 @@
|
||||
"e2e:debug": "(test -f android/app/build/outputs/apk/debug/app-debug.apk && test -f android/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk) || npm run e2e:debug-build; npm run e2e:debug-test",
|
||||
"e2e:release-build": "npx detox build -c android.emu.release",
|
||||
"e2e:release-test": "detox test -c android.emu.release --record-videos all --take-screenshots all --headless",
|
||||
"lint": "eslint *.js screen/**/*.js blue_modules/crypto.js class/**/*.js models/ loc/ tests/**/*.js",
|
||||
"lint": "eslint *.js screen/**/*.js blue_modules/*.js class/**/*.js models/ loc/ tests/**/*.js",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
"lint:quickfix": "git status --porcelain | grep -v '\\.json' | grep '\\.js' --color=never | awk '{print $2}' | xargs eslint --fix; exit 0",
|
||||
"unit": "jest tests/unit/*"
|
||||
@ -65,6 +65,7 @@
|
||||
"@react-native-community/blur": "3.6.0",
|
||||
"@react-native-community/clipboard": "1.2.2",
|
||||
"@react-native-community/masked-view": "0.1.10",
|
||||
"@react-native-community/push-notification-ios": "1.3.0",
|
||||
"@react-native-community/slider": "3.0.0",
|
||||
"@react-navigation/native": "5.6.1",
|
||||
"@react-navigation/stack": "5.6.2",
|
||||
@ -128,6 +129,7 @@
|
||||
"react-native-popup-menu-android": "1.0.3",
|
||||
"react-native-privacy-snapshot": "git+https://github.com/BlueWallet/react-native-privacy-snapshot.git",
|
||||
"react-native-prompt-android": "git+https://github.com/BlueWallet/react-native-prompt-android.git#2073b07f64bf5dc95807f64d79f37bdb111e6951",
|
||||
"react-native-push-notification": "4.0.0",
|
||||
"react-native-qrcode-svg": "6.0.6",
|
||||
"react-native-quick-actions": "0.3.13",
|
||||
"react-native-randombytes": "3.5.3",
|
||||
|
@ -15,6 +15,7 @@ import { WebView } from 'react-native-webview';
|
||||
import { BlueNavigationStyle, SafeBlueArea } from '../../BlueComponents';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import PropTypes from 'prop-types';
|
||||
const notifications = require('../../blue_modules/notifications');
|
||||
|
||||
let processedInvoices = {};
|
||||
let lastTimeTriedToPay = 0;
|
||||
@ -392,6 +393,11 @@ export default class Browser extends Component {
|
||||
// event; note how data is passed in 'detail', not 'data'
|
||||
const jsonstr = JSON.stringify({ bluewalletResponse: { paymentRequest: payreq }, id: json.id });
|
||||
this.webview.injectJavaScript("document.dispatchEvent( new CustomEvent('message', { detail: '" + jsonstr + "' }) );");
|
||||
|
||||
// lets decode payreq and subscribe groundcontrol so we can receive push notification when our invoice is paid
|
||||
const decoded = await fromWallet.decodeInvoice(payreq);
|
||||
await notifications.tryToObtainPermissions();
|
||||
notifications.majorTomToGroundControl([], [decoded.payment_hash]);
|
||||
},
|
||||
},
|
||||
],
|
||||
|
@ -32,6 +32,7 @@ const currency = require('../../blue_modules/currency');
|
||||
const BlueApp = require('../../BlueApp');
|
||||
const EV = require('../../blue_modules/events');
|
||||
const loc = require('../../loc');
|
||||
const notifications = require('../../blue_modules/notifications');
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
createButton: {
|
||||
@ -222,6 +223,13 @@ export default class LNDCreateInvoice extends Component {
|
||||
EV(EV.enum.TRANSACTIONS_COUNT_CHANGED);
|
||||
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
|
||||
|
||||
// lets decode payreq and subscribe groundcontrol so we can receive push notification when our invoice is paid
|
||||
/** @type LightningCustodianWallet */
|
||||
const fromWallet = this.state.fromWallet;
|
||||
const decoded = await fromWallet.decodeInvoice(invoiceRequest);
|
||||
await notifications.tryToObtainPermissions();
|
||||
notifications.majorTomToGroundControl([], [decoded.payment_hash]);
|
||||
|
||||
// send to lnurl-withdraw callback url if that exists
|
||||
if (this.state.lnurlParams) {
|
||||
const { callback, k1 } = this.state.lnurlParams;
|
||||
|
@ -37,6 +37,7 @@ import { BlueCurrentTheme } from '../../components/themes';
|
||||
const BlueApp = require('../../BlueApp');
|
||||
const loc = require('../../loc');
|
||||
const currency = require('../../blue_modules/currency');
|
||||
const notifications = require('../../blue_modules/notifications');
|
||||
|
||||
const ReceiveDetails = () => {
|
||||
const { secret } = useRoute().params;
|
||||
@ -151,7 +152,6 @@ const ReceiveDetails = () => {
|
||||
} else {
|
||||
BlueApp.saveToDisk(); // caching whatever getAddressAsync() generated internally
|
||||
}
|
||||
setAddress(address);
|
||||
} else if (wallet.chain === Chain.OFFCHAIN) {
|
||||
try {
|
||||
await Promise.race([wallet.getAddressAsync(), BlueApp.sleep(1000)]);
|
||||
@ -166,8 +166,12 @@ const ReceiveDetails = () => {
|
||||
}
|
||||
}
|
||||
setAddress(address);
|
||||
await notifications.tryToObtainPermissions();
|
||||
notifications.majorTomToGroundControl([address], []);
|
||||
} else if (wallet.getAddress) {
|
||||
setAddress(wallet.getAddress());
|
||||
await notifications.tryToObtainPermissions();
|
||||
notifications.majorTomToGroundControl([wallet.getAddress()], []);
|
||||
}
|
||||
InteractionManager.runAfterInteractions(async () => {
|
||||
const bip21encoded = DeeplinkSchemaMatch.bip21encode(address);
|
||||
|
Loading…
Reference in New Issue
Block a user