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

# TxBuilder

> Fluent builder for batching StarkNet multicalls into atomic transactions with fee estimation.

<Warning>
  `@chipi-stack/core` is in development (v0.1.0). APIs may change before stable release.
</Warning>

## Overview

`TxBuilder` provides a fluent API for composing multiple StarkNet calls into a single atomic transaction. All calls execute together via `Account.execute()`, which is more gas-efficient than separate transactions (important when sponsoring gas via a paymaster).

## Usage

```typescript theme={null}
import { TxBuilder } from "@chipi-stack/core";
import type { Account } from "starknet";

const result = await new TxBuilder(account)
  .approve(tokenAddr, spenderAddr, amount)
  .transfer(tokenAddr, [{ to: recipient, amount: 1_000_000n }])
  .send();

console.log(result.transaction_hash);
```

## Constructor

```typescript theme={null}
new TxBuilder(account: Account, opts?: { paymaster?: PaymasterAdapter })
```

### Parameters

* `account` (Account): A starknet.js `Account` instance
* `opts.paymaster` (PaymasterAdapter, optional): Adapter for gasless transactions via `sendSponsored()`

## Methods

### `add(call)`

Add one or more raw StarkNet calls to the batch.

```typescript theme={null}
builder.add({
  contractAddress: "0x...",
  entrypoint: "swap",
  calldata: [tokenIn, tokenOut, amountIn, "0"],
});

// Or add multiple at once
builder.add([call1, call2, call3]);
```

#### Parameters

* `call` (Call | Call\[]): A single Call or array of Calls

#### Returns

`this` (chainable)

### `approve(token, spender, amount)`

Add an ERC20 approve call. Handles uint256 encoding automatically.

```typescript theme={null}
builder.approve(USDC_ADDRESS, DEX_ADDRESS, 1_000_000n);
```

#### Parameters

* `token` (string): Token contract address
* `spender` (string): Address to approve
* `amount` (bigint): Raw amount in base units

#### Returns

`this` (chainable)

### `transfer(token, targets)`

Add one or more ERC20 transfer calls.

```typescript theme={null}
builder.transfer(USDC_ADDRESS, [
  { to: "0xalice...", amount: 500_000n },
  { to: "0xbob...", amount: 300_000n },
]);
```

#### Parameters

* `token` (string): Token contract address
* `targets` (TransferTarget\[]): Array of `{ to: string, amount: bigint }` pairs

#### Returns

`this` (chainable)

### `calls()`

Returns a copy of the current call batch (for inspection).

```typescript theme={null}
const currentCalls = builder.calls();
console.log(`${currentCalls.length} calls queued`);
```

#### Returns

`Call[]`

### `send()`

Execute all batched calls atomically.

```typescript theme={null}
const result = await builder.send();
console.log(result.transaction_hash);
```

#### Returns

`Promise<InvokeFunctionResponse>`

#### Throws

* If no calls have been added
* If `send()` was already called (builders are single-use)

### `sendSponsored()`

Execute via Chipi's paymaster (gasless). Requires a `PaymasterAdapter` in the constructor.

```typescript theme={null}
const txHash = await builder.sendSponsored();
console.log(txHash); // "0x..."
```

#### Returns

`Promise<string>` (transaction hash)

#### Throws

* If no `paymaster` was configured in the constructor
* If no calls have been added
* If `send()` or `sendSponsored()` was already called (builders are single-use)

### `estimateFee()`

Estimate the fee for the current batch without executing.

```typescript theme={null}
const fee = await builder.estimateFee();
console.log(`Estimated fee: ${fee.overall_fee} wei`);
```

#### Returns

`Promise<EstimateFeeResponse>`

#### Throws

* If no calls have been added

### `preflight()`

Simulate the transaction without submitting. Returns the transaction trace and fee estimation. Useful for checking if a transaction would succeed before sending.

```typescript theme={null}
const sim = await builder.preflight();
console.log(`Would cost: ${sim.fee_estimation.overall_fee} wei`);
```

#### Returns

`Promise<PreflightResult>` with `transaction_trace` and `fee_estimation`

#### Throws

