LogoLogo
SupportGithubSign InGet Access
  • Introduction
  • GETTING STARTED
    • SDK Quick Start
    • API Quick Start
  • Guides
    • Web
      • Create a wallet
      • Send tokens
      • Sign a transaction
      • Simulate a transaction
      • Back up a wallet
      • Recover a wallet
      • Cross-device sessions
      • Manage wallet lifecycle states
      • Web authentication methods
      • Perform swaps
      • Add custom signature hooks
      • MPC progress callbacks
      • Portal API methods
      • Configure a custom subdomain
      • Eject a wallet
      • Using the EIP-1193 Provider
      • Legacy documentation
        • Back up a wallet
          • Backup Options
        • Recover a wallet
    • iOS
      • Create a wallet
      • Send tokens
      • Sign a transaction
      • Simulate a transaction
      • Back up a wallet
      • Recover a wallet
      • Cross-device sessions
      • Manage wallet lifecycle states
      • Connect with WalletConnect
      • Build a WebView
      • Perform swaps
      • Add custom signature hooks
      • MPC progress callbacks
      • Portal API methods
      • Manage ERC20 tokens
      • Eject a wallet
      • Legacy documentation
        • Back up a wallet
          • Backup Options
          • Passkey + Enclave Storage
        • Recover a wallet
      • Troubleshooting Tips
      • Feature Flags
    • Android
      • Create a wallet
      • Send tokens
      • Sign a transaction
      • Simulate a transaction
      • Back up a wallet
      • Recover a wallet
      • Cross-device sessions
      • Manage wallet lifecycle states
      • Connect with WalletConnect
      • Build a WebView
      • Perform swaps
      • Add custom signature hooks
      • MPC progress callbacks
      • Portal API methods
      • Eject a wallet
      • Legacy documentation
        • Back up a wallet
          • Backup Options
        • Recover a wallet
    • React Native
      • Create a wallet
      • Send tokens
      • Sign a transaction
      • Simulate a transaction
      • Back up a wallet
      • Recover a wallet
      • Cross-device sessions
      • Manage wallet lifecycle states
      • Connect with WalletConnect
      • Build a WebView
      • Perform swaps
      • Add custom signature hooks
      • MPC progress callbacks
      • Portal API methods
      • Eject a wallet
      • Legacy documentation
        • Back up a wallet
          • Backup Options
        • Recover a wallet
    • Enclave MPC API
      • Create a client
      • Create a wallet
      • Send tokens
      • Sign Ethereum transactions
      • Sign Solana transactions
      • Sign Tron transactions
      • Sign Stellar Transaction
      • Concurrent Transactions
      • Back up a wallet
      • Eject a wallet
  • Reference
    • iOS
      • createWallet
      • backupWallet
      • recoverWallet
      • ejectPrivateKeys
      • registerBackupMethod
      • setGDriveConfiguration
      • setPasskeyConfiguration
      • setPasskeyAuthenticationAnchor
      • setPassword
      • availableRecoveryMethods
      • doesWalletExist
      • isWalletBackedUp
      • isWalletOnDevice
      • isWalletRecoverable
      • getBalances
      • getAssets
      • getNftAssets
      • getTransactions
      • sendSol
      • evaluateTransaction
      • buildEip155Transaction
      • buildSolanaTransaction
      • getWalletCapabilities
    • Android
      • Reference Documentation
    • React Native
      • @portal-hq/core
      • Storage adapters
        • Cloud storage
          • @portal-hq/gdrive-storage
          • @portal-hq/icloud-storage
        • Mobile storage
          • @portal-hq/keychain
          • @portal-hq/mobile-key-values
    • Enclave MPC API
      • V1 endpoints
    • Client API
      • V3 endpoints
      • V1 endpoints
    • Custodian API
      • V3 endpoints
      • V1 endpoints
    • Swaps API
      • V3 endpoints
      • V1 endpoints
  • Resources
    • Flutter
      • iOS
      • Android
    • Error codes
      • Overview
      • MPC errors
      • Network errors
      • General errors
      • Encryption errors
      • Portal Connect errors
    • Portal's MPC architecture
    • Authentication and API Keys
    • Self-Managed Backups
    • Alert Webhooks
    • Wallet lifecycle
    • Backup options
      • Password/PIN
      • GDrive
      • iCloud
      • Passkey + Enclave
    • WalletConnect metadata
    • Advanced security scanning
    • Account abstraction
    • Security firewall
    • Eject
    • Security
    • Blockchain support
    • Chain ID formatting
    • Testnet faucets
    • Going to Production
    • Rate Limits
    • Multi-backup migration guide
    • Multi-wallet migration guides
      • Migrating from Android SDK v3.x.x to v4.x.x
      • Migrating from iOS SDK v3.0.x to v3.2.x
  • Support
    • Changelog
      • Android
      • iOS
      • React Native
      • Web
      • Past Releases
        • 2024 Releases
        • 2023 Releases
    • Celo Hackathon Hub
    • Glossary
Powered by GitBook
On this page
  • Signing a Solana Transaction
  • Raw sign
  • Estimating Gas

Was this helpful?

  1. Guides
  2. React Native

Sign a transaction

Want to implement your own style, but with all the functionality Portal offers? Use these functions to implement your own custom web3 UI for your users.

PreviousSend tokensNextSimulate a transaction

