# Bankr SDK

> **⚠️ Alpha Release** - This SDK is currently in alpha. For support and questions, join our [Discord server](https://discord.gg/bankr).

> **💰 Pricing** - Each request costs $0.10 in USDC using standard [x402 payment](https://www.x402.org/) protocol.

> **🎯 Recommended Method** - Use `client.promptAndWait()` for the simplest experience - it handles everything automatically!

Official SDK for the Bankr API with automatic [x402 payment](https://www.x402.org/) support. Each request costs $0.10 in USDC. This SDK is intended to be used in a secure server environment and not in the browser.

When requesting transactions, ie Buy $5 of $BNKR, Bankr will return transaction data that you can execute with any wallet.

## Swap Transactions

For ERC20 token swaps, Bankr uses [0x](https://0x.org/) for routing. To complete a swap from one ERC20 token to another, you will need to approve the AllowanceHolder contract address to move your tokens. The address required for approval can be found in the `metadata.allowanceTarget` field of the returned transaction data.

Also reference the following documentation:

- https://0x.org/docs/introduction/0x-cheat-sheet#allowanceholder-recommended
- https://github.com/0xProject/0x-settler/blob/master/README.md#allowanceholder-addresses

## Prerequisites

Before using the SDK, you need to:

1. **USDC Balance**: Ensure you have USDC tokens in your wallet for payments. Each request costs $0.10 in USDC.

2. **No API Key Required**: The v2/prompt endpoint uses standard x402 payment protocol, so no API key is needed.

## Quick Start

```typescript
import { BankrClient } from "@bankr/sdk";

// Initialize client
const client = new BankrClient({
  privateKey: "0x...", // Payment wallet
  walletAddress: "0x...", // Your wallet for transactions
});

// Send a prompt and wait for the result (recommended)
const result = await client.promptAndWait({
  prompt: "What are some trending coins on Base?",
});

console.log(result.response); // "here are some trending coins on base..."
```

## Installation

```bash
npm install @bankr/sdk
```

## Usage

### Basic Setup

```typescript
import { BankrClient } from "@bankr/sdk";

const client = new BankrClient({
  privateKey: "0x...", // Required: Payment wallet (derived address used for x402 USDC payments)
  walletAddress: "0x...", // Optional: Context wallet for prompts/transactions (e.g., "What are my balances?" or "Swap ETH to USDC" will use this address)
});
```

### 🎯 Recommended: Send Prompt and Wait for Response

> **Best Practice**: Use `promptAndWait()` for the simplest and most reliable experience. This method sends your prompt and automatically polls until completion or failure.

```typescript
// Basic query example
const result = await client.promptAndWait({
  prompt: "What's the current price of ETH?",
});

console.log(result.response);
// "The current price of ETH is $2,500..."

// Transaction example - Swap with full response
const swapResult = await client.promptAndWait({
  prompt: "Swap 0.1 ETH to USDC",
});

console.log(swapResult);
// {
//   success: true,
//   jobId: "job_456",
//   status: "completed",
//   prompt: "Swap 0.1 ETH to USDC",
//   response: "I'll help you swap 0.1 ETH to USDC...",
//   transactions: [
//     {
//       type: "swap",
//       metadata: {
//         __ORIGINAL_TX_DATA__: {
//           chain: "base",
//           humanReadableMessage: "Swap 0.1 ETH to USDC",
//           inputTokenAddress: "0x4200000000000000000000000000000000000006",
//           inputTokenAmount: "0.1",
//           inputTokenTicker: "ETH",
//           outputTokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
//           outputTokenTicker: "USDC",
//           receiver: "0x..." // Your context wallet receives the USDC
//         },
//         transaction: {
//           chainId: 8453,
//           to: "0x...",
//           data: "0x...",
//           gas: "300000",
//           value: "100000000000000000" // 0.1 ETH in wei
//         },
//         allowanceTarget: "0x..." // For ERC20->ERC20: approve this address first
//       }
//     }
//   ],
//   richData: [],
//   createdAt: "2024-01-01T00:00:00.000Z",
//   processingTime: 5000
// }

// Execute the transaction with your wallet client
// const tx = await wallet.sendTransaction(swapResult.transactions[0].metadata.transaction);
```

## ⚠️ Important: Payment vs Context Wallets

> **Two Different Wallets**: The SDK supports using different wallets for different purposes:
>
> - **Payment Wallet** (`privateKey`): Used for x402 USDC payments ($0.10 per request)
> - **Context Wallet** (`walletAddress`): Used for prompt context and transaction receiver
>
> **Examples:**
>
> - **Swaps**: "Swap 0.1 ETH to USDC" → USDC will be sent to your context wallet
> - **Purchases**: "Buy $100 of $BNKR" → Tokens will be sent to your context wallet
> - **Balance Checks**: "What are my balances?" → Checks your context wallet
>
> **You can use different wallets**: Pay with wallet A, but have transactions sent to wallet B!

## Payment Setup

### USDC Payment

The SDK uses standard x402 payment protocol with USDC. No token approvals are needed - the SDK automatically handles USDC payments through the x402 protocol.

### Advanced: Manual Prompt and Polling

> **Note**: Only use this approach if you need fine-grained control over the prompt submission and status checking. For most use cases, use `promptAndWait()` instead.

```typescript
// Step 1: Send a prompt and get a job ID
const response = await client.prompt({
  prompt: "Swap 0.1 ETH to USDC",
  walletAddress: "0x...", // Optional, overrides default context wallet for this prompt
  xmtp: false, // Optional, convert transaction data to XMTP format
});

console.log(response);
// {
//   success: true,
//   jobId: "job_123",
//   status: "pending",
//   message: "Prompt submitted successfully. Use the jobId to check status.",
//   price: {
//     amount: "100000", // $0.10 in USDC (6 decimals)
//     asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" // USDC on Base
//   }
// }

// Step 2: Manually check status or poll for completion
const status = await client.getJobStatus(response.jobId);
// OR
const result = await client.pollJob({
  jobId: response.jobId,
  interval: 2000,
  maxAttempts: 150,
  timeout: 300000,
});
```

### Using Different Wallets for Payment vs Context

```typescript
// Example: Pay with one wallet, but have transactions sent to another
const client = new BankrClient({
  privateKey: "0x123...", // Payment wallet (pays $0.10 USDC per request)
  walletAddress: "0x456...", // Context wallet (receives swapped tokens)
});

// This will:
// 1. Pay $0.10 USDC from wallet 0x123... (payment wallet)
// 2. Send the swapped USDC to wallet 0x456... (context wallet)
const response = await client.prompt({
  prompt: "Swap 0.1 ETH to USDC",
});

// You can also override the context wallet per prompt:
const response2 = await client.prompt({
  prompt: "Buy $100 of $BNKR",
  walletAddress: "0x789...", // Send tokens to a different wallet
});
```

### Advanced: Check Job Status

> **Note**: Only needed for manual polling. Use `promptAndWait()` for automatic polling.

```typescript
const status = await client.getJobStatus("job_123");
console.log(status);
// Returns JobStatus object with response, transactions, and richData
```

### Advanced: Poll for Completion

> **Note**: Only needed for manual polling. Use `promptAndWait()` for automatic polling.

```typescript
const result = await client.pollJob({
  jobId: "job_123",
  interval: 2000, // Check every 2 seconds
  maxAttempts: 150, // Max 5 minutes
  timeout: 300000, // 5 minutes total timeout
});
```

### Cancel a Job

```typescript
// Cancel a running job
const status = await client.cancelJob("job_123");
console.log(status);
// {
//   success: true,
//   jobId: "job_123",
//   status: "cancelled",
//   prompt: "What's the current price of ETH?",
//   createdAt: "2024-01-01T00:00:00.000Z",
//   cancelledAt: "2024-01-01T00:01:00.000Z"
// }
```

## Payment Integration

The SDK uses [x402-fetch](https://www.npmjs.com/package/x402-fetch) to automatically handle x402 payment requirements:

1. **Automatic Payment Handling**: When a prompt requires payment, x402-fetch automatically creates and signs payments using the provided private key.

2. **Dynamic Pricing**: The API calculates pricing based on prompt complexity, and x402-fetch handles the payment requirements.

3. **Payment Verification**: x402-fetch handles payment verification and settlement through the Bankr facilitator.

4. **Error Handling**: If payment is required but not provided, the SDK will throw an error with payment requirements.

5. **Network Support**: Supports base network through viem chain configuration.

## API Methods Overview

The SDK provides three approaches for sending prompts:

1. **`promptAndWait()`** - **✅ RECOMMENDED** - Sends prompt and automatically waits for completion
   - Simplest to use
   - Handles polling automatically
   - Best for most use cases

2. **`prompt()` + `pollJob()`** - Manual control over submission and polling
   - Use when you need to store the job ID separately
   - Useful for background processing
   - More complex but gives you fine-grained control

3. **`prompt()` + `getJobStatus()`** - Full manual control
   - Use when implementing custom polling logic
   - Check status on-demand without automatic polling
   - Most complex but most flexible

## Configuration

### BankrClientConfig

```typescript
interface BankrClientConfig {
  privateKey: `0x${string}`; // Required: Private key for x402 USDC payments
  walletAddress?: string; // Optional: Default wallet address for prompt context and as transaction receiver (e.g., "What are my balances?" or "Swap ETH to USDC" will send USDC to this address)
}
```

### PromptOptions

```typescript
interface PromptOptions {
  prompt: string; // Required: The prompt to send
  walletAddress?: string; // Optional: Override default wallet for prompt context and as transaction receiver (e.g., balance lookups, "Swap ETH to USDC" will send USDC to this address)
  xmtp?: boolean; // Optional: Convert transaction data to XMTP call data format
}
```

### PollOptions

```typescript
interface PollOptions {
  jobId: string; // Required: Job ID to poll
  interval?: number; // Optional: Polling interval in ms
  maxAttempts?: number; // Optional: Max polling attempts
  timeout?: number; // Optional: Total timeout in ms
}
```

## Transaction and Rich Data

The SDK now supports rich transaction data and analytics in job responses:

### Transaction Types

The SDK includes comprehensive transaction types:

- `SwapTransaction`: Token swaps
- `ApprovalTransaction`: Token approvals
- `TransferErc20Transaction`: ERC20 token transfers
- `TransferEthTransaction`: ETH transfers
- `ConvertEthToWethTransaction`: ETH to WETH conversions
- `ConvertWethToEthTransaction`: WETH to ETH conversions
- `TransferNftTransaction`: NFT transfers
- `MintManifoldNftTransaction`: NFT mints
- `BuyNftTransaction`: NFT purchases
- `AvantisTradeTransaction`: Avantis trading
- `SwapCrossChainTransaction`: Cross-chain swaps/bridges

### Rich Data Types

- `SocialCard`: Analysis cards with text content
- `Chart`: Chart URLs for data visualization

### XMTP Integration

When `xmtp: true` is set in the prompt options, transaction data is converted to XMTP call data format for seamless integration with XMTP messaging.

## Error Handling

The SDK handles various error scenarios:

- **402 Payment Required**: When payment is required but not provided
- **400 Bad Request**: Invalid prompt or request format
- **500 Internal Server Error**: Server-side errors

## Networks

Supported networks for payments:

- `base` (default)

## Security

- Private keys are used only for signing payments through x402-fetch
- No private key data is sent to the server
- All payments are signed locally using viem
- Payment verification is handled server-side
- Uses the official [x402-fetch](https://www.npmjs.com/package/x402-fetch) library for reliable payment handling
