> ## Documentation Index
> Fetch the complete documentation index at: https://docs.socket.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# readContract() — SocketFi Read-Only Contract Call

> Run a read-only Soroban smart contract call with no user approval. Fetch balances, metadata, and on-chain state before submitting transactions.

`readContract()` runs a read-only simulation against a Soroban smart contract and returns the result. Unlike `requestTransaction()`, it does not open any popup, does not require the user's approval, and does not submit anything to the Stellar network. It is the right tool whenever you need on-chain data — a token balance, contract configuration, pool state, or any other view function — without changing state or spending gas.

## Method signature

```typescript theme={null}
readContract(req: ReadContractRequest): Promise<unknown>
```

## Parameters

<ParamField path="req" type="ReadContractRequest" required>
  The read request describing the contract and function to simulate.

  <Expandable title="ReadContractRequest fields">
    <ParamField path="req.contractId" type="string" required>
      The Soroban contract address on the Stellar network (e.g. `"CBXXXXXX..."`). Must be a deployed contract on the network configured in your `SocketFi` instance.
    </ParamField>

    <ParamField path="req.method" type="string" required>
      The name of the read-only contract function to invoke (e.g. `"balance"`, `"get_metadata"`, `"allowance"`). This function must not modify contract state.
    </ParamField>

    <ParamField path="req.args" type="unknown[]">
      An optional array of arguments to pass to the contract function. Omit this field if the function takes no parameters.
    </ParamField>
  </Expandable>
</ParamField>

## Return value

`readContract()` returns `Promise<unknown>`. The resolved value is the raw return value of the contract function — the shape depends entirely on the contract you are calling. Cast the result to a known type after calling:

```typescript theme={null}
const balance = await socketfi.readContract({
  contractId: TOKEN_CONTRACT,
  method: 'balance',
  args: [walletAddress],
}) as bigint;
```

## No approval required

Because `readContract()` only simulates execution and never submits a transaction, it requires **no active session and no user interaction**. You can call it at any point — on page load, in the background, or before asking the user to authenticate — to pre-fetch the data your UI needs.

## Examples

### Read a token balance

```typescript theme={null}
import { socketfi } from '@/lib/socketfi';

const balance = await socketfi.readContract({
  contractId: process.env.NEXT_PUBLIC_TOKEN_CONTRACT!,
  method: 'balance',
  args: ['GDZX_WALLET_ADDRESS_HERE'],
}) as bigint;

console.log('Balance (stroops):', balance.toString());
```

### Read token metadata

```typescript theme={null}
const metadata = await socketfi.readContract({
  contractId: process.env.NEXT_PUBLIC_TOKEN_CONTRACT!,
  method: 'token_metadata',
}) as { name: string; symbol: string; decimals: number };

console.log(`${metadata.name} (${metadata.symbol}), decimals: ${metadata.decimals}`);
```

### Read staking pool state

```typescript theme={null}
interface PoolState {
  totalStaked: bigint;
  rewardRate: bigint;
  lastUpdated: number;
}

const pool = await socketfi.readContract({
  contractId: STAKING_CONTRACT,
  method: 'get_pool_state',
}) as PoolState;

console.log('Total staked:', pool.totalStaked.toString());
```

### Read an allowance

```typescript theme={null}
const allowance = await socketfi.readContract({
  contractId: TOKEN_CONTRACT,
  method: 'allowance',
  args: [ownerAddress, spenderAddress],
}) as bigint;
```

### Pre-fetching data before a transaction

A common pattern is to read state first to validate inputs before prompting the user to approve a transaction:

```typescript theme={null}
async function transferTokens(recipient: string, amount: bigint) {
  // Check balance before opening the transaction popup
  const balance = await socketfi.readContract({
    contractId: TOKEN_CONTRACT,
    method: 'balance',
    args: [userWalletAddress],
  }) as bigint;

  if (balance < amount) {
    throw new Error('Insufficient balance');
  }

  // Only now open the transaction approval popup
  return socketfi.requestTransaction({
    contractId: TOKEN_CONTRACT,
    method: 'transfer',
    args: [recipient, amount.toString()],
  });
}
```

## `readContract()` vs `requestTransaction()`

|                          | `readContract()`               | `requestTransaction()`      |
| ------------------------ | ------------------------------ | --------------------------- |
| Modifies contract state  | No                             | Yes                         |
| Requires user approval   | No                             | Yes                         |
| Opens a popup            | No                             | Yes                         |
| Requires active session  | No                             | Yes                         |
| Returns transaction hash | No                             | Yes                         |
| Use for                  | Balances, metadata, view calls | Transfers, staking, minting |

<Tip>
  Use `readContract()` freely — it is cheap, requires no authentication, and carries no risk of unintended state changes. Reach for `requestTransaction()` only when you need to write to the contract.
</Tip>

## TypeScript interface

```typescript theme={null}
interface ReadContractRequest {
  contractId: string;
  method: string;
  args?: unknown[];
}
```
