Skip to content

fix: add TextDecoder/TextEncoder polyfill for React Native#1578

Draft
devin-ai-integration[bot] wants to merge 2 commits intomainfrom
devin/1770844083-add-text-encoding-polyfill-rn
Draft

fix: add TextDecoder/TextEncoder polyfill for React Native#1578
devin-ai-integration[bot] wants to merge 2 commits intomainfrom
devin/1770844083-add-text-encoding-polyfill-rn

Conversation

@devin-ai-integration
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Feb 11, 2026

Description

Fixes ReferenceError: Property 'TextDecoder' doesn't exist reported by a client using CrossmintEmbeddedCheckout in a bare React Native 0.76.5 app on Android (Pylon ticket).

React Native's JS engines (Hermes/JSC) don't include TextDecoder/TextEncoder by default. The SDK uses these in API key validation (validateAPIKey.ts:53,76) and HPKE encryption (hpke.ts:78,82), causing an immediate crash on Android.

This adds fast-text-encoding as a polyfill to @crossmint/client-sdk-rn-window, following the same pattern established for crypto.getRandomValues via react-native-get-random-values.

⚠️ Items for reviewer attention

  1. Polyfill load timing — The polyfill is loaded via polyfills.ts → RNWebViewTransport.ts. If TextDecoder is needed before the transport is initialized (e.g. early API key validation), it may still fail. This matches the existing react-native-get-random-values pattern, but worth considering whether polyfills should be re-exported from the package entry point instead.

Link to Devin run | Requested by @xmint-guille

Test plan

  • Lint passes (pnpm lint)
  • All unit tests pass (pnpm test:vitest, 11/11 suites)
  • pnpm build:libs succeeds
  • Not tested on a real React Native Android device — the fix can only be fully validated on bare RN 0.76+ on Android, which is the affected environment. Unit tests run in Node.js where TextDecoder is already available natively.

Package updates

  • Added fast-text-encoding@^1.0.6 to @crossmint/client-sdk-rn-window dependencies
  • Changeset added for patch bump on @crossmint/client-sdk-rn-window

Add fast-text-encoding polyfill to @crossmint/client-sdk-rn-window,
mirroring the existing react-native-get-random-values pattern.

Fixes ReferenceError: Property 'TextDecoder' doesn't exist on bare
React Native apps (Android) using CrossmintEmbeddedCheckout.
@changeset-bot
Copy link

changeset-bot bot commented Feb 11, 2026

🦋 Changeset detected

Latest commit: 7bf1479

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

This PR includes changesets to release 3 packages
Name Type
@crossmint/client-sdk-rn-window Patch
expo-demo Patch
@crossmint/client-sdk-react-native-ui Patch

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

@devin-ai-integration
Copy link
Contributor Author

devin-ai-integration bot commented Feb 11, 2026

Original prompt from Guille
check this ticket

i made claude code to analyze it and propose a diagnosis. evaluate his analysis, and in case useful propose a fix in a draft pr. don't tag nobody in the pr review.

# TextDecoder Issue in Crossmint React Native SDK - Diagnosis

## Issue Summary

Client reported: **ReferenceError: Property 'TextDecoder' doesn't exist** when using `CrossmintEmbeddedCheckout` in a bare React Native 0.76.5 app on Android.

**Client's Workaround**: Installing `text-encoding` library and importing it globally.

---

## Root Cause Analysis

### 1. **Environment Limitation**
- `TextDecoder` and `TextEncoder` are Web APIs that are **not available** in React Native's JavaScript environment by default, especially on Android
- These APIs are standard in browsers and Node.js, but React Native uses JavaScriptCore (iOS) or Hermes (Android) which don't include them

### 2. **Where TextDecoder is Used in the SDK**

The Crossmint SDK uses `TextDecoder` in two critical places:

#### a) **API Key Validation** (`@crossmint/common-sdk-base`)
File: `packages/common/base/src/apiKey/validateAPIKey.ts:53`

```typescript
function decodeAPIKeyAndGetParts(apiKey: string, prefix: APIKeyPrefix) {
    const base58EncodedPart = apiKey.slice(`${prefix}_`.length);
    const decodedPartUint8 = base58.decode(base58EncodedPart);
    const decodedPartString = new TextDecoder().decode(decodedPartUint8);  // ← FAILS HERE
    // ...
}

Also uses TextEncoder at line 76:

const keyDataBytes = new TextEncoder().encode(keyData);

b) HPKE Encryption (@crossmint/client-signers-cryptography)

File: packages/client/signers-cryptography/src/algorithms/asymmetric/hpke.ts:82

private deserialize<T extends EncryptablePayload>(data: ArrayBuffer): T {
    return JSON.parse(new TextDecoder().decode(data)) as T;  // ← FAILS HERE
}

Also uses `... (5396 chars truncated...)

</details>

@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@Crossmint Crossmint deleted a comment from devin-ai-integration bot Feb 11, 2026
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