> ## 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: 20 exports of the contracts module of @eco-incorp/sauce, including buildDescriptor, buildMethods, buildPerChainAddress, deriveChainSlugs, deriveContractName, chainContracts.

The `contracts` namespace describes protocol contracts as descriptors (ABI, methods, per-chain addresses) and exposes them as typed accessors route bodies can call.

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

This page covers `sdk/dist/descriptors/derive.d.ts`, `sdk/dist/descriptors/accessors.d.ts`, `sdk/dist/descriptors/call.d.ts`, `sdk/dist/descriptors/names.d.ts`.

<Note>
  Generated from the type declarations shipped in `@eco-incorp/sauce` 0.99.4. Each entry shows the package authors' JSDoc and declaration for this SDK version. For runtime compatibility and deployed addresses, see [architecture and deployments](/programmable-transactions/sauce/architecture-and-deployments).
</Note>

### `contracts.buildDescriptor`

*Function* · `sdk/dist/descriptors/derive.d.ts`

Assembles one full ContractDescriptor from a link entry plus the protocol's already-resolved data.

```typescript theme={null}
export declare function buildDescriptor(link: ContractLink, protocolInfo: ProtocolInfo, abi: Abi | undefined): ContractDescriptor;
```

### `contracts.buildMethods`

*Function* · `sdk/dist/descriptors/derive.d.ts`

ABI -> ordered DescriptorMethod\[] (no name-collapse - an overloaded name would appear twice, see the linkage test's zero-overload invariant).

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

### `contracts.buildPerChainAddress`

*Function* · `sdk/dist/descriptors/derive.d.ts`

role key -> sparse, EIP-55-checksummed per-chain address map. `undefined` roleKey (kind:"interface") -> \{}.

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

### `contracts.deriveChainSlugs`

*Function* · `sdk/dist/descriptors/derive.d.ts`

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* · `sdk/dist/descriptors/derive.d.ts`

Default contract-name derivation: `abiExport` minus its trailing "ABI"
minus the protocol-name prefix, e.g. "UniswapV4UniversalRouterABI" with
protocol name "Uniswap V4" -> "UniversalRouter". Only used when the link
carries no explicit `contract` override (see links.ts's module comment for
why 6 of the 29 starter entries need one).

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

### `contracts.chainContracts`

*Function* · `sdk/dist/descriptors/accessors.d.ts`

Builds the whole lazy tree for one resolved chain. Every canonical
protocol namespace is memoised once per `chainContracts` call, so a family
alias resolving a non-ambiguous name (`Base.Uniswap.UniversalRouter`)
forwards to the EXACT SAME accessor object as the canonical path
(`Base.UniswapV4.UniversalRouter`) - verified by identity in
`test/descriptors-accessors.test.ts`.

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

### `contracts.on`

*Function* · `sdk/dist/descriptors/accessors.d.ts`

Import-based front door (option-b): `contracts.on('base').Uniswap.UniversalRouter.execute(...)`.
Escape hatch for `__ECO_ROUTES_NO_GLOBALS__` hosts and for the TS2451 own-`const Base` caveat.

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

### `contracts.ChainContracts`

*Type* · `sdk/dist/descriptors/accessors.d.ts`

The whole typed tree `chainContracts(...)` returns - chain-INDEPENDENT by
design (per-chain address presence is runtime data, not literally typed;
see the design doc's `ChainContracts` note), so it instantiates once
regardless of how many chain globals intersect it.

```typescript theme={null}
export type ChainContracts = {
    readonly [P in ProtocolSlug as PascalOf<P>]: {
        readonly [C in ContractNameOf<P>]: ContractAccessor;
    };
} & {
    readonly [F in FamilyKey]: {
        readonly [C in FamilyContracts<F>]: ContractAccessor;
    };
};
```

### `contracts.ContractAccessor`

*Interface* · `sdk/dist/descriptors/accessors.d.ts`

One leaf: a bound (protocol, contract) on a specific chain, plus every
real ABI method as a callable producing a `ContractCall`. Method names are
NOT part of the static type (kept loose as `unknown` via the index
signature below) - they are derived from the descriptor's real ABI at
BUILD time, so `Base.UniswapV4.UniversalRouter.execute(...)` resolves a
real method and `.exactIn` is `undefined`, matching E2.2's "surface what
exists, invent nothing" stance.

```typescript theme={null}
export interface ContractAccessor {
    readonly descriptor: ContractDescriptor;
    readonly chain: CanonicalChain;
    readonly address: Address | undefined;
    readonly available: boolean;
    readonly chains: readonly ChainSlug[];
    readonly coverage: ContractCoverage;
    readonly abi: Abi;
    readonly methods: readonly DescriptorMethod[];
    at(address: Address): ContractAccessor;
    readonly [method: string]: unknown;
}
```

### `contracts.makeContractCall`

*Function* · `sdk/dist/descriptors/call.d.ts`

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

### `contracts.CONTRACT_BASE_DIRS`

*Variable* · `sdk/dist/descriptors/call.d.ts`

`baseDirs` for compiling a `toSauceScript()` program - same two-entry
shape (dist root + shipped `sdk/src`) and rationale as
`deposit/source.ts`'s `DEPOSIT_BASE_DIRS`: a contract's `.json` import
resolves against the SDK's protocol registry, not the engine-vendored
`dist/artifacts`.

```typescript theme={null}
CONTRACT_BASE_DIRS: readonly string[]
```

### `contracts.ContractCall`

*Interface* · `sdk/dist/descriptors/call.d.ts`

```typescript theme={null}
export interface ContractCall {
    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;
        readonly baseDirs: readonly string[];
    };
}
```

### `contracts.EncodeOptions`

*Interface* · `sdk/dist/descriptors/call.d.ts`

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

### `contracts.SauceScriptOptions`

*Interface* · `sdk/dist/descriptors/call.d.ts`

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

### `contracts.ContractNameOf`

*Type* · `sdk/dist/descriptors/names.d.ts`

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* · `sdk/dist/descriptors/names.d.ts`

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* · `sdk/dist/descriptors/names.d.ts`

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* · `sdk/dist/descriptors/names.d.ts`

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* · `sdk/dist/descriptors/names.d.ts`

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

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

### `contracts.ProtocolSlug`

*Type* · `sdk/dist/descriptors/names.d.ts`

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

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