Skip to content

✨ app: wallet provisioning#956

Draft
aguxez wants to merge 8 commits intomainfrom
provisioning
Draft

✨ app: wallet provisioning#956
aguxez wants to merge 8 commits intomainfrom
provisioning

Conversation

@aguxez
Copy link
Copy Markdown
Contributor

@aguxez aguxez commented Apr 15, 2026

Closes #154

Summary by CodeRabbit

  • New Features

    • Added native wallet provisioning functionality enabling users to seamlessly add payment cards to Apple Pay and Google Pay wallets directly from the app with real-time eligibility detection and loading feedback during the provisioning process.
  • Chores

    • Updated dependencies and npm registry configuration to support the new wallet provisioning features and infrastructure.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 15, 2026

🦋 Changeset detected

Latest commit: 601a6ee

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

Warning

Rate limit exceeded

@aguxez has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 12 minutes and 18 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c7e23b26-c136-4b18-9883-fdff9a074c73

📥 Commits

Reviewing files that changed from the base of the PR and between 8b193ec and 601a6ee.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • src/assets/images/google-wallet-button.svg is excluded by !**/*.svg
📒 Files selected for processing (18)
  • .changeset/chilly-suns-dress.md
  • .changeset/gentle-cases-fold.md
  • .changeset/rich-months-double.md
  • .npmrc
  • app.config.ts
  • cspell.json
  • package.json
  • patches/@meawallet__react-native-mpp.patch
  • server/api/card.ts
  • server/test/api/card.test.ts
  • server/test/e2e.ts
  • server/utils/panda.ts
  • src/assets/mea_config
  • src/components/card/CardDetails.tsx
  • src/components/card/WalletButtons.tsx
  • src/components/card/WalletButtons.web.tsx
  • src/components/card/useWalletProvisioning.ts
  • src/utils/server.ts

Walkthrough

This pull request adds native wallet provisioning support for iOS and Android platforms. It introduces SDK integration via configuration plugins, React Native components for Apple Pay and Google Pay provisioning flows, server-side wallet credential retrieval with processor card details, and corresponding test coverage with necessary dependency and build configuration updates.

Changes

Cohort / File(s) Summary
Configuration & Dependency Management
.changeset/gentle-cases-fold.md, .changeset/rich-months-double.md, .changeset/chilly-suns-dress.md, .npmrc, cspell.json, package.json, patches/@meawallet__react-native-mpp.patch
Added Changesets entries for patch releases; configured npm registry routing for @meawallet scope to Nexus; added @meawallet/react-native-mpp dependency with patched CocoaPods configuration requiring React-RCTAppDelegate; updated overrides for TypeScript ESLint and ESLint plugin versions.
Mobile App Configuration
app.config.ts
Added iOS entitlements for payment-pass provisioning and three inline Expo config plugins: (1) copy mea_config assets to Android and iOS, (2) inject Meawallet Nexus Maven repository into Android build.gradle with credentials, (3) patch iOS Podfile with React-RCTAppDelegate headers and Swift flags for meawallet-react-native-mpp target.
Mobile Wallet Components
src/components/card/CardDetails.tsx, src/components/card/WalletButtons.tsx, src/components/card/WalletButtons.web.tsx, src/components/card/useWalletProvisioning.ts
Refactored CardDetails to remove dismissible alert state; introduced WalletButtons component that conditionally renders Apple Pay and Google Pay buttons using eligibility from new useWalletProvisioning hook; hook manages SDK initialization, wallet eligibility detection, and card provisioning operations with promise-based error handling.
Server Wallet Credential Retrieval
src/utils/server.ts, server/utils/panda.ts
Added getWalletCredentials to fetch wallet endpoint data; introduced getProcessorDetails(cardId) utility to retrieve processor card details from Panda API including processorCardId and timeBasedSecret.
Server API & Provisioning Endpoint
server/api/card.ts
Extended GET / endpoint to accept optional scope=provisioning parameter; enriched CardResponse with optional provisioning object containing processor card data; added processor-details fetching and error handling for stale cards (404); updated Sentry instrumentation for provisioning-specific failure modes; set Cache-Control: no-store for provisioning responses.
Test Coverage
server/test/api/card.test.ts, server/test/e2e.ts
Added comprehensive provisioning tests covering stale-card errors, user approval checks, processor-detail failures, and success paths; mocked panda.getProcessorDetails in e2e test utilities; tightened response assertions including cache headers and JSON payload validation.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CardDetails as CardDetails Component
    participant WalletButtons as WalletButtons Component
    participant useWalletProvisioning as useWalletProvisioning Hook
    participant MeaPushSDK as MeaPushProvisioning SDK
    participant Backend as Backend Server
    participant ApplePay as Apple Pay / Google Pay
    
    User->>CardDetails: View card details
    CardDetails->>WalletButtons: Render with card data (lastFour, displayName)
    WalletButtons->>useWalletProvisioning: Query wallet eligibility & state
    useWalletProvisioning->>MeaPushSDK: Initialize SDK (cached)
    MeaPushSDK->>Backend: Check Apple Pay capabilities & Google Pay availability
    Backend-->>useWalletProvisioning: Return eligibility (eligible.apple, eligible.google)
    WalletButtons->>User: Display Apple/Google Pay buttons (if eligible)
    
    User->>WalletButtons: Tap Add to Wallet button
    WalletButtons->>useWalletProvisioning: Call addToAppleWallet() or addToGoogleWallet()
    useWalletProvisioning->>Backend: getWalletCredentials() → Fetch card wallet data
    Backend->>Backend: Get processor details via Panda API
    Backend-->>useWalletProvisioning: Return credentials & processor details (with timeBasedSecret)
    useWalletProvisioning->>MeaPushSDK: Build MppCardDataParameters with credentials
    useWalletProvisioning->>ApplePay: Trigger OEM tokenization & presentation or push card to Google Pay
    ApplePay-->>User: Display payment pass provisioning dialog
    User->>ApplePay: Confirm addition to wallet
    ApplePay-->>useWalletProvisioning: Success
    useWalletProvisioning->>WalletButtons: Update provisioning state
    WalletButtons->>User: Show success or reset UI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Possibly related PRs

  • PR#794: Modifies server-side panda integration and error/telemetry utilities that are invoked by the new provisioning-flow processor-details retrieval and error reporting paths.
  • PR#791: Updates server/api/card.ts with error-handling and response-generation logic that overlaps with provisioning-scope CardResponse changes and GET endpoint modifications.

Suggested reviewers

  • dieguezguille
  • franm91
  • nfmelendez
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title '✨ app: wallet provisioning' is clear and directly summarizes the main feature being added - native wallet provisioning functionality across app and server packages.
Linked Issues check ✅ Passed The PR description indicates it closes issue #154 (ui: push provisioning). The changeset includes comprehensive implementation of wallet provisioning features including native components, hooks, server endpoints, and credential handling.
Out of Scope Changes check ✅ Passed All changes are directly related to wallet provisioning: new wallet components, provisioning hooks, API endpoints, dependencies, and configuration. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch provisioning

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 12 minutes and 18 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces native wallet provisioning for Apple Pay and Google Pay using the MeaWallet SDK. The implementation includes new UI components, a custom hook for provisioning logic, and Expo config plugins to manage native assets and build-time configurations. Feedback highlights a security risk regarding hardcoded credentials in the .npmrc file and points out the fragility of using regex-based string replacements for modifying build.gradle and Podfile, which could lead to silent failures during the build process.

Comment thread .npmrc
Comment thread app.config.ts Outdated
Comment thread app.config.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 57f13078-e054-43d7-ac63-6fce08240922

📥 Commits

Reviewing files that changed from the base of the PR and between 2f6644b and 8417b1d.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • src/assets/images/google-wallet-button.svg is excluded by !**/*.svg
📒 Files selected for processing (15)
  • .changeset/gentle-cases-fold.md
  • .changeset/rich-months-double.md
  • .npmrc
  • app.config.ts
  • babel.config.js
  • common/eslint/base.mjs
  • cspell.json
  • package.json
  • patches/@meawallet__react-native-mpp.patch
  • src/assets/mea_config
  • src/components/card/CardDetails.tsx
  • src/components/card/WalletButtons.tsx
  • src/components/card/WalletButtons.web.tsx
  • src/components/card/useWalletProvisioning.ts
  • src/utils/server.ts

