bloque-sdk-ts

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Bloque SDK Integration

Bloque SDK 集成指南

TypeScript SDK for programmable financial infrastructure: accounts, cards, spending controls, transfers, and webhooks.
用于可编程金融基础设施的TypeScript SDK:涵盖账户、卡片、支出控制、转账及Webhook功能。

When to Apply

适用场景

Use this skill when:
  • Integrating the Bloque SDK into a new or existing project
  • Creating accounts (virtual pockets, cards, Polygon wallets, bank accounts)
  • Setting up card spending controls (default or smart MCC routing)
  • Handling card transaction webhooks
  • Transferring funds between accounts (single or batch)
  • Building budgeting or expense-management features
  • Querying balances or transaction history
在以下场景中使用本技能:
  • 将Bloque SDK集成到新的或现有项目中
  • 创建账户(虚拟口袋、卡片、Polygon钱包、银行账户)
  • 设置卡片支出控制(默认模式或智能MCC路由)
  • 处理卡片交易Webhook
  • 在账户间转账(单笔或批量)
  • 构建预算或支出管理功能
  • 查询余额或交易历史

SDK at a Glance

SDK概览

@bloque/sdk          → Main package (aggregates everything)
@bloque/sdk-core     → HttpClient, errors, types
@bloque/sdk-accounts → Accounts, cards, transfers
@bloque/sdk-identity → User identities and aliases
@bloque/sdk-compliance → KYC/KYB verification
@bloque/sdk-orgs     → Organizations
@bloque/sdk-swap     → Currency swap and bank transfers
Platforms: Node.js, Bun, Deno (API key auth) | Browser, React Native (JWT auth) Assets:
DUSD/6
,
COPB/6
,
COPM/2
,
KSM/12
Amounts: Always strings to preserve precision.
"10000000"
= 10 DUSD (6 decimals).
@bloque/sdk          → 主包(整合所有功能)
@bloque/sdk-core     → HttpClient、错误处理、类型定义
@bloque/sdk-accounts → 账户、卡片、转账功能
@bloque/sdk-identity → 用户身份与别名管理
@bloque/sdk-compliance → KYC/KYB验证
@bloque/sdk-orgs     → 组织管理
@bloque/sdk-swap     → 货币兑换与银行转账
支持平台:Node.js、Bun、Deno(API密钥认证)| 浏览器、React Native(JWT认证) 支持资产
DUSD/6
COPB/6
COPM/2
KSM/12
金额格式:始终以字符串形式保存以保证精度。例如
"10000000"
等价于10 DUSD(保留6位小数)。

Quick Start

快速开始

typescript
import { SDK } from '@bloque/sdk';

const bloque = new SDK({
  origin: process.env.ORIGIN,
  auth: { type: 'apiKey', apiKey: process.env.API_KEY },
  mode: 'sandbox',
});

// Register a new user
await bloque.register('@alice', {
  type: 'individual',
  profile: { firstName: 'Alice', lastName: 'Smith', email: 'alice@example.com',
    phone: '+1234567890', birthdate: '1990-01-01', city: 'Miami', state: 'FL',
    postalCode: '33101', countryOfBirthCode: 'US', countryOfResidenceCode: 'US' },
});

// Connect to an existing user
const user = await bloque.connect('@alice');

// Create a pocket and a card
const pocket = await user.accounts.virtual.create({}, { waitLedger: true });
const card = await user.accounts.card.create(
  { ledgerId: pocket.ledgerId, name: 'My Card' },
  { waitLedger: true },
);
typescript
import { SDK } from '@bloque/sdk';

const bloque = new SDK({
  origin: process.env.ORIGIN,
  auth: { type: 'apiKey', apiKey: process.env.API_KEY },
  mode: 'sandbox',
});

// 注册新用户
await bloque.register('@alice', {
  type: 'individual',
  profile: { firstName: 'Alice', lastName: 'Smith', email: 'alice@example.com',
    phone: '+1234567890', birthdate: '1990-01-01', city: 'Miami', state: 'FL',
    postalCode: '33101', countryOfBirthCode: 'US', countryOfResidenceCode: 'US' },
});

