diff --git a/.eslintignore b/.eslintignore index 19c084e..5643d10 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,6 +6,7 @@ # Output of the build process & scripts lib/**/* +plugin/build/**/* scripts/**/* babel.config.js @@ -14,3 +15,4 @@ react-native.config.js jest.config.js webpack.config.js .eslintrc.js +app.plugin.js diff --git a/.eslintrc.js b/.eslintrc.js index f9ab6dd..32b2f89 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,6 +29,7 @@ module.exports = { }, }, root: true, + ignorePatterns: ['plugins/build/**'], rules: { 'rulesdir/prefer-underscore-method': 'off', 'rulesdir/prefer-import-module-contents': 'off', @@ -66,5 +67,11 @@ module.exports = { '@typescript-eslint/array-type': ['error', {default: 'array-simple'}], '@typescript-eslint/consistent-type-definitions': 'off', 'curly': ['error', 'all'], + '@lwc/lwc/no-async-await': 'off', + 'no-return-await': 'off', + 'no-else-return': 'off', + 'import/prefer-default-export': 'off', + 'no-restricted-imports': 'off', + 'react/destructuring-assignment': 'off', }, }; diff --git a/.github/workflows/typescript.yml b/.github/workflows/typescript.yml index 4a65494..54f3ddb 100644 --- a/.github/workflows/typescript.yml +++ b/.github/workflows/typescript.yml @@ -32,5 +32,5 @@ jobs: - name: Typecheck library run: npm run typecheck -- --project tsconfig.json - - name: Typecheck example app - run: npm run typecheck -- --project example/tsconfig.json + - name: Typecheck common app + run: npm run typecheck -- --project apps/common-app/tsconfig.json diff --git a/.gitignore b/.gitignore index 32b5ccd..3fcaa5c 100644 --- a/.gitignore +++ b/.gitignore @@ -39,10 +39,10 @@ android.iml # Cocoapods # -example/ios/Pods +apps/basic-example/ios/Pods # Ruby -example/vendor/ +apps/basic-example/vendor/ # node.js # @@ -66,6 +66,10 @@ ios/generated android/generated # Android libs (Google Tap And Pay SDK) -example/android/libs +apps/basic-example/android/libs .kotlin/ + +# expo plugin build +plugin/build/ +*.tsbuildinfo diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..d67f374 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +node-linker=hoisted diff --git a/.prettierignore b/.prettierignore index a57c5db..5713496 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,6 +6,7 @@ CODE_OF_CONDUCT.md .well-known desktop/dist/**/*.js dist/**/*.js +plugin/build/**/*.js assets/animations android ios diff --git a/README.md b/README.md index b65b52f..413ad3a 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,11 @@ - ♻️ Universal solution (Apple Wallet and Google Wallet) - πŸ’³ Easy and secure addition of payment cards from your app directly - πŸ’° Supports Visa, MasterCard, Amex and Discover payment cards +- πŸŽ‰ Expo support (expo-plugin) ## Getting started -Using the `react-native-wallet` Push Provisioning features requires proper configuration and access from both Google and Apple. +Using the `react-native-wallet` Push Provisioning features requires proper configuration and access from both Google and Apple. Please follow the instructions below before installing the library: ### Android @@ -20,10 +21,10 @@ To be able to interact with the Google Wallet on the Android please make sure to 1. Visit [the Google Pay Android Push Provisioning API documentation](https://developers.google.com/pay/issuers/apis/push-provisioning/android/) and request access to it. 2. Once getting an approval from the Google team - 1. Download the [TapAndPay SDK](https://developers.google.com/pay/issuers/apis/push-provisioning/android/releases). - 2. Unzip it and extract the SDK into the `/android/libs` folder in your React Native project (if there is no `libs` folder, create one). + 1. Download the [TapAndPay SDK](https://developers.google.com/pay/issuers/apis/push-provisioning/android/releases). + 2. Unzip it and extract the SDK into the `/android/libs` folder in your React Native project (if there is no `libs` folder, create one). 3. Add `/android/libs` to `.gitignore`. - + 3. Then connect the SDK to your project in `build.gradle`, for example like in [example/android/build.gradle](https://github.com/Expensify/react-native-wallet/blob/main/example/android/build.gradle): ```groovy @@ -37,7 +38,7 @@ allprojects { #### Step 2: Whitelist your app for SDK use. -To use the Google SDK in your app, you will need to whitelist your app details. Without it, calling some functions will result in a `Not verified` error. +To use the Google SDK in your app, you will need to whitelist your app details. Without it, calling some functions will result in a `Not verified` error. To resolve it, please follow the instructions from [the official Google documentation](https://developers.google.com/pay/issuers/apis/push-provisioning/android/allowlist). For your builds, you will need to prepare your app's `package name` and `fingerprint` following [these steps](https://developers.google.com/pay/issuers/apis/push-provisioning/android/allowlist#how_to_get_your_apps_fingerprint). The values should, for example, look like this: @@ -72,13 +73,13 @@ Make sure to familiarize yourself with that document before deploying your app. ### Step 2: Activate the entitlement -After getting a positive response from Apple, open the developer portal panel and search `Certificates, Identifiers & Profiles` -> `Profiles` -> `Our distribution profile` -> `Edit` and add the `ApplePay In-App Provisioning Distribution` entitlement. +After getting a positive response from Apple, open the developer portal panel and search `Certificates, Identifiers & Profiles` -> `Profiles` -> `Our distribution profile` -> `Edit` and add the `ApplePay In-App Provisioning Distribution` entitlement. It’s available only for the production environment so your QA must work with physical devices and cards. ### Step 3: Add the entitlement to your project -Add `com.apple.developer.payment-pass-provisioning` entitlement to your project. Find or create `.entitlements` file in your project and add the entitlement like below (similarly to [WalletExample.entitlements](https://github.com/Expensify/react-native-wallet/blob/main/example/ios/WalletExample/WalletExample.entitlements)): +Add `com.apple.developer.payment-pass-provisioning` entitlement to your project. Find or create `.entitlements` file in your project and add the entitlement like below (similarly to [WalletExample.entitlements](https://github.com/Expensify/react-native-wallet/blob/main/example/ios/WalletExample/WalletExample.entitlements)): ```xml @@ -105,14 +106,44 @@ or yarn add @expensify/react-native-wallet ``` +### Expo plugin + +To use `@expensify/react-native-wallet` with expo, you will need to use the expo-plugin. + +In your `app.json` file, add the following configuration: + +```json +{ + "expo": { + "plugins": [ + [ + "@expensify/react-native-wallet", + { + enableApplePayProvisioning: true, + googleTapAndPaySdkPath: "./libs/tapandpay-v18.7.0.zip", // path to the Google Tap & Pay SDK zip file + }, + ], + ] + } +} +``` +You will need to rebuild your app after that since the lib has native files. + +```bash +npx expo prebuild --clean +npx expo run:ios +npx expo run:android +``` -## Required data + + +## Required data Here you can find data elements used in the library, essential to work with Google Wallet and Apple Wallet APIs. ### Android - **Opaque Payment Card** (OPC) - a binary blob of information Google Pay receives from the issuer app that could be presented to TSP to receive a token. -- **Token Service Provider** (TSP) - a service that enhances payment security by replacing a credit card number during transactions with a unique digital identifier - token. The TSP specifies the tokenization service used to create a given token e.g. Visa, MasterCard, American Express. +- **Token Service Provider** (TSP) - a service that enhances payment security by replacing a credit card number during transactions with a unique digital identifier - token. The TSP specifies the tokenization service used to create a given token e.g. Visa, MasterCard, American Express. - **Token Reference ID** - a unique identifying number to refer to a DPAN (Dynamic Personal Account Number). Token Providers will assign each DPAN an issuer token ID at the time of tokenization. ### iOS @@ -170,10 +201,10 @@ The library offers seven functions for seamless integration and use of the Apple ### `AddToWalletButton` A ready-to-use component that simplifies the addition of payment cards to Google Wallet and Apple Wallet. The button automatically adapts its appearance according to the platform and language specified. -It uses official assets provided by [Google](https://developers.google.com/wallet/generic/resources/brand-guidelines) and [Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/) in their Wallet-related branding guidelines. +It uses official assets provided by [Google](https://developers.google.com/wallet/generic/resources/brand-guidelines) and [Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/) in their Wallet-related branding guidelines. > [!IMPORTANT] -> Please bear in mind the brand rules provided by [Google](https://developers.google.com/wallet/generic/resources/brand-guidelines) and [Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/) when adding this component to your application. +> Please bear in mind the brand rules provided by [Google](https://developers.google.com/wallet/generic/resources/brand-guidelines) and [Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/) when adding this component to your application. Adhering to these guidelines is crucial not only to comply with legal requirements but also to reassure users of the authenticity and security of your application. @@ -204,6 +235,40 @@ Adhering to these guidelines is crucial not only to comply with legal requiremen |:----:|:---------------:| | | | +# Hex Encoding + +This library use base64 encoding to encode the data. Yours might use hex encoding. + +If that is the case, you will need to convert the data in the proper format. + +This is an example of how to convert data to hex format: + +```ts +import { Buffer } from "buffer" +const base64ToHex = (base64: string): string => Buffer.from(base64, "base64").toString("hex") + +[...] + + const issuerEncryptPayloadCallback = async ( + nonce: string, + nonceSignature: string, + certificate: string[], + ): Promise => { + try { + const payload = { + encryptionDetails: { + nonce: base64ToHex(nonce), + nonceSignature: base64ToHex(nonceSignature), + wspCertificates: certificate, + }, + serialNumber, + wspId: "APPLE" as const, + } +[...] +``` + +This will depend on the implementation of your backend/issuer so make sure to check with them otherwise IOS might fail to provision the card. + # Publishing your app To successfully publish your app, you will need to navigate through a series of mandatory test cases on both platforms. @@ -214,14 +279,14 @@ Before deploying your app to the Google Play Store, make sure you have taken car The latest information about deploying apps with Google TapAndPay SDK can be found in the [pre-launch process](https://developers.google.com/pay/issuers/apis/push-provisioning/android/launch-process#step_3_issuer_app_product_review) and [beta tests](https://developers.google.com/pay/issuers/apis/push-provisioning/android/beta-testing) sections in Google documentation. Make sure to complete all of the steps specified by Google connected to the __Google's branding__, __API safety__, and __app stability__. -The app will need to be reviewed by Google. During this process, it will need to pass 4 mandatory test cases that are specified [here](https://developers.google.com/pay/issuers/apis/push-provisioning/android/test-cases). They verify how your app handles card state tracking in different scenarios. +The app will need to be reviewed by Google. During this process, it will need to pass 4 mandatory test cases that are specified [here](https://developers.google.com/pay/issuers/apis/push-provisioning/android/test-cases). They verify how your app handles card state tracking in different scenarios. > [!NOTE] >Please make sure to hide the `Add to Google Wallet` buttons when cards are already added to the wallet. ### iOS -When implementing the In-App Push Provisioning feature in your App make sure that your app follows Apple's [branding guidelines connected to Apple Wallet](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/). Remember that you must not create your own buttons or your app could be rejected at revision. You can use the[ AddWalletButton component](#components) instead! +When implementing the In-App Push Provisioning feature in your App make sure that your app follows Apple's [branding guidelines connected to Apple Wallet](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/). Remember that you must not create your own buttons or your app could be rejected at revision. You can use the[ AddWalletButton component](#components) instead! When the pass is already provisioned, make sure to hide this button and replace it with text like `Added to Apple Wallet`. The card is fully provisioned once it added to your main device (user's iPhone) and all linked devices (for example Apple Watch). Next to branding guidelines, please follow the instructions and best practices from [the In-App provisioning documentation]((#ios)) provided by Apple. @@ -246,7 +311,6 @@ Additionally, when submitting your app to the App Store, you must include: `@expensify/react-native-wallet` is compatible with the five latest minor releases of React Native (β‰₯0.76.0) and works exclusively with the new architecture. - # Contributing Contributions to this library are done under [https://github.com/Expensify/App](https://github.com/Expensify/App). Please refer to that repo and all its guidelines for contributing. diff --git a/app.plugin.js b/app.plugin.js new file mode 100644 index 0000000..55fcda1 --- /dev/null +++ b/app.plugin.js @@ -0,0 +1,2 @@ +// This file configures the entry file for your plugin. +module.exports = require('./plugins/build'); diff --git a/example/.eslintrc.js b/apps/basic-example/.eslintrc.js similarity index 100% rename from example/.eslintrc.js rename to apps/basic-example/.eslintrc.js diff --git a/example/.gitignore b/apps/basic-example/.gitignore similarity index 100% rename from example/.gitignore rename to apps/basic-example/.gitignore diff --git a/example/Gemfile b/apps/basic-example/Gemfile similarity index 100% rename from example/Gemfile rename to apps/basic-example/Gemfile diff --git a/example/Gemfile.lock b/apps/basic-example/Gemfile.lock similarity index 100% rename from example/Gemfile.lock rename to apps/basic-example/Gemfile.lock diff --git a/apps/basic-example/README.md b/apps/basic-example/README.md new file mode 100644 index 0000000..f0376d5 --- /dev/null +++ b/apps/basic-example/README.md @@ -0,0 +1,136 @@ +# Basic Example App + +Example React Native application demonstrating the `@expensify/react-native-wallet` library with Apple Pay and Google Pay integration. + +## Prerequisites + +- Node.js 18+ +- React Native development environment ([Setup Guide](https://reactnative.dev/docs/environment-setup)) +- For Android: Google TapAndPay SDK (see setup below) +- For iOS: Xcode and CocoaPods + +## Setup + +### 1. Install dependencies + +From the repository root: + +```bash +npm install +``` + +### 2. Configure Google TapAndPay SDK (Android only) + +The Google TapAndPay SDK is required for Android builds. Extract and place the SDK files in the Android libs directory: + +```bash +# Create the libs directory if it doesn't exist +mkdir -p android/libs +``` + +Extract the SDK ZIP file contents into `android/libs/` +The extracted files should be directly in` android/libs/`, not in a subdirectory +Example structure: + +``` +android/libs/com/google/android/gms/play-services-tapandpay/[version]/... +``` + +**Important**: Place the **extracted contents** of the ZIP file into `android/libs/`, not the ZIP file itself. The Gradle build expects a Maven repository structure. + +### 3. Install iOS dependencies + +```bash +cd ios +pod install +cd .. +``` + +## Running the App + +### Start Metro Bundler + +```bash +npm start +``` + +### iOS + +```bash +npm run ios +``` + +Or open in Xcode: +```bash +open ios/WalletExample.xcworkspace +``` + +### Android + +```bash +npm run android +``` + +## Development + +### Reload the app + +- **iOS**: Press Cmd ⌘ + R in the simulator +- **Android**: Press R twice or Ctrl/Cmd + M to open Developer Menu + +### Clean build + +```bash +# iOS +npm run clean-ios +npm run pods + +# Android +npm run clean-android +``` + +## Project Structure + +- `index.ts` - Entry point +- `app.json` - React Native configuration +- `android/libs/` - Google TapAndPay SDK location +- `../common-app/` - Shared app code used by both example apps + +## Troubleshooting + +### SDK not found (Android) + +If you get errors about missing TapAndPay SDK: +1. Verify the SDK files are extracted into `android/libs/` directory +2. The structure should be: `android/libs/com/google/android/gms/play-services-tapandpay/...` +3. Do NOT place the .zip file directly - extract it first +4. Clean and rebuild: `cd android && ./gradlew clean && cd ..` + +### Metro bundler issues + +Clear cache and restart: +```bash +npm start -- --reset-cache +``` + +### iOS build issues + +```bash +cd ios +pod deintegrate +pod install +cd .. +``` + +### Android build issues + +```bash +cd android +./gradlew clean +cd .. +``` + +## Learn More + +- [@expensify/react-native-wallet](../../README.md) - Main library documentation + diff --git a/example/android/app/build.gradle b/apps/basic-example/android/app/build.gradle similarity index 97% rename from example/android/app/build.gradle rename to apps/basic-example/android/app/build.gradle index 73ab5c0..828f14d 100644 --- a/example/android/app/build.gradle +++ b/apps/basic-example/android/app/build.gradle @@ -11,9 +11,9 @@ react { // The root of your project, i.e. where "package.json" lives. Default is '../..' // root = file("../../") // The folder where the react-native NPM package is. Default is ../../node_modules/react-native - reactNativeDir = file("../../../node_modules/react-native") + reactNativeDir = file("../../../../node_modules/react-native") // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen - codegenDir = file("../../../node_modules/@react-native/codegen") + codegenDir = file("../../../../node_modules/@react-native/codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js // cliFile = file("../../node_modules/react-native/cli.js") diff --git a/example/android/app/debug.keystore b/apps/basic-example/android/app/debug.keystore similarity index 100% rename from example/android/app/debug.keystore rename to apps/basic-example/android/app/debug.keystore diff --git a/example/android/app/proguard-rules.pro b/apps/basic-example/android/app/proguard-rules.pro similarity index 100% rename from example/android/app/proguard-rules.pro rename to apps/basic-example/android/app/proguard-rules.pro diff --git a/example/android/app/src/debug/AndroidManifest.xml b/apps/basic-example/android/app/src/debug/AndroidManifest.xml similarity index 100% rename from example/android/app/src/debug/AndroidManifest.xml rename to apps/basic-example/android/app/src/debug/AndroidManifest.xml diff --git a/example/android/app/src/main/AndroidManifest.xml b/apps/basic-example/android/app/src/main/AndroidManifest.xml similarity index 100% rename from example/android/app/src/main/AndroidManifest.xml rename to apps/basic-example/android/app/src/main/AndroidManifest.xml diff --git a/example/android/app/src/main/java/com/expensify/walletexample/MainActivity.kt b/apps/basic-example/android/app/src/main/java/com/expensify/walletexample/MainActivity.kt similarity index 100% rename from example/android/app/src/main/java/com/expensify/walletexample/MainActivity.kt rename to apps/basic-example/android/app/src/main/java/com/expensify/walletexample/MainActivity.kt diff --git a/example/android/app/src/main/java/com/expensify/walletexample/MainApplication.kt b/apps/basic-example/android/app/src/main/java/com/expensify/walletexample/MainApplication.kt similarity index 100% rename from example/android/app/src/main/java/com/expensify/walletexample/MainApplication.kt rename to apps/basic-example/android/app/src/main/java/com/expensify/walletexample/MainApplication.kt diff --git a/example/android/app/src/main/res/drawable/rn_edit_text_material.xml b/apps/basic-example/android/app/src/main/res/drawable/rn_edit_text_material.xml similarity index 100% rename from example/android/app/src/main/res/drawable/rn_edit_text_material.xml rename to apps/basic-example/android/app/src/main/res/drawable/rn_edit_text_material.xml diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/apps/basic-example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to apps/basic-example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/apps/basic-example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png similarity index 100% rename from example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png rename to apps/basic-example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/apps/basic-example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to apps/basic-example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/apps/basic-example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png similarity index 100% rename from example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png rename to apps/basic-example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/apps/basic-example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to apps/basic-example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/apps/basic-example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png rename to apps/basic-example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/apps/basic-example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to apps/basic-example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/apps/basic-example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png rename to apps/basic-example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apps/basic-example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to apps/basic-example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/apps/basic-example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png rename to apps/basic-example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png diff --git a/example/android/app/src/main/res/values/strings.xml b/apps/basic-example/android/app/src/main/res/values/strings.xml similarity index 100% rename from example/android/app/src/main/res/values/strings.xml rename to apps/basic-example/android/app/src/main/res/values/strings.xml diff --git a/example/android/app/src/main/res/values/styles.xml b/apps/basic-example/android/app/src/main/res/values/styles.xml similarity index 100% rename from example/android/app/src/main/res/values/styles.xml rename to apps/basic-example/android/app/src/main/res/values/styles.xml diff --git a/example/android/build.gradle b/apps/basic-example/android/build.gradle similarity index 100% rename from example/android/build.gradle rename to apps/basic-example/android/build.gradle diff --git a/example/android/gradle.properties b/apps/basic-example/android/gradle.properties similarity index 100% rename from example/android/gradle.properties rename to apps/basic-example/android/gradle.properties diff --git a/example/android/gradle/wrapper/gradle-wrapper.jar b/apps/basic-example/android/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from example/android/gradle/wrapper/gradle-wrapper.jar rename to apps/basic-example/android/gradle/wrapper/gradle-wrapper.jar diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/apps/basic-example/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from example/android/gradle/wrapper/gradle-wrapper.properties rename to apps/basic-example/android/gradle/wrapper/gradle-wrapper.properties diff --git a/example/android/gradlew b/apps/basic-example/android/gradlew similarity index 100% rename from example/android/gradlew rename to apps/basic-example/android/gradlew diff --git a/example/android/gradlew.bat b/apps/basic-example/android/gradlew.bat similarity index 100% rename from example/android/gradlew.bat rename to apps/basic-example/android/gradlew.bat diff --git a/example/android/settings.gradle b/apps/basic-example/android/settings.gradle similarity index 84% rename from example/android/settings.gradle rename to apps/basic-example/android/settings.gradle index 22c2b61..ed08b64 100644 --- a/example/android/settings.gradle +++ b/apps/basic-example/android/settings.gradle @@ -1,9 +1,9 @@ -pluginManagement { includeBuild("../../node_modules/@react-native/gradle-plugin") } +pluginManagement { includeBuild("../../../node_modules/@react-native/gradle-plugin") } plugins { id("com.facebook.react.settings") } extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } rootProject.name = 'WalletExample' include ':app' -includeBuild('../../node_modules/@react-native/gradle-plugin') +includeBuild('../../../node_modules/@react-native/gradle-plugin') // includeBuild('../node_modules/react-native') { // dependencySubstitution { // substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid")) diff --git a/apps/basic-example/app.json b/apps/basic-example/app.json new file mode 100644 index 0000000..a5f4000 --- /dev/null +++ b/apps/basic-example/app.json @@ -0,0 +1,4 @@ +{ + "name": "WalletExample", + "displayName": "WalletExample" +} diff --git a/apps/basic-example/babel.config.js b/apps/basic-example/babel.config.js new file mode 100644 index 0000000..f7b3da3 --- /dev/null +++ b/apps/basic-example/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:@react-native/babel-preset'], +}; diff --git a/example/index.ts b/apps/basic-example/index.ts similarity index 78% rename from example/index.ts rename to apps/basic-example/index.ts index ef707c2..7ace3dc 100644 --- a/example/index.ts +++ b/apps/basic-example/index.ts @@ -1,5 +1,5 @@ import {AppRegistry} from 'react-native'; -import App from './src/App'; +import App from '../common-app/App'; import {name as appName} from './app.json'; AppRegistry.registerComponent(appName, () => App); diff --git a/example/ios/.xcode.env b/apps/basic-example/ios/.xcode.env similarity index 100% rename from example/ios/.xcode.env rename to apps/basic-example/ios/.xcode.env diff --git a/example/ios/AppDelegate.swift b/apps/basic-example/ios/AppDelegate.swift similarity index 100% rename from example/ios/AppDelegate.swift rename to apps/basic-example/ios/AppDelegate.swift diff --git a/example/ios/Podfile b/apps/basic-example/ios/Podfile similarity index 100% rename from example/ios/Podfile rename to apps/basic-example/ios/Podfile diff --git a/example/ios/Podfile.lock b/apps/basic-example/ios/Podfile.lock similarity index 82% rename from example/ios/Podfile.lock rename to apps/basic-example/ios/Podfile.lock index 807771f..3b38411 100644 --- a/example/ios/Podfile.lock +++ b/apps/basic-example/ios/Podfile.lock @@ -1719,7 +1719,7 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - SocketRocket - - react-native-safe-area-context (5.6.1): + - react-native-safe-area-context (5.6.2): - boost - DoubleConversion - fast_float @@ -1737,8 +1737,8 @@ PODS: - React-graphics - React-ImageManager - React-jsi - - react-native-safe-area-context/common (= 5.6.1) - - react-native-safe-area-context/fabric (= 5.6.1) + - react-native-safe-area-context/common (= 5.6.2) + - react-native-safe-area-context/fabric (= 5.6.2) - React-NativeModulesApple - React-RCTFabric - React-renderercss @@ -1749,7 +1749,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-safe-area-context/common (5.6.1): + - react-native-safe-area-context/common (5.6.2): - boost - DoubleConversion - fast_float @@ -1777,7 +1777,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-safe-area-context/fabric (5.6.1): + - react-native-safe-area-context/fabric (5.6.2): - boost - DoubleConversion - fast_float @@ -1806,7 +1806,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-wallet (0.1.10): + - react-native-wallet (0.1.15): - boost - DoubleConversion - fast_float @@ -2342,81 +2342,81 @@ PODS: - Yoga (0.0.0) DEPENDENCIES: - - boost (from `../../node_modules/react-native/third-party-podspecs/boost.podspec`) - - DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - - fast_float (from `../../node_modules/react-native/third-party-podspecs/fast_float.podspec`) - - FBLazyVector (from `../../node_modules/react-native/Libraries/FBLazyVector`) - - fmt (from `../../node_modules/react-native/third-party-podspecs/fmt.podspec`) - - glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`) - - hermes-engine (from `../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - RCT-Folly (from `../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCTDeprecation (from `../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - - RCTRequired (from `../../node_modules/react-native/Libraries/Required`) - - RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`) - - React (from `../../node_modules/react-native/`) - - React-callinvoker (from `../../node_modules/react-native/ReactCommon/callinvoker`) - - React-Core (from `../../node_modules/react-native/`) - - React-Core/RCTWebSocket (from `../../node_modules/react-native/`) - - React-CoreModules (from `../../node_modules/react-native/React/CoreModules`) - - React-cxxreact (from `../../node_modules/react-native/ReactCommon/cxxreact`) - - React-debug (from `../../node_modules/react-native/ReactCommon/react/debug`) - - React-defaultsnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) - - React-domnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/dom`) - - React-Fabric (from `../../node_modules/react-native/ReactCommon`) - - React-FabricComponents (from `../../node_modules/react-native/ReactCommon`) - - React-FabricImage (from `../../node_modules/react-native/ReactCommon`) - - React-featureflags (from `../../node_modules/react-native/ReactCommon/react/featureflags`) - - React-featureflagsnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) - - React-graphics (from `../../node_modules/react-native/ReactCommon/react/renderer/graphics`) - - React-hermes (from `../../node_modules/react-native/ReactCommon/hermes`) - - React-idlecallbacksnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) - - React-ImageManager (from `../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) - - React-jserrorhandler (from `../../node_modules/react-native/ReactCommon/jserrorhandler`) - - React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`) - - React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`) - - React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector-modern`) - - React-jsinspectorcdp (from `../../node_modules/react-native/ReactCommon/jsinspector-modern/cdp`) - - React-jsinspectornetwork (from `../../node_modules/react-native/ReactCommon/jsinspector-modern/network`) - - React-jsinspectortracing (from `../../node_modules/react-native/ReactCommon/jsinspector-modern/tracing`) - - React-jsitooling (from `../../node_modules/react-native/ReactCommon/jsitooling`) - - React-jsitracing (from `../../node_modules/react-native/ReactCommon/hermes/executor/`) - - React-logger (from `../../node_modules/react-native/ReactCommon/logger`) - - React-Mapbuffer (from `../../node_modules/react-native/ReactCommon`) - - React-microtasksnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) - - react-native-safe-area-context (from `../../node_modules/react-native-safe-area-context`) - - react-native-wallet (from `../..`) - - React-NativeModulesApple (from `../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - - React-oscompat (from `../../node_modules/react-native/ReactCommon/oscompat`) - - React-perflogger (from `../../node_modules/react-native/ReactCommon/reactperflogger`) - - React-performancetimeline (from `../../node_modules/react-native/ReactCommon/react/performance/timeline`) - - React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`) - - React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`) - - React-RCTAppDelegate (from `../../node_modules/react-native/Libraries/AppDelegate`) - - React-RCTBlob (from `../../node_modules/react-native/Libraries/Blob`) - - React-RCTFabric (from `../../node_modules/react-native/React`) - - React-RCTFBReactNativeSpec (from `../../node_modules/react-native/React`) - - React-RCTImage (from `../../node_modules/react-native/Libraries/Image`) - - React-RCTLinking (from `../../node_modules/react-native/Libraries/LinkingIOS`) - - React-RCTNetwork (from `../../node_modules/react-native/Libraries/Network`) - - React-RCTRuntime (from `../../node_modules/react-native/React/Runtime`) - - React-RCTSettings (from `../../node_modules/react-native/Libraries/Settings`) - - React-RCTText (from `../../node_modules/react-native/Libraries/Text`) - - React-RCTVibration (from `../../node_modules/react-native/Libraries/Vibration`) - - React-rendererconsistency (from `../../node_modules/react-native/ReactCommon/react/renderer/consistency`) - - React-renderercss (from `../../node_modules/react-native/ReactCommon/react/renderer/css`) - - React-rendererdebug (from `../../node_modules/react-native/ReactCommon/react/renderer/debug`) - - React-RuntimeApple (from `../../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) - - React-RuntimeCore (from `../../node_modules/react-native/ReactCommon/react/runtime`) - - React-runtimeexecutor (from `../../node_modules/react-native/ReactCommon/runtimeexecutor`) - - React-RuntimeHermes (from `../../node_modules/react-native/ReactCommon/react/runtime`) - - React-runtimescheduler (from `../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - - React-timing (from `../../node_modules/react-native/ReactCommon/react/timing`) - - React-utils (from `../../node_modules/react-native/ReactCommon/react/utils`) + - boost (from `../../../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - fast_float (from `../../../node_modules/react-native/third-party-podspecs/fast_float.podspec`) + - FBLazyVector (from `../../../node_modules/react-native/Libraries/FBLazyVector`) + - fmt (from `../../../node_modules/react-native/third-party-podspecs/fmt.podspec`) + - glog (from `../../../node_modules/react-native/third-party-podspecs/glog.podspec`) + - hermes-engine (from `../../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - RCT-Folly (from `../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTDeprecation (from `../../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) + - RCTRequired (from `../../../node_modules/react-native/Libraries/Required`) + - RCTTypeSafety (from `../../../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../../../node_modules/react-native/`) + - React-callinvoker (from `../../../node_modules/react-native/ReactCommon/callinvoker`) + - React-Core (from `../../../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../../../node_modules/react-native/`) + - React-CoreModules (from `../../../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../../../node_modules/react-native/ReactCommon/cxxreact`) + - React-debug (from `../../../node_modules/react-native/ReactCommon/react/debug`) + - React-defaultsnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) + - React-domnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/dom`) + - React-Fabric (from `../../../node_modules/react-native/ReactCommon`) + - React-FabricComponents (from `../../../node_modules/react-native/ReactCommon`) + - React-FabricImage (from `../../../node_modules/react-native/ReactCommon`) + - React-featureflags (from `../../../node_modules/react-native/ReactCommon/react/featureflags`) + - React-featureflagsnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) + - React-graphics (from `../../../node_modules/react-native/ReactCommon/react/renderer/graphics`) + - React-hermes (from `../../../node_modules/react-native/ReactCommon/hermes`) + - React-idlecallbacksnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) + - React-ImageManager (from `../../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) + - React-jserrorhandler (from `../../../node_modules/react-native/ReactCommon/jserrorhandler`) + - React-jsi (from `../../../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../../../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsinspectorcdp (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern/cdp`) + - React-jsinspectornetwork (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern/network`) + - React-jsinspectortracing (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern/tracing`) + - React-jsitooling (from `../../../node_modules/react-native/ReactCommon/jsitooling`) + - React-jsitracing (from `../../../node_modules/react-native/ReactCommon/hermes/executor/`) + - React-logger (from `../../../node_modules/react-native/ReactCommon/logger`) + - React-Mapbuffer (from `../../../node_modules/react-native/ReactCommon`) + - React-microtasksnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) + - react-native-safe-area-context (from `../../../node_modules/react-native-safe-area-context`) + - "react-native-wallet (from `../../../node_modules/@expensify/react-native-wallet`)" + - React-NativeModulesApple (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-oscompat (from `../../../node_modules/react-native/ReactCommon/oscompat`) + - React-perflogger (from `../../../node_modules/react-native/ReactCommon/reactperflogger`) + - React-performancetimeline (from `../../../node_modules/react-native/ReactCommon/react/performance/timeline`) + - React-RCTActionSheet (from `../../../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../../../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTAppDelegate (from `../../../node_modules/react-native/Libraries/AppDelegate`) + - React-RCTBlob (from `../../../node_modules/react-native/Libraries/Blob`) + - React-RCTFabric (from `../../../node_modules/react-native/React`) + - React-RCTFBReactNativeSpec (from `../../../node_modules/react-native/React`) + - React-RCTImage (from `../../../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../../../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../../../node_modules/react-native/Libraries/Network`) + - React-RCTRuntime (from `../../../node_modules/react-native/React/Runtime`) + - React-RCTSettings (from `../../../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../../../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../../../node_modules/react-native/Libraries/Vibration`) + - React-rendererconsistency (from `../../../node_modules/react-native/ReactCommon/react/renderer/consistency`) + - React-renderercss (from `../../../node_modules/react-native/ReactCommon/react/renderer/css`) + - React-rendererdebug (from `../../../node_modules/react-native/ReactCommon/react/renderer/debug`) + - React-RuntimeApple (from `../../../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) + - React-RuntimeCore (from `../../../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimeexecutor (from `../../../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-RuntimeHermes (from `../../../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimescheduler (from `../../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) + - React-timing (from `../../../node_modules/react-native/ReactCommon/react/timing`) + - React-utils (from `../../../node_modules/react-native/ReactCommon/react/utils`) - ReactAppDependencyProvider (from `build/generated/ios`) - ReactCodegen (from `build/generated/ios`) - - ReactCommon/turbomodule/core (from `../../node_modules/react-native/ReactCommon`) + - ReactCommon/turbomodule/core (from `../../../node_modules/react-native/ReactCommon`) - SocketRocket (~> 0.7.1) - - Yoga (from `../../node_modules/react-native/ReactCommon/yoga`) + - Yoga (from `../../../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: trunk: @@ -2424,152 +2424,152 @@ SPEC REPOS: EXTERNAL SOURCES: boost: - :podspec: "../../node_modules/react-native/third-party-podspecs/boost.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/boost.podspec" DoubleConversion: - :podspec: "../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" fast_float: - :podspec: "../../node_modules/react-native/third-party-podspecs/fast_float.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/fast_float.podspec" FBLazyVector: - :path: "../../node_modules/react-native/Libraries/FBLazyVector" + :path: "../../../node_modules/react-native/Libraries/FBLazyVector" fmt: - :podspec: "../../node_modules/react-native/third-party-podspecs/fmt.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/fmt.podspec" glog: - :podspec: "../../node_modules/react-native/third-party-podspecs/glog.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/glog.podspec" hermes-engine: - :podspec: "../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + :podspec: "../../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2025-07-07-RNv0.81.0-e0fc67142ec0763c6b6153ca2bf96df815539782 RCT-Folly: - :podspec: "../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" RCTDeprecation: - :path: "../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" + :path: "../../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" RCTRequired: - :path: "../../node_modules/react-native/Libraries/Required" + :path: "../../../node_modules/react-native/Libraries/Required" RCTTypeSafety: - :path: "../../node_modules/react-native/Libraries/TypeSafety" + :path: "../../../node_modules/react-native/Libraries/TypeSafety" React: - :path: "../../node_modules/react-native/" + :path: "../../../node_modules/react-native/" React-callinvoker: - :path: "../../node_modules/react-native/ReactCommon/callinvoker" + :path: "../../../node_modules/react-native/ReactCommon/callinvoker" React-Core: - :path: "../../node_modules/react-native/" + :path: "../../../node_modules/react-native/" React-CoreModules: - :path: "../../node_modules/react-native/React/CoreModules" + :path: "../../../node_modules/react-native/React/CoreModules" React-cxxreact: - :path: "../../node_modules/react-native/ReactCommon/cxxreact" + :path: "../../../node_modules/react-native/ReactCommon/cxxreact" React-debug: - :path: "../../node_modules/react-native/ReactCommon/react/debug" + :path: "../../../node_modules/react-native/ReactCommon/react/debug" React-defaultsnativemodule: - :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/defaults" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/defaults" React-domnativemodule: - :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/dom" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/dom" React-Fabric: - :path: "../../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-FabricComponents: - :path: "../../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-FabricImage: - :path: "../../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-featureflags: - :path: "../../node_modules/react-native/ReactCommon/react/featureflags" + :path: "../../../node_modules/react-native/ReactCommon/react/featureflags" React-featureflagsnativemodule: - :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" React-graphics: - :path: "../../node_modules/react-native/ReactCommon/react/renderer/graphics" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/graphics" React-hermes: - :path: "../../node_modules/react-native/ReactCommon/hermes" + :path: "../../../node_modules/react-native/ReactCommon/hermes" React-idlecallbacksnativemodule: - :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" React-ImageManager: - :path: "../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" React-jserrorhandler: - :path: "../../node_modules/react-native/ReactCommon/jserrorhandler" + :path: "../../../node_modules/react-native/ReactCommon/jserrorhandler" React-jsi: - :path: "../../node_modules/react-native/ReactCommon/jsi" + :path: "../../../node_modules/react-native/ReactCommon/jsi" React-jsiexecutor: - :path: "../../node_modules/react-native/ReactCommon/jsiexecutor" + :path: "../../../node_modules/react-native/ReactCommon/jsiexecutor" React-jsinspector: - :path: "../../node_modules/react-native/ReactCommon/jsinspector-modern" + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern" React-jsinspectorcdp: - :path: "../../node_modules/react-native/ReactCommon/jsinspector-modern/cdp" + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern/cdp" React-jsinspectornetwork: - :path: "../../node_modules/react-native/ReactCommon/jsinspector-modern/network" + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern/network" React-jsinspectortracing: - :path: "../../node_modules/react-native/ReactCommon/jsinspector-modern/tracing" + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern/tracing" React-jsitooling: - :path: "../../node_modules/react-native/ReactCommon/jsitooling" + :path: "../../../node_modules/react-native/ReactCommon/jsitooling" React-jsitracing: - :path: "../../node_modules/react-native/ReactCommon/hermes/executor/" + :path: "../../../node_modules/react-native/ReactCommon/hermes/executor/" React-logger: - :path: "../../node_modules/react-native/ReactCommon/logger" + :path: "../../../node_modules/react-native/ReactCommon/logger" React-Mapbuffer: - :path: "../../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-microtasksnativemodule: - :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" react-native-safe-area-context: - :path: "../../node_modules/react-native-safe-area-context" + :path: "../../../node_modules/react-native-safe-area-context" react-native-wallet: - :path: "../.." + :path: "../../../node_modules/@expensify/react-native-wallet" React-NativeModulesApple: - :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" React-oscompat: - :path: "../../node_modules/react-native/ReactCommon/oscompat" + :path: "../../../node_modules/react-native/ReactCommon/oscompat" React-perflogger: - :path: "../../node_modules/react-native/ReactCommon/reactperflogger" + :path: "../../../node_modules/react-native/ReactCommon/reactperflogger" React-performancetimeline: - :path: "../../node_modules/react-native/ReactCommon/react/performance/timeline" + :path: "../../../node_modules/react-native/ReactCommon/react/performance/timeline" React-RCTActionSheet: - :path: "../../node_modules/react-native/Libraries/ActionSheetIOS" + :path: "../../../node_modules/react-native/Libraries/ActionSheetIOS" React-RCTAnimation: - :path: "../../node_modules/react-native/Libraries/NativeAnimation" + :path: "../../../node_modules/react-native/Libraries/NativeAnimation" React-RCTAppDelegate: - :path: "../../node_modules/react-native/Libraries/AppDelegate" + :path: "../../../node_modules/react-native/Libraries/AppDelegate" React-RCTBlob: - :path: "../../node_modules/react-native/Libraries/Blob" + :path: "../../../node_modules/react-native/Libraries/Blob" React-RCTFabric: - :path: "../../node_modules/react-native/React" + :path: "../../../node_modules/react-native/React" React-RCTFBReactNativeSpec: - :path: "../../node_modules/react-native/React" + :path: "../../../node_modules/react-native/React" React-RCTImage: - :path: "../../node_modules/react-native/Libraries/Image" + :path: "../../../node_modules/react-native/Libraries/Image" React-RCTLinking: - :path: "../../node_modules/react-native/Libraries/LinkingIOS" + :path: "../../../node_modules/react-native/Libraries/LinkingIOS" React-RCTNetwork: - :path: "../../node_modules/react-native/Libraries/Network" + :path: "../../../node_modules/react-native/Libraries/Network" React-RCTRuntime: - :path: "../../node_modules/react-native/React/Runtime" + :path: "../../../node_modules/react-native/React/Runtime" React-RCTSettings: - :path: "../../node_modules/react-native/Libraries/Settings" + :path: "../../../node_modules/react-native/Libraries/Settings" React-RCTText: - :path: "../../node_modules/react-native/Libraries/Text" + :path: "../../../node_modules/react-native/Libraries/Text" React-RCTVibration: - :path: "../../node_modules/react-native/Libraries/Vibration" + :path: "../../../node_modules/react-native/Libraries/Vibration" React-rendererconsistency: - :path: "../../node_modules/react-native/ReactCommon/react/renderer/consistency" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/consistency" React-renderercss: - :path: "../../node_modules/react-native/ReactCommon/react/renderer/css" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/css" React-rendererdebug: - :path: "../../node_modules/react-native/ReactCommon/react/renderer/debug" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/debug" React-RuntimeApple: - :path: "../../node_modules/react-native/ReactCommon/react/runtime/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime/platform/ios" React-RuntimeCore: - :path: "../../node_modules/react-native/ReactCommon/react/runtime" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime" React-runtimeexecutor: - :path: "../../node_modules/react-native/ReactCommon/runtimeexecutor" + :path: "../../../node_modules/react-native/ReactCommon/runtimeexecutor" React-RuntimeHermes: - :path: "../../node_modules/react-native/ReactCommon/react/runtime" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime" React-runtimescheduler: - :path: "../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" React-timing: - :path: "../../node_modules/react-native/ReactCommon/react/timing" + :path: "../../../node_modules/react-native/ReactCommon/react/timing" React-utils: - :path: "../../node_modules/react-native/ReactCommon/react/utils" + :path: "../../../node_modules/react-native/ReactCommon/react/utils" ReactAppDependencyProvider: :path: build/generated/ios ReactCodegen: :path: build/generated/ios ReactCommon: - :path: "../../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" Yoga: - :path: "../../node_modules/react-native/ReactCommon/yoga" + :path: "../../../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 @@ -2612,8 +2612,8 @@ SPEC CHECKSUMS: React-logger: 04ce9229cb57db2c2a8164eaec1105f89da7fb22 React-Mapbuffer: e402e7a0535b2213c50727553621480fe8cd8ade React-microtasksnativemodule: a63ce5595016996a9bac1f10c70a7a7fe6506649 - react-native-safe-area-context: c6e2edd1c1da07bdce287fa9d9e60c5f7b514616 - react-native-wallet: d94a1e8eabd6a6b65c0e96eb4f73545838d559ea + react-native-safe-area-context: c00143b4823773bba23f2f19f85663ae89ceb460 + react-native-wallet: e082f2023e0fc86b51ac6c0a7596dcdf17ee30b0 React-NativeModulesApple: b3766e1f87b08064ebc459b9e1538da2447ca874 React-oscompat: 34f3d3c06cadcbc470bc4509c717fb9b919eaa8b React-perflogger: a1edb025fd5d44f61bf09307e248f7608d7b2dcf @@ -2642,11 +2642,11 @@ SPEC CHECKSUMS: React-timing: 25e8229ad1cf6874e9f0711515213cb2bc322215 React-utils: 068cec677032ba78ca0700f2dcbe6d08a0939647 ReactAppDependencyProvider: c91900fa724baee992f01c05eeb4c9e01a807f78 - ReactCodegen: c3a2e945d68bcf8839624acaf1b276acbb41e9ba + ReactCodegen: 8125d6ee06ea06f48f156cbddec5c2ca576d62e6 ReactCommon: 116d6ee71679243698620d8cd9a9042541e44aa6 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 00013dd9cde63a2d98e8002fcc4f5ddb66c10782 PODFILE CHECKSUM: 6ad5830138f1a5db61378ca75df6ff989d88aa3a -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/example/ios/WalletExample.xcodeproj/project.pbxproj b/apps/basic-example/ios/WalletExample.xcodeproj/project.pbxproj similarity index 99% rename from example/ios/WalletExample.xcodeproj/project.pbxproj rename to apps/basic-example/ios/WalletExample.xcodeproj/project.pbxproj index b0306e8..f7826e3 100644 --- a/example/ios/WalletExample.xcodeproj/project.pbxproj +++ b/apps/basic-example/ios/WalletExample.xcodeproj/project.pbxproj @@ -394,7 +394,7 @@ "$(inherited)", " ", ); - REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native"; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; SWIFT_VERSION = 5.0; @@ -474,7 +474,7 @@ "$(inherited)", " ", ); - REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native"; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_VERSION = 5.0; USE_HERMES = true; diff --git a/example/ios/WalletExample.xcodeproj/xcshareddata/xcschemes/WalletExample.xcscheme b/apps/basic-example/ios/WalletExample.xcodeproj/xcshareddata/xcschemes/WalletExample.xcscheme similarity index 100% rename from example/ios/WalletExample.xcodeproj/xcshareddata/xcschemes/WalletExample.xcscheme rename to apps/basic-example/ios/WalletExample.xcodeproj/xcshareddata/xcschemes/WalletExample.xcscheme diff --git a/example/ios/WalletExample.xcworkspace/contents.xcworkspacedata b/apps/basic-example/ios/WalletExample.xcworkspace/contents.xcworkspacedata similarity index 100% rename from example/ios/WalletExample.xcworkspace/contents.xcworkspacedata rename to apps/basic-example/ios/WalletExample.xcworkspace/contents.xcworkspacedata diff --git a/example/ios/WalletExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/basic-example/ios/WalletExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/ios/WalletExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to apps/basic-example/ios/WalletExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/WalletExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/apps/basic-example/ios/WalletExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from example/ios/WalletExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to apps/basic-example/ios/WalletExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/example/ios/WalletExample/Images.xcassets/AppIcon.appiconset/Contents.json b/apps/basic-example/ios/WalletExample/Images.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from example/ios/WalletExample/Images.xcassets/AppIcon.appiconset/Contents.json rename to apps/basic-example/ios/WalletExample/Images.xcassets/AppIcon.appiconset/Contents.json diff --git a/example/ios/WalletExample/Images.xcassets/Contents.json b/apps/basic-example/ios/WalletExample/Images.xcassets/Contents.json similarity index 100% rename from example/ios/WalletExample/Images.xcassets/Contents.json rename to apps/basic-example/ios/WalletExample/Images.xcassets/Contents.json diff --git a/example/ios/WalletExample/Info.plist b/apps/basic-example/ios/WalletExample/Info.plist similarity index 100% rename from example/ios/WalletExample/Info.plist rename to apps/basic-example/ios/WalletExample/Info.plist diff --git a/example/ios/WalletExample/LaunchScreen.storyboard b/apps/basic-example/ios/WalletExample/LaunchScreen.storyboard similarity index 100% rename from example/ios/WalletExample/LaunchScreen.storyboard rename to apps/basic-example/ios/WalletExample/LaunchScreen.storyboard diff --git a/example/ios/WalletExample/PrivacyInfo.xcprivacy b/apps/basic-example/ios/WalletExample/PrivacyInfo.xcprivacy similarity index 100% rename from example/ios/WalletExample/PrivacyInfo.xcprivacy rename to apps/basic-example/ios/WalletExample/PrivacyInfo.xcprivacy diff --git a/example/ios/WalletExample/WalletExample.entitlements b/apps/basic-example/ios/WalletExample/WalletExample.entitlements similarity index 100% rename from example/ios/WalletExample/WalletExample.entitlements rename to apps/basic-example/ios/WalletExample/WalletExample.entitlements diff --git a/example/metro.config.js b/apps/basic-example/metro.config.js similarity index 69% rename from example/metro.config.js rename to apps/basic-example/metro.config.js index 7fd57bd..d818a8d 100644 --- a/example/metro.config.js +++ b/apps/basic-example/metro.config.js @@ -1,7 +1,7 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); const path = require('path'); -const root = path.resolve(__dirname, '..'); +const root = path.resolve(__dirname, '../..'); /** * Metro configuration @@ -10,8 +10,13 @@ const root = path.resolve(__dirname, '..'); * @type {import('@react-native/metro-config').MetroConfig} */ const config = { - watchFolders: [root, __dirname], - + watchFolders: [root], + resolver: { + nodeModulesPaths: [ + path.resolve(__dirname, 'node_modules'), + path.resolve(__dirname, '../../node_modules'), + ], + }, transformer: { getTransformOptions: async () => ({ transform: { diff --git a/example/package.json b/apps/basic-example/package.json similarity index 63% rename from example/package.json rename to apps/basic-example/package.json index 7f00e44..c1b7a09 100644 --- a/example/package.json +++ b/apps/basic-example/package.json @@ -6,9 +6,18 @@ "android": "react-native run-android", "ios": "react-native run-ios", "lint": "eslint .", - "start": "react-native start" + "start": "react-native start", + "test": "jest", + "ts-check": "yarn tsc --noEmit", + "lint-js": "eslint --ext '.js,.ts,.tsx' src/ && yarn prettier --check './src/**/*.{js,jsx,ts,tsx}'", + "format-js": "prettier --write --list-different './src/**/*.{js,jsx,ts,tsx}'", + "clean-android": "rm -rf android/.gradle android/.kotlin android/build", + "clean-ios": "rm -rf ios/build ios/Pods ios/Podfile.lock", + "clean": "rm -rf node_modules && yarn clean-android && yarn clean-ios", + "pods": "cd ios && bundle install && bundle exec pod install" }, "dependencies": { + "@expensify/react-native-wallet": "*", "react": "^19.1.0", "react-native": "0.81.0", "react-native-safe-area-context": "^5.5.2" @@ -16,7 +25,7 @@ "devDependencies": { "@babel/core": "^7.25.2", "@babel/preset-env": "^7.25.3", - "@babel/runtime": "^7.25.0", + "@babel/runtime": "^7.28.6", "@react-native-community/cli": "20.0.0", "@react-native-community/cli-platform-android": "20.0.0", "@react-native-community/cli-platform-ios": "20.0.0", diff --git a/apps/basic-example/tsconfig.json b/apps/basic-example/tsconfig.json new file mode 100644 index 0000000..f252bcb --- /dev/null +++ b/apps/basic-example/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "strict": true, + "jsx": "react-native" + }, + "include": ["../common-app/src/**/*.tsx", "../common-app/src/walletUtils.ts", "../common-app/App.tsx"], + "exclude": ["node_modules"] +} diff --git a/example/src/App.tsx b/apps/common-app/App.tsx similarity index 76% rename from example/src/App.tsx rename to apps/common-app/App.tsx index 83f30a7..7d89366 100644 --- a/example/src/App.tsx +++ b/apps/common-app/App.tsx @@ -1,23 +1,12 @@ import * as React from 'react'; import {useState, useEffect, useMemo, useCallback} from 'react'; import {StyleSheet, View, Text, Alert, ScrollView} from 'react-native'; -import { - checkWalletAvailability, - getSecureWalletInfo, - getCardStatusBySuffix, - getCardStatusByIdentifier, - addListener, - removeListener, - AddToWalletButton, -} from '@expensify/react-native-wallet'; -import type { - CardStatus, - AndroidWalletData, -} from '@expensify/react-native-wallet'; -import PlatformInfo from './PlatformInfo'; -import LabeledButton from './LabeledButton'; -import {addCardToWallet} from './walletUtils'; -import {SafeAreaView} from 'react-native-safe-area-context'; +import {checkWalletAvailability, getSecureWalletInfo, getCardStatusBySuffix, getCardStatusByIdentifier, addListener, removeListener, AddToWalletButton} from '@expensify/react-native-wallet'; +import type {CardStatus, AndroidWalletData} from '@expensify/react-native-wallet'; +import {SafeAreaProvider, useSafeAreaInsets} from 'react-native-safe-area-context'; +import PlatformInfo from './src/PlatformInfo'; +import LabeledButton from './src/LabeledButton'; +import {addCardToWallet} from './src/walletUtils'; const CARD_LAST_4_DIGITS = '4321'; const TOKEN_REF_ID = 'tokenID123'; @@ -26,12 +15,13 @@ const getWalletInfoTextValue = (walletData: AndroidWalletData | undefined) => { return `{\n\t\twalletId: ${walletData?.walletAccountID}\n\t\thardwareId: ${walletData?.deviceID}\n}`; }; -export default function App() { +function AppContent() { const [isWalletAvailable, setIsWalletAvailable] = useState(false); const [walletData, setWalletData] = useState(); const [cardStatus, setCardStatus] = useState(); const [tokenStatus, setTokenStatus] = useState(); const [addCardStatus, setAddCardStatus] = useState(); + const insets = useSafeAreaInsets(); const handleCheckWalletAvailability = useCallback(() => { checkWalletAvailability().then(setIsWalletAvailable); @@ -39,13 +29,14 @@ export default function App() { const handleGetSecureWalletInfo = useCallback(() => { getSecureWalletInfo() - .then(data => { + .then((data) => { setWalletData(data); }) - .catch(e => { - if (e instanceof Error) { - Alert.alert('Error', e.message); + .catch((e) => { + if (!(e instanceof Error)) { + return; } + Alert.alert('Error', e.message); }); }, []); @@ -59,24 +50,21 @@ export default function App() { const handleAddCardToWallet = useCallback(() => { addCardToWallet(cardStatus) - .then(status => { + .then((status) => { setAddCardStatus(status); }) - .catch(e => { + .catch((e) => { console.error(e); setAddCardStatus('failed'); }); }, [cardStatus]); - const walletSecureInfo = useMemo( - () => getWalletInfoTextValue(walletData), - [walletData], - ); + const walletSecureInfo = useMemo(() => getWalletInfoTextValue(walletData), [walletData]); useEffect(() => { handleCheckWalletAvailability(); - const subscription = addListener('onCardActivated', data => { + const subscription = addListener('onCardActivated', (data) => { Alert.alert('onCardActivated listener', JSON.stringify(data)); }); @@ -88,8 +76,8 @@ export default function App() { }, []); return ( - - + + react-native-wallet example app @@ -139,18 +127,27 @@ export default function App() { /> - + + ); +} + +export default function App() { + return ( + + + ); } const styles = StyleSheet.create({ container: { + flex: 1, + backgroundColor: 'white', + }, + scrollContent: { paddingTop: 20, alignItems: 'center', justifyContent: 'center', - gap: 10, - backgroundColor: 'white', - flex: 1, }, header: { gap: 10, diff --git a/apps/common-app/index.ts b/apps/common-app/index.ts new file mode 100644 index 0000000..f1f2a24 --- /dev/null +++ b/apps/common-app/index.ts @@ -0,0 +1,3 @@ +import App from './App'; + +export default App; diff --git a/apps/common-app/package.json b/apps/common-app/package.json new file mode 100644 index 0000000..1a43963 --- /dev/null +++ b/apps/common-app/package.json @@ -0,0 +1,51 @@ +{ + "name": "@expensify/react-native-wallet-common-app", + "version": "0.0.1", + "private": true, + "scripts": { + "android": "react-native run-android", + "ios": "react-native run-ios", + "lint": "eslint .", + "start": "react-native start", + "test": "jest", + "ts-check": "yarn tsc --noEmit", + "lint-js": "eslint --ext '.js,.ts,.tsx' src/ && yarn prettier --check './src/**/*.{js,jsx,ts,tsx}'", + "format-js": "prettier --write --list-different './src/**/*.{js,jsx,ts,tsx}'", + "clean-android": "rm -rf android/.gradle android/.kotlin android/build", + "clean-ios": "rm -rf ios/build ios/Pods ios/Podfile.lock", + "clean": "rm -rf node_modules && yarn clean-android && yarn clean-ios", + "pods": "cd ios && bundle install && bundle exec pod install" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + }, + "dependencies": { + "@expensify/react-native-wallet": "*", + "react-native-safe-area-context": "^5.5.2" + }, + "devDependencies": { + "@babel/core": "^7.25.2", + "@babel/preset-env": "^7.25.3", + "@babel/runtime": "^7.28.6", + "@react-native-community/cli": "20.0.0", + "@react-native-community/cli-platform-android": "20.0.0", + "@react-native-community/cli-platform-ios": "20.0.0", + "@react-native/babel-preset": "0.81.0", + "@react-native/eslint-config": "0.81.0", + "@react-native/metro-config": "0.81.0", + "@react-native/typescript-config": "0.81.0", + "@types/react": "^19.1.0", + "@types/react-test-renderer": "^19.1.0", + "babel-jest": "^29.6.3", + "babel-plugin-module-resolver": "^5.0.0", + "eslint": "^8.19.0", + "jest": "^29.6.3", + "prettier": "2.8.8", + "react-test-renderer": "19.0.0", + "typescript": "5.8.3" + }, + "engines": { + "node": ">=18" + } +} diff --git a/example/src/CONST.ts b/apps/common-app/src/CONST.ts similarity index 87% rename from example/src/CONST.ts rename to apps/common-app/src/CONST.ts index 34bb1a7..8752ef1 100644 --- a/example/src/CONST.ts +++ b/apps/common-app/src/CONST.ts @@ -1,10 +1,4 @@ -import type { - AndroidCardData, - UserAddress, - IOSEncryptPayload, - IOSCardData, - AndroidResumeCardData, -} from '../../src/NativeWallet'; +import type {AndroidCardData, UserAddress, IOSEncryptPayload, IOSCardData, AndroidResumeCardData} from '@expensify/react-native-wallet/src/NativeWallet'; const dummyAddress: UserAddress = { name: 'John Doe', diff --git a/example/src/LabeledButton.tsx b/apps/common-app/src/LabeledButton.tsx similarity index 77% rename from example/src/LabeledButton.tsx rename to apps/common-app/src/LabeledButton.tsx index 92b0a74..53082af 100644 --- a/example/src/LabeledButton.tsx +++ b/apps/common-app/src/LabeledButton.tsx @@ -8,18 +8,16 @@ type LabelProps = { onPress?: () => void; }; -export default function LabeledButton({ - text, - value, - buttonTitle, - onPress, -}: LabelProps) { +export default function LabeledButton({text, value, buttonTitle, onPress}: LabelProps) { return ( {text} {value || '-'} -