Last updated 3 months ago

Was this helpful?

This example screen displays how the Portal Provider interacts with the MPC wallet and the blockchain.

The Provider has an input box to set a toAddress for the transaction of sending 0.001 ETH from our MPC wallet. The Provider then receives a signed transaction from our mobile MPC library and submits that to chain using the configured RPC url.

Ensure you have set the gateway URL correctly with or when you initialize the Portal class.

NativeSendTx.tsx
import React, { FC, useState } from 'react'
import { Button, Text, TextInput, View } from 'react-native'
import { usePortal } from '@portal-hq/core'

const NativeSendTx = () => {
  const portal = usePortal()
  const [toAddress, setToAddress] = useState('')
  const [txHash, setTxHash] = useState('')

  const handleSend = async () => {
    try {
      // Build the transaction using the simplified API
      const { transaction } = await portal.api.buildTransaction(
        toAddress,    // recipient address
        'NATIVE',     // token type (native ETH)
        '0.001', // amount
        'sepolia'     // network
      )

      // Send the transaction
      const newTxHash = await portal.request({
        method: 'eth_sendTransaction',
        params: transaction,
        chainId: 'eip155:11155111'
      })

      setTxHash(newTxHash)
      setToAddress('')
    } catch (error) {
      console.error('Failed to send transaction:', error)
    }
  }
3
  return (
    <View>
      <Text>Send 0.001 ETH</Text>
      <TextInput
        onChangeText={setToAddress}
        placeholder="Enter recipient address"
        value={toAddress}
      />

      <View style={{ marginTop: 10 }}>
        <Button
          disabled={!portal || !toAddress || !toAddress.length}
          onPress={handleSend}
          title="Send ETH"
        />
      </View>

      {txHash && txHash.length > 0 && (
        <View>
          <Text>Successfully sent transaction!</Text>
          <Text>Transaction Hash: {txHash}</Text>
        </View>
      )}
    </View>
  )
}

export default NativeSendTx

Signing a Solana Transaction

You can use our provider just like you do with Ethereum with Solana. Simply specify the method and the chainId for Solana. This example uses solana/web3.js to construct a transaction object to sign and pass to the multi-chain provider.

Solana Provider Methods

  • sol_signMessage

  • sol_signTransaction

  • sol_signAndSendTransaction

  • sol_signAndConfirmTransaction

import React, { useState } from 'react'
import { Button, Text, TextInput, View } from 'react-native'
import { usePortal } from '@portal-hq/core'

const SolanaSendTx = () => {
  const portal = usePortal()
  const [toAddress, setToAddress] = useState('')
  const [txHash, setTxHash] = useState('')

  const handleSend = async () => {
    try {
      const chainId = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1' // Solana Devnet

      // Build the transaction using the simplified API
      const { transaction } = await portal.api.buildTransaction(
        toAddress,         // recipient address
        'NATIVE',          // token type (native SOL)
        '0.001',           // amount in SOL
        chainId            // CAIP-2 Chain, or friendly name like "solana-devnet"
      )

      // Send the transaction
      const newTxHash = await portal.request({
        method: 'sol_signAndSendTransaction',
        params: [transaction], // transaction is already base64 encoded
        chainId,
      })

      setTxHash(newTxHash)
      setToAddress('')
    } catch (error) {
      console.error('Failed to send transaction:', error)
    }
  }

  return (
    <View>
      <Text>Send 0.001 SOL</Text>
      <TextInput
        onChangeText={setToAddress}
        placeholder="Enter recipient address"
        value={toAddress}
      />

      <View style={{ marginTop: 10 }}>
        <Button
          disabled={!portal || !toAddress || !toAddress.length}
          onPress={handleSend}
          title="Send SOL"
        />
      </View>

      {txHash?.length > 0 && (
        <View>
          <Text>Successfully sent transaction!</Text>
          <Text>Transaction Hash: {txHash}</Text>
        </View>
      )}
    </View>
  )
}

export default SolanaSendTx

Raw sign

You can now utilize our SDK to generate raw signatures that are generated using the underlying key share without adding any chain specific formatting to the signature. This effectively unlocks your ability to use the Portal SDK with any chain that uses SECP256K1 or ED25519.

  const handleRawSign = async () => {
    try {
      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
      const signedMessage = await portal!.rawSign(
        '74657374', // Must be in hex format, e.g. "test" is "74657374" in hex.
        'eip155:11155111', // choose the chainId eip155 = secp256k1, solana = ed25519
      )
      console.log('✅ Signed message', signedMessage)
    } catch (error) {
      console.error(error)
      console.log('❌ Failed to sign')
      throw error
    }
  }

Estimating Gas

By default, Portal will estimate and populate the gas property in a transaction object if the property is undefined.

To estimate the gas value manually use the eth_estimateGas RPC call and pass in your transaction as the parameter.

// Build a transaction to be sent
const transaction = {
  from: await portal.keychain.getAddress(),
  to: toAddress,
  value: BigNumber.from('1').toHexString(), // Example value
}

// Use the Portal Web3 Provider to make requests
const gas = await portal.request({
  method: 'eth_estimateGas',
  params: [transaction],
})

console.log(gas) // "0x5208"

And now you are signing transactions with Portal! 🚀

Next, we'll explore how to simulate a transaction so that you can create smoother experiences for your users.

Infura
Alchemy