// 连接现有用户
const user = await bloque.connect('@alice');

// 创建虚拟口袋和卡片
const pocket = await user.accounts.virtual.create({}, { waitLedger: true });
const card = await user.accounts.card.create(
  { ledgerId: pocket.ledgerId, name: 'My Card' },
  { waitLedger: true },
);

References

参考文档

For deeper guidance, read these files in order of relevance to the task:
FileWhen to read
references/api-reference.md
Read first for any integration. All methods, params, and exact return types.
references/quick-start.md
First-time setup, configuration, auth strategies
references/accounts.md
Creating pockets, Polygon wallets, bank accounts
references/cards-and-spending-controls.md
Card creation, default/smart spending, MCC routing
references/webhooks.md
Handling transaction events, webhook payloads
references/transfers.md
Moving funds, batch transfers, movement metadata
如需更深入的指导,请按与任务相关的优先级顺序阅读以下文档:
文档文件阅读时机
references/api-reference.md
任何集成场景下都请首先阅读。包含所有方法、参数及精确的返回类型。
references/quick-start.md
首次设置、配置、认证策略相关内容
references/accounts.md
创建虚拟口袋、Polygon钱包、银行账户相关内容
references/cards-and-spending-controls.md
卡片创建、默认/智能支出控制、MCC路由相关内容
references/webhooks.md
处理交易事件、Webhook负载相关内容
references/transfers.md
资金划转、批量转账、转账元数据相关内容

Key Concepts

核心概念

  1. Pockets — Virtual accounts that hold funds. Every card must be linked to a pocket via
    ledgerId
    .
  2. Spending Controls
    "default"
    (one pocket, all merchants) or
    "smart"
    (MCC-based multi-pocket routing).
  3. MCC Routing — Map Merchant Category Codes to pockets. Priority order determines fallback.
  4. Webhooks — Async events for card transactions (authorization, adjustment). Delivered to
    webhookUrl
    .
  5. Assets — Format is
    SYMBOL/DECIMALS
    . Amounts are raw integer strings.
    10 DUSD = "10000000"
    .
  1. Pockets(虚拟口袋) — 用于存放资金的虚拟账户。每张卡片必须通过
    ledgerId
    关联到一个虚拟口袋。
  2. 支出控制 — 分为
    "default"
    (单口袋,支持所有商户)或
    "smart"
    (基于MCC的多口袋路由)模式。
  3. MCC路由 — 将商户类别码(MCC)映射到不同虚拟口袋。优先级顺序决定了 fallback 逻辑。
  4. Webhook — 用于卡片交易(授权、调整)的异步事件。会推送至指定的
    webhookUrl
  5. 资产格式 — 格式为
    SYMBOL/DECIMALS
    。金额以原始整数字符串表示。例如10 DUSD等价于
    "10000000"

Critical: Alias Consistency

重要提示:别名一致性

The alias used in
register()
and
connect()
MUST be identical.
If you register a user as
'@alice'
, you must connect with exactly
'@alice'
— not
'alice'
,
'@Alice'
, or any variation. A mismatch will throw a
BloqueNotFoundError
("identity not found").
typescript
// Register
await bloque.register('@alice', { type: 'individual', profile: { ... } });

// Connect — MUST use the exact same alias
const user = await bloque.connect('@alice');  // ✅ correct
const user = await bloque.connect('alice');   // ❌ BloqueNotFoundError
const user = await bloque.connect('@Alice');  // ❌ BloqueNotFoundError
Rule: Pick one alias string and reuse it everywhere. Store it in a constant or environment variable.
register()
connect()
中使用的别名必须完全一致
。如果您以
'@alice'
注册用户,那么连接时必须使用完全相同的
'@alice'
——不能是
'alice'
'@Alice'
或任何其他变体。不匹配会抛出
BloqueNotFoundError
(错误信息:“identity not found”)。
typescript
// 注册
await bloque.register('@alice', { type: 'individual', profile: { ... } });

