diff --git a/android/app/build.gradle b/android/app/build.gradle index 975fd5c52..f38330280 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -82,6 +82,7 @@ project.ext.react = [ ] apply from: "../../node_modules/react-native/react.gradle" +apply plugin: "com.bugsnag.android.gradle" /** * Set this to true to create two separate APKs instead of one: @@ -221,4 +222,7 @@ task copyDownloadableDepsToLibs(type: Copy) { } 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) \ No newline at end of file +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) +bugsnag { + uploadReactNativeMappings = true +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 91cc9df31..a6e4ba9d6 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -93,6 +93,8 @@ /> + + diff --git a/android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java b/android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java index 792d8899d..11c16adfc 100644 --- a/android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java +++ b/android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java @@ -11,6 +11,7 @@ import com.facebook.soloader.SoLoader; import java.lang.reflect.InvocationTargetException; import com.facebook.react.modules.i18nmanager.I18nUtil; import java.util.List; +import com.bugsnag.android.Bugsnag; public class MainApplication extends Application implements ReactApplication { @@ -44,6 +45,7 @@ public class MainApplication extends Application implements ReactApplication { @Override public void onCreate() { super.onCreate(); + Bugsnag.start(this); I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance(); sharedI18nUtilInstance.allowRTL(getApplicationContext(), true); SoLoader.init(this, /* native exopackage */ false); diff --git a/android/build.gradle b/android/build.gradle index b86b4e163..8b9e5074c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -19,6 +19,7 @@ buildscript { } dependencies { classpath('com.android.tools.build:gradle:4.2.1') + classpath("com.bugsnag:bugsnag-android-gradle-plugin:5.+") classpath 'com.google.gms:google-services:4.3.5' // Google Services plugin diff --git a/blue_modules/analytics.js b/blue_modules/analytics.js index 64bd7ad8c..6428fcde2 100644 --- a/blue_modules/analytics.js +++ b/blue_modules/analytics.js @@ -1,13 +1,23 @@ +import { getUniqueId } from 'react-native-device-info'; +import Bugsnag from '@bugsnag/react-native'; const BlueApp = require('../BlueApp'); +let userHasOptedOut = false; + if (process.env.NODE_ENV !== 'development') { - // nop + Bugsnag.start({ + collectUserIp: false, + user: { + id: getUniqueId(), + }, + onError: function (event) { + return !userHasOptedOut; + }, + }); } BlueApp.isDoNotTrackEnabled().then(value => { - if (value) { - // nop - } + if (value) userHasOptedOut = true; }); const A = async event => {}; @@ -23,9 +33,7 @@ A.ENUM = { }; A.setOptOut = value => { - if (value) { - // nop - } + if (value) userHasOptedOut = true; }; module.exports = A; diff --git a/index.js b/index.js index 234e6826f..2a4a84f12 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,12 @@ +import Bugsnag from '@bugsnag/react-native'; + import React, { useEffect } from 'react'; import './shim.js'; import { AppRegistry } from 'react-native'; import App from './App'; import { BlueStorageProvider } from './blue_modules/storage-context'; import { enableScreens } from 'react-native-screens'; +Bugsnag.start(); const A = require('./blue_modules/analytics'); enableScreens(false); if (!Error.captureStackTrace) { diff --git a/ios/BlueWallet/AppDelegate.m b/ios/BlueWallet/AppDelegate.m index f426eccd7..7a3d30620 100644 --- a/ios/BlueWallet/AppDelegate.m +++ b/ios/BlueWallet/AppDelegate.m @@ -1,3 +1,4 @@ +#import /** * Copyright (c) Facebook, Inc. and its affiliates. * @@ -40,6 +41,8 @@ static void InitializeFlipper(UIApplication *application) { - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [Bugsnag start]; + #if !TARGET_OS_MACCATALYST #ifdef FB_SONARKIT_ENABLED InitializeFlipper(application); diff --git a/ios/BlueWallet/Info.plist b/ios/BlueWallet/Info.plist index 2eada192f..1722c8ee8 100644 --- a/ios/BlueWallet/Info.plist +++ b/ios/BlueWallet/Info.plist @@ -350,5 +350,10 @@ + bugsnag + + apiKey + 17ba9059f676f1cc4f45d98182388b01 + diff --git a/package-lock.json b/package-lock.json index 1f1c4236f..c64ec4f03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1115,6 +1115,137 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@bugsnag/core": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/core/-/core-7.11.0.tgz", + "integrity": "sha512-xCaaONqQEAewifrvHC8v+yqN+Is4WNUcmK+sdeLcSb+ghLQ52y3BQ9nEDYzQxGuJRpv1zW3edCVIB4RN5eunSQ==", + "requires": { + "@bugsnag/cuid": "^3.0.0", + "@bugsnag/safe-json-stringify": "^6.0.0", + "error-stack-parser": "^2.0.3", + "iserror": "0.0.2", + "stack-generator": "^2.0.3" + } + }, + "@bugsnag/cuid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/cuid/-/cuid-3.0.0.tgz", + "integrity": "sha512-LOt8aaBI+KvOQGneBtpuCz3YqzyEAehd1f3nC5yr9TIYW1+IzYKa2xWS4EiMz5pPOnRPHkyyS5t/wmSmN51Gjg==" + }, + "@bugsnag/delivery-react-native": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/delivery-react-native/-/delivery-react-native-7.11.0.tgz", + "integrity": "sha512-W1wPpfGKW8FepWbZJqPZEShBlSixEJwa/NDXQUAjVSMJdeVAhTrJbsdzXjHlH5PjdOtuiz28mp0oYVkexgVHQQ==" + }, + "@bugsnag/plugin-console-breadcrumbs": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-console-breadcrumbs/-/plugin-console-breadcrumbs-7.11.0.tgz", + "integrity": "sha512-d9wpGqFk4MDJDBsZfJvISzyyXMJlV4JNyJrmPdMcCwlnUWZ/xxNTdPfuO7NG3juF4Xrn1GA3jB4jZfn3FboozQ==" + }, + "@bugsnag/plugin-network-breadcrumbs": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-network-breadcrumbs/-/plugin-network-breadcrumbs-7.11.0.tgz", + "integrity": "sha512-tb+jQ1ufUIMhwCPtecQF96r0cXi1janhFV9E4+88ceMdDdFc1MJEfl71UIimjFOqdGs4hvX5t2lnht/wHpf4xg==" + }, + "@bugsnag/plugin-react": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react/-/plugin-react-7.11.0.tgz", + "integrity": "sha512-YFs5lNAAmwOTvZ6WOzhZI75o4V2+fIUedxVfXOjUGB6wCBfYGvM6+pqcVSXXO+0OWm4trmwmkpkNvb8sbqteIg==" + }, + "@bugsnag/plugin-react-native-client-sync": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-client-sync/-/plugin-react-native-client-sync-7.11.0.tgz", + "integrity": "sha512-8RnMXfrsJTqKgg6rV2anwE5VD7WGeSUw/2ECLghbvho4TKMZ9PesdYS4vP1AYB2leYTN/LdBEooGNP+Qn8tUtQ==" + }, + "@bugsnag/plugin-react-native-event-sync": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-event-sync/-/plugin-react-native-event-sync-7.11.0.tgz", + "integrity": "sha512-G6+Mfl1KdrffauqHycNad3G+npXh2aEqg/4vcxeQYVmMYlQ6hIROErgFNXsx3OY35u9wjyKNuePjTQWb+ATvyw==" + }, + "@bugsnag/plugin-react-native-global-error-handler": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-global-error-handler/-/plugin-react-native-global-error-handler-7.11.0.tgz", + "integrity": "sha512-Shj77a63kd9gq3BWfwzj6NeOkKytG25sIIzsnLvfRUVEEn9C+zcePIg+JBtpcZLqWjYGihQahyB9o8/ZDh8pEA==" + }, + "@bugsnag/plugin-react-native-hermes": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-hermes/-/plugin-react-native-hermes-7.11.0.tgz", + "integrity": "sha512-BC837mokURePx1yOtFWiql4+HdQA9VEJmmvOXeOCeFA8TfAJXvP6RYuEIS1C+DoktU+ZCo4qx54GiFuPW8diXg==" + }, + "@bugsnag/plugin-react-native-session": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-session/-/plugin-react-native-session-7.11.0.tgz", + "integrity": "sha512-9vesh2MC+I5Lpg0SLf2N9W3SMG+6/iyNVk5FndnIj7wUDLWbm07DKsjX84WkBpljCpriA4WXxFViYx4bam6L1g==" + }, + "@bugsnag/plugin-react-native-unhandled-rejection": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@bugsnag/plugin-react-native-unhandled-rejection/-/plugin-react-native-unhandled-rejection-7.11.0.tgz", + "integrity": "sha512-5GmRXrmL0VWX8u1BFplfVsDnmKD1R9f+cG02CaFH+VvnyBVwKU81ZGw32ix4ugevsEYqYrR9DNHUu3TMLUlNLQ==" + }, + "@bugsnag/react-native": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@bugsnag/react-native/-/react-native-7.12.0.tgz", + "integrity": "sha512-jfI1JcQ7G7JG1Zg5Jlod9isr2IdFQ1jAA0dnjSkBcNEEjWgoaaFmE0DJY8bEOdUqyn8FgAy4/9908LRP7PBUuw==", + "requires": { + "@bugsnag/core": "^7.11.0", + "@bugsnag/delivery-react-native": "^7.11.0", + "@bugsnag/plugin-console-breadcrumbs": "^7.11.0", + "@bugsnag/plugin-network-breadcrumbs": "^7.11.0", + "@bugsnag/plugin-react": "^7.11.0", + "@bugsnag/plugin-react-native-client-sync": "^7.11.0", + "@bugsnag/plugin-react-native-event-sync": "^7.11.0", + "@bugsnag/plugin-react-native-global-error-handler": "^7.11.0", + "@bugsnag/plugin-react-native-hermes": "^7.11.0", + "@bugsnag/plugin-react-native-session": "^7.11.0", + "@bugsnag/plugin-react-native-unhandled-rejection": "^7.11.0", + "iserror": "^0.0.2" + } + }, + "@bugsnag/safe-json-stringify": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/safe-json-stringify/-/safe-json-stringify-6.0.0.tgz", + "integrity": "sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA==" + }, + "@bugsnag/source-maps": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@bugsnag/source-maps/-/source-maps-2.3.0.tgz", + "integrity": "sha512-59z/qFR/XB7P4wMj3uwyTe+damIAxZRfjnbq8pR+A6vPJ6Ep8YPeXbSxuzARPMyuNKPHUkj6Ix9ZXUbSW4tceA==", + "dev": true, + "requires": { + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "concat-stream": "^2.0.0", + "consola": "^2.15.0", + "form-data": "^3.0.0", + "glob": "^7.1.6", + "read-pkg-up": "^7.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@cnakazawa/watch": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", @@ -6406,6 +6537,32 @@ "typical": "^4.0.0" } }, + "command-line-usage": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.1.tgz", + "integrity": "sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "chalk": "^2.4.2", + "table-layout": "^1.0.1", + "typical": "^5.2.0" + }, + "dependencies": { + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -6521,6 +6678,12 @@ } } }, + "consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "dev": true + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -10081,6 +10244,11 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "iserror": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/iserror/-/iserror-0.0.2.tgz", + "integrity": "sha1-vVNFH+L2aLnyQCwZZnh6qix8C/U=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -18510,6 +18678,12 @@ "resolve": "^1.1.6" } }, + "reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "dev": true + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -19413,6 +19587,14 @@ "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", "integrity": "sha1-0ZLJ/06moiyUxN1FkXHj8AzqEoU=" }, + "stack-generator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.5.tgz", + "integrity": "sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==", + "requires": { + "stackframe": "^1.1.1" + } + }, "stackframe": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", @@ -19767,6 +19949,32 @@ } } }, + "table-layout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", + "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "dependencies": { + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, "tail": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/tail/-/tail-2.2.3.tgz", @@ -20645,6 +20853,24 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wordwrapjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", + "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", + "dev": true, + "requires": { + "reduce-flatten": "^2.0.0", + "typical": "^5.2.0" + }, + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } + } + }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 06b7eee92..77a4526f4 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,8 @@ }, "dependencies": { "@babel/preset-env": "7.12.1", + "@bugsnag/react-native": "7.12.0", + "@bugsnag/source-maps": "2.3.0", "@keystonehq/bc-ur-registry": "https://github.com/BlueWallet/ur-registry", "@ngraveio/bc-ur": "https://github.com/BlueWallet/bc-ur", "@react-native-async-storage/async-storage": "1.15.5", diff --git a/screen/settings/about.js b/screen/settings/about.js index 03e54c480..81dcfbb55 100644 --- a/screen/settings/about.js +++ b/screen/settings/about.js @@ -9,6 +9,7 @@ import { BlueButton, BlueCard, BlueListItem, BlueSpacing20, BlueTextCentered } f import navigationStyle from '../../components/navigationStyle'; import loc, { formatStringAddTwoWhiteSpaces } from '../../loc'; import Clipboard from '@react-native-clipboard/clipboard'; +import Bugsnag from '@bugsnag/react-native'; const About = () => { const { navigate } = useNavigation(); @@ -215,6 +216,7 @@ const About = () => { accessibilityRole="button" onPress={() => { const stringToCopy = 'user.id:' + getUniqueId(); + Bugsnag.notify(new Error('copied unique id')); Clipboard.setString(stringToCopy); }} >