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

# contracts: Accessors, calls and derivation

> Accessors, calls and derivation: the declaration and description of each of the 30 exports of @eco-incorp/sauce.

The `contracts` namespace describes each registry protocol's contracts: per-chain addresses, each bound to the ABI the registry checked against the deployed code. `contracts.on(chain)` returns typed accessors (`contracts.on("base").Uniswap.UniversalRouter`) whose methods build `ContractCall` objects you run with your own viem client.

```typescript theme={null}
import { contracts } from "@eco-incorp/sauce";
```

Generated from the type declarations of `@eco-incorp/sauce`.

### `contracts.chainContracts`

*Function* · `@eco-incorp/sauce`

Builds the whole lazy tree for one resolved chain.

```typescript theme={null}
export declare function chainContracts(chainRef: ChainRef): ChainContracts;
```

### `contracts.on`

*Function* · `@eco-incorp/sauce`

Chain-ref front door: `contracts.on('base').Uniswap.UniversalRouter.execute(...)` - for a
caller resolving the chain at run time rather than importing the `Base` accessor.

```typescript theme={null}
export declare function on(chainRef: ChainRef): ChainContracts;
```

### `contracts.AddressOnlyContract`

*Type* · `@eco-incorp/sauce`

A contract the registry has an address for and no ABI: `.address` and `.available`, no methods.

```typescript theme={null}
export type AddressOnlyContract = ContractAccessor<readonly [
]>;
```

### `contracts.Contract`

*Type* · `@eco-incorp/sauce`

A contract with an ABI: its accessor properties and its methods.

```typescript theme={null}
export type Contract<TAbi extends Abi = Abi> = ContractAccessor<TAbi> & ContractMethods<TAbi>;
```

### `contracts.ContractAccessor`

*Type* · `@eco-incorp/sauce`

One leaf's own properties: a (protocol, contract) on a specific chain. Its methods are separate
(`ContractMethods`): `Contract` is the two together. A type rather than an interface, so a
contract typed from its ABI is assignable to the untyped `Contract`.

```typescript theme={null}
export type ContractAccessor<TAbi extends Abi = Abi> = {
    readonly descriptor: ContractDescriptor;
    readonly chain: CanonicalChain;
    readonly address: Address | undefined;
    readonly available: boolean;
    readonly chains: readonly ChainSlug[];
    readonly coverage: ContractCoverage;
    readonly abi: TAbi;
    readonly methods: readonly DescriptorMethod[];
    at(address: Address): Contract<TAbi>;
};
```

### `contracts.ContractMethod`

*Type* · `@eco-incorp/sauce`

One ABI method: takes the ABI's arguments and returns the call, typed from the ABI.

```typescript theme={null}
export type ContractMethod<TAbi extends Abi, TName extends ContractFunctionName<TAbi>> = <const TArgs extends ContractFunctionArgs<TAbi, AbiStateMutability, TName> & readonly unknown[]>(...args: TArgs) => ContractCall<TAbi, TName, TArgs>;
```

### `contracts.ContractMethods`

*Type* · `@eco-incorp/sauce`

Every function of `TAbi`, by its ABI name. An untyped ABI has an index of `unknown` instead.

```typescript theme={null}
export type ContractMethods<TAbi extends Abi> = Abi extends TAbi ? {
    readonly [method: string]: unknown;
} : {
    readonly [N in FunctionNameOf<TAbi> & ContractFunctionName<TAbi>]: ContractMethod<TAbi, N>;
};
```

### `contracts.InterfaceContract`

*Type* · `@eco-incorp/sauce`

An ABI with no fixed address: bind a deployment with `.at(address)` to call it.

```typescript theme={null}
export type InterfaceContract<TAbi extends Abi> = ContractAccessor<TAbi>;
```

### `contracts.makeContractCall`

*Function* · `@eco-incorp/sauce`

```typescript theme={null}
export declare function makeContractCall(descriptor: ContractDescriptor, chain: CanonicalChain, address: Address, method: DescriptorMethod, args: readonly unknown[]): ContractCall;
```

### `contracts.ContractCall`

*Type* · `@eco-incorp/sauce`

A call to one registry method, typed from the method's ABI where the accessor knows it
(`Base.UniswapV3.QuoterV2.quoteExactInputSingle(...)`). Every call has `read`; a state-changing
one also has `simulate` and `write`. Untyped (`ContractCall`), it carries all three, and
`simulate`/`write` on a view or pure method throw.

