use-truapi
Contracts

useContractAt

Ad-hoc contract handle from an H160 address and an ABI

useContractAt builds a typed contract handle from a raw H160 address and an ABI, without a cdm.json manifest. data is the same kind of Contract handle useContract returns, so useContractQuery and useContractTx work identically. Reach for it when the address arrives at runtime (user input, route params, a registry lookup) or when you interact with a contract you didn't deploy.

While address is undefined the hook stays disabled (isPending with no fetch), so you can pass a possibly-missing address without guarding. The result is cached under the chain key and the address.

Usage

import { useContractAt, useContractQuery } from "@use-truapi/react";
import { counterAbi } from "./counter-contract";

function CounterAt({ address }: { address?: `0x${string}` }) {
  const contract = useContractAt(address, counterAbi);
  const count = useContractQuery<bigint>(contract.data, "getCount", []);

  if (!address) return <p>Enter a contract address.</p>;
  if (contract.error) return <p>Failed to load contract: {contract.error.message}</p>;

  return <p>Count: {count.data?.toString() ?? "…"}</p>;
}
<script setup lang="ts">
import { useContractAt, useContractQuery } from "@use-truapi/vue";
import { counterAbi } from "./counter-contract";

const props = defineProps<{ address?: `0x${string}` }>();

const contract = useContractAt(() => props.address, counterAbi);
const count = useContractQuery<bigint>(contract, "getCount", []);
</script>

<template>
  <p v-if="!props.address">Enter a contract address.</p>
  <p v-else-if="contract.error">Failed to load contract: {{ contract.error.message }}</p>
  <p v-else>Count: {{ count.data?.toString() ?? "…" }}</p>
</template>

Pass a getter (() => props.address) so the handle re-resolves when the address changes, and pass the whole contract query result to the downstream composables.

To build against a specific chain, pass its key:

const contract = useContractAt(address, counterAbi, { chain: "assetHub" });

See also

API reference

React

function useContractAt(
   address, 
   abi, 
options?): UseQueryResult<Contract<ContractDef>, Error>;

Ad-hoc contract from an H160 address + ABI — no manifest needed.

Parameters

ParameterType
address`0x${string}` | undefined
abiAbiEntry[]
options?{ chain?: string; query?: QueryOptions<Contract<ContractDef>>; }
options.chain?string
options.query?QueryOptions<Contract<ContractDef>>

Returns

UseQueryResult<Contract<ContractDef>, Error>

Vue

function useContractAt(
   address, 
   abi, 
options?): QueryResult<Contract<ContractDef>>;

Ad-hoc contract from an H160 address + ABI — no manifest needed.

Parameters

ParameterType
addressMaybeGetter<`0x${string}` | undefined>
abiAbiEntry[]
options?{ chain?: string; query?: QueryOptions<Contract<ContractDef>>; }
options.chain?string
options.query?QueryOptions<Contract<ContractDef>>

Returns

QueryResult<Contract<ContractDef>>

On this page