Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.getpara.com/llms.txt

Use this file to discover all available pages before exploring further.

Learn how to set up with Para SDK to interact with Cosmos-based blockchains.

Prerequisites

Use the Proto signer for transaction operations like sending tokens, staking, and IBC transfers.

Install

npm install @getpara/react-native-wallet @getpara/cosmjs-v0-integration @cosmjs/stargate
@getpara/cosmjs-v0-integration is a separate package — install it alongside @getpara/react-native-wallet.

Usage

Use the hook to create a CosmJS OfflineDirectSigner for your user’s Para embedded wallet or external wallet. The hook wraps signAndBroadcast in a React Query mutation.
import { useParaCosmjsProtoSigner, useParaCosmjsSignAndBroadcast } from "@getpara/react-native-wallet/cosmos";
import { SigningStargateClient, coins } from "@cosmjs/stargate";
import { useState, useEffect } from "react";
import { Text, TouchableOpacity } from "react-native";

const RPC_URL = "https://rpc.cosmos.directory/cosmoshub";

function SendTokens() {
  const { protoSigner, isLoading } = useParaCosmjsProtoSigner();
  const [client, setClient] = useState<SigningStargateClient>();

  useEffect(() => {
    if (protoSigner) {
      SigningStargateClient.connectWithSigner(RPC_URL, protoSigner).then(setClient);
    }
  }, [protoSigner]);

  const { signAndBroadcastAsync, isPending } = useParaCosmjsSignAndBroadcast(protoSigner, client);

  const handleSend = async () => {
    const result = await signAndBroadcastAsync({
      messages: [{ typeUrl: "/cosmos.bank.v1beta1.MsgSend", value: {
        fromAddress: protoSigner!.address,
        toAddress: "cosmos1...",
        amount: coins(1000000, "uatom"),
      }}],
      fee: { amount: coins(5000, "uatom"), gas: "200000" },
    });
    console.log("Tx hash:", result.transactionHash);
  };

  if (isLoading) return <Text>Loading...</Text>;
  return (
    <TouchableOpacity onPress={handleSend} disabled={isPending}>
      <Text>{isPending ? "Broadcasting..." : "Send 1 ATOM"}</Text>
    </TouchableOpacity>
  );
}

Wallet Resolution

When no address or walletId is passed, the hook resolves the wallet in this order:
  1. Selected wallet — if the user selected a Cosmos wallet in the UI. If there is only one Cosmos wallet in the session, it is already selected by default
  2. First Cosmos wallet — the first available Cosmos wallet on the account
To target a specific wallet:
const { protoSigner } = useParaCosmjsProtoSigner({
  address: "cosmos1...",  // or walletId: "uuid-..."
  prefix: "osmo",  // optional chain prefix, defaults to "cosmos"
});

Metro Configuration

@cosmjs/crypto depends on libsodium-wrappers-sumo, a WASM-based cryptography library that is incompatible with React Native. Since Para handles signing server-side via MPC, this library is not needed at runtime. However, Metro will still bundle it and crash when the WASM module loads. To fix this, stub out the module in your metro.config.js using a custom resolveRequest:
metro.config.js
const { getDefaultConfig } = require('expo/metro-config');

const config = getDefaultConfig(__dirname);

const emptyModule = require.resolve('./lib/empty-module.js');

// libsodium-wrappers-sumo uses WASM which doesn't work in React Native.
// Since Para signs via MPC, this module is not needed.
// We must use resolveRequest (not extraNodeModules) because the package
// is installed in node_modules and extraNodeModules only acts as a fallback.
const stubbedModules = new Set(['libsodium-wrappers-sumo']);
const originalResolveRequest = config.resolver.resolveRequest;
config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (stubbedModules.has(moduleName)) {
    return { type: 'sourceFile', filePath: emptyModule };
  }
  if (originalResolveRequest) {
    return originalResolveRequest(context, moduleName, platform);
  }
  return context.resolveRequest(context, moduleName, platform);
};

module.exports = config;
Create the empty module stub:
lib/empty-module.js
module.exports = {};
Using extraNodeModules will not work for this case. Metro’s extraNodeModules only acts as a fallback when a module can’t be found. Since libsodium-wrappers-sumo is installed as a transitive dependency of @cosmjs/crypto, Metro resolves it from node_modules before checking extraNodeModules. The resolveRequest override intercepts resolution before that happens.

Next Steps