```typescript theme={null}
export type ContractCall<TAbi extends Abi = Abi, TName extends string = string, TArgs = readonly unknown[]> = ContractCallBase & ReadActions<TAbi, TName, TArgs> & (Abi extends TAbi ? WriteActions<TAbi, TName, TArgs> : TName extends NamesOf<TAbi, ReadMutability> ? unknown : WriteActions<TAbi, TName, TArgs>);
```

### `contracts.ContractCallBase`

*Interface* · `@eco-incorp/sauce`

Every field of a call, whatever its method's mutability.

```typescript theme={null}
export interface ContractCallBase {
    readonly chain: CanonicalChain;
    readonly protocol: string;
    readonly contract: string;
    readonly address: Address;
    readonly method: DescriptorMethod;
    readonly args: readonly unknown[];
    readonly fidelity: "exact" | "widened";
    readonly caveats: readonly string[];
    readonly data: Hex;
    encode(opts?: EncodeOptions): Hex;
    toCall(opts?: EncodeOptions): {
        readonly target: Address;
        readonly data: Hex;
        readonly value: bigint;
    };
    toSauceScript(opts?: SauceScriptOptions): {
        readonly imports: readonly string[];
        readonly statement: string;
        readonly source: string;
    };
}
```

### `contracts.EncodeOptions`

*Interface* · `@eco-incorp/sauce`

```typescript theme={null}
export interface EncodeOptions {
    readonly allowWidened?: boolean;
    readonly value?: bigint;
}
```

### `contracts.ReadActions`

*Interface* · `@eco-incorp/sauce`

```typescript theme={null}
export interface ReadActions<TAbi extends Abi, TName extends string, TArgs> {
    read(client: Client): Promise<ReadResult<TAbi, TName, TArgs>>;
}
```

### `contracts.ReadResult`

*Type* · `@eco-incorp/sauce`

What `read` resolves to: the method's ABI outputs, decoded by viem.

```typescript theme={null}
export type ReadResult<TAbi extends Abi, TName extends string, TArgs> = TName extends ContractFunctionName<TAbi> ? TArgs extends ContractFunctionArgs<TAbi, AbiStateMutability, TName> ? ContractFunctionReturnType<TAbi, AbiStateMutability, TName, TArgs> : unknown : unknown;
```

### `contracts.SauceScriptOptions`

*Interface* · `@eco-incorp/sauce`

```typescript theme={null}
export interface SauceScriptOptions {
    readonly binding?: string;
}
```

### `contracts.SimulateOptions`

*Interface* · `@eco-incorp/sauce`

```typescript theme={null}
export interface SimulateOptions {
    readonly account: Account | Address;
    readonly value?: bigint;
}
```

### `contracts.SimulateResult`

*Type* · `@eco-incorp/sauce`

What `simulate` resolves to: viem's `{ result, request }`, `result` decoded from the outputs.

```typescript theme={null}
export type SimulateResult<TAbi extends Abi, TName extends string, TArgs> = TName extends NamesOf<TAbi, WriteMutability> & ContractFunctionName<TAbi, WriteMutability> ? TArgs extends ContractFunctionArgs<TAbi, WriteMutability, TName> ? SimulateContractReturnType<TAbi, TName, TArgs> : SimulateContractReturnType : SimulateContractReturnType;
```

### `contracts.WriteActions`

*Interface* · `@eco-incorp/sauce`

```typescript theme={null}
export interface WriteActions<TAbi extends Abi, TName extends string, TArgs> {
    simulate(client: Client, options: SimulateOptions): Promise<SimulateResult<TAbi, TName, TArgs>>;
    write(client: Client, options?: WriteOptions): Promise<Hash>;
}
```

### `contracts.WriteOptions`

*Interface* · `@eco-incorp/sauce`

```typescript theme={null}
export interface WriteOptions {
    readonly account?: Account | Address;
    readonly value?: bigint;
}
```

### `contracts.ContractNameOf`

*Type* · `@eco-incorp/sauce`

Every contract literally linked under protocol `P`, e.g. `ContractNameOf<"uniswap-v4">` = "PoolManager" | "UniversalRouter" | "PositionManager".

```typescript theme={null}
export type ContractNameOf<P extends ProtocolSlug> = LinkOf<P>["contract"];
```

### `contracts.FamilyContracts`

*Type* · `@eco-incorp/sauce`

