### Start Metro Server for Example App Source: https://github.com/expensify/react-native-wallet/blob/main/CONTRIBUTING.md Starts the Metro bundler to serve the example application. Changes to JavaScript code will be reflected without a rebuild. ```sh npm run example start ``` -------------------------------- ### Run Example App on iOS Source: https://github.com/expensify/react-native-wallet/blob/main/CONTRIBUTING.md Builds and runs the example application on an iOS simulator or device. ```sh npm run example ios ``` -------------------------------- ### Initialize on App Start Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Example of checking wallet availability when the app starts using useEffect. Sets a state variable based on availability. ```typescript import { checkWalletAvailability } from '@expensify/react-native-wallet' useEffect(() => { checkWalletAvailability() .then(available => setWalletReady(available)) .catch(err => console.error(err)) }, []) ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/expensify/react-native-wallet/blob/main/apps/basic-example/README.md Run this command from the repository root to install all necessary project dependencies. ```bash npm install ``` -------------------------------- ### Setup iOS Project for New Architecture Source: https://github.com/expensify/react-native-wallet/blob/main/CONTRIBUTING.md Installs bundler dependencies and CocoaPods for the iOS project, enabling the new architecture. ```sh cd example/ios && bundler install && RCT_NEW_ARCH_ENABLED=1 bundler exec pod install npm run example ios ``` -------------------------------- ### Run Example App on Android Source: https://github.com/expensify/react-native-wallet/blob/main/CONTRIBUTING.md Builds and runs the example application on an Android device or emulator. ```sh npm run example android ``` -------------------------------- ### Install react-native-wallet Package Source: https://github.com/expensify/react-native-wallet/blob/main/README.md Install the react-native-wallet package using npm or yarn after completing the initial project setup. ```sh npm install @expensify/react-native-wallet ``` ```sh yarn add @expensify/react-native-wallet ``` -------------------------------- ### Example UserAddress Object Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Provides an example of how to construct a `UserAddress` object for Android provisioning. Ensure all required fields are populated correctly. ```typescript const address: UserAddress = { name: 'John Doe', addressOne: '123 Main Street', addressTwo: 'Suite 450', administrativeArea: 'CA', locality: 'San Francisco', countryCode: 'US', postalCode: '94102', phoneNumber: '+1-555-123-4567', }; ``` -------------------------------- ### Install iOS Dependencies Source: https://github.com/expensify/react-native-wallet/blob/main/apps/basic-example/README.md Navigate to the 'ios' directory and run this command to install iOS-specific dependencies using CocoaPods. ```bash cd ios pod install cd .. ``` -------------------------------- ### Resume Google Wallet Provisioning Example Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Demonstrates how to use `resumeAddCardToGoogleWallet` with `AndroidResumeCardData`. Requires prior token retrieval. ```typescript import { resumeAddCardToGoogleWallet, listTokens } from '@expensify/react-native-wallet'; import type { AndroidResumeCardData } from '@expensify/react-native-wallet'; const tokens = await listTokens(); const token = tokens[0]; // Get first token const resumeData: AndroidResumeCardData = { network: 'VISA', tokenReferenceID: token.identifier, cardHolderName: 'John Doe', lastDigits: '4321', }; const result = await resumeAddCardToGoogleWallet(resumeData); ``` -------------------------------- ### API Reference Examples Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/00-MANIFEST.txt Examples for various API functions are available in the API reference documentation. ```javascript checkWalletAvailability() getSecureWalletInfo() getCardStatusBySuffix() getCardStatusByIdentifier() addCardToGoogleWallet() resumeAddCardToGoogleWallet() listTokens() addCardToAppleWallet() addListener() removeListener() ``` -------------------------------- ### Run Example App on Android with New Architecture Source: https://github.com/expensify/react-native-wallet/blob/main/CONTRIBUTING.md Enables the new architecture for the Android build by setting the ORG_GRADLE_PROJECT_newArchEnabled environment variable. ```sh ORG_GRADLE_PROJECT_newArchEnabled=true npm run example android ``` -------------------------------- ### Android Package Name and Fingerprint Example Source: https://github.com/expensify/react-native-wallet/blob/main/README.md Example format for your app's package name and SHA-256 fingerprint required for Google Wallet SDK whitelisting. ```text Package name: com.app.package.name Fingerprint: SHA256: 36:38:63:59:6E:...:00:82:16:4E:FF ``` -------------------------------- ### Install Native Dependencies (iOS) Source: https://github.com/expensify/react-native-wallet/blob/main/apps/expo-example/README.md Navigates to the `ios` directory, installs CocoaPods dependencies, and returns to the project root. This is necessary for resolving native module issues on iOS. ```bash # iOS cd ios && pod install && cd .. ``` -------------------------------- ### Start Metro Bundler Source: https://github.com/expensify/react-native-wallet/blob/main/apps/basic-example/README.md Starts the Metro bundler, which is essential for running the React Native application. ```bash npm start ``` -------------------------------- ### Safe Card Provisioning with Error Handling (Android) Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/07-integration-patterns.md Provides a robust method for provisioning cards on Android, including prerequisite checks for wallet availability and comprehensive error handling with user-friendly alerts for various failure scenarios. This function guides the user through setup or recovery steps. ```typescript import { checkWalletAvailability, addCardToGoogleWallet } from '@expensify/react-native-wallet'; import type { AndroidCardData } from '@expensify/react-native-wallet'; import { Alert } from 'react-native'; async function safeProvisionCard(cardData: AndroidCardData) { try { // Prerequisite check const isAvailable = await checkWalletAvailability(); if (!isAvailable) { Alert.alert('Setup Required', 'Please install or enable Google Wallet'); return; } // Main provisioning const result = await addCardToGoogleWallet(cardData); switch (result) { case 'success': Alert.alert('Success', 'Card added to wallet'); break; case 'canceled': console.log('User canceled'); break; case 'error': Alert.alert('Error', 'Card provisioning failed. Please try again.'); break; } } catch (error) { if (error instanceof Error) { if (error.message.includes('Failed to load Wallet module')) { Alert.alert('Installation Error', 'React Native Wallet not properly installed. Please reinstall the app.'); } else if (error.message.includes('Wallet could not be initialized')) { Alert.alert('Wallet Error', 'Unable to initialize Google Wallet. Please restart your device.'); } else { Alert.alert('Error', error.message); } } } } ``` -------------------------------- ### Example Usage of TokenInfo Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Demonstrates how to iterate through a list of tokens and access their properties. It also shows how to use the token identifier to check card status. ```typescript const tokens = await listTokens(); tokens.forEach(token => { console.log(`Token ID: ${token.identifier}`); console.log(`Card: ****${token.lastDigits}`); console.log(`State: ${token.tokenState}`); // Use identifier for status checks const status = await getCardStatusByIdentifier(token.identifier, 'VISA'); }); ``` -------------------------------- ### Issuer Encrypt Payload Callback Example Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md An example implementation of the callback function for `addCardToAppleWallet` that handles nonce, nonce signature, and certificates to encrypt payload for the issuer. ```typescript const issuerEncryptPayloadCallback = async ( nonce: string, nonceSignature: string, certificate: string[] ): Promise => { // nonce, nonceSignature, certificate come from IOSAddPaymentPassData const response = await fetch('https://api.issuer.com/encrypt', { method: 'POST', body: JSON.stringify({ nonce, nonceSignature, certificate }), }); return response.json(); }; ``` -------------------------------- ### Example Usage of AndroidWalletData Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Demonstrates how to obtain and use `AndroidWalletData` for backend communication. The `deviceID` and `walletAccountID` are sent to the backend. ```typescript const walletInfo = await getSecureWalletInfo(); // Send to backend: // POST /api/card-provisioning/initialize // { deviceID: "...", walletAccountID: "..." } ``` -------------------------------- ### Add Card to Google Wallet Example Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Demonstrates how to use the `addCardToGoogleWallet` function with a fully populated `AndroidCardData` object. Ensure the OPC is obtained securely from the issuer backend. ```typescript import { addCardToGoogleWallet } from '@expensify/react-native-wallet'; import type { AndroidCardData } from '@expensify/react-native-wallet'; const cardData: AndroidCardData = { network: 'VISA', opaquePaymentCard: 'base64EncodedOPCFromBackend', cardHolderName: 'John Doe', lastDigits: '4321', userAddress: { name: 'John Doe', addressOne: '123 Main St', addressTwo: '', administrativeArea: 'CA', locality: 'San Francisco', countryCode: 'US', postalCode: '94102', phoneNumber: '+1-555-123-4567', }, }; const result = await addCardToGoogleWallet(cardData); ``` -------------------------------- ### Clean and Rebuild Project Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Commands to clean the project, reinstall dependencies, install pods for iOS, and restart the Metro bundler with cache reset. Useful for resolving module linking issues. ```bash # Clean and rebuild npm run clean npm install cd ios && pod install && cd .. npm start -- --reset-cache ``` -------------------------------- ### Integration Patterns Examples Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/00-MANIFEST.txt Twelve complete, ready-to-use code patterns are provided for various integration scenarios, including check-then-add flow, conditional rendering by status, Android add-with-resume, iOS issuer encryption callback, event listener management, error handling strategies, custom button integration, form validation, and analytics/logging. ```javascript Check-then-add flow Conditional rendering by status Android add-with-resume iOS issuer encryption callback Event listener management Error handling strategies Custom button integration Form validation Analytics and logging ``` -------------------------------- ### Add Card to Apple Wallet Example Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Shows how to use `addCardToAppleWallet` with `IOSCardData`. The issuer encrypt payload callback is required for nonce and signature handling. ```typescript import { addCardToAppleWallet } from '@expensify/react-native-wallet'; import type { IOSCardData } from '@expensify/react-native-wallet'; const cardData: IOSCardData = { network: 'VISA', cardHolderName: 'John Doe', lastDigits: '4321', cardDescription: 'Personal Visa', }; await addCardToAppleWallet(cardData, issuerEncryptPayloadCallback); ``` -------------------------------- ### CodeGen Configuration in package.json Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/06-native-module.md Example of the codegenConfig object within package.json. This configures the Turbo module specification, including its name, source directory, and platform-specific settings. ```json { "codegenConfig": { "name": "RNWalletSpec", "type": "all", "jsSrcsDir": "src", "android": { "javaPackageName": "com.expensify.wallet" } } } ``` -------------------------------- ### Handle Wallet Initialization Error Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/05-errors.md Catch and log errors indicating that the Google Wallet SDK failed to initialize. This might prompt the user to install or enable Google Pay. ```typescript try { const walletInfo = await getSecureWalletInfo(); } catch (error) { if (error instanceof Error && error.message === 'Wallet could not be initialized') { // Google Pay not available on this device console.log('Google Wallet not available'); // Show UI prompt to install/enable Google Pay } } ``` -------------------------------- ### Tokenization Status Check Example Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Illustrates how to handle the result of adding a card to Google Wallet using the TokenizationStatus type. Differentiates between successful addition, user cancellation, and general errors. ```typescript const result = await addCardToGoogleWallet(cardData); if (result === 'success') { // Show success message Alert.alert('Success', 'Card added to Google Wallet'); } else if (result === 'canceled') { // User dismissed the flow Alert.alert('Canceled', 'Card provisioning was canceled'); } else { // Provisioning error (OPC invalid, network error, etc.) Alert.alert('Error', 'Failed to provision card'); } ``` -------------------------------- ### Track Provisioning Events with Analytics Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/07-integration-patterns.md Implement this pattern to log card provisioning events for analytics purposes. It tracks the start, completion, and errors of the provisioning process, including duration and card network. ```typescript import { addCardToGoogleWallet, addListener, removeListener } from '@expensify/react-native-wallet'; import type { AndroidCardData, TokenizationStatus } from '@expensify/react-native-wallet'; // Analytics service const analyticsService = { logEvent: (eventName: string, properties?: Record) => { console.log(`Analytics: ${eventName}`, properties); // Send to analytics platform (Segment, Amplitude, etc.) }, }; async function provisionCardWithAnalytics(cardData: AndroidCardData) { const startTime = Date.now(); analyticsService.logEvent('card_provisioning_started', { cardNetwork: cardData.network, timestamp: new Date().toISOString(), }); try { const result = await addCardToGoogleWallet(cardData); const duration = Date.now() - startTime; analyticsService.logEvent('card_provisioning_completed', { result, duration, cardNetwork: cardData.network, }); return result; } catch (error) { const duration = Date.now() - startTime; analyticsService.logEvent('card_provisioning_error', { error: error instanceof Error ? error.message : String(error), duration, cardNetwork: cardData.network, }); throw error; } } // Also log activation events export function setupActivationLogging() { const subscription = addListener('onCardActivated', (data) => { analyticsService.logEvent('card_activated', { tokenId: data.tokenId, status: data.status, }); }); return () => removeListener(subscription); } ``` -------------------------------- ### GitHub Actions CI/CD Pipeline Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Defines the CI/CD workflow for building both Android and iOS applications using GitHub Actions. It includes steps for checking out code, setting up Node.js, installing dependencies, and running build commands. ```yaml # .github/workflows/build.yml name: Build on: push: branches: [main] jobs: build-android: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: '18' - run: npm install - run: cd android && ./gradlew assembleRelease env: KEYSTORE_PATH: ${{ secrets.ANDROID_KEYSTORE_PATH }} KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} build-ios: runs-on: macos-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: '18' - run: npm install - run: cd ios && pod install && cd .. - run: xcodebuild -scheme YourApp -configuration Release ``` -------------------------------- ### Project File Structure Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Overview of the project's directory structure, highlighting the entry point, native module bridge, React component, and utility files. ```text src/ ├── index.tsx ← Entry point, public API ├── NativeWallet.ts ← Native module bridge ├── AddToWalletButton.tsx ← React component └── utils.ts ← Status code mappers ``` -------------------------------- ### Module Initialization Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/06-native-module.md Loads the native Wallet module using TurboModuleRegistry.getEnforcing. Includes error handling to prevent app crashes if the module is not found and exports the module reference and package name. ```APIDOC ## Module Initialization ### Description Loads the native Wallet module using `TurboModuleRegistry.getEnforcing`. Includes error handling to prevent app crashes if the module is not found and exports the module reference and package name. ### Code ```typescript import { TurboModuleRegistry } from 'react-native'; let Wallet: Spec | undefined; try { Wallet = TurboModuleRegistry.getEnforcing('RNWallet'); } catch (error) { console.warn(`[@expensify/react-native-wallet] Failed to load Wallet module, ${error.message}`); } export default Wallet; export const PACKAGE_NAME = '@expensify/react-native-wallet'; ``` ``` -------------------------------- ### Initialize Wallet Turbo Module Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/06-native-module.md Loads the Wallet Turbo Module using `TurboModuleRegistry.getEnforcing`. Includes error handling to prevent app crashes if the module is not linked and exports the module reference and package name. ```typescript import { TurboModuleRegistry } from 'react-native'; let Wallet: Spec | undefined; try { Wallet = TurboModuleRegistry.getEnforcing('RNWallet'); } catch (error) { console.warn(`[@expensify/react-native-wallet] Failed to load Wallet module, ${error.message}`); } export default Wallet; export const PACKAGE_NAME = '@expensify/react-native-wallet'; ``` -------------------------------- ### Issuer Encrypt Payload Callback Example Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md An example of a callback function that fetches encrypted payload data from an issuer backend. Ensure all fields in the returned object are base64-encoded. ```typescript const issuerEncryptPayloadCallback = async ( nonce: string, nonceSignature: string, certificate: string[] ): Promise => { const response = await fetch('https://api.issuer.com/encrypt-apple', { method: 'POST', body: JSON.stringify({ nonce, nonceSignature, certificate }), }); const encrypted: IOSEncryptPayload = await response.json(); return encrypted; // Must include: // { // encryptedPassData: "base64...", // activationData: "base64...", // ephemeralPublicKey: "base64..." // } }; ``` -------------------------------- ### Check Wallet Availability at Runtime Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Import and call the `checkWalletAvailability` function to determine if the wallet is ready for provisioning. This should be done once at app startup. ```typescript import { checkWalletAvailability } from '@expensify/react-native-wallet'; // Check if wallet is available (should be done once at app startup) checkWalletAvailability() .then(available => { if (available) { console.log('Wallet ready for provisioning'); } else { console.log('Wallet not available'); } }) .catch(error => console.error('Wallet check failed:', error)); ``` -------------------------------- ### Wallet Data and Configuration Source: https://github.com/expensify/react-native-wallet/blob/main/README.md Information on entitlements, installation, and Expo plugin configuration for react-native-wallet. ```APIDOC ## Project Setup for react-native-wallet ### Entitlements To enable In-App Provisioning for Apple Pay, add the `com.apple.developer.payment-pass-provisioning` entitlement to your project's `.entitlements` file. ```xml ... com.apple.developer.payment-pass-provisioning ``` ### Installation Install the package using npm or yarn: ```sh npm install @expensify/react-native-wallet ``` ```sh yarn add @expensify/react-native-wallet ``` ### Expo Plugin Configuration For Expo projects, configure the plugin in your `app.json` file: ```json { "expo": { "plugins": [ [ "@expensify/react-native-wallet", { "enableApplePayProvisioning": true, "googleTapAndPaySdkPath": "./libs/tapandpay-v18.7.0.zip" } ] ] } } ``` After configuration, rebuild your app: ```bash npx expo prebuild --clean npx expo run:ios npx expo run:android ``` ### Required Data **Android Specific:** * **Opaque Payment Card (OPC):** Binary data for Google Pay from the issuer app. * **Token Service Provider (TSP):** Service that replaces card numbers with tokens (e.g., Visa, MasterCard). * **Token Reference ID:** Unique ID for a DPAN, assigned by the Token Provider. **iOS Specific:** * **Nonce:** One-time nonce value from Apple's servers. * **Nonce Signature:** Device-specific signature for the nonce. * **Certificates:** Array of DER encoded X.509 certificates (leaf first, root last). * **Encrypted Pass Data:** Base64 encoded JSON with sensitive information for Apple Pay. * **Ephemeral Public Key:** Base64 encoded key for ECC. ``` -------------------------------- ### Get Card Status by Suffix Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Retrieves the status of a card using its last 4 digits. ```typescript getCardStatusBySuffix(last4Digits: string): Promise ``` -------------------------------- ### Create Android Libs Directory Source: https://github.com/expensify/react-native-wallet/blob/main/apps/basic-example/README.md This command creates the 'libs' directory within the 'android' folder if it does not already exist, which is necessary for storing the Google TapAndPay SDK. ```bash # Create the libs directory if it doesn't exist mkdir -p android/libs ``` -------------------------------- ### Get Secure Wallet Info Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Retrieves secure wallet information for the device. This function is only supported on Android. ```APIDOC ## getSecureWalletInfo() ### Description Retrieves secure wallet information for the device. This function is only supported on Android. ### Method `getSecureWalletInfo(): Promise` ### Parameters None ### Response #### Success Response - **AndroidWalletData**: An object containing `deviceID` and `walletAccountID`. - **deviceID** (string) - The device ID. - **walletAccountID** (string) - The wallet account ID. ### Request Example ```typescript import { getSecureWalletInfo } from '@expensify/react-native-wallet' getSecureWalletInfo() .then(info => console.log('Secure wallet info:', info)) .catch(err => console.error('Error getting secure wallet info:', err)) ``` ``` -------------------------------- ### Android Native: Resume Card Provisioning Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/09-data-flow.md Details the native Android steps to resume card provisioning after an interruption. This includes looking up the token, checking activation status, launching the Google Wallet UI, and handling the completion status. ```android ┌────────────────────────────▼────────────────────────────────────────┐ │ Android Native: resumeAddCardToGoogleWallet │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 1. Look up token by reference ID │ │ │ │ 2. Check if token needs activation │ │ │ │ 3. Launch Google Wallet UI for completion │ │ │ │ 4. User confirms and completes activation │ │ │ │ 5. Return status code │ │ │ └──────────────────────────────────────────────────────────────┘ │ └────────────────────────────┬────────────────────────────────────────┘ │ Return TokenizationStatus ``` -------------------------------- ### Get Card Status by Identifier Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Retrieves the status of a card using its identifier (token reference ID or PAI) and TSP. ```typescript getCardStatusByIdentifier(identifier: string, tsp: string): Promise ``` -------------------------------- ### Integrate AddToWalletButton for Card Provisioning Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/04-component-reference.md Demonstrates how to use the AddToWalletButton component to initiate card provisioning for both Google Wallet on Android and Apple Wallet on iOS. Includes handling provisioning states and results. ```typescript import { AddToWalletButton, addCardToGoogleWallet, addCardToAppleWallet } from '@expensify/react-native-wallet'; import type { AndroidCardData, IOSCardData } from '@expensify/react-native-wallet'; function CardDetailsScreen() { const [isProvisioning, setIsProvisioning] = useState(false); const handleProvisioningPress = async () => { setIsProvisioning(true); try { let result; if (Platform.OS === 'android') { result = await addCardToGoogleWallet(androidCardData); } else { result = await addCardToAppleWallet(iosCardData, issuerCallback); } if (result === 'success') { Alert.alert('Success', 'Card added to wallet'); } else if (result === 'canceled') { Alert.alert('Canceled', 'User canceled provisioning'); } else { Alert.alert('Error', 'Failed to provision card'); } } finally { setIsProvisioning(false); } }; return ( {isProvisioning && } ); } ``` -------------------------------- ### Logging Errors with checkWalletAvailability Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/05-errors.md An example of how to wrap `checkWalletAvailability` to log errors to a remote service before re-throwing them. This is crucial for production error monitoring. ```typescript import { checkWalletAvailability } from '@expensify/react-native-wallet'; async function checkWalletWithLogging() { try { return await checkWalletAvailability(); } catch (error) { // Log to remote error tracking service logErrorToService({ error: error instanceof Error ? error.message : String(error), function: 'checkWalletAvailability', timestamp: new Date().toISOString(), platform: Platform.OS, }); throw error; } } ``` -------------------------------- ### Import All Exported Types Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Demonstrates importing all available types from the main library entry point. This is useful for projects that use many types from the wallet library. ```typescript import type { AndroidCardData, AndroidWalletData, CardStatus, IOSEncryptPayload, IOSCardData, IOSAddPaymentPassData, onCardActivatedPayload, TokenizationStatus, TokenInfo, UserAddress, } from '@expensify/react-native-wallet'; ``` -------------------------------- ### Optional Dev Dependencies for TypeScript Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Example of optional development dependencies for TypeScript integration. These are not required for the library to function but can aid in development. ```json { "devDependencies": { "@types/react": "^19.0.0", "@types/react-native": "^0.76.0" } } ``` -------------------------------- ### Get Tokenization Status Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/09-data-flow.md Maps the result of a tokenization operation to a status string. Returns a Promise that resolves to 'success', 'canceled', or 'error'. ```javascript getTokenizationStatus() ``` -------------------------------- ### checkWalletAvailability Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/02-api-reference.md Checks if the wallet is ready and initializes it if possible. This is a prerequisite call that validates the native module is properly linked and the device is capable of provisioning cards. ```APIDOC ## checkWalletAvailability ### Description Checks if the wallet is ready and initializes it if possible. This is a prerequisite call that validates the native module is properly linked and the device is capable of provisioning cards. ### Method Asynchronous function (Promise) ### Parameters None ### Returns - `Promise`: Resolves to `true` if wallet is available and initialized, `false` otherwise. ### Throws - `Error: Failed to load Wallet module...`: Native module not linked ### Usage Example ```typescript import { checkWalletAvailability } from '@expensify/react-native-wallet'; const handleCheckWallet = async () => { try { const isAvailable = await checkWalletAvailability(); if (isAvailable) { console.log('Wallet is ready for provisioning'); } else { console.log('Wallet is not available on this device'); } } catch (error) { console.error('Wallet check failed:', error); } }; ``` ``` -------------------------------- ### Get Android Certificate Fingerprint using apksigner Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Use the apksigner verify command to retrieve the SHA-256 certificate fingerprint from a release APK. ```bash # Or using apksigner apksigner verify -v app/build/outputs/apk/release/app-release.apk ``` -------------------------------- ### Run iOS App Source: https://github.com/expensify/react-native-wallet/blob/main/apps/basic-example/README.md Builds and runs the iOS application on a simulator or device. ```bash npm run ios ``` -------------------------------- ### Get Card Status by Suffix Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Retrieves the status of a card using its last 4 digits. Requires the last 4 digits of the card number. ```APIDOC ## getCardStatusBySuffix() ### Description Retrieves the status of a card using its last 4 digits. Requires the last 4 digits of the card number. ### Method `getCardStatusBySuffix(last4Digits: string): Promise` ### Parameters #### Query Parameters - **last4Digits** (string) - Required - The last 4 digits of the card number. ### Response #### Success Response - **CardStatus**: The status of the card ('not found', 'active', 'requireActivation', 'pending', 'suspended', 'deactivated'). ### Request Example ```typescript import { getCardStatusBySuffix } from '@expensify/react-native-wallet' getCardStatusBySuffix('1234') .then(status => console.log('Card status:', status)) .catch(err => console.error('Error getting card status:', err)) ``` ``` -------------------------------- ### ensureGoogleWalletInitialized Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/06-native-module.md Initializes the Google Wallet SDK. This method should be called before performing other wallet operations. Returns a promise that resolves to a boolean indicating success or failure. ```APIDOC ## ensureGoogleWalletInitialized ### Description Initializes the Google Wallet SDK. This method should be called before performing other wallet operations. Returns a promise that resolves to a boolean indicating success or failure. ### Signature ```typescript ensureGoogleWalletInitialized(): Promise ``` ### Returns `true` if initialization successful, `false` if failed. ### Implementation Initializes Google Wallet SDK; called before wallet operations. ``` -------------------------------- ### Configure Android Repositories Source: https://github.com/expensify/react-native-wallet/blob/main/README.md Add the local libs directory to your project's repositories in build.gradle to include the Google TapAndPay SDK. ```groovy allprojects { repositories { google() maven { url "file://${rootDir}/libs" } } } ``` -------------------------------- ### Get Android Certificate Fingerprint using keytool Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Use the keytool command to retrieve your Android debug keystore's SHA-256 certificate fingerprint. ```bash # Using keytool keytool -list -v -keystore ~/.android/debug.keystore ``` -------------------------------- ### Run Android App Source: https://github.com/expensify/react-native-wallet/blob/main/apps/basic-example/README.md Builds and runs the Android application on an emulator or device. ```bash npm run android ``` -------------------------------- ### Ensure Google Wallet Initialization Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/06-native-module.md Initializes the Google Wallet SDK. This method should be called before performing other wallet operations. Returns `true` on successful initialization, `false` on failure. ```typescript ensureGoogleWalletInitialized(): Promise ``` -------------------------------- ### Check Wallet Availability Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/02-api-reference.md Verifies if the wallet is ready and initializes it. This is a prerequisite for provisioning cards and ensures the native module is linked and the device is capable. ```typescript import { checkWalletAvailability } from '@expensify/react-native-wallet'; const handleCheckWallet = async () => { try { const isAvailable = await checkWalletAvailability(); if (isAvailable) { console.log('Wallet is ready for provisioning'); } else { console.log('Wallet is not available on this device'); } } catch (error) { console.error('Wallet check failed:', error); } }; ``` -------------------------------- ### Log Wallet State and Tokenization Codes Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Uses utility functions to get human-readable status strings for card states and tokenization results based on numeric codes. ```javascript const { getCardState, getTokenizationStatus } = require('@expensify/react-native-wallet/src/utils') console.log(getCardState(0)) // 'active' console.log(getTokenizationStatus(0)) // 'success' ``` -------------------------------- ### Use AddToWalletButton Component Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/README.md Renders a pre-built button for initiating the wallet provisioning flow. The button can be customized with different types and handles press events. ```typescript import { AddToWalletButton } from '@expensify/react-native-wallet' console.log('Button pressed')} buttonType="basic" /> ``` -------------------------------- ### Get Card Status by Identifier Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Retrieves the status of a card using its token reference ID or PAI. Requires the identifier and TSP (Token Service Provider) identifier. ```APIDOC ## getCardStatusByIdentifier() ### Description Retrieves the status of a card using its token reference ID or PAI. Requires the identifier and TSP (Token Service Provider) identifier. ### Method `getCardStatusByIdentifier(identifier: string, tsp: string): Promise` ### Parameters #### Query Parameters - **identifier** (string) - Required - The token reference ID or PAI of the card. - **tsp** (string) - Required - The Token Service Provider identifier. ### Response #### Success Response - **CardStatus**: The status of the card ('not found', 'active', 'requireActivation', 'pending', 'suspended', 'deactivated'). ### Request Example ```typescript import { getCardStatusByIdentifier } from '@expensify/react-native-wallet' getCardStatusByIdentifier('token_ref_id_123', 'tsp_abc') .then(status => console.log('Card status:', status)) .catch(err => console.error('Error getting card status:', err)) ``` ``` -------------------------------- ### Android Gradle Build with Local SDK Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Commands to clean and assemble a debug build after manually adding the Google Wallet SDK to the `android/libs/` directory. Ensure your `build.gradle` is configured to use this local repository. ```bash ./gradlew clean && ./gradlew assembleDebug ``` -------------------------------- ### Get Android Debug Keystore SHA-256 Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Command to list the SHA-256 fingerprint of your Android debug keystore. This is required for submitting debug fingerprints to Google for development testing. ```bash keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey # Default password: android ``` -------------------------------- ### Expo Clean Build and Run Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Commands for Expo users to clean the project, prebuild, and run on iOS or Android. Useful for resolving module linking issues in Expo managed projects. ```bash # For Expo npx expo prebuild --clean npx expo run:ios npx expo run:android ``` -------------------------------- ### Get Secure Wallet Information Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/06-native-module.md Retrieves secure information from Google Wallet, including the device ID and wallet account ID. Returns an object containing `deviceID` and `walletAccountID`. ```typescript getSecureWalletInfo(): Promise ``` -------------------------------- ### Basic AddToWalletButton Usage Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/04-component-reference.md Demonstrates the default usage of the AddToWalletButton component. Requires importing the component and defining an onPress handler. ```typescript import { AddToWalletButton } from '@expensify/react-native-wallet'; function CardProvisioningScreen() { const handleAddPress = () => { console.log('User pressed Add to Wallet'); // Initiate provisioning flow }; return ( ); } ``` -------------------------------- ### List Provisioned Tokens and Get Status (Android) Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/07-integration-patterns.md Retrieves a list of all provisioned tokens and their activation statuses specifically for Android devices. Ensure the platform is Android before calling these functions. ```typescript import { listTokens, getCardStatusByIdentifier } from '@expensify/react-native-wallet'; import { Platform } from 'react-native'; async function getActivationStatus() { if (Platform.OS !== 'android') { return []; } try { const tokens = await listTokens(); // Get detailed status for each token const statuses = await Promise.all( tokens.map(async (token) => ({ ...token, status: await getCardStatusByIdentifier(token.identifier, 'VISA'), })) ); return statuses; } catch (error) { console.error('Failed to get token statuses:', error); return []; } } ``` -------------------------------- ### Check Wallet Module Loading Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/10-quick-reference.md Verifies if the native Wallet module has been loaded successfully. This is a basic check for module availability. ```typescript import Wallet from '@expensify/react-native-wallet/src/NativeWallet' console.log('Module loaded:', Wallet !== undefined) ``` -------------------------------- ### Get Android Release Keystore SHA-256 Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md Command to list the SHA-256 fingerprint of your Android release keystore. This is required for submitting release fingerprints to Google before Play Store submission. ```bash keytool -list -v -keystore /path/to/release.keystore # Enter keystore password when prompted ``` -------------------------------- ### Publish New Version Source: https://github.com/expensify/react-native-wallet/blob/main/CONTRIBUTING.md Uses release-it to automate the process of bumping versions, creating tags, and publishing new releases to npm. ```sh npm run release ``` -------------------------------- ### Handling Card Activation Events Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Shows how to set up an event listener for card activation status changes. It logs messages based on whether the card was activated or canceled. ```typescript import { addListener, removeListener } from '@expensify/react-native-wallet'; useEffect(() => { const subscription = addListener('onCardActivated', (payload: onCardActivatedPayload) => { const { tokenId, status } = payload; if (status === 'activated') { console.log(`Card ${tokenId} is now active`); // Update card list UI, show success message } else if (status === 'canceled') { console.log(`Card ${tokenId} activation was canceled`); // Update UI, possibly show retry option } }); return () => removeListener(subscription); }, []); ``` -------------------------------- ### Issuer Encryption Callback with Certificate Pinning Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/08-configuration.md An example TypeScript function for handling issuer encryption callbacks. It includes a placeholder for certificate validation and suggests implementing certificate pinning for enhanced security. ```typescript const issuerEncryptPayloadCallback = async ( nonce: string, nonceSignature: string, certificate: string[] ): Promise => { // Validate certificate chain before sending sensitive data // Implement certificate pinning if desired const response = await fetch('https://api.issuer.com/encrypt', { method: 'POST', headers: { 'Content-Type': 'application/json', // Consider adding authentication token 'Authorization': `Bearer ${issuerToken}`, }, body: JSON.stringify({ nonce, nonceSignature, certificate }), }); return response.json(); }; ``` -------------------------------- ### Get Secure Wallet Info Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/02-api-reference.md Retrieves platform-specific wallet information, including device ID and wallet account ID, necessary for secure transactions and backend communication. This function is only available on Android. ```typescript import { getSecureWalletInfo } from '@expensify/react-native-wallet'; const handleGetWalletInfo = async () => { try { const walletInfo = await getSecureWalletInfo(); // Send to backend: {deviceID, walletAccountID} console.log('Device ID:', walletInfo.deviceID); console.log('Wallet Account ID:', walletInfo.walletAccountID); } catch (error) { console.error('Failed to retrieve wallet info:', error); } }; ``` -------------------------------- ### JavaScript: Resume Interrupted Card Provisioning Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/09-data-flow.md Illustrates the JavaScript steps to resume an interrupted card provisioning process. It involves listing tokens, finding a specific token, extracting its identifier, and then calling the resume function. ```javascript ┌─────────────────────────────────────────────────────────────────────┐ │ JavaScript Application │ │ User wants to retry interrupted provisioning │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 1. listTokens() → Get all tokens from wallet │ │ │ │ 2. Find token matching lastDigits: '4321' │ │ │ │ 3. Extract token.identifier (Token Reference ID) │ │ │ │ 4. Call resumeAddCardToGoogleWallet() │ │ │ └──────────────────────────────────────────────────────────────┘ │ └────────────────────────────┬────────────────────────────────────────┘ ``` -------------------------------- ### Get Card Status by Identifier Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/06-native-module.md Queries the status of a token using its reference ID and the Token Service Provider (TSP). Returns a numeric status code. This implementation queries the token status by reference ID. ```typescript getCardStatusByIdentifier(identifier: string, tsp: string): Promise ``` -------------------------------- ### Get Card Status by Suffix Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/06-native-module.md Queries Google Wallet for the status of a card using its last 4 digits. Returns a numeric status code. The implementation queries Google Wallet for card status by suffix. ```typescript getCardStatusBySuffix(last4Digits: string): Promise ``` -------------------------------- ### Troubleshoot Android Build Issues Source: https://github.com/expensify/react-native-wallet/blob/main/apps/basic-example/README.md Executes a clean build command for the Android project to resolve build errors. ```bash cd android ./gradlew clean cd .. ``` -------------------------------- ### Card Status Switch Statement Example Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/03-types.md Demonstrates how to use the CardStatus type to conditionally render UI elements based on the card's current state. Handles various states including 'not found', 'active', 'pending', and 'suspended'. ```typescript const status = await getCardStatusBySuffix('4321'); switch (status) { case 'not found': // Show "Add to Wallet" button break; case 'active': // Show "Manage Card" button break; case 'pending': // Show "Activation Pending" indicator break; case 'suspended': // Show "Card Suspended" message break; default: // Show generic status } ``` -------------------------------- ### Types Source: https://github.com/expensify/react-native-wallet/blob/main/_autodocs/00-MANIFEST.txt Complete type definitions for 9 distinct types used within the library, including platform-specific types (AndroidWalletData, AndroidCardData, UserAddress, IOSCardData, IOSEncryptPayload), status types (CardStatus, TokenizationStatus), and collection types (TokenInfo). Import patterns and examples are also provided. ```APIDOC ## Types This section provides complete definitions for 9 types used throughout the library. ### AndroidWalletData **Description**: Represents wallet data specific to Android. ### AndroidCardData **Description**: Represents card data specific to Android. ### UserAddress **Description**: Represents a user's address. ### IOSCardData **Description**: Represents card data specific to iOS. ### IOSEncryptPayload **Description**: Represents the payload for encryption on iOS. ### CardStatus **Description**: Represents the status of a card. ### TokenizationStatus **Description**: Represents the status of tokenization. ### TokenInfo **Description**: Contains information about a token. ```