# Custom Contract Calls

## Custom Contract Calls

Custom contract calls allow you to execute additional smart contract operations after the deposit swap is completed. This enables advanced use cases like automatically staking tokens, providing liquidity, or interacting with any protocol contract—all within a single user transaction flow.

### Purpose

Custom contract calls extend the Swapper deposit SDK to support complex DeFi workflows beyond simple token deposits. Common use cases include:

* **Staking**: Automatically stake deposited tokens into a staking contract
* **Liquidity Provision**: Deposit tokens into liquidity pools
* **Token Wrapping**: Convert tokens (e.g., ETH to WETH)
* **Protocol Interactions**: Interact with lending protocols, vaults, or any custom contract

The SDK handles the entire flow: swap → deposit → custom operations, all executed atomically in the user's transaction.

### How It Works

1. User deposits funds using any supported method (crypto transfer, on-ramp, etc.)
2. Swapper routes and swaps to the destination token
3. Custom contract calls are executed in sequence
4. Final tokens are delivered to the recipient wallet

Each custom call is a `ContractCall` object that specifies:

* **callType**: How to handle token amounts (exact amount vs. full balance)
* **target**: The contract address to call
* **value**: ETH value to send (usually "0" for ERC20 operations)
* **callData**: Encoded function call data
* **payload**: Additional data for balance encoding

### Basic Example

#### TypeScript SDK (iframe)

```typescript
import { 
  SwapperIframe, 
  ContractCallType,
  approveBalance,
  transferBalance 
} from '@swapper-finance/deposit-sdk';
import { ethers } from 'ethers';

// Define custom contract interface
const stakingInterface = new ethers.utils.Interface([
  "function stake(uint256 amount) returns (bool)"
]);

const abiCoder = new ethers.utils.AbiCoder();

const swapper = new SwapperIframe({
  container: '#swapper-container',
  integratorId: 'your-integrator-id',
  dstChainId: '1',
  dstTokenAddr: '0x...', // Token to receive
  depositWalletAddress: '0x...',
  customContractCalls: [
    // Step 1: Approve staking contract to spend tokens
    approveBalance(
      '0x...', // Token address
      '0x...'  // Staking contract address
    ),
    
    // Step 2: Call custom staking function
    {
      callType: ContractCallType.FULL_TOKEN_BALANCE,
      target: '0x...', // Staking contract
      value: '0',
      callData: stakingInterface.encodeFunctionData('stake', ['0']),
      payload: abiCoder.encode(
        ['address', 'uint256'],
        ['0x...', '0'] // Token address, amount will be auto-filled
      )
    }
  ]
});
```

### Helper Functions

The SDK provides built-in helper functions for common ERC20 operations, eliminating the need for manual ABI encoding.

#### Exact Amount Functions

Use these when you know the exact amount to transfer:

**`approve(tokenAddress, spender, amount)`**

Approves a specific amount of tokens for spending.

```typescript
import { approve } from '@swapper-finance/deposit-sdk';

approve(
  '0x...', // Token address
  '0x...', // Spender address
  '1000000000000000000' // Amount (1 token with 18 decimals)
)
```

**`transfer(tokenAddress, recipient, amount)`**

Transfers a specific amount of tokens.

```typescript
import { transfer } from '@swapper-finance/deposit-sdk';

transfer(
  '0x...', // Token address
  '0x...', // Recipient address
  '5000000' // Amount (5 USDC with 6 decimals)
)
```

**`transferFrom(tokenAddress, from, to, amount)`**

Transfers a specific amount from one address to another.

```typescript
import { transferFrom } from '@swapper-finance/deposit-sdk';

transferFrom(
  '0x...', // Token address
  '0x...', // From address
  '0x...', // To address
  '1000000000000000000' // Amount
)
```

#### Full Balance Functions

Use these when you want to use the entire token balance (most common for post-swap operations):

**`approveBalance(tokenAddress, spender)`**

Approves the full token balance for spending.

```typescript
import { approveBalance } from '@swapper-finance/deposit-sdk';

approveBalance(
  '0x...', // Token address
  '0x...', // Spender address
)
```

**`transferBalance(tokenAddress, recipient)`**

Transfers the full token balance to a recipient.

```typescript
import { transferBalance } from '@swapper-finance/deposit-sdk';

transferBalance(
  '0x...', // Token address
  '0x...', // Recipient address
)
```

### Contract Call Types

Different call types determine how the SDK handles token amounts:

#### `ContractCallType.DEFAULT` (0)

Use exact amounts specified in callData. The SDK does not modify amounts.

```typescript
{
  callType: ContractCallType.DEFAULT,
  callData: '0x...' // Amounts are exactly as encoded
}
```

#### `ContractCallType.FULL_TOKEN_BALANCE` (1)

Uses the complete balance of a specified token. The SDK automatically replaces amount placeholders with the actual balance.

```typescript
{
  callType: ContractCallType.FULL_TOKEN_BALANCE,
  callData: '0x...', // Amount parameter should be '0'
  payload: abiCoder.encode(
    ['address', 'uint256'],
    ['0x...', '0'] // Token address, balance slot
  )
}
```

#### `ContractCallType.FULL_NATIVE_BALANCE` (2)

Uses the complete native token (ETH) balance.

#### `ContractCallType.COLLECT_TOKEN_BALANCE` (3)

Collects the accumulated token balance from previous operations.

### Important Notes

* **Order Matters**: Custom calls execute sequentially. Ensure approvals come before operations that require them.
* **Gas Estimation**: Complex call chains may require more gas. The SDK handles estimation automatically.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.swapper.finance/custom-contract-calls.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
