magic-js icon indicating copy to clipboard operation
magic-js copied to clipboard

AlgorandExtension returns Ethereum publicAddress instead of Algorand in Expo SDK 53 + RN 0.79

Open drichar opened this issue 7 months ago • 4 comments

✅ Prerequisites

  • [x] Did you perform a cursory search of open issues? Is this bug already reported elsewhere?
  • [x] Are you running the latest SDK version?
  • [x] Are you reporting to the correct repository (magic-sdk)?

🐛 Description

Magic SDK v30.1.0 with AlgorandExtension returns Ethereum publicAddress (0x...) instead of Algorand address when using Expo SDK 53 + React Native 0.79.3 + New Architecture. This breaks existing Algorand functionality and prevents production apps from upgrading to newer Expo SDK versions.

The issue occurs specifically when using Firebase Authentication with Magic's "Bring Your Own Auth" (OIDC) approach via magic.openid.loginWithOIDC().

🧩 Steps to Reproduce

  1. Create Expo project with SDK 53 + React Native 0.79.3 + New Architecture enabled
  2. Install Magic Expo SDK v30.1.0 with AlgorandExtension and OpenIdExtension
  3. Install and configure React Native Firebase Authentication
  4. Configure Firebase as an identity provider in Magic (POST to federated_idp endpoint)
  5. Initialize Magic instance:
    const magic = new Magic(process.env.EXPO_PUBLIC_MAGIC_PUBLIC_KEY ?? '', {
      extensions: {
        algorand: new AlgorandExtension({
          rpcUrl: '',
        }),
        openid: new OpenIdExtension(),
      },
    })
    
  6. Authenticate with Firebase (email/password or Google), then call:
    const idToken = await user.getIdToken(true);
    await magic.openid.loginWithOIDC({
      jwt: idToken,
      providerId: process.env.EXPO_PUBLIC_MAGIC_PROVIDER_ID
    });
    
  7. Retrieve user info: const user = await magic.user.getInfo();
  8. Observe user.publicAddress format

🤔 Expected behavior

publicAddress should return Algorand format (as it does in Expo SDK 52):

"CFIVOY2M6IUNF6TDYSU33WI7ZQRPOSBDSNVLZEBEVS3LB3HHJCQ2DID3QE"

This is the expected behavior when using AlgorandExtension regardless of the underlying React Native version.

😮 Actual behavior

publicAddress returns Ethereum format instead:

"0xCA0CeB87Fe5858521235514b14443ccA8509B901"

Additional observations:

  • The issuer field remains consistent between SDK versions
  • The Ethereum address returned in publicAddress matches the address in the issuer property:
    "issuer": "did:ethr:0xCA0CeB87Fe5858521235514b14443ccA8509B901",
    "publicAddress": "0xCA0CeB87Fe5858521235514b14443ccA8509B901"
    
  • Only the publicAddress format changes unexpectedly
  • The same Magic configuration works correctly in Expo SDK 52
  • AlgorandExtension appears to be ignored or incorrectly processed

💻 Code Sample

// magic.ts
import { Magic } from '@magic-sdk/react-native-expo'
import { AlgorandExtension } from '@magic-ext/algorand'
import { OpenIdExtension } from '@magic-ext/oidc'

export const magic = new Magic(process.env.EXPO_PUBLIC_MAGIC_PUBLIC_KEY ?? '', {
  extensions: {
    algorand: new AlgorandExtension({
      rpcUrl: '',
    }),
    openid: new OpenIdExtension(),
  },
})
// AuthContext.tsx (simplified reproduction)
import { magic } from '@/lib/magic'
import auth, { type FirebaseAuthTypes } from '@react-native-firebase/auth'
import { GoogleSignin } from '@react-native-google-signin/google-signin'

async function authenticateWithMagic(user: FirebaseAuthTypes.User) {
  try {
    // Get Firebase ID token
    const idToken = await user.getIdToken(true)
    
    // Magic OIDC login - THIS IS WHERE THE BUG OCCURS
    await magic.openid.loginWithOIDC({
      jwt: idToken,
      providerId: process.env.EXPO_PUBLIC_MAGIC_PROVIDER_ID ?? '',
    })
    
    // Get user info - publicAddress format is WRONG in Expo SDK 53
    const metadata = await magic.user.getInfo()
    console.log('Public Address:', metadata.publicAddress)
    
    // Expected in Expo SDK 53 with AlgorandExtension:
    // "CFIVOY2M6IUNF6TDYSU33WI7ZQRPOSBDSNVLZEBEVS3LB3HHJCQ2DID3QE"
    
    // Actual in Expo SDK 53 (BROKEN):
    // "0xCA0CeB87Fe5858521235514b14443ccA8509B901"
    
    return metadata.publicAddress
  } catch (error) {
    console.error('Magic authentication failed:', error)
    throw error
  }
}

