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

# JavaScript SDK

> KillB 官方 JavaScript/TypeScript SDK

## 概述

KillB JavaScript SDK 提供了一个类型安全、易于使用的接口，用于将 KillB 的加密出入金 API 集成到您的 Node.js 或 TypeScript 应用程序中。

<CardGroup cols={2}>
  <Card title="NPM 包" icon="npm" href="https://www.npmjs.com/package/@killb/sdk">
    在 NPM 注册表查看
  </Card>

  <Card title="GitHub" icon="github" href="https://github.com/Kill-B/sdk">
    查看源代码
  </Card>
</CardGroup>

## 安装

<CodeGroup>
  ```bash npm theme={null}
  npm install @killb/sdk
  ```

  ```bash yarn theme={null}
  yarn add @killb/sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @killb/sdk
  ```
</CodeGroup>

## 快速开始

### 初始化 SDK

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { KillB } from '@killb/sdk';

  const killb = new KillB({
    email: process.env.KILLB_EMAIL,
    password: process.env.KILLB_PASSWORD,
    environment: 'sandbox' // 或 'production'
  });

  // SDK 自动处理身份验证
  await killb.initialize();
  ```

  ```javascript JavaScript theme={null}
  const { KillB } = require('@killb/sdk');

  const killb = new KillB({
    email: process.env.KILLB_EMAIL,
    password: process.env.KILLB_PASSWORD,
    environment: 'sandbox'
  });

  await killb.initialize();
  ```
</CodeGroup>

### 配置选项

```typescript theme={null}
interface KillBConfig {
  email: string;              // 您的 KillB 邮箱
  password: string;           // 您的 KillB 密码
  apiKey?: string;           // 可选的 API 密钥
  environment?: 'sandbox' | 'production'; // 默认: 'sandbox'
  timeout?: number;          // 请求超时（毫秒）
  retries?: number;          // 最大重试次数
  debug?: boolean;           // 启用调试日志
}
```

## 核心功能

### 用户管理

<CodeGroup>
  ```typescript 创建用户 theme={null}
  const user = await killb.users.create({
    type: 'PERSON',
    externalId: 'user-12345',
    data: {
      firstName: 'Juan',
      lastName: 'García',
      email: 'juan@example.com',
      phone: '+573001234567',
      dateOfBirth: '1990-01-01',
      address: {
        street1: 'Calle 123',
        city: 'Bogotá',
        state: 'Cundinamarca',
        zipCode: '110111',
        countryCode: 'CO'
      },
      document: {
        type: 'PASSPORT',
        number: 'AB123456',
        issuedCountryCode: 'CO'
      }
    }
  });

  console.log('用户已创建:', user.id);
  console.log('KYC 级别:', user.accessLevel);
  ```

  ```typescript 获取用户 theme={null}
  // 通过 ID 获取
  const user = await killb.users.get(userId);

  // 通过外部 ID 获取
  const user = await killb.users.getByExternalId('user-12345');

  // 查询用户
  const result = await killb.users.list({
    type: 'PERSON',
    email: 'juan@example.com',
    limit: 10,
    page: 1
  });

  console.log('找到用户:', result.users.length);
  console.log('总页数:', result.totalPage);
  ```

  ```typescript 更新用户 theme={null}
  const updated = await killb.users.update(userId, {
    data: {
      email: 'newemail@example.com',
      phone: '+573009876543'
    }
  });

  console.log('用户已更新:', updated.id);
  ```
</CodeGroup>

### 账户管理

<CodeGroup>
  ```typescript 创建钱包账户 theme={null}
  const wallet = await killb.accounts.create({
    type: 'WALLET',
    userId: user.id,
    externalId: 'wallet-polygon-usdc',
    data: {
      firstName: 'Juan',
      lastName: 'García',
      email: 'juan@example.com',
      phone: '+573001234567',
      currency: 'USDC',
      network: 'POLYGON',
      address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
      countryCode: 'CO',
      document: {
        type: 'PASSPORT',
        number: 'AB123456',
        issuedCountryCode: 'CO'
      }
    }
  });

  console.log('钱包已创建:', wallet.id);
  ```

  ```typescript 创建银行账户 theme={null}
  const bankAccount = await killb.accounts.create({
    type: 'PSE',
    userId: user.id,
    externalId: 'bank-pse-1',
    data: {
      firstName: 'Juan',
      lastName: 'García',
      email: 'juan@example.com',
      phone: '+573001234567',
      accountNumber: '1234567890',
      bankCode: '0001',
      type: 'savings',
      countryCode: 'CO',
      document: {
        type: 'NUIP',
        number: '1234567890',
        issuedCountryCode: 'CO'
      }
    }
  });

  console.log('银行账户已创建:', bankAccount.id);
  ```

  ```typescript 获取用户账户 theme={null}
  const accounts = await killb.accounts.getByUserId(userId);

  // 过滤账户
  const wallets = accounts.filter(a => a.type === 'WALLET');
  const banks = accounts.filter(a => ['PSE', 'SPEI'].includes(a.type));

  console.log('钱包数量:', wallets.length);
  console.log('银行账户数量:', banks.length);
  ```
</CodeGroup>

### 报价

<CodeGroup>
  ```typescript 创建报价 theme={null}
  const quote = await killb.quotations.create({
    fromCurrency: 'COP',
    toCurrency: 'USDC',
    amount: 100000,
    amountIsToCurrency: false,
    cashInMethod: 'PSE',
    cashOutMethod: 'POLYGON'
  });

  console.log('汇率:', quote.rate);
  console.log('您将收到:', quote.toAmount, 'USDC');
  console.log('过期时间:', new Date(quote.expiresAt));

  // 检查是否过期
  if (quote.isExpired()) {
    const newQuote = await killb.quotations.create(/* 相同参数 */);
  }
  ```

  ```typescript 模拟报价 theme={null}
  // 获取指示性价格，无需创建报价
  const simulation = await killb.quotations.simulate({
    fromCurrency: 'COP',
    toCurrency: 'USDC',
    amount: 100000,
    amountIsToCurrency: false,
    cashInMethod: 'PSE',
    cashOutMethod: 'POLYGON'
  });

  console.log('预估汇率:', simulation.rate);
  console.log('预估金额:', simulation.toAmount);
  ```

  ```typescript 获取报价 theme={null}
  const quote = await killb.quotations.get(quoteId);

  // 等待报价被使用或过期
  await quote.waitForUse({ timeout: 30000 });
  ```
</CodeGroup>

### 出入金

<CodeGroup>
  ```typescript 创建入金 theme={null}
  // 完整的入金流程
  const ramp = await killb.ramps.create({
    quotationId: quote.id,
    userId: user.id,
    accountId: wallet.id,
    externalId: 'onramp-123'
  });

  console.log('出入金 ID:', ramp.id);
  console.log('状态:', ramp.status);
  console.log('支付 URL:', ramp.paymentInfo[0].url);

  // 重定向用户到支付页面
  // window.location.href = ramp.paymentInfo[0].url;
  ```

  ```typescript 创建出金 theme={null}
  // 完整的出金流程
  const ramp = await killb.ramps.create({
    quotationId: quote.id,
    userId: user.id,
    accountId: bankAccount.id,
    refundInstructions: {
      network: 'POLYGON',
      address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
      asset: 'USDC'
    }
  });

  console.log('发送加密货币到:', ramp.paymentInfo[0].address);
  console.log('网络:', ramp.paymentInfo[0].network);
  ```

  ```typescript 监控出入金 theme={null}
  // 轮询状态更新
  const completed = await ramp.waitForCompletion({
    pollInterval: 10000, // 每 10 秒检查一次
    timeout: 3600000     // 1 小时超时
  });

  console.log('出入金已完成!');
  console.log('转账证明:', completed.transferProof);

  // 或监听特定状态
  await ramp.waitForStatus('CASH_IN_COMPLETED');
  console.log('支付已收到!');
  ```

  ```typescript 查询出入金 theme={null}
  // 获取用户的所有出入金
  const ramps = await killb.ramps.list({
    userId: user.id,
    status: 'COMPLETED',
    limit: 10,
    page: 1
  });

  // 通过外部 ID 获取出入金
  const ramp = await killb.ramps.getByExternalId('onramp-123');

  // 获取状态历史
  const history = await killb.ramps.getStatusHistory(rampId);
  console.log('状态转换:', history);
  ```
</CodeGroup>

### Webhooks

<CodeGroup>
  ```typescript 设置 Webhook theme={null}
  const webhook = await killb.webhooks.create({
    url: 'https://api.yourapp.com/webhooks/killb',
    secret: process.env.WEBHOOK_SECRET,
    events: ['RAMP', 'USER', 'ACCOUNT']
  });

  console.log('Webhook 已配置:', webhook.id);
  ```

  ```typescript 验证 Webhook 签名 theme={null}
  import { KillB } from '@killb/sdk';

  app.post('/webhooks/killb', (req, res) => {
    const signature = req.headers['x-signature-sha256'];
    
    // 使用 SDK 辅助函数验证
    const isValid = KillB.verifyWebhookSignature(
      req.body,
      signature,
      process.env.WEBHOOK_SECRET
    );
    
    if (!isValid) {
      return res.status(401).json({ error: '无效签名' });
    }
    
    // 处理事件
    const event = req.body;
    console.log('收到事件:', event.event);
    
    res.status(200).json({ received: true });
  });
  ```

  ```typescript 处理 Webhook 事件 theme={null}
  import { WebhookHandler } from '@killb/sdk';

  const handler = new WebhookHandler(process.env.WEBHOOK_SECRET);

  handler.on('ramp.completed', async (data) => {
    console.log('出入金已完成:', data.id);
    await updateDatabase(data);
    await notifyUser(data.userId);
  });

  handler.on('ramp.failed', async (data) => {
    console.log('出入金失败:', data.id);
    await handleFailure(data);
  });

  app.post('/webhooks/killb', async (req, res) => {
    await handler.handle(req.body, req.headers['x-signature-sha256']);
    res.status(200).json({ received: true });
  });
  ```
</CodeGroup>

### 储蓄账户

<CodeGroup>
  ```typescript 创建储蓄账户 theme={null}
  const savings = await killb.savings.create({
    userId: user.id,
    acceptedTermsAndConditions: true
  });

  console.log('储蓄账户:', savings.id);
  ```

  ```typescript 获取余额 theme={null}
  const balance = await killb.savings.getBalance(savingsAccountId);
  console.log(`余额: $${balance.amount} ${balance.currency}`);
  ```

  ```typescript 获取存款说明 theme={null}
  // ACH 存款说明
  const achInstructions = await killb.savings.getDepositInstructions(
    savingsAccountId,
    'ACH'
  );

  console.log('账户号码:', achInstructions.accountNumber);
  console.log('路由号码:', achInstructions.routingNumber);
  console.log('备注:', achInstructions.memo);

  // 加密货币存款说明
  const cryptoInstructions = await killb.savings.getCryptoDepositInstructions(
    savingsAccountId
  );

  console.log('存款地址:', cryptoInstructions.address);
  console.log('网络:', cryptoInstructions.network);
  ```

  ```typescript 创建提现 theme={null}
  const withdrawal = await killb.savings.withdraw({
    source: {
      savingsAccountId: savingsAccountId
    },
    destination: {
      savingsAccountId: savingsAccountId,
      externalAccountId: bankAccountId
    },
    amount: 1000,
    comment: '提现到银行'
  });

  console.log('提现已发起:', withdrawal.id);
  console.log('状态:', withdrawal.status);
  ```
</CodeGroup>

## 高级功能

### 分页

```typescript theme={null}
// 自动分页辅助函数
const allUsers = await killb.users.listAll({
  type: 'PERSON'
});