Comment thread .npmrc
Comment thread app.config.ts
Comment thread common/eslint/base.mjs Outdated
@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 15, 2026

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
705 2 703 1
View the top 2 failed test(s) by shortest run time
test/api/card.test.ts > authenticated > returns 500 when provisioning reports unexpected error
Stack Traces | 0.00956s run time
AssertionError: expected "vi.fn()" to not be called at all, but actually been called 1 times

Received:

  1st vi.fn() call:

    Array [
      [Sardine401: 401],
      Object {
        "level": "error",
      },
    ]


Number of calls: 1

 ❯ test/api/card.test.ts:1000:34
web::web
Stack Traces | 401s run time
Assertion is false: "Manually add your card to Apple Pay & Google Pay to make contactless payments." is visible

To view more test analytics, go to the Prevent Tests Dashboard

@aguxez aguxez force-pushed the provisioning branch 2 times, most recently from 42eb9ec to 235b158 Compare April 15, 2026 11:27
@aguxez aguxez changed the title wallet provisioning app: wallet provisioning Apr 15, 2026
@aguxez aguxez force-pushed the server-provisioning branch 3 times, most recently from b49e535 to 1cf381c Compare April 21, 2026 14:40
@aguxez aguxez changed the base branch from server-provisioning to main April 21, 2026 14:40
@cruzdanilo cruzdanilo changed the title app: wallet provisioning ✨ app: wallet provisioning Apr 27, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0ef42f30-9abb-400b-ba0a-92db897d922d

📥 Commits

