RathRath Finance
SDK Reference

Relay Signed Transactions

Learn how to submit pre-signed transactions with automatic funding using the Tachyon SDK.

Relay Signed Transactions

The Tachyon SDK provides a specialized method for submitting pre-signed transactions with automatic funding. This is useful when you need to execute transactions from a specific address while having Tachyon handle the gas payments and ensure the account has sufficient balance.

Overview

The relaySignedTx() method allows you to:

  • Submit pre-signed transactions for execution
  • Automatically fund the sender address with the minimum required balance
  • Track transaction status using the same methods as regular relay transactions
  • Maintain control over transaction signing while outsourcing gas payment

Use Cases:

  • Executing transactions from deterministic addresses
  • Managing multiple accounts with centralized funding
  • Implementing account abstraction patterns
  • Batch operations requiring specific signer addresses

Method Reference

relaySignedTx(params)

Submits a pre-signed transaction to the Tachyon relay network. Tachyon will ensure the sender address is funded with at least minBalanceRequired before broadcasting the signed transaction.

Parameters:

The SignedTransactionParams object defines the parameters required when calling the relaySignedTx() method.

NameTypeRequiredDescription
chainIdnumberYesThe blockchain network ID where the transaction will be executed. Must be a supported chain.
fromAddressstringYesThe address that signed the transaction. This address will be funded if needed. Must be a valid address for the specified chain.
signedTxstringYesThe complete signed transaction data in hexadecimal format. This should be the raw signed transaction ready for broadcast.
minBalanceRequiredstringYesThe minimum balance required in the sender's account to execute the transaction (in smallest unit - wei for EVM chains). Typically calculated as gasLimit * maxFeePerGas.
labelstringNoOptional human-readable label for easier transaction identification and tracking.

Returns: Promise<string> — A unique transaction ID that can be used to track the transaction status and execution.

Throws:

  • Error if required parameters are missing
  • Error if the from address is invalid for the specified chain
  • Error if the funding cost exceeds account limits
  • Error if the account has insufficient balance
  • Error if the chain is disabled for the account

Complete Examples

Basic EVM Transaction

import { Tachyon, ChainId } from '@rathfi/tachyon'
import { ethers } from 'ethers'

async function relaySignedTransaction() {
  // Initialize Tachyon
  const tachyon = new Tachyon({
    apiKey: 'YOUR_API_KEY',
  })

  // Create wallet
  const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY')

  // Prepare transaction
  const tx = {
    to: '0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49',
    value: ethers.parseEther('0.01'),
    data: '0x',
    chainId: 8453, // Base
    nonce: 0,
    gasLimit: 21000,
    maxFeePerGas: ethers.parseUnits('2', 'gwei'),
    maxPriorityFeePerGas: ethers.parseUnits('1', 'gwei'),
  }

  // Sign transaction
  const signedTx = await wallet.signTransaction(tx)

  // Calculate minimum balance (gas cost)
  const minBalance = (
    BigInt(tx.gasLimit) * BigInt(tx.maxFeePerGas)
  ).toString()

  // Submit to Tachyon
  const txId = await tachyon.relaySignedTx({
    chainId: tx.chainId,
    fromAddress: wallet.address,
    signedTx: signedTx,
    minBalanceRequired: minBalance,
    label: 'Transfer 0.01 ETH',
  })

  console.log('Transaction ID:', txId)

  // Wait for execution
  const result = await tachyon.waitForExecutionHash(txId, 60000)
  console.log('Transaction executed:', result.executionTxHash)

  return result
}

relaySignedTransaction()

Smart Contract Interaction

import { Tachyon } from '@rathfi/tachyon'
import { ethers } from 'ethers'

async function callContract() {
  const tachyon = new Tachyon({
    apiKey: 'YOUR_API_KEY',
  })

  const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY')

  // Encode contract call
  const contractAddress = '0x...'
  const abi = ['function transfer(address to, uint256 amount)']
  const iface = new ethers.Interface(abi)
  const callData = iface.encodeFunctionData('transfer', [
    '0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49',
    ethers.parseEther('100'),
  ])

  // Prepare and sign transaction
  const tx = {
    to: contractAddress,
    value: 0,
    data: callData,
    chainId: 8453,
    nonce: 0,
    gasLimit: 100000,
    maxFeePerGas: ethers.parseUnits('2', 'gwei'),
    maxPriorityFeePerGas: ethers.parseUnits('1', 'gwei'),
  }

  const signedTx = await wallet.signTransaction(tx)
  const minBalance = (
    BigInt(tx.gasLimit) * BigInt(tx.maxFeePerGas)
  ).toString()

  // Submit signed transaction
  const txId = await tachyon.relaySignedTx({
    chainId: tx.chainId,
    fromAddress: wallet.address,
    signedTx: signedTx,
    minBalanceRequired: minBalance,
    label: 'Token Transfer',
  })

  return txId
}