// 或手动分页
let page = 1;
let hasMore = true;

while (hasMore) {
  const result = await killb.users.list({ page, limit: 50 });
  processUsers(result.users);
  
  hasMore = page < result.totalPage;
  page++;
}
```

### 错误处理

```typescript theme={null}
import { KillBError, QuotationExpiredError, InsufficientBalanceError } from '@killb/sdk';

try {
  const ramp = await killb.ramps.create(rampData);
} catch (error) {
  if (error instanceof QuotationExpiredError) {
    console.log('报价已过期，创建新报价...');
    const newQuote = await killb.quotations.create(quoteParams);
    return await killb.ramps.create({ ...rampData, quotationId: newQuote.id });
  }
  
  if (error instanceof InsufficientBalanceError) {
    console.log('预存余额不足');
    await notifyAdminToTopUp();
  }
  
  if (error instanceof KillBError) {
    console.error('KillB API 错误:', error.code, error.message);
  }
  
  throw error;
}
```

### 重试配置

```typescript theme={null}
const killb = new KillB({
  email: process.env.KILLB_EMAIL,
  password: process.env.KILLB_PASSWORD,
  retryConfig: {
    maxRetries: 3,
    retryDelay: 1000,
    retryableStatuses: [500, 502, 503, 504]
  }
});
```

### 自定义请求头

```typescript theme={null}
// 向请求添加自定义请求头
killb.setHeaders({
  'X-Custom-Header': 'value',
  'X-Request-ID': requestId
});

