# Read Contracts

URL: https://docs.blux.cc/javascript/core/readContracts

Read state from Soroban smart contracts by simulating contract calls.

`readContracts` is a **Soroban** helper that reads data from one or more smart contracts. It builds each call, simulates it against the network (no signature, no fee, no on-chain state change), and returns the decoded results. Use it for any read-only contract method — token balances, metadata, pool reserves, configuration, and so on.

It accepts an **array of calls** and runs them in parallel, so you can batch several reads in a single request. For one call, use [`readContract`](/javascript/core/readContract) — it takes a single call and returns `{ raw, value }` instead of arrays.

<Callout type="info">
  `readContracts` simulates against a null source account, so it never spends fees or requires the user to be connected. For methods that mutate state, use [`writeContract`](/javascript/core/writeContract).
</Callout>

## Type
```ts
type IContractCall = {
  address: string;   // C… contract ID, SEP-2 address, or .xlm name
  fn: string;        // function name to invoke
  args: unknown[];   // native values in the function's positional order
};

type ReadContractsOptions = {
  network?: string;    // Omit to use the active network
};

// Returns the simulation objects and the decoded native values,
// index-aligned with the calls you passed in.
type ReadContractsResult<TValues extends readonly unknown[]> = {
  raws: SimulateTransactionResponse[];
  values: TValues;
};

const readContracts: <TValues extends readonly unknown[] = readonly unknown[]>(
  calls: IContractCall[],
  options?: ReadContractsOptions,
) => Promise<ReadContractsResult<TValues>>;
```

## Native contract arguments

Pass ordinary JavaScript values in the same order as the contract function's parameters. Blux loads the deployed contract spec and encodes every value as the declared Soroban type, so `args` does not require the `ToScVal` class.

```ts
args: [
  "alice.xlm",      // resolved and encoded when the spec declares Address
  "1000000000",     // encoded as i128 when the spec declares i128
  true,              // encoded as bool when the spec declares bool
]
```

Common native values include:

| Soroban parameter | JavaScript value |
|---|---|
| Address, string, or symbol | `string` |
| Boolean | `boolean` |
| Integer | Safe `number`, `bigint`, or decimal `string` |
| Bytes | `Uint8Array` |
| Vector or tuple | `Array` |
| Map | `Map` or an array of `[key, value]` entries |
| Struct | An object or tuple matching the contract definition |

For wide integers such as `i128`, prefer a `bigint` or decimal string so the value cannot lose precision. Argument count, order, and shape must still match the contract spec.

Address-typed values accept `G…`, `C…`, SEP-2 federation addresses, and `.xlm`
names. Resolution also works when an ABI `Address` is nested in an option,
vector, tuple, map, struct, or union. See [address resolution](/javascript/core/address-resolution).

<Callout type="info">
  Existing code may continue passing pre-encoded `xdr.ScVal` arguments. Native values and pre-encoded values can also be mixed, but manual encoding is no longer required.
</Callout>

## Usage

Read a single value — for example a token's `balance`:

```ts

const { values } = await core.readContracts<[string]>([
  {
    address: "CB64D3G7SM2RTH6JSGG34DDTFTQ5CFDKVDZJZSODMCX4NJ2HV2KN7OG",
    fn: "balance",
    args: ["alice.xlm"],
  },
]);

console.log(values[0]); // decoded balance, e.g. "1000000000"
```

Batch several reads at once — results are index-aligned with the calls:

```ts

const TOKEN = "CB64D3G7SM2RTH6JSGG34DDTFTQ5CFDKVDZJZSODMCX4NJ2HV2KN7OG";

const { values } = await core.readContracts<[string, number, string]>([
  { address: TOKEN, fn: "name", args: [] },
  { address: TOKEN, fn: "decimals", args: [] },
  { address: TOKEN, fn: "balance", args: ["GA...USER"] },
]);

const [name, decimals, balance] = values;
```

## Return types

The deployed ABI is loaded at runtime, so TypeScript cannot infer a return type
from runtime `address`, `fn`, and `network` strings. Pass one tuple generic for
the batch, in the same order as the calls:

```ts
const result = await core.readContracts<[string, number, string]>(calls);

result.values[0]; // string
result.values[1]; // number
result.values[2]; // string
```

Omit the generic when the return shapes are not known; values are then
`readonly unknown[]`. Include `null` in an entry's type when that function can
return no value.

<Callout type="info">
  `bigint` results are returned as strings so they're safe to serialize. The raw simulation objects are available under `raws` if you need footprint or resource details.
</Callout>