// 连接 — 必须使用完全相同的别名
const user = await bloque.connect('@alice');  // ✅ 正确
const user = await bloque.connect('alice');   // ❌ 抛出BloqueNotFoundError
const user = await bloque.connect('@Alice');  // ❌ 抛出BloqueNotFoundError
规则:选择一个别名字符串并在所有地方复用。将其存储在常量或环境变量中。

Critical:
connect()
Always Succeeds

重要提示:
connect()
始终返回会话

connect()
always returns a session — even if
register()
was never called for that alias.
It does NOT validate whether the identity exists. You will only discover the error later when you try to call account methods (e.g.,
user.accounts.card.create()
will fail).
The SDK does NOT provide a "user exists" check. Your application must track whether a user has been registered before calling
connect()
.
typescript
// ❌ Wrong — no way to know if '@bob' was ever registered
const user = await bloque.connect('@bob');       // Returns session (no error!)
const card = await user.accounts.card.create();  // 💥 Fails here — identity not found

// ✅ Correct — track registration state in your app
const isRegistered = await db.users.exists('@bob');

if (!isRegistered) {
  await bloque.register('@bob', { type: 'individual', profile: { ... } });
  await db.users.markRegistered('@bob');
}

const user = await bloque.connect('@bob');
Rule: Never assume
connect()
validates the user. Always ensure
register()
has been called first, using your own application logic.
connect()
始终会返回一个会话——即使该别名从未被
register()
注册过
。它不会验证身份是否存在。只有当您后续尝试调用账户方法时(例如
user.accounts.card.create()
)才会发现错误。 SDK不提供“用户是否存在”的检查功能。您的应用必须在调用
connect()
之前自行跟踪用户是否已注册
typescript
// ❌ 错误做法 — 无法确认'@bob'是否已注册
const user = await bloque.connect('@bob');       // 返回会话(无错误!)
const card = await user.accounts.card.create();  // 💥 此处失败 — 身份未找到

// ✅ 正确做法 — 在您的应用中跟踪注册状态
const isRegistered = await db.users.exists('@bob');

if (!isRegistered) {
  await bloque.register('@bob', { type: 'individual', profile: { ... } });
  await db.users.markRegistered('@bob');
}

const user = await bloque.connect('@bob');
规则:永远不要假设
connect()
会验证用户身份。务必确保在调用
connect()
之前已通过您自己的应用逻辑完成
register()
调用。

Error Handling

错误处理

All errors extend
BloqueAPIError
and include
requestId
,
timestamp
, and
toJSON()
:
Error ClassHTTPWhen
BloqueValidationError
400Invalid params
BloqueAuthenticationError
401/403Bad API key or JWT
BloqueNotFoundError
404Resource missing
BloqueRateLimitError
429Too many requests
BloqueInsufficientFundsError
Not enough balance
BloqueNetworkError
Connection failed
BloqueTimeoutError
Request timed out
typescript
import { BloqueInsufficientFundsError } from '@bloque/sdk-core';

try {
  await user.accounts.transfer({ sourceUrn, destinationUrn, amount, asset });
} catch (err) {
  if (err instanceof BloqueInsufficientFundsError) {
    console.log('Not enough funds:', err.toJSON());
  }
}
所有错误均继承自
BloqueAPIError
,并包含
requestId
timestamp
toJSON()
方法:
错误类HTTP状态码触发场景
BloqueValidationError
400参数无效
BloqueAuthenticationError
401/403API密钥或JWT无效
BloqueNotFoundError
404资源不存在
BloqueRateLimitError
429请求过于频繁
BloqueInsufficientFundsError
余额不足
BloqueNetworkError
连接失败
BloqueTimeoutError
请求超时
typescript
import { BloqueInsufficientFundsError } from '@bloque/sdk-core';

try {
  await user.accounts.transfer({ sourceUrn, destinationUrn, amount, asset });
} catch (err) {
  if (err instanceof BloqueInsufficientFundsError) {
    console.log('余额不足:', err.toJSON());
  }
}