跳转到主要内容

概述

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

安装

npm install @killb/sdk

快速开始

初始化 SDK

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();

配置选项

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

核心功能

用户管理

const user = await killb.users.create({
  type: 'PERSON',
  externalId: 'user-12345',
  data: {
    firstName: 'Juan',
    lastName: 'García',
    email: '[email protected]',
    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);

账户管理

const wallet = await killb.accounts.create({
  type: 'WALLET',
  userId: user.id,
  externalId: 'wallet-polygon-usdc',
  data: {
    firstName: 'Juan',
    lastName: 'García',
    email: '[email protected]',
    phone: '+573001234567',
    currency: 'USDC',
    network: 'POLYGON',
    address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
    countryCode: 'CO',
    document: {
      type: 'PASSPORT',
      number: 'AB123456',
      issuedCountryCode: 'CO'
    }
  }
});

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

报价

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(/* 相同参数 */);
}

出入金

// 完整的入金流程
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;

Webhooks

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);

储蓄账户

const savings = await killb.savings.create({
  userId: user.id,
  acceptedTermsAndConditions: true
});

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

高级功能

分页

// 自动分页辅助函数
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++;
}

错误处理

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;
}

重试配置

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

自定义请求头

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

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

请求日志

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)
  }
});

完整示例

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: '[email protected]',
        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: '[email protected]',
        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 定义:
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);
};

工具函数

辅助函数

// 验证地址
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 验证

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);

测试辅助函数(仅限沙盒)

// 仅在沙盒环境中可用
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);
}

最佳实践

// 使用环境变量存储凭据
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'
});
// 始终在 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;
}
// 创建一次,在整个应用中复用
export const killb = new KillB(config);

// 在其他文件中
import { killb } from './killb-client';
const user = await killb.users.create(data);
// 始终提供外部 ID 以实现幂等性
const ramp = await killb.ramps.create({
  quotationId: quote.id,
  userId: user.id,
  accountId: wallet.id,
  externalId: `order-${orderId}` // 您的系统 ID
});

API 参考

KillB 客户端

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
}

资源管理器

每个资源都有一致的方法:
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)

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)

const user = await killb.users.create(userData);
优势:
  • ✅ 无需手动身份验证请求头
  • ✅ 自动令牌刷新
  • ✅ 类型安全
  • ✅ 更好的错误处理
  • ✅ 更少的样板代码

资源

下一步