Para provides comprehensive support for Cosmos ecosystem integration in Swift applications, allowing you to leverage Para’s secure wallet infrastructure with multiple Cosmos-based blockchains.
Overview
The ParaCosmosSigner
class enables seamless interaction with Cosmos chains through Para’s secure key management system. It provides:
- Direct signing methods for both Direct (modern protobuf) and Amino (legacy) formats
- Balance queries and wallet management across multiple chains
- Message signing for arbitrary data authentication
- Chain-specific configurations with proper prefixes and denominations
- Secure key operations via Para’s MPC infrastructure
- Bridge-based implementation that delegates to CosmJS signers for consistency
- Clean, focused API that follows single responsibility principles
Supported Chains
Para Swift SDK supports the following Cosmos chains with reliable, CORS-enabled RPC endpoints:
Chain | Chain ID | Prefix | Default Denom | Network Type |
---|
Cosmos Hub | cosmoshub-4 | cosmos | uatom | Mainnet |
Osmosis | osmosis-1 | osmo | uosmo | Mainnet |
Juno | juno-1 | juno | ujuno | Mainnet |
Stargaze | stargaze-1 | stars | ustars | Mainnet |
Cosmos Testnet | provider | cosmos | uatom | Testnet |
Osmosis Testnet | osmo-test-5 | osmo | uosmo | Testnet |
Quick Start
1. Initialize ParaCosmosSigner
Create a ParaCosmosSigner
instance with chain-specific configuration:
import ParaSwift
// Initialize for Cosmos Hub mainnet (recommended)
let cosmosSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "cosmoshub-4",
rpcUrl: "https://cosmos-rpc.publicnode.com",
prefix: "cosmos"
)
// Initialize for Osmosis mainnet
let osmosSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "osmosis-1",
rpcUrl: "https://osmosis-rpc.publicnode.com",
prefix: "osmo"
)
// Initialize for Juno mainnet
let junoSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "juno-1",
rpcUrl: "https://rpc-juno.itastakers.com",
prefix: "juno"
)
// Initialize for Cosmos testnet
let testnetSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "provider",
rpcUrl: "https://rpc.provider-state-sync-01.rs-testnet.polypore.xyz",
prefix: "cosmos"
)
// Or initialize with a specific wallet
let cosmosSignerWithWallet = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "cosmoshub-4",
rpcUrl: "https://cosmos-rpc.publicnode.com",
prefix: "cosmos",
walletId: "your-wallet-id"
)
2. Select a Wallet
Choose which Cosmos wallet to use for signing operations:
// Fetch available wallets
let wallets = try await paraManager.fetchWallets()
let cosmosWallet = wallets.first { $0.type == .cosmos }
// Select the wallet for signing
if let walletId = cosmosWallet?.id {
try await cosmosSigner.selectWallet(walletId: walletId)
}
3. Get Wallet Address
Retrieve the bech32 address for the selected wallet with the chain-specific prefix:
// Get address for Cosmos Hub
let cosmosAddress = try await cosmosSigner.getAddress()
print("Cosmos address: \(cosmosAddress)")
// Output: cosmos1abc123...
// Get address for Osmosis
let osmosAddress = try await osmosSigner.getAddress()
print("Osmosis address: \(osmosAddress)")
// Output: osmo1abc123...
// Get address for Juno
let junoAddress = try await junoSigner.getAddress()
print("Juno address: \(junoAddress)")
// Output: juno1abc123...
Wallet Operations
Check Balance
Query the wallet’s token balance with chain-specific denominations:
// Get ATOM balance on Cosmos Hub (default denomination)
let atomBalance = try await cosmosSigner.getBalance()
print("ATOM balance: \(atomBalance) uatom")
// Get OSMO balance on Osmosis (default denomination)
let osmoBalance = try await osmosSigner.getBalance()
print("OSMO balance: \(osmoBalance) uosmo")
// Get specific token balance with custom denomination
let usdcBalance = try await cosmosSigner.getBalance(denom: "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4")
print("USDC balance: \(usdcBalance)")
Sign Transactions
The ParaCosmosSigner provides direct signing methods that return signature data without broadcasting. This follows the single responsibility principle - the signer signs, but doesn’t handle transaction construction or broadcasting:
// Sign with Direct method (recommended - modern protobuf approach)
let directSignDocBase64 = "..." // Your transaction's SignDoc encoded as base64
let directResult = try await cosmosSigner.signDirect(signDocBase64: directSignDocBase64)
// The result contains the signature and signed document
if let signature = directResult["signature"] as? [String: Any],
let signatureData = signature["signature"] as? String {
print("Direct signature: \(signatureData)")
}
// Sign with Amino method (legacy - for compatibility)
let aminoSignDocBase64 = "..." // Your amino SignDoc encoded as base64
let aminoResult = try await cosmosSigner.signAmino(signDocBase64: aminoSignDocBase64)
// Handle the amino signature result
if let signature = aminoResult["signature"] as? [String: Any],
let signatureData = signature["signature"] as? String {
print("Amino signature: \(signatureData)")
}
Transaction Signing Details
Bridge-Based Implementation
The ParaCosmosSigner
uses a bridge-based implementation that delegates to CosmJS signers in the web environment, ensuring consistent behavior with the broader Cosmos ecosystem. This provides:
- Direct access to CosmJS signing methods (
cosmJsSignDirect
, cosmJsSignAmino
)
- Proper protobuf and amino handling through proven CosmJS libraries
- Cross-platform consistency between Swift and web implementations
Signing Methods
Para supports both Cosmos signing methods with clear terminology:
- Direct Signing - Modern, efficient binary format using protobuf encoding (SIGN_MODE_DIRECT)
- Amino Signing - Legacy JSON format for backward compatibility
Note: Direct signing is the protobuf-based signing method in CosmJS.
Creating SignDoc for Signing
To use the signing methods, you need to create properly formatted SignDoc objects:
// For Direct signing: create base64-encoded protobuf SignDoc
// This would typically be constructed using transaction building libraries
let directSignDocBase64 = createDirectSignDoc(
chainId: "cosmoshub-4",
accountNumber: 12345,
sequence: 0,
bodyBytes: txBodyBytes,
authInfoBytes: authInfoBytes
)
// For Amino signing: create base64-encoded JSON SignDoc
let aminoSignDoc = [
"chain_id": "cosmoshub-4",
"account_number": "12345",
"sequence": "0",
"fee": ["amount": [["denom": "uatom", "amount": "5000"]], "gas": "200000"],
"msgs": [/* your transaction messages */],
"memo": "Demo transaction"
]
let aminoSignDocBase64 = try JSONSerialization.data(withJSONObject: aminoSignDoc)
.base64EncodedString()
Message Signing
Sign arbitrary messages for authentication or verification:
let message = "Welcome to Para Cosmos!"
let signature = try await cosmosSigner.signMessage(message)
print("Message signature: \(signature.hexString())")
Error Handling
Handle Cosmos-specific errors appropriately:
do {
let result = try await cosmosSigner.signDirect(signDocBase64: directSignDocBase64)
// Handle successful signing
} catch ParaCosmosSignerError.missingWalletId {
print("Please select a wallet first")
} catch ParaCosmosSignerError.invalidWalletAddress {
print("Invalid Cosmos wallet address")
} catch ParaCosmosSignerError.protoSigningFailed(let underlyingError) {
print("Direct signing failed: \(underlyingError?.localizedDescription ?? "Unknown error")")
} catch ParaCosmosSignerError.aminoSigningFailed(let underlyingError) {
print("Amino signing failed: \(underlyingError?.localizedDescription ?? "Unknown error")")
} catch ParaCosmosSignerError.bridgeError(let message) {
print("Bridge communication error: \(message)")
} catch {
print("Unexpected error: \(error)")
}
Chain Configuration Examples
Here are complete examples for each supported chain with reliable RPC endpoints:
Cosmos Hub Mainnet (Recommended)
let cosmosSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "cosmoshub-4",
rpcUrl: "https://cosmos-rpc.publicnode.com",
prefix: "cosmos"
)
Osmosis Mainnet
let osmosSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "osmosis-1",
rpcUrl: "https://osmosis-rpc.publicnode.com",
prefix: "osmo"
)
Juno Mainnet
let junoSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "juno-1",
rpcUrl: "https://rpc-juno.itastakers.com",
prefix: "juno"
)
Stargaze Mainnet
let stargazeSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "stargaze-1",
rpcUrl: "https://rpc.stargaze-apis.com",
prefix: "stars"
)
Cosmos Testnet
let testnetSigner = try ParaCosmosSigner(
paraManager: paraManager,
chainId: "provider",
rpcUrl: "https://rpc.provider-state-sync-01.rs-testnet.polypore.xyz",
prefix: "cosmos"
)
Important Notes
Chain-Specific Configuration
Each chain requires specific configuration parameters:
- Chain ID: The unique identifier for the network (e.g., “cosmoshub-4”, “osmosis-1”)
- Prefix: The bech32 address prefix (e.g., “cosmos”, “osmo”, “juno”, “stars”)
- RPC URL: The Tendermint RPC endpoint for the specific chain
RPC Endpoints
Para uses reliable, CORS-enabled RPC endpoints optimized for mobile applications:
- ✅ PublicNode endpoints (recommended):
https://cosmos-rpc.publicnode.com
- ✅ ITAStakers endpoints:
https://rpc-juno.itastakers.com
- ✅ Official chain endpoints:
https://rpc.stargaze-apis.com
These endpoints are specifically chosen for:
- SSL/TLS compatibility with mobile environments
- CORS support for browser and mobile app usage
- High availability and reliability
- No rate limiting for development usage
API Design Philosophy
The ParaCosmosSigner follows single responsibility principle:
- Focused on signing only - doesn’t handle transaction construction or broadcasting
- Clean separation of concerns - signing vs. transaction building vs. broadcasting
- Direct access to CosmJS methods -
signDirect()
and signAmino()
- Minimal surface area - easier to understand and maintain
This approach provides:
- Flexibility for advanced transaction construction
- Compatibility with existing Cosmos tooling
- Clarity about what each method does
- Maintainability through focused responsibilities
- Direct signing is generally faster and more efficient than Amino
- Bridge architecture provides direct access to proven CosmJS implementations
- CORS-enabled endpoints eliminate connection issues in mobile environments
- Mainnet defaults provide more reliable service than testnets
Next Steps