Upgrade to RN 0.82, various tweaks

This commit is contained in:
minibits-cash
2025-12-03 23:05:43 +01:00
parent 2cf9545811
commit f4116a936f
19 changed files with 3073 additions and 3588 deletions
+2
View File
@@ -105,3 +105,5 @@ tasks.md
# hot-updater # hot-updater
.hot-updater/output .hot-updater/output
# hot-updater
.env.hotupdater
+2 -2
View File
@@ -95,8 +95,8 @@ android {
applicationId "com.minibits_wallet" applicationId "com.minibits_wallet"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 58051 versionCode 58056
versionName "0.3.3" versionName "0.3.4"
} }
splits { splits {
@@ -5,42 +5,29 @@ import com.facebook.react.PackageList
import com.facebook.react.ReactApplication import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost // minibits
import com.facebook.react.modules.network.OkHttpClientProvider import com.facebook.react.modules.network.OkHttpClientProvider
import com.hotupdater.HotUpdater import com.hotupdater.HotUpdater
class MainApplication : Application(), ReactApplication { class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost = override val reactHost: ReactHost by lazy {
object : DefaultReactNativeHost(this) { getDefaultReactHost(
override fun getPackages(): List<ReactPackage> = context = applicationContext,
PackageList(this).packages.apply { packageList =
// Packages that cannot be autolinked yet can be added manually here, for example: PackageList(this).packages.apply {
// add(MyReactNativePackage()) // Packages that cannot be autolinked yet can be added manually here, for example:
} // add(MyReactNativePackage())
},
override fun getJSMainModuleName(): String = "index" jsBundleFilePath = HotUpdater.getJSBundleFile(applicationContext),
)
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG }
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
override fun getJSBundleFile(): String? {
return HotUpdater.getJSBundleFile(applicationContext)
}
}
override val reactHost: ReactHost
get() = getDefaultReactHost(applicationContext, reactNativeHost)
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
OkHttpClientProvider.setOkHttpClientFactory(CorePlaneOkHttpClientFactory()) OkHttpClientProvider.setOkHttpClientFactory(CorePlaneOkHttpClientFactory())
loadReactNative(this) loadReactNative(this)
} }
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
019acc82-c83f-745c-b197-db89afcc5a30
+4 -2
View File
@@ -1,10 +1,12 @@
import { bare } from "@hot-updater/bare"; import { bare } from "@hot-updater/bare";
import { withSentry } from "@hot-updater/sentry-plugin"; import { withSentry } from "@hot-updater/sentry-plugin";
import { firebaseDatabase, firebaseStorage } from "@hot-updater/firebase"; import { firebaseDatabase, firebaseStorage } from "@hot-updater/firebase";
import "dotenv/config";
import * as admin from "firebase-admin"; import * as admin from "firebase-admin";
import { config } from "dotenv";
import { defineConfig } from "hot-updater"; import { defineConfig } from "hot-updater";
config({ path: ".env.hotupdater" });
// https://firebase.google.com/docs/admin/setup?hl=en#initialize_the_sdk_in_non-google_environments // https://firebase.google.com/docs/admin/setup?hl=en#initialize_the_sdk_in_non-google_environments
// Check your .env file and add the credentials // Check your .env file and add the credentials
// Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to your credentials file path // Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to your credentials file path
@@ -31,5 +33,5 @@ export default defineConfig({
projectId: process.env.HOT_UPDATER_FIREBASE_PROJECT_ID!, projectId: process.env.HOT_UPDATER_FIREBASE_PROJECT_ID!,
credential, credential,
}), }),
updateStrategy: "appVersion", updateStrategy: "appVersion", // or "fingerprint"
}); });
+405 -368
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -47,7 +47,7 @@ class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
#if DEBUG #if DEBUG
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else #else
Bundle.main.url(forResource: "main", withExtension: "jsbundle") //Bundle.main.url(forResource: "main", withExtension: "jsbundle")
return HotUpdater.bundleURL() return HotUpdater.bundleURL()
#endif #endif
} }
+15 -14
View File
@@ -1,16 +1,16 @@
{ {
"name": "minibits_wallet", "name": "minibits_wallet",
"version": "0.3.3-beta.1", "version": "0.3.4-beta.1",
"private": true, "private": true,
"scripts": { "scripts": {
"android:clean": "cd android && ./gradlew clean", "android:clean": "cd android && ./gradlew clean",
"android:dev": "react-native run-android --active-arch-only", "android:dev": "npx react-native run-android --active-arch-only",
"android:test": "react-native run-android --mode=release --active-arch-only", "android:test": "npx react-native run-android --mode=release --active-arch-only",
"android:bundle": "react-native build-android --mode=release", "android:bundle": "npx react-native build-android --mode=release",
"android:apk": "cd android && ./gradlew assembleRelease", "android:apk": "cd android && ./gradlew assembleRelease",
"ios:dev": "npx react-native run-ios --scheme \"minibits_wallet\"", "ios:dev": "npx react-native run-ios --scheme \"minibits_wallet\"",
"lint": "eslint .", "lint": "eslint .",
"start": "react-native start", "start": "npx react-native start",
"test": "jest", "test": "jest",
"test:i18n": "node __tests__/missingTranslations.js && node __tests__/incorrectTranslationPlaceholders.js && node __tests__/missingTranslationKeys.js", "test:i18n": "node __tests__/missingTranslations.js && node __tests__/incorrectTranslationPlaceholders.js && node __tests__/missingTranslationKeys.js",
"adb": "adb devices && adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:9001 tcp:9001 && adb reverse tcp:8081 tcp:8081", "adb": "adb devices && adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:9001 tcp:9001 && adb reverse tcp:8081 tcp:8081",
@@ -42,6 +42,7 @@
"@react-navigation/stack": "^7.6.8", "@react-navigation/stack": "^7.6.8",
"@scure/bip39": "1.6.0", "@scure/bip39": "1.6.0",
"@sentry/react-native": "^7.7.0", "@sentry/react-native": "^7.7.0",
"buffer-equal-constant-time": "^1.0.1",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"i18n-js": "^4.5.1", "i18n-js": "^4.5.1",
"js-lnurl": "^0.6.0", "js-lnurl": "^0.6.0",
@@ -54,8 +55,8 @@
"nostr-tools": "minibits-cash/nostr-tools#2991f59d0150a0cb2c71e2f9a4cb6c8aca3b19d7", "nostr-tools": "minibits-cash/nostr-tools#2991f59d0150a0cb2c71e2f9a4cb6c8aca3b19d7",
"numbro": "^2.5.0", "numbro": "^2.5.0",
"patch-package": "^8.0.1", "patch-package": "^8.0.1",
"react": "19.1.0", "react": "19.1.1",
"react-native": "0.81.4", "react-native": "0.82.1",
"react-native-animated-pagination-dots": "^0.1.73", "react-native-animated-pagination-dots": "^0.1.73",
"react-native-camera-kit": "16.1.3", "react-native-camera-kit": "16.1.3",
"react-native-exit-app": "^2.0.0", "react-native-exit-app": "^2.0.0",
@@ -95,15 +96,15 @@
"@react-native-community/cli": "20.0.0", "@react-native-community/cli": "20.0.0",
"@react-native-community/cli-platform-android": "20.0.0", "@react-native-community/cli-platform-android": "20.0.0",
"@react-native-community/cli-platform-ios": "20.0.0", "@react-native-community/cli-platform-ios": "20.0.0",
"@react-native/babel-preset": "0.81.4", "@react-native/babel-preset": "0.82.1",
"@react-native/eslint-config": "0.81.4", "@react-native/eslint-config": "0.82.1",
"@react-native/metro-config": "0.81.4", "@react-native/metro-config": "0.82.1",
"@react-native/typescript-config": "0.81.4", "@react-native/typescript-config": "0.82.1",
"@sentry/cli": "^2.58.2", "@sentry/cli": "^2.58.2",
"@tsconfig/react-native": "^3.0.7", "@tsconfig/react-native": "^3.0.7",
"@types/jest": "^29.5.13", "@types/jest": "^29.5.13",
"@types/lodash.clonedeep": "^4.5.9", "@types/lodash.clonedeep": "^4.5.9",
"@types/react": "^19.1.0", "@types/react": "^19.1.1",
"@types/react-test-renderer": "^19.1.0", "@types/react-test-renderer": "^19.1.0",
"babel-plugin-module-resolver": "^5.0.2", "babel-plugin-module-resolver": "^5.0.2",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
@@ -111,12 +112,12 @@
"eslint-plugin-unused-imports": "^2.0.0", "eslint-plugin-unused-imports": "^2.0.0",
"firebase-admin": "^13.6.0", "firebase-admin": "^13.6.0",
"firebase-tools": "^14.26.0", "firebase-tools": "^14.26.0",
"hot-updater": "^0.23.1", "hot-updater": "0.23.1",
"jest": "^29.6.3", "jest": "^29.6.3",
"prettier": "2.8.8", "prettier": "2.8.8",
"react-native-clean-project": "^4.0.3", "react-native-clean-project": "^4.0.3",
"react-native-dotenv": "^3.4.11", "react-native-dotenv": "^3.4.11",
"react-test-renderer": "19.1.0", "react-test-renderer": "19.1.1",
"typescript": "^5.8.3" "typescript": "^5.8.3"
}, },
"engines": { "engines": {
@@ -1,26 +1,26 @@
diff --git a/node_modules/@scure/bip32/index.ts b/node_modules/@scure/bip32/index.ts diff --git a/node_modules/@scure/bip32/index.ts b/node_modules/@scure/bip32/index.ts
index 0c9c91c..14c9ae2 100644 index 65e4bb2..7b7d7f7 100644
--- a/node_modules/@scure/bip32/index.ts --- a/node_modules/@scure/bip32/index.ts
+++ b/node_modules/@scure/bip32/index.ts +++ b/node_modules/@scure/bip32/index.ts
@@ -25,6 +25,7 @@ import { bytesToHex, concatBytes, createView, hexToBytes, utf8ToBytes } from '@n @@ -30,6 +30,7 @@ import {
import { secp256k1 as secp } from '@noble/curves/secp256k1'; utf8ToBytes,
import { mod } from '@noble/curves/abstract/modular'; } from '@noble/hashes/utils';
import { createBase58check } from '@scure/base'; import { createBase58check } from '@scure/base';
+import QuickCrypto from 'react-native-quick-crypto'; +import QuickCrypto from 'react-native-quick-crypto'
const Point = secp.ProjectivePoint; const Point = secp.ProjectivePoint;
const base58check = createBase58check(sha256); const base58check = createBase58check(sha256);
@@ -114,7 +115,8 @@ export class HDKey { @@ -119,7 +120,8 @@ export class HDKey {
seed.length seed.length
); );
} }
- const I = hmac(sha512, MASTER_SECRET, seed); - const I = hmac(sha512, MASTER_SECRET, seed);
+ // const I = hmac(sha512, MASTER_SECRET, seed); + //const I = hmac(sha512, MASTER_SECRET, seed);
+ const I = new Uint8Array(QuickCrypto.createHmac('sha512', MASTER_SECRET).update(seed).digest()); + const I = new Uint8Array(QuickCrypto.createHmac('sha512', MASTER_SECRET).update(seed).digest());
return new HDKey({ return new HDKey({
versions, versions,
chainCode: I.slice(32), chainCode: I.slice(32),
@@ -237,7 +239,8 @@ export class HDKey { @@ -242,7 +244,8 @@ export class HDKey {
// Normal child: serP(point(kpar)) || ser32(index) // Normal child: serP(point(kpar)) || ser32(index)
data = concatBytes(this.pubKey, data); data = concatBytes(this.pubKey, data);
} }
@@ -31,7 +31,7 @@ index 0c9c91c..14c9ae2 100644
const chainCode = I.slice(32); const chainCode = I.slice(32);
if (!secp.utils.isValidPrivateKey(childTweak)) { if (!secp.utils.isValidPrivateKey(childTweak)) {
diff --git a/node_modules/@scure/bip32/package.json b/node_modules/@scure/bip32/package.json diff --git a/node_modules/@scure/bip32/package.json b/node_modules/@scure/bip32/package.json
index e866fba..6389575 100644 index c40252d..7695067 100644
--- a/node_modules/@scure/bip32/package.json --- a/node_modules/@scure/bip32/package.json
+++ b/node_modules/@scure/bip32/package.json +++ b/node_modules/@scure/bip32/package.json
@@ -6,15 +6,8 @@ @@ -6,15 +6,8 @@
@@ -49,5 +49,5 @@ index e866fba..6389575 100644
- } - }
- }, - },
"dependencies": { "dependencies": {
"@noble/curves": "~1.8.1", "@noble/curves": "~1.9.0",
"@noble/hashes": "~1.7.1", "@noble/hashes": "~1.8.0",
+4 -3
View File
@@ -256,7 +256,7 @@ export const NfcPayScreen = observer(function NfcPayScreen({ route }: Props) {
// ——— SUCCESS: Receiver claimed the ecash ——— // ——— SUCCESS: Receiver claimed the ecash ———
if (completedTransactionIds?.includes(transactionId)) { if (completedTransactionIds?.includes(transactionId)) {
log.trace('[NfcScreen] Ecash claimed successfully', { transactionId }); log.debug('[NfcScreen] Ecash claimed successfully by the payee.', { transactionId });
const amountSentInt = Math.round( const amountSentInt = Math.round(
(toNumber(amountToPay || '0') * getCurrency(unitRef.current).precision) (toNumber(amountToPay || '0') * getCurrency(unitRef.current).precision)
@@ -346,7 +346,7 @@ export const NfcPayScreen = observer(function NfcPayScreen({ route }: Props) {
const handleTransferTaskResult = useCallback( const handleTransferTaskResult = useCallback(
async (result: TransactionTaskResult) => { async (result: TransactionTaskResult) => {
log.trace('[NfcScreen] handleTransferTaskResult triggered', result) log.trace('[NfcScreen] handleTransferTaskResult triggered', {result})
setIsLoading(false) setIsLoading(false)
@@ -460,6 +460,7 @@ export const NfcPayScreen = observer(function NfcPayScreen({ route }: Props) {
if (isProcessing) return if (isProcessing) return
setIsProcessing(true) setIsProcessing(true)
setNfcInfo('Reading payment request...') setNfcInfo('Reading payment request...')
log.debug('NFC tag discovered, reading...', { tag })
try { try {
const ndefMessage = tag.ndefMessage?.[0] const ndefMessage = tag.ndefMessage?.[0]
@@ -480,7 +481,7 @@ export const NfcPayScreen = observer(function NfcPayScreen({ route }: Props) {
payload = new TextDecoder().decode(ndefMessage.payload) payload = new TextDecoder().decode(ndefMessage.payload)
} }
log.trace('NFC tag read', { payload }) log.debug('NFC tag read', { payload })
setReadNfcData(payload) setReadNfcData(payload)
await handlePaymentRequest(payload) await handlePaymentRequest(payload)
+9 -6
View File
@@ -71,16 +71,19 @@ export const SettingsScreen = observer(function SettingsScreen({ route }: Props)
} }
if(!__DEV__) { if(!__DEV__) {
setIsUpdateAvailable(true) setIsUpdateAvailable(true)
setUpdateDescription(updateInfo.message || '') setUpdateDescription(updateInfo.message || '')
if (updateInfo.shouldForceUpdate) { if (updateInfo.shouldForceUpdate) {
// apply emergency update immediately // apply emergency update immediately
await HotUpdater.updateBundle(updateInfo.id, updateInfo.fileUrl) const isDownloaded = await updateInfo.updateBundle()
HotUpdater.reload() if(isDownloaded) {
await HotUpdater.reload()
} }
}
} }
} catch (e: any) { } catch (e: any) {
log.error(e) log.error(e)
return false return false
+7 -3
View File
@@ -48,7 +48,7 @@ export const UpdateScreen = observer(function UpdateScreen({ route }: Props) {
prevScreen prevScreen
} = route.params } = route.params
const { progress, isBundleUpdated } = useHotUpdaterStore() const { progress, isUpdateDownloaded } = useHotUpdaterStore()
useHeader({ useHeader({
leftIcon: 'faArrowLeft', leftIcon: 'faArrowLeft',
@@ -102,8 +102,12 @@ export const UpdateScreen = observer(function UpdateScreen({ route }: Props) {
throw new AppError(Err.NETWORK_ERROR, translate('updateScreen_couldNotRetrieveUpdate')) throw new AppError(Err.NETWORK_ERROR, translate('updateScreen_couldNotRetrieveUpdate'))
} }
await HotUpdater.updateBundle(updateInfo.id, updateInfo.fileUrl) const isDownloaded = await updateInfo.updateBundle()
HotUpdater.reload() if(isDownloaded) {
await HotUpdater.reload()
} else {
throw new AppError(Err.NETWORK_ERROR, 'Could not download update bundle')
}
} catch(e: any) { } catch(e: any) {
handleError(e) handleError(e)
+5 -2
View File
@@ -132,8 +132,10 @@ export const WalletScreen = observer(function WalletScreen({ route }: Props) {
if (updateInfo.shouldForceUpdate) { if (updateInfo.shouldForceUpdate) {
// apply emergency update immediately // apply emergency update immediately
await HotUpdater.updateBundle(updateInfo.id, updateInfo.fileUrl) const isDownloaded = await updateInfo.updateBundle()
HotUpdater.reload() if(isDownloaded) {
await HotUpdater.reload()
}
} }
} }
@@ -818,6 +820,7 @@ export const WalletScreen = observer(function WalletScreen({ route }: Props) {
tx="walletScreen_payWithLightning" tx="walletScreen_payWithLightning"
subTx="walletScreen_payWithLightningDesc" subTx="walletScreen_payWithLightningDesc"
onPress={() => gotoLightningPay()} onPress={() => gotoLightningPay()}
bottomSeparator={true}
/> />
<ListItem <ListItem
leftIcon='faNfcSymbol' leftIcon='faNfcSymbol'
+2 -2
View File
@@ -19,7 +19,7 @@ import AppError, { Err } from "../utils/AppError"
const { userSettingsStore } = rootStoreInstance const { userSettingsStore } = rootStoreInstance
if (__DEV__) { //TODO turn off!!! if (!__DEV__) {
Sentry.init({ Sentry.init({
dsn: SENTRY_DSN, dsn: SENTRY_DSN,
environment: APP_ENV, environment: APP_ENV,
@@ -185,7 +185,7 @@ const log = logger.createLogger({
warn: 3, warn: 3,
error: 4, error: 4,
}, },
transport: customSentryTransport, transport: __DEV__ ? consoleTransport : customSentryTransport,
transportOptions: { transportOptions: {
SENTRY: Sentry, SENTRY: Sentry,
} as TransportOptions, } as TransportOptions,
+3 -3
View File
@@ -1,4 +1,4 @@
import {createMMKV, type MMKV} from 'react-native-mmkv' import {MMKV} from 'react-native-mmkv'
import {log} from './logService' import {log} from './logService'
import AppError, {Err} from '../utils/AppError' import AppError, {Err} from '../utils/AppError'
@@ -8,7 +8,7 @@ let _storage: MMKV | undefined
const getInstance = function () { const getInstance = function () {
if (!_storage) { if (!_storage) {
_storage = createMMKV({ _storage = new MMKV({
id: STORAGE_KEY, id: STORAGE_KEY,
}) })
@@ -135,7 +135,7 @@ const save = function (key: string, value: any): boolean {
const remove = function (key: string): void { const remove = function (key: string): void {
try { try {
const storage = getInstance() const storage = getInstance()
storage.remove(key) storage.delete(key)
} catch (e: any) { } catch (e: any) {
throw new AppError(Err.DATABASE_ERROR, e.message) throw new AppError(Err.DATABASE_ERROR, e.message)
} }
+2585 -3139
View File
File diff suppressed because it is too large Load Diff