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

# BuildRaw

> /instructions/build-raw

This instruction type enables contract interactions using pre-encoded calldata. Provide raw hex-encoded function calls for maximum control over the exact calldata being executed.

## How It Works

The build-raw flow:

1. **Accepts pre-encoded calldata** - Raw hex strings representing complete function calls
2. **Validates calldata format** - Ensures proper hex encoding
3. **Generates instructions** - Creates executable MEE instructions
4. **Enables composition** - Combines with other flow types seamlessly

## When to Use BuildRaw

<CardGroup cols={2}>
  <Card title="✅ Use BuildRaw When">
    * You have pre-generated calldata from another system
    * You need exact control over the calldata format
    * You're migrating from a system that already encodes calldata
    * You want to avoid ABI parsing overhead client-side
  </Card>

  <Card title="❌ Use /instructions/build Instead">
    * You need runtime balance injection
    * You want the API to handle encoding
    * You prefer working with function signatures
    * You want more readable code
  </Card>
</CardGroup>

## Key Differences from Build

| Feature         | `/instructions/build`     | `/instructions/build-raw` |
| --------------- | ------------------------- | ------------------------- |
| Input           | Function signature + args | Pre-encoded calldata      |
| Runtime Balance | ✅ Supported               | ❌ **NOT Supported**       |
| Client Encoding | API encodes               | Client encodes            |
| Use Case        | Most common operations    | Advanced/custom calldata  |

<Warning>
  **Critical Limitation**: BuildRaw does **NOT** support runtime balance injection. The calldata must be fully encoded client-side with concrete values. If you need runtime balance (e.g., transferring all remaining tokens), use `/instructions/build` instead.
</Warning>

## Parameters

When using `/instructions/build-raw` in your `composeFlows` array:

| Parameter  | Type   | Required | Description                                                |
| ---------- | ------ | -------- | ---------------------------------------------------------- |
| `data`     | string | Yes      | Pre-encoded calldata as hex string (e.g., "0xa9059cbb...") |
| `to`       | string | Yes      | Target contract address (checksummed)                      |
| `chainId`  | number | Yes      | Chain ID for execution                                     |
| `value`    | string | No       | Native token value in wei (default: "0")                   |
| `gasLimit` | string | No       | Gas limit override                                         |

## Complete Workflow Examples