With Automatic Nonce Management

import { Tachyon } from '@rathfi/tachyon'
import { ethers } from 'ethers'

async function relayWithAutoNonce(provider) {
  const tachyon = new Tachyon({
    apiKey: 'YOUR_API_KEY',
  })

  const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY', provider)

  // Get current nonce from provider
  const nonce = await provider.getTransactionCount(wallet.address)

  // Get current gas prices
  const feeData = await provider.getFeeData()

  const tx = {
    to: '0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49',
    value: ethers.parseEther('0.001'),
    data: '0x',
    chainId: 8453,
    nonce: nonce,
    gasLimit: 21000,
    maxFeePerGas: feeData.maxFeePerGas,
    maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,
  }

  const signedTx = await wallet.signTransaction(tx)
  const minBalance = (
    BigInt(tx.gasLimit) * BigInt(tx.maxFeePerGas)
  ).toString()

  const txId = await tachyon.relaySignedTx({
    chainId: tx.chainId,
    fromAddress: wallet.address,
    signedTx: signedTx,
    minBalanceRequired: minBalance,
  })

  return txId
}

Batch Processing Multiple Signed Transactions

import { Tachyon } from '@rathfi/tachyon'
import { ethers } from 'ethers'

async function batchRelaySignedTransactions() {
  const tachyon = new Tachyon({
    apiKey: 'YOUR_API_KEY',
  })

  const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY')

  const recipients = [
    '0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49',
    '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
    '0x8888888888888888888888888888888888888888',
  ]

  const txIds = []

  for (let i = 0; i < recipients.length; i++) {
    const tx = {
      to: recipients[i],
      value: ethers.parseEther('0.001'),
      data: '0x',
      chainId: 8453,
      nonce: i, // Sequential nonces
      gasLimit: 21000,
      maxFeePerGas: ethers.parseUnits('2', 'gwei'),
      maxPriorityFeePerGas: ethers.parseUnits('1', 'gwei'),
    }

    const signedTx = await wallet.signTransaction(tx)
    const minBalance = (
      BigInt(tx.gasLimit) * BigInt(tx.maxFeePerGas)
    ).toString()

    const txId = await tachyon.relaySignedTx({
      chainId: tx.chainId,
      fromAddress: wallet.address,
      signedTx: signedTx,
      minBalanceRequired: minBalance,
      label: `Batch transfer ${i + 1}/${recipients.length}`,
    })

    txIds.push(txId)
    console.log(`Submitted transaction ${i + 1}:`, txId)
  }

  // Wait for all transactions to execute
  const results = await Promise.all(
    txIds.map(txId => tachyon.waitForExecutionHash(txId))
  )

  return results
}

How It Works

  1. Transaction Signing: You sign the transaction with your private key using your preferred wallet/signer
  2. Funding Check: Tachyon checks if the sender address has sufficient balance
  3. Automatic Funding: If needed, Tachyon funds the address with the minBalanceRequired amount
  4. Transaction Broadcast: Once funded, Tachyon broadcasts your pre-signed transaction
  5. Execution: The transaction executes on-chain from your specified address

Cost Calculation

The cost for a signed transaction relay includes:

  • Funding Cost: The minBalanceRequired amount needed to execute your transaction
  • Service Fee: A 8% service fee applied to the funding cost

Example:

// If minBalanceRequired = 0.001 ETH (in wei)
// Funding cost = 0.001 ETH
// Total cost = 0.001 ETH * 1.08 = 0.00108 ETH

The funding cost is deducted from your Tachyon account balance, not from the sender address.

Important Notes

  • The fromAddress must be a valid address for the specified chain
  • The signedTx must be properly signed and ready for broadcast
  • minBalanceRequired should cover the maximum possible gas cost (gasLimit × maxFeePerGas)
  • Tachyon will fund the address before broadcasting, so ensure your account has sufficient balance
  • The transaction type is automatically set to FUNDING_SIGNED
  • Once submitted, you can track the transaction using the same status methods as regular relay transactions

Error Handling

try {
  const txId = await tachyon.relaySignedTx({
    chainId: 8453,
    fromAddress: wallet.address,
    signedTx: signedTx,
    minBalanceRequired: minBalance,
  })
  console.log('Success:', txId)
} catch (error) {
  if (error.message.includes('Invalid from address')) {
    console.error('Address validation failed')
  } else if (error.message.includes('Insufficient balance')) {
    console.error('Not enough balance in Tachyon account')
  } else if (error.message.includes('Cost exceeded')) {
    console.error('Transaction cost exceeds limits')
  } else {
    console.error('Submission failed:', error.message)
  }
}

On this page