Skip to main content
When a partner enables policies in the , users see a permissions consent screen during login and may need to approve individual transactions that fall outside their granted permissions. On web, the SDK handles this automatically with popups. On React Native, you need to tell the SDK how to open review URLs since there’s no popup API available. When policies are enabled, the Para portal shows a permissions consent screen after authentication. Users approve the requested scopes (e.g., “Message Signing”, “Transaction Sending”) before being redirected back to your app. This works automatically with the one-click login flow (openPopup / ASWebAuthenticationSession) — no extra code needed. The portal handles the consent UI internally.

Transaction Review Setup

If a signing operation requires additional user approval (e.g., the transaction doesn’t match any granted permission), the SDK needs to open a review URL. There are two ways to handle this: Set a global handler once when you initialize Para. This covers all signing paths, including integration libraries like viem and ethers that don’t pass per-call callbacks.
para.ts
import { ParaMobile, Environment } from '@getpara/react-native-wallet';
import { openBrowserAsync } from 'expo-web-browser';

const para = new ParaMobile(Environment.BETA, API_KEY, undefined, {
  disableWorkers: true,
});

para.setTransactionReviewHandler((url) => {
  openBrowserAsync(url);
});

export { para };
Any library that opens a browser works here — expo-web-browser, react-native-inappbrowser, or a custom WebView.

Option 2: Per-Call Callback

Pass onTransactionReviewUrl directly to signMessage or signTransaction for per-operation control:
import { openBrowserAsync } from 'expo-web-browser';

const result = await para.signMessage({
  walletId,
  messageBase64,
  onTransactionReviewUrl: (url) => {
    openBrowserAsync(url);
  },
});
This takes precedence over the global handler when provided.

How It Works

  1. Your app calls signMessage() or signTransaction()
  2. The backend evaluates the operation against the user’s granted permissions
  3. If allowed, signing completes immediately and returns a signature
  4. If not allowed, the backend returns a pendingTransactionId and the SDK opens a review URL
  5. The user approves or denies in the browser
  6. The SDK polls for the result and returns the signature (or throws on denial/timeout)

Error Handling

Handle denial and timeout errors from the signing flow:
import { TransactionReviewDenied, TransactionReviewTimeout } from '@getpara/react-native-wallet';

try {
  const result = await para.signMessage({
    walletId,
    messageBase64,
  });
  console.log('Signature:', result.signature);
} catch (error) {
  if (error instanceof TransactionReviewDenied) {
    // User denied the transaction
    console.warn('Transaction denied by user');
  } else if (error instanceof TransactionReviewTimeout) {
    // User didn't respond in time
    console.warn('Transaction review timed out');
    // error.transactionReviewUrl and error.pendingTransactionId
    // are available for retry
  }
}
The default approval timeout is 5 minutes for transactions that require review.

Next Steps