Skip to content

feat(mobile): Plaid Link SDK cutover for Bridge external accounts [ENG-524]#668

Draft
islandbitcoin wants to merge 1 commit into
mainfrom
jabariennis/eng-524-featmobile-plaid-link-sdk-cutover-linktoken
Draft

feat(mobile): Plaid Link SDK cutover for Bridge external accounts [ENG-524]#668
islandbitcoin wants to merge 1 commit into
mainfrom
jabariennis/eng-524-featmobile-plaid-link-sdk-cutover-linktoken

Conversation

@islandbitcoin

Copy link
Copy Markdown
Contributor

Why

Client side of backend PR lnflash/flash#446, which replaced the hosted Bridge Plaid linkUrl webview with the Plaid Link SDK + server-side public_token exchange (the Api-Key never leaves the backend). Closes ENG-524.

Backend contract after #446:

  • bridgeAddExternalAccount now returns linkToken: String! (+ existing expiresAt); linkUrl is now nullable and @deprecated.
  • New mutation bridgeExchangePlaidPublicToken(input: { linkToken, publicToken }): { errors, message }.
  • New error codes BRIDGE_INVALID_PLAID_TOKEN, BRIDGE_PLAID_NOT_AVAILABLE.

What changed

  • Dependency: add react-native-plaid-link-sdk@12.8.3 — the last line with the classic imperative create() / open() API and no Expo-modules dependency (v13 is an Expo rewrite and would need expo-modules-core, which this bare RN app doesn't have).
  • Schema snapshot (app/graphql/public-schema.graphql): BridgeExternalAccountLink gains linkToken; linkUrl → nullable + @deprecated. Added BridgeExchangePlaidPublicTokenInput / …Payload and the bridgeExchangePlaidPublicToken mutation. Codegen regenerated (app/graphql/generated.ts / .gql).
  • GraphQL docs (app/graphql/front-end-mutations.ts): select linkToken in BridgeAddExternalAccount; add the BridgeExchangePlaidPublicToken mutation.
  • Flow (TopupCashout.tsxcheckBridgeKyc): open Plaid Link with linkToken, then call bridgeExchangePlaidPublicToken({ linkToken, publicToken }) on onSuccess. The external account is provisioned asynchronously via Bridge's external_account webhook, so we refetch and inform the user it will appear shortly.
  • Additive fallback (matches the backend's cutover): if no linkToken is returned (older backend), fall back to the existing BridgeExternalAccountWebView on linkUrl. The BRIDGE_PLAID_NOT_AVAILABLE → manual bank-entry path is unchanged.
  • jest: manual mock __mocks__/react-native-plaid-link-sdk.js for the native module.

The pre-existing dirty Gemfile / project.pbxproj / Podfile.lock in the working tree are not part of this PR.

Verified locally

  • yarn tsc:check — clean.
  • yarn check-code — tsc + translations + graphql-check (docs valid; the one "deprecated field" note is the intentional linkUrl fallback selection). Codegen is deterministic (re-running produces no diff) and the regenerated files are committed.
  • yarn test37 suites / 161 tests pass.

Not in this PR / needs device testing

  • OAuth-bank redirect config — iOS associated domains + AppDelegate redirect handler, Android intent-filter, plus a redirect URI registered in the Plaid dashboard. Non-OAuth Link works without it; wiring this blind (untestable here) would be guesswork, so it's a tracked follow-up.
  • Device/simulator runpod install (autolinked; the repo's postinstall runs it on yarn install) and Android autolink/build were not exercised in the authoring environment.

⚠ Sequencing — do not merge yet

bridgeExchangePlaidPublicToken does not exist server-side until flash#446 is merged and deployed. Kept as a draft until then. Once #446 is live: verify on device, then un-draft.

🤖 Generated with Claude Code

…G-524]

Match backend flash#446, which replaced the hosted Plaid linkUrl with a
linkToken + server-side public_token exchange.

- Add react-native-plaid-link-sdk (12.8.3, classic imperative API; no Expo dep).
- Schema snapshot: BridgeExternalAccountLink gains linkToken; linkUrl is now
  nullable + @deprecated. Add bridgeExchangePlaidPublicToken mutation + input/
  payload types. Regen codegen.
- GraphQL docs: select linkToken in BridgeAddExternalAccount; add
  BridgeExchangePlaidPublicToken mutation.
- TopupCashout.checkBridgeKyc: open Plaid Link with linkToken, then call
  bridgeExchangePlaidPublicToken({ linkToken, publicToken }) on success. The
  linked account arrives asynchronously via Bridge's webhook.
- Additive fallback: no linkToken (older backend) -> existing linkUrl WebView;
  BRIDGE_PLAID_NOT_AVAILABLE -> manual bank entry (unchanged).
- jest mock for the native SDK.

Follow-ups: OAuth-bank redirect config (iOS associated domains + AppDelegate
handler, Android intent-filter; needs a Plaid-dashboard redirect URI) and
device/simulator verification. Do not merge before flash#446 ships.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linear

linear Bot commented Jul 16, 2026

Copy link
Copy Markdown

ENG-524

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.

1 participant