Reviewing files that changed from the base of the PR and between 8417b1d and 8b193ec.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • src/assets/images/google-wallet-button.svg is excluded by !**/*.svg
📒 Files selected for processing (18)
  • .changeset/chilly-suns-dress.md
  • .changeset/gentle-cases-fold.md
  • .changeset/rich-months-double.md
  • .npmrc
  • app.config.ts
  • cspell.json
  • package.json
  • patches/@meawallet__react-native-mpp.patch
  • server/api/card.ts
  • server/test/api/card.test.ts
  • server/test/e2e.ts
  • server/utils/panda.ts
  • src/assets/mea_config
  • src/components/card/CardDetails.tsx
  • src/components/card/WalletButtons.tsx
  • src/components/card/WalletButtons.web.tsx
  • src/components/card/useWalletProvisioning.ts
  • src/utils/server.ts

Comment thread app.config.ts
Comment on lines +152 to +173
((config) =>
withDangerousMod(config, [
"android",
(c) => {
const buildGradle = path.join(c.modRequest.projectRoot, "android/build.gradle");
const meaRepo = ` maven {
url "https://nexus.ext.meawallet.com/repository/mpp-android-group/"
credentials {
username = "${env.MEAWALLET_ANDROID_USER}"
password = "${env.MEAWALLET_ANDROID_PASS}"
}
}`;
const contents = readFileSync(buildGradle, "utf8");
if (!contents.includes("nexus.ext.meawallet.com")) {
const replaced = contents.replace(/(allprojects[\s\S]*?repositories\s*\{)/, `$1\n${meaRepo}`); // cspell:ignore allprojects
if (replaced === contents)
throw new Error("meawallet: failed to inject maven repo into android/build.gradle");
writeFileSync(buildGradle, replaced);
}
return c;
},
])) satisfies ConfigPlugin,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if these env vars are documented anywhere
rg -i "MEAWALLET_ANDROID" --type=md --type=yaml

Repository: exactly/exa

Length of output: 37


🏁 Script executed:

#!/bin/bash
# Search for MEAWALLET_ANDROID in all files (not just md/yaml)
echo "=== All references to MEAWALLET_ANDROID ==="
rg "MEAWALLET_ANDROID" --max-count=20

echo -e "\n=== Looking for .env files ==="
fd -e env -e example -e sample

echo -e "\n=== Check README and docs ==="
fd -i readme
fd -type f -path '*/docs/*' | head -20

Repository: exactly/exa

Length of output: 491


🏁 Script executed:

#!/bin/bash
# Check README content
echo "=== README.md content ==="
cat README.md

echo -e "\n=== Looking for CI/CD config files ==="
fd -type f -path '*/.github/*'
fd -type f -name '*.yml' -o -name '*.yaml'

echo -e "\n=== Looking for setup/docs files ==="
find . -type f \( -name 'SETUP*' -o -name 'setup*' -o -name '.env*' \) | head -20

Repository: exactly/exa

Length of output: 1728


🏁 Script executed:

#!/bin/bash
# Final check for CI workflows and any remaining setup docs
echo "=== Searching for workflow files ==="
find . -type f \( -name '*.workflow' -o -name '*.yml' -o -name '*.yaml' \) 2>/dev/null | grep -E '(workflow|ci|github|build)' || echo "No workflow files found"

echo -e "\n=== Check if env vars are referenced in package.json or scripts ==="
rg "MEAWALLET" --type json --type sh

Repository: exactly/exa

Length of output: 739


🏁 Script executed:

#!/bin/bash
echo "=== mobile-beta.yaml ==="
cat ./.github/workflows/mobile-beta.yaml

echo -e "\n=== mobile-expo.yaml ==="
cat ./.github/workflows/mobile-expo.yaml

echo -e "\n=== mobile-production.yaml ==="
cat ./.github/workflows/mobile-production.yaml

Repository: exactly/exa

Length of output: 3859


Document MEAWALLET_ANDROID_USER and MEAWALLET_ANDROID_PASS in CI workflows and README.

These Maven credentials are injected into the Android build but are not documented in CI configuration or setup docs. Add these to the mobile workflow files (.github/workflows/mobile-*.yaml) and the README's development setup section to prevent build failures.

Comment thread cspell.json
"mainqueg",
"mateo-soso",
"mdpi",
"meawallet",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check how many times and in how many files "meawallet" appears.
# Expected: Should appear in multiple files across the codebase to justify global dictionary entry.

echo "=== Files containing 'meawallet' (case-insensitive) ==="
rg -i --files-with-matches 'meawallet'

echo -e "\n=== Total occurrences with context ==="
rg -i -C2 'meawallet'

echo -e "\n=== Summary ==="
echo "Total files: $(rg -i --files-with-matches 'meawallet' | wc -l)"
echo "Total occurrences: $(rg -i 'meawallet' | wc -l)"

Repository: exactly/exa

Length of output: 6095


Remove "meawallet" from the dictionary and use inline cspell:ignore annotations instead.

The term appears only as package imports in 2 source files. Per the learning guidance, one-off or limited occurrences should use inline cspell:ignore annotations on the same line as the unknown word—not pollute the global dictionary. Place cspell:ignore on the two import lines in src/components/card/useWalletProvisioning.ts and src/components/card/WalletButtons.tsx, then remove "meawallet" from this file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ui: push provisioning

1 participant