// 移除自定义请求头
killb.removeHeaders(['X-Custom-Header']);
```

### 请求日志

```typescript theme={null}
const killb = new KillB({
  email: process.env.KILLB_EMAIL,
  password: process.env.KILLB_PASSWORD,
  debug: true,
  logger: {
    log: (message) => console.log('[KillB]', message),
    error: (message) => console.error('[KillB ERROR]', message)
  }
});
```

## 完整示例

```typescript theme={null}
import { KillB } from '@killb/sdk';

async function executeOnRamp(
  walletAddress: string,
  amount: number
) {
  // 初始化 SDK
  const killb = new KillB({
    email: process.env.KILLB_EMAIL!,
    password: process.env.KILLB_PASSWORD!,
    environment: 'sandbox'
  });

  await killb.initialize();

  try {
    // 1. 创建用户
    const user = await killb.users.create({
      type: 'PERSON',
      externalId: `user-${Date.now()}`,
      data: {
        firstName: 'Test',
        lastName: 'User',
        email: 'test@example.com',
        phone: '+573001234567',
        dateOfBirth: '1990-01-01',
        address: {
          street1: 'Test Street 123',
          city: 'Bogotá',
          state: 'Cundinamarca',
          zipCode: '110111',
          countryCode: 'CO'
        },
        document: {
          type: 'PASSPORT',
          number: 'TEST123',
          issuedCountryCode: 'CO'
        }
      }
    });

    console.log('✅ 用户已创建:', user.id);

    // 2. 创建钱包账户
    const wallet = await killb.accounts.create({
      type: 'WALLET',
      userId: user.id,
      externalId: `wallet-${Date.now()}`,
      data: {
        firstName: 'Test',
        lastName: 'User',
        email: 'test@example.com',
        phone: '+573001234567',
        currency: 'USDC',
        network: 'POLYGON',
        address: walletAddress,
        countryCode: 'CO',
        document: {
          type: 'PASSPORT',
          number: 'TEST123',
          issuedCountryCode: 'CO'
        }
      }
    });

    console.log('✅ 钱包已创建:', wallet.id);

    // 3. 获取报价
    const quote = await killb.quotations.create({
      fromCurrency: 'COP',
      toCurrency: 'USDC',
      amount: amount,
      amountIsToCurrency: false,
      cashInMethod: 'PSE',
      cashOutMethod: 'POLYGON'
    });

    console.log('✅ 报价已创建:', quote.id);
    console.log('   汇率:', quote.rate);
    console.log('   您将收到:', quote.toAmount, 'USDC');

    // 4. 创建出入金
    const ramp = await killb.ramps.create({
      quotationId: quote.id,
      userId: user.id,
      accountId: wallet.id,
      externalId: `onramp-${Date.now()}`
    });

    console.log('✅ 出入金已创建:', ramp.id);
    console.log('   支付 URL:', ramp.paymentInfo[0].url);

    // 5. 在沙盒环境中，模拟支付
    if (killb.environment === 'sandbox') {
      await killb.faker.cashIn(ramp.id);
      console.log('✅ 支付已模拟');
    }

    // 6. 等待完成
    const completed = await ramp.waitForCompletion({
      pollInterval: 5000,
      timeout: 300000
    });

    console.log('✅ 出入金已完成!');
    console.log('   转账证明:', completed.transferProof);
    
    return completed;

  } catch (error) {
    console.error('❌ 错误:', error);
    throw error;
  }
}