* If no calls have been added

## Examples

### Simple Transfer

```typescript theme={null}
const result = await new TxBuilder(account)
  .transfer(USDC_ADDRESS, [{ to: recipient, amount: 1_500_000n }])
  .send();
```

### Approve + Swap (Atomic Batch)

```typescript theme={null}
const result = await new TxBuilder(account)
  .approve(USDC_ADDRESS, DEX_ADDRESS, 1_000_000n)
  .add({
    contractAddress: DEX_ADDRESS,
    entrypoint: "swap",
    calldata: [USDC_ADDRESS, ETH_ADDRESS, "1000000", "0"],
  })
  .send();
```

### Fee Preview Before Sending

```typescript theme={null}
const builder = new TxBuilder(account)
  .transfer(USDC_ADDRESS, [{ to, amount }]);

const fee = await builder.estimateFee();
console.log(`This will cost: ${fee.overall_fee} wei`);

// User confirms, create new builder to send
const result = await new TxBuilder(account)
  .transfer(USDC_ADDRESS, [{ to, amount }])
  .send();
```

### With Erc20 and Amount

```typescript theme={null}
import { TxBuilder, Erc20, Amount, TokenRegistry } from "@chipi-stack/core";

const registry = new TokenRegistry("mainnet");
const usdcInfo = registry.bySymbol("USDC")!;
const usdc = new Erc20(usdcInfo, account);
const amount = Amount.parse("50.0", usdcInfo);

const result = await new TxBuilder(account)
  .add(usdc.approveCall(spender, amount))
  .add(usdc.transferCall(recipient, amount))
  .send();
```

### Gasless with Argent X / Braavos (browser)

```typescript theme={null}
import { connect } from "starknetkit";
import { TxBuilder } from "@chipi-stack/core";
import { ChipiBrowserSDK } from "@chipi-stack/backend";

const { wallet } = await connect();
const sdk = new ChipiBrowserSDK({ apiPublicKey: "pk_..." });
const paymaster = sdk.createPaymasterAdapter(userBearerToken);

// wallet.account already has the Argent/Braavos signer — triggers popup on sign
const txHash = await new TxBuilder(wallet.account, { paymaster })
  .transfer(USDC, [{ to: recipient, amount: 1_000_000n }])
  .sendSponsored(); // popup -> sign -> gasless execution
```

### Gasless with Cartridge Controller

```typescript theme={null}
import Controller from "@cartridge/controller";
import { TxBuilder } from "@chipi-stack/core";
import { ChipiBrowserSDK } from "@chipi-stack/backend";

const controller = new Controller();
await controller.connect();

const sdk = new ChipiBrowserSDK({ apiPublicKey: "pk_..." });
const paymaster = sdk.createPaymasterAdapter(userBearerToken);

// controller IS Account-compatible
const txHash = await new TxBuilder(controller, { paymaster })
  .transfer(USDC, [{ to, amount }])
  .sendSponsored();
```

### Backend Automation (gasless)

```typescript theme={null}
import { createAccount, DirectSigner, TxBuilder } from "@chipi-stack/core";
import { ChipiServerSDK } from "@chipi-stack/backend";

const sdk = new ChipiServerSDK({ apiPublicKey: "pk_...", apiSecretKey: "sk_..." });
const paymaster = sdk.createPaymasterAdapter();

const provider = { nodeUrl: "https://starknet-mainnet.infura.io/v3/YOUR_KEY" };
const accountAddress = "0xYOUR_ACCOUNT_ADDRESS";
const signer = new DirectSigner(process.env.AUTOMATION_KEY!, accountAddress);
const account = await createAccount({ signer, provider });

const txHash = await new TxBuilder(account, { paymaster })
  .approve(USDC, spender, amount)
  .transfer(USDC, [{ to, amount }])
  .sendSponsored(); // gasless, no popup
```

## Related

* [Amount](/sdk/core/amount): Type-safe token amounts for use with TxBuilder
* [Erc20](/sdk/core/erc20): Generate typed Call objects for approve/transfer
* [SignerAdapter](/sdk/core/signer-adapter): Different signing strategies for the Account