Contract names safely exposed on family alias `F` - a strict ALLOWLIST:
a name owned by exactly ONE family member passes through; a name owned by
two or more (e.g. "Factory" under "Uniswap", present in both uniswap-v2
and uniswap-v3) resolves its own mapped-type branch to `never` and is
dropped from the union entirely. Fail-closed by construction, not by
enumerating known-bad names.

```typescript theme={null}
export type FamilyContracts<F extends FamilyKey> = {
    [N in FamilyLinksOf<F>["contract"]]: IsUnion<Extract<FamilyLinksOf<F>, {
        contract: N;
    }>["protocol"]> extends true ? never : N;
}[FamilyLinksOf<F>["contract"]];
```

### `contracts.FamilyKey`

*Type* · `@eco-incorp/sauce`

Every family alias key actually present in the starter set, e.g. "Uniswap" | "Aave" | "Compound" | ...

```typescript theme={null}
export type FamilyKey = {
    [P in ProtocolSlug]: FamilyOf<P>;
}[ProtocolSlug];
```

### `contracts.FamilyOf`

*Type* · `@eco-incorp/sauce`

The PascalCase family alias a protocol slug belongs to, or `never` if it has none.

```typescript theme={null}
export type FamilyOf<P extends ProtocolSlug> = StripV<P> extends never ? never : PascalOf<StripV<P>>;
```

### `contracts.ProtocolNamespaceKey`

*Type* · `@eco-incorp/sauce`

`PascalOf<ProtocolSlug>` - the CANONICAL namespace key, e.g. "UniswapV4". Always unambiguous.

```typescript theme={null}
export type ProtocolNamespaceKey = PascalOf<ProtocolSlug>;
```

### `contracts.ProtocolSlug`

*Type* · `@eco-incorp/sauce`

The literal protocol-slug union underlying the starter set, e.g. "uniswap-v4" | ... | "erc4626".

```typescript theme={null}
export type ProtocolSlug = Links["protocol"];
```

### `contracts.buildDescriptor`

*Function* · `@eco-incorp/sauce`

Assembles one full ContractDescriptor from a link entry plus the protocol's already-resolved data.
`deployments` defaults to the protocol's catalog deployments; `returns` is the contracts the ABI's
methods return, by signature (`RETURNED_CONTRACTS`). Methods, addresses and coverage are computed
when first read: the registry holds about 300 contracts, and a program names a few.

```typescript theme={null}
export declare function buildDescriptor(link: ContractLink, protocolInfo: ProtocolInfo, abi: Abi | undefined, deployments?: readonly ChainDeployment[], returns?: ReadonlyMap<string, readonly MethodReturn[]>): ContractDescriptor;
```

### `contracts.buildMethods`

*Function* · `@eco-incorp/sauce`

ABI -> ordered DescriptorMethod\[] (no name-collapse: an overloaded name appears once per overload, which the linkage test holds to distinct argument counts).

```typescript theme={null}
export declare function buildMethods(abi: Abi): DescriptorMethod[];
```

### `contracts.buildPerChainAddress`

*Function* · `@eco-incorp/sauce`

role key -> sparse, EIP-55-checksummed per-chain address map, over canonical EVM chains (a Solana
program id under the same role is no EVM contract). `undefined` roleKey (kind:"interface") -> \{}.
`chains` narrows it to the deployments one ABI binding covers.

```typescript theme={null}
export declare function buildPerChainAddress(chains: readonly ChainDeployment[], roleKey: string | undefined, only?: readonly number[]): Record<number, Address>;
```

### `contracts.deriveChainSlugs`

*Function* · `@eco-incorp/sauce`

Sparse per-chain address map -> the chain slugs it resolves to, id-ascending. Fails closed (throws) on an id the canonical registry doesn't know - see test invariant #6.

```typescript theme={null}
export declare function deriveChainSlugs(perChainAddress: Readonly<Record<number, Address>>): ChainSlug[];
```

### `contracts.deriveContractName`

*Function* · `@eco-incorp/sauce`

An ABI export's contract name: the export without its trailing "ABI" and without the protocol's
own prefix - its display name squashed ("Uniswap V4"), or its slug's PascalCase ("arrakis" for
"Arrakis Finance") - e.g. "UniswapV4UniversalRouterABI" under "Uniswap V4" is "UniversalRouter".
A prefix is stripped only where a word follows it. This names the registry's interfaces, and a role
bound to different ABIs on different chains; every other contract is named after its role key
(see links.ts). `scripts/gen-source-globals.mjs` applies the same rule.

```typescript theme={null}
export declare function deriveContractName(protocolName: string, abiExport: string, slug?: string): string;
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.