// 使用
executeOnRamp('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 100000)
  .then(() => console.log('✅ 全部完成!'))
  .catch(console.error);
```

## TypeScript 支持

包含完整的 TypeScript 定义：

```typescript theme={null}
import type {
  User,
  CreateUserRequest,
  Account,
  CreateAccountRequest,
  Ramp,
  CreateRampRequest,
  Quotation,
  WebhookEvent
} from '@killb/sdk';

// 类型安全的操作
const createUser = async (data: CreateUserRequest): Promise<User> => {
  return await killb.users.create(data);
};
```

## 工具函数

### 辅助函数

```typescript theme={null}
// 验证地址
import { validateAddress } from '@killb/sdk/utils';

const isValid = validateAddress('0x742d35...', 'POLYGON');
console.log('有效地址:', isValid);

// 格式化货币
import { formatCurrency } from '@killb/sdk/utils';

const formatted = formatCurrency(1234.56, 'COP');
console.log(formatted); // "$ 1,234.56 COP"

// 计算费用
import { calculateFees } from '@killb/sdk/utils';

const fees = calculateFees(quote);
console.log('平台费用:', fees.platform);
console.log('网络费用:', fees.network);
console.log('总费用:', fees.total);
```

### Webhook 验证

```typescript theme={null}
import { verifyWebhookSignature } from '@killb/sdk';

// Express 中间件
const webhookMiddleware = (req, res, next) => {
  const signature = req.headers['x-signature-sha256'];
  const isValid = verifyWebhookSignature(
    JSON.stringify(req.body),
    signature,
    process.env.WEBHOOK_SECRET
  );
  
  if (!isValid) {
    return res.status(401).json({ error: '无效签名' });
  }
  
  next();
};

app.post('/webhooks/killb', webhookMiddleware, handleWebhook);
```

## 测试辅助函数（仅限沙盒）

```typescript theme={null}
// 仅在沙盒环境中可用
if (killb.environment === 'sandbox') {
  // 模拟入金
  await killb.faker.cashIn(rampId);
  
  // 模拟出金
  await killb.faker.cashOut(rampId);
  
  // 创建测试用户
  const testUser = await killb.faker.createUser();
  
  // 创建测试钱包
  const testWallet = await killb.faker.createWallet(userId);
}
```

## 最佳实践

<AccordionGroup>
  <Accordion title="环境变量" icon="lock">
    ```typescript theme={null}
    // 使用环境变量存储凭据
    const killb = new KillB({
      email: process.env.KILLB_EMAIL!,
      password: process.env.KILLB_PASSWORD!,
      apiKey: process.env.KILLB_API_KEY,
      environment: process.env.NODE_ENV === 'production' 
        ? 'production' 
        : 'sandbox'
    });
    ```
  </Accordion>

  <Accordion title="错误处理" icon="shield">
    ```typescript theme={null}
    // 始终在 try-catch 中包装 SDK 调用
    try {
      const result = await killb.ramps.create(data);
      return result;
    } catch (error) {
      if (error instanceof KillBError) {
        // 处理 KillB 特定错误
        logError(error.code, error.message);
      }
      throw error;
    }
    ```
  </Accordion>

  <Accordion title="复用 SDK 实例" icon="recycle">
    ```typescript theme={null}
    // 创建一次，在整个应用中复用
    export const killb = new KillB(config);

    // 在其他文件中
    import { killb } from './killb-client';
    const user = await killb.users.create(data);
    ```
  </Accordion>

  <Accordion title="使用外部 ID" icon="hashtag">
    ```typescript theme={null}
    // 始终提供外部 ID 以实现幂等性
    const ramp = await killb.ramps.create({
      quotationId: quote.id,
      userId: user.id,
      accountId: wallet.id,
      externalId: `order-${orderId}` // 您的系统 ID
    });
    ```
  </Accordion>
</AccordionGroup>

## API 参考

### KillB 客户端

```typescript theme={null}
class KillB {
  constructor(config: KillBConfig)
  
  // 初始化（使用前必须调用）
  async initialize(): Promise<void>
  
  // 资源管理器
  users: UsersManager
  accounts: AccountsManager
  ramps: RampsManager
  quotations: QuotationsManager
  webhooks: WebhooksManager
  savings: SavingsManager
  customers: CustomersManager
  banks: BanksManager
  
  // 沙盒辅助函数
  faker: FakerManager
  
  // 静态工具函数
  static verifyWebhookSignature(
    payload: any,
    signature: string,
    secret: string
  ): boolean
}
```

### 资源管理器

每个资源都有一致的方法：

```typescript theme={null}
interface ResourceManager<T> {
  create(data: CreateRequest): Promise<T>
  get(id: string): Promise<T>
  list(params?: ListParams): Promise<ListResponse<T>>
  update(id: string, data: UpdateRequest): Promise<T>
  delete(id: string): Promise<void>
}
```

## 从 REST API 迁移

### 之前（REST API）

```javascript theme={null}
const response = await fetch('/api/v2/users', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(userData)
});