// Firebase auth flow (works with both email/password and Google Sign-in)
export function AuthProvider({ children }: { children: React.ReactNode }) {
  React.useEffect(() => {
    const unsubscribe = auth().onAuthStateChanged(async (user) => {
      if (user) {
        try {
          // Bug reproduces with ANY Firebase auth method:
          const algorandAddress = await authenticateWithMagic(user)
          console.log('Retrieved address:', algorandAddress)
          
          // In Expo SDK 52: Returns Algorand format (correct)
          // In Expo SDK 53: Returns Ethereum format (BROKEN)
        } catch (error) {
          console.error('Authentication flow failed:', error)
        }
      }
    })
    return unsubscribe
  }, [])

  // ... rest of auth provider
}

// Email/Password login (reproduces bug)
const loginWithEmail = async (email: string, password: string) => {
  await auth().signInWithEmailAndPassword(email, password)
  // Bug manifests in onAuthStateChanged -> authenticateWithMagic
}

// Google Sign-in (also reproduces bug)
const loginWithGoogle = async () => {
  const signInResult = await GoogleSignin.signIn()
  const googleCredential = auth.GoogleAuthProvider.credential(
    signInResult.data?.idToken,
  )
  await auth().signInWithCredential(googleCredential)
  // Bug manifests in onAuthStateChanged -> authenticateWithMagic
}

Package.json dependencies:

{
  "dependencies": {
    "@magic-ext/algorand": "^24.1.0",
    "@magic-ext/oidc": "^12.1.0",
    "@magic-sdk/react-native-expo": "30.1.0",
    "@react-native-firebase/app": "^22.2.0",
    "@react-native-firebase/auth": "^22.2.0",
    "expo": "^53.0.0",
    "react": "19.0.0",
    "react-dom": "19.0.0",
    "react-native": "0.79.3",
    "react-native-webview": "13.13.0",
  }
}

🌎 Environment

Software Version(s)
@magic-sdk/react-native-expo 30.1.0
@magic-ext/algorand 24.1.0
@magic-ext/oidc 12.1.0
Expo SDK 53 (broken) / 52 (working)
React Native 0.79.3 (broken) / 0.76.9 (working)
New Architecture Enabled
Platform iOS 18.5 / Android 15.0
Operating System macOS Sequoia 15.4.1

drichar avatar Jun 16 '25 16:06 drichar

Hi @drichar ,

Thank you for opening an issue! I see you are not calling getWallet on the algorand module. Would you try following the code snippet below and let us know if this resolves your issue today?


import { Magic } from 'magic-sdk';
import { AlgorandExtension } from '@magic-ext/algorand';

const magic = new Magic('YOUR_API_KEY', {
  extensions: {
    algorand: new AlgorandExtension({
      rpcUrl: '',
    }),
  },
});

// Get user's Algorand public address
const publicAddress = await magic.algorand.getWallet();
console.log('algorand public address', publicAddress);

The above snippet can be found in the Magic docs: Magic Docs | Algorand - Get Wallet

am-hernandez avatar Jun 16 '25 16:06 am-hernandez

I tested the recommended approach of using magic.algorand.getWallet() instead of magic.user.getInfo().publicAddress.

I'm not sure what has changed, but now magic.openid.loginWithOIDC() fails with Magic RPC Error: [-32603] Internal error: User denied signing.

I made the recommended change to the Expo SDK 52 version of our app, rebuilt, and magic.algorand.getWallet() works perfectly - it returns the correct Algorand address.

Then, after reapplying the Expo SDK 53 migration changes and rebuilding, I'm back to the Magic RPC Error: [-32603] Internal error: User denied signing. error again. What does this error mean?

drichar avatar Jun 16 '25 19:06 drichar

Note: I based the magic.user.getInfo().publicAddress approach on the Algorand example: https://github.com/magiclabs/example-algorand/blob/master/src/App.js

drichar avatar Jun 16 '25 19:06 drichar

I'm using the SolanaExtension, and I get an error when calling getInfo(). After reloading the browser, it returns: Magic RPC Error: [-32603] Internal error: User denied account access.

natanfirst avatar Jul 16 '25 15:07 natanfirst

Hello @drichar,

Starting with the React Native SDK v31.0.0, the publicAddress field has been removed from the response and replaced with a structured wallets object.

Could you please try upgrading to the newer version and retrieve the public address from the wallets object instead? For example: wallets.algorand.publicAddress

Let me know if that works for you or if you have any questions.

sherzod-bakhodirov avatar Dec 17 '25 13:12 sherzod-bakhodirov