<Tabs>
  <Tab title="Simple ERC20 Transfer">
    **Transfer tokens using pre-encoded calldata**

    ```typescript theme={null}
    import { createWalletClient, http, parseUnits, encodeFunctionData, parseAbi } from 'viem';
    import { privateKeyToAccount } from 'viem/accounts';
    import { base } from 'viem/chains';

    const account = privateKeyToAccount('0x...');
    const walletClient = createWalletClient({
      account,
      chain: base,
      transport: http()
    });

    // Encode the calldata client-side
    const transferAbi = parseAbi(['function transfer(address to, uint256 value)']);
    const transferCalldata = encodeFunctionData({
      abi: transferAbi,
      functionName: 'transfer',
      args: [
        '0x742d35cc6639cb8d4b5d1c5d7b8b5e2e7c0c7a8a',  // Recipient
        parseUnits('100', 6)                              // Amount (must be concrete)
      ],
    });

    // Build quote request using build-raw
    const quoteRequest = {
      mode: 'smart-account',
      ownerAddress: account.address,
      composeFlows: [
        {
          type: '/instructions/build-raw',
          data: {
            to: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',  // USDC on Base
            data: transferCalldata,                             // Pre-encoded calldata
            chainId: 8453
          }
        }
      ]
    };

    // Get quote
    const quote = await fetch('https://api.biconomy.io/v1/quote', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(quoteRequest)
    }).then(r => r.json());

    // Then sign and POST to /v1/execute
    ```
  </Tab>

  <Tab title="WETH Deposit with Value">
    **Deposit ETH to WETH contract**

    ```typescript theme={null}
    import { encodeFunctionData, parseAbi, parseUnits } from 'viem';

    // Encode WETH deposit
    const wethAbi = parseAbi(['function deposit()']);
    const depositCalldata = encodeFunctionData({
      abi: wethAbi,
      functionName: 'deposit',
    });

    const quoteRequest = {
      mode: 'smart-account',
      ownerAddress: account.address,
      composeFlows: [
        {
          type: '/instructions/build-raw',
          data: {
            to: '0x4200000000000000000000000000000000000006',  // WETH on Base
            data: depositCalldata,
            chainId: 8453,
            value: parseUnits('1', 18).toString(),             // Send 1 ETH
            gasLimit: '100000'
          }
        }
      ]
    };

    // Then quote → sign → execute
    ```
  </Tab>

  <Tab title="Combining with /build">
    **Use build-raw for static calls, /build for dynamic amounts**

    ```typescript theme={null}
    import { encodeFunctionData, parseAbi, parseUnits } from 'viem';

    // Encode approve calldata with concrete amount
    const approveAbi = parseAbi(['function approve(address spender, uint256 amount)']);
    const approveCalldata = encodeFunctionData({
      abi: approveAbi,
      functionName: 'approve',
      args: [
        '0x...spenderAddress',
        parseUnits('100', 6)  // Concrete approval amount
      ],
    });

    const quoteRequest = {
      mode: 'eoa',
      ownerAddress: account.address,
      fundingTokens: [{
        tokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
        chainId: 8453,
        amount: parseUnits('100', 6).toString()
      }],
      composeFlows: [
        // Use build-raw for approval with fixed amount
        {
          type: '/instructions/build-raw',
          data: {
            to: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
            data: approveCalldata,
            chainId: 8453
          }
        },
        // Use /build for withdrawal with runtime balance
        {
          type: '/instructions/build',
          data: {
            functionSignature: 'function transfer(address to, uint256 value)',
            args: [
              account.address,
              {
                type: 'runtimeErc20Balance',
                tokenAddress: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
                constraints: { gte: '1' }
              }
            ],
            to: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
            chainId: 8453
          }
        }
      ]
    };

    // Then quote → sign → execute
    ```
  </Tab>
</Tabs>

## BuildRaw vs Build Decision Guide

```typescript theme={null}
// ❌ CANNOT use buildRaw for runtime balance
{
  type: '/instructions/build-raw',  // Wrong! Runtime balance not supported
  data: {
    to: tokenAddress,
    data: encodeFunctionData({
      abi: [...],
      functionName: 'transfer',
      args: [recipient, { type: 'runtimeErc20Balance', ... }]  // Error!
    }),
    chainId: 8453
  }
}

// ✅ Use /build for runtime balance
{
  type: '/instructions/build',
  data: {
    functionSignature: 'function transfer(address to, uint256 value)',
    args: [
      recipient,
      {
        type: 'runtimeErc20Balance',
        tokenAddress: tokenAddress,
        constraints: { gte: '1' }
      }
    ],
    to: tokenAddress,
    chainId: 8453
  }
}

// ✅ Use buildRaw when you have concrete calldata
{
  type: '/instructions/build-raw',
  data: {
    to: tokenAddress,
    data: '0xa9059cbb...',  // Pre-encoded transfer calldata
    chainId: 8453
  }
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Validate Encoded Calldata">
    Always validate your encoded calldata before sending:

    ```typescript theme={null}
    // ✅ Good - validate calldata format
    if (!calldata.startsWith('0x') || calldata.length < 10) {
      throw new Error('Invalid calldata format');
    }

    // ✅ Good - decode to verify
    import { decodeFunctionData, parseAbi } from 'viem';

    try {
      const decoded = decodeFunctionData({
        abi: transferAbi,
        data: calldata
      });
      console.log('Decoded args:', decoded.args);
    } catch (error) {
      throw new Error('Invalid calldata encoding');
    }
    ```
  </Accordion>

  <Accordion title="Set Appropriate Gas Limits">
    Override gas limits for complex operations:

    ```typescript theme={null}
    // Simple operations
    gasLimit: '50000'

    // DeFi protocol interactions
    gasLimit: '350000'

    // Complex multi-step operations
    gasLimit: '500000'
    ```
  </Accordion>

  <Accordion title="Know When to Use Build Instead">
    Use `/instructions/build` when you need:

    * Runtime balance injection for dynamic amounts
    * Better code readability with function signatures
    * API-side encoding to reduce client complexity

    Use `/instructions/build-raw` when you need:

    * Pre-encoded calldata from external systems
    * Exact control over calldata format
    * Migration from existing systems with encoded data
  </Accordion>

  <Accordion title="Test with Small Amounts First">
    Always test your encoded calldata with small amounts:

    ```typescript theme={null}
    // ❌ Bad - testing with large amount
    args: [recipient, parseUnits('10000', 6)]

    // ✅ Good - test with small amount first
    args: [recipient, parseUnits('1', 6)]
    ```
  </Accordion>
</AccordionGroup>

## Common Use Cases

### Pre-generated Transaction Data

```typescript theme={null}
// When you already have encoded calldata from another source
const existingCalldata = '0xa9059cbb000000000000000000000000742d35cc6639cb8d4b5d1c5d7b8b5e2e7c0c7a8a0000000000000000000000000000000000000000000000000000000000989680';

{
  type: '/instructions/build-raw',
  data: {
    to: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
    data: existingCalldata,
    chainId: 8453
  }
}
```

### Multicall Operations

```typescript theme={null}
import { encodeFunctionData, parseAbi } from 'viem';

// Encode multicall
const multicallAbi = parseAbi(['function multicall(bytes[] calldata data) returns (bytes[] memory)']);
const multicallData = encodeFunctionData({
  abi: multicallAbi,
  functionName: 'multicall',
  args: [[
    '0x...', // First call
    '0x...', // Second call
    '0x...'  // Third call
  ]]
});

{
  type: '/instructions/build-raw',
  data: {
    to: '0x...multicallContract',
    data: multicallData,
    chainId: 8453,
    gasLimit: '500000'
  }
}
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Invalid calldata format">
    Ensure your calldata:

    * Starts with `0x`
    * Is a valid hex string
    * Has even length (excluding `0x`)
    * Matches the expected function selector
  </Accordion>

  <Accordion title="Transaction reverted">
    Common causes:

    * Incorrect calldata encoding
    * Wrong function parameters or order
    * Insufficient balance for operation
    * Missing approvals for token operations
    * Gas limit too low
  </Accordion>

  <Accordion title="Cannot use runtime balance">
    BuildRaw does NOT support runtime balance injection. If you need dynamic amounts:

    ```typescript theme={null}
    // ❌ Won't work with build-raw
    {
      type: 'runtimeErc20Balance',
      tokenAddress: '0x...'
    }

    // ✅ Use /instructions/build instead
    {
      type: '/instructions/build',
      data: {
        functionSignature: 'function transfer(address to, uint256 value)',
        args: [recipient, { type: 'runtimeErc20Balance', ... }],
        to: tokenAddress,
        chainId: 8453
      }
    }
    ```
  </Accordion>

  <Accordion title="Calldata encoding mismatch">
    Verify your encoding matches the contract ABI:

    ```typescript theme={null}
    // Decode your calldata to verify
    import { decodeFunctionData } from 'viem';

    const decoded = decodeFunctionData({
      abi: yourAbi,
      data: yourCalldata
    });

    console.log('Function name:', decoded.functionName);
    console.log('Arguments:', decoded.args);
    ```
  </Accordion>
</AccordionGroup>

## Related Documentation

<CardGroup cols={2}>
  <Card title="/instructions/build" icon="hammer" href="/supertransaction-api/endpoints/build">
    Use when you need runtime balance or prefer function signatures
  </Card>

  <Card title="/instructions/intent-simple" icon="shuffle" href="/supertransaction-api/endpoints/intent-simple">
    For simple swaps and bridges with automatic routing
  </Card>
</CardGroup>