const user = await response.json();
```

### 之后（SDK）

```typescript theme={null}
const user = await killb.users.create(userData);
```

**优势:**

* ✅ 无需手动身份验证请求头
* ✅ 自动令牌刷新
* ✅ 类型安全
* ✅ 更好的错误处理
* ✅ 更少的样板代码

## 资源

<CardGroup cols={3}>
  <Card title="NPM 包" icon="npm" href="https://www.npmjs.com/package/@killb/sdk">
    在 NPM 查看
  </Card>

  <Card title="GitHub 仓库" icon="github" href="https://github.com/Kill-B/sdk">
    源代码
  </Card>

  <Card title="示例" icon="code" href="/zh/demo-apps">
    代码示例
  </Card>
</CardGroup>

## 下一步

<CardGroup cols={2}>
  <Card title="安装指南" icon="download" href="/zh/sdks/javascript-installation">
    详细的安装说明
  </Card>

  <Card title="示例" icon="book-open" href="/zh/sdks/javascript-examples">
    更多代码示例
  </Card>

  <Card title="API 参考" icon="code" href="/zh/api-reference/introduction">
    REST API 文档
  </Card>

  <Card title="TypeScript 类型" icon="file-code" href="/zh/sdks/typescript-types">
    类型定义参考
  </Card>
</CardGroup>
