@debridge-finance/borderless-validation-sdk

中文文档
0.6.0发布于 2026/11/12BUSL-1.1TypeScriptESM + CJS零依赖近 30 天下载 2600

Validation SDK for deBridge borderless intents API responses

原始使用文档
文档目录21 节
  1. Purpose
  2. Threats mitigated
  3. Installation
  4. Basic usage
  5. API
  6. Integration guide for UI teams
  7. 1. Where to call
  8. 2. Choosing the environment
  9. 3. Pass the exact URL you called
  10. 4. Handling violations
  11. 5. Browser compatibility
  12. 6. Bundle size
  13. 7. TypeScript
  14. 8. What NOT to do
  15. Development
  16. Releasing
  17. Java parity E2E validation
  18. 1. Running the check
  19. 2. Execution flow and generated files
  20. 3. Comparison rules
  21. License

@debridge-finance/borderless-validation-sdk

Validation SDK for deBridge borderless intents API (POST /v1.0/bundle) responses.

Purpose

When a user submits a bundle request to the deBridge API, the response contains transactions and signable payloads (EIP-712 messages, permits, Solana transactions, etc.) that the user is expected to sign.

Every field the user signs is a potential attack vector. If the API is compromised (MITM, server bug, malicious rewrite), the user could unknowingly sign a transaction that drains their funds.

This SDK runs on the client before signing. It validates the response structure and checks signable payloads against the original request, protocol invariants, and environment-specific whitelists.

Threats mitigated

  • MITM attacks against the API endpoint.
  • Bugs on the API side that produce subtly wrong responses.
  • Reduced API trust — the client no longer has to take API responses on faith.
  • Regression safety net when testing new API versions.

Installation

npm install @debridge-finance/borderless-validation-sdk

Declared peer dependency ranges:

  • @solana/web3.js >= 1.90.0
  • bs58 >= 5.0.0
  • viem >= 2.0.0
  • zod ^3.0.0 || ^4.0.0

Basic usage

import {
    createValidator,
    Environment,
    ViolationCode,
} from "@debridge-finance/borderless-validation-sdk";

const validator = createValidator({ environment: Environment.Prod });

const url = "https://cross-chain-api.debridge.finance/v1.0/bundle";

const response = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(request),
}).then(res => res.json());

const result = validator.validate(url, request, response);

if (!result.ok) {
    if (result.violations.some(v => v.code === ViolationCode.HigherApiVersion)) {
        // Special case: the API response was produced for a newer validation
        // version than this SDK supports. The SDK cannot reliably validate it.
        // Decide in your app whether to block, warn, update the SDK, or use
        // another fallback flow.
        console.error("API validation version is newer than SDK support:", result.violations);
        return;
    }

    if (result.violations.some(v => v.code === ViolationCode.UnexpectedValidationError)) {
        // Special case: this indicates an internal Validation SDK error.
        // The client app must decide how to handle it: block signing, report
        // telemetry, retry after SDK update, or use another fallback flow.
        console.error("Validation SDK internal error:", result.violations);
        return;
    }

    console.error("Validation failed:", result.violations);
    // Do NOT let the user sign anything.
    return;
}

// Safe to proceed with signing.

API

createValidator(config: ValidatorConfig): Validator

type ValidatorConfig = {
    environment: Environment;
};

type Validator = {
    validate(url: string, request: object, response: object): ValidationResult;
};

type ValidationResult = {
    ok: boolean;             // true if no violations
    violations: Violation[]; // all issues found
};

type Violation = {
    code: ViolationCode;     // machine-readable identifier
    message: string;         // human-readable description
    path: string;            // JSON path of the offending field
    expected?: unknown;      // the value the validator expected (concrete, comparable to `actual`)
    actual?: unknown;        // the value found in the response (concrete, comparable to `expected`)
    details?: unknown;       // extra machine-readable context (e.g. caught error object)
};

validator.validate() never throws — every error condition is reported as a Violation. Safe to call in any code path.

Integration guide for UI teams

The SDK is designed to run between receiving the API response and presenting it to the user for signing. Wire it into that seam.

1. Where to call

┌───────────────┐     ┌─────────┐     ┌────────────────────┐     ┌───────────────┐
│ Build request │ ──▶ │ fetch() │ ──▶ │ validator.validate │ ──▶ │ Sign / submit │
└───────────────┘     └─────────┘     └────────────────────┘     └───────────────┘
                                              │
                                              ▼
                                     ok ? proceed : block
  • Before validate: the user has not yet seen or signed anything.
  • After validate: if result.ok === false, do not forward any signable payload (intent message, permit, transaction) to the wallet. The API response cannot be trusted.

2. Choosing the environment

import { Environment } from "@debridge-finance/borderless-validation-sdk";
  • Environment.Prod — production without gasless features.
  • Environment.Gasless — production with gasless features.
  • Environment.Dev — developer environment (also known as Stage).

Pass the same environment your app is already configured for — don't make it user-selectable.

3. Pass the exact URL you called

const url = "https://cross-chain-api.debridge.finance/v1.0/bundle";
const response = await fetch(url, { ... });
const result = validator.validate(url, request, response);

The url argument is accepted for API compatibility and future endpoint checks. Pass the same string you handed to fetch; do not rely on URL validation until it is explicitly enabled in a release.

4. Handling violations

On result.ok === false:

  1. Block the signing flow. Do not show a wallet popup or write any pending tx to state.
  2. Log the full violations array to your error reporting system (Sentry / Datadog / etc.). Include code, path, expected, actual, details.
  3. Show the user a generic error. Do not leak raw Violation data into the UI — messages are for developers, not end-users. A single "Quote is invalid, please retry" is enough.
  4. Do not retry automatically. If the API is compromised, retries make it worse. Let the user manually trigger a retry.

5. Browser compatibility

The SDK is published as both CJS and ESM and uses only browser-compatible APIs (no fs, crypto, Buffer, process).

Tree-shaking: the ESM build preserves named exports. Importing only createValidator will not pull in unused validators.

6. Bundle size

Roughly 1 MB unpacked (a lot of it is source maps — drop them in production). The heaviest peer dep is @solana/web3.js; if your app only deals with EVM trades, your bundler's tree-shaking should eliminate most of it.

7. TypeScript

Full type declarations ship in dist/types/. ValidatorConfig, ValidationResult, Violation, and ViolationCode are all exported — use them directly, don't re-declare.

8. What NOT to do

  • ❌ Don't skip validation because "the API is our own." Compromise detection is the whole point.
  • ❌ Don't mutate request or response between the API call and validate() — the validator needs the exact payload the user received.
  • ❌ Don't interpret violations[].message programmatically — message wording may change between versions. Branch on code instead.
  • ❌ Don't cache the validator if environment changes. Create a new instance via createValidator for each environment.

Development

See CLAUDE.md for project conventions, validation rules, and security guidelines. See src/README.md for an overview of the source code structure and validation flow.

  • Unit tests: npm test
  • Zod 3 unit compatibility tests: npm run test:zod3
  • Zod 3 E2E compatibility tests: npm run test:e2e:zod3
  • Zod 3 E2E compatibility tests (CI mode): npm run test:e2e:zod3:ci
  • Zod 3/4 full compatibility checks: npm run test:zod-compat
  • Unit test coverage: npm run coverage
  • E2E tests (use the stage API by default; override with API_BASE_URL): npm run test:e2e
  • E2E tests with validation-case recording: npm run test:e2e:record-validation-cases
  • E2E tests (CI mode, serial with longer timeout): npm run test:e2e:ci
  • E2E coverage: npm run coverage:e2e
  • Download the matching Java validator CLI: npm run download:java-validator-cli
  • Compare TypeScript and Java E2E validation results: npm run test:e2e:java-parity
  • Full build: npm run build
  • Build ESM only: npm run build:esm
  • Build CJS only: npm run build:cjs
  • Build type declarations only: npm run build:types
  • Clean build output: npm run clean

Releasing

Releases are cut by Nx Release from the conventional-commit PR titles:

  1. Title the PR as a conventional commit: fix: ... (patch), feat: ... (minor), feat!: ... (major). Other types (ci, chore, docs, test, refactor, ...) do not trigger a release.
  2. Squash-merge the PR into master.
  3. Actions → Create Release → Run workflow on master; tick dry-run to preview the next version and changelog first. After the approval of the release environment the workflow bumps package.json, updates CHANGELOG.md, pushes the v<version> tag, creates the GitHub release and publishes the package to npm (trusted publishing, no npm token).

To release changes merged without a fix:/feat: title, set version (patch, minor, major or 1.2.3). If only the npm publish step failed, re-run Create Release with publish_only.

Java parity E2E validation

This check runs the repository's E2E validation cases through both the TypeScript SDK and its Java port, then verifies that both implementations produce equivalent validation results.

1. Running the check

Use the TypeScript SDK version from the root package.json:

npm run test:e2e:java-parity

To select the Java release associated with another TypeScript SDK version, pass that version explicitly:

npm run test:e2e:java-parity [-- <typescript-sdk-version>]

The argument selects the Java release mapping only. It does not check out or install that version of the TypeScript SDK; TypeScript results always come from the current working tree.

The command requires Java and access to GitHub releases. For authenticated GitHub access, it uses GITHUB_TOKEN, GH_TOKEN, or the token returned by gh auth token, in that order.

2. Execution flow and generated files

The command performs the following steps:

  1. Determines the requested TypeScript SDK version from the command-line argument or the root package.json.

  2. Finds the newest published Java release whose release notes contain TypeScript SDK tag: v<version> and expects that release to contain exactly one cli-*.jar asset.

  3. Downloads and verifies the Java CLI, unless the same verified release is already cached under:

    .cache/java-validation-sdk/releases/<typescript-version>/<java-release-tag>/
    

    This directory contains the CLI JAR and its metadata.json cache metadata.

  4. Checks that the Java CLI supports the expected CLI contract version.

  5. Runs the regular TypeScript E2E suite with validation-case recording enabled. Every Jest worker writes its validator inputs and TypeScript results to a separate JSONL file:

    .cache/recorded-validation-cases/<date>__<unix-timestamp>/
    └── recorded-cases__pid-<pid>.jsonl
    

    Each JSONL line contains the test identity, validator URL, request, response, validator config, and TypeScript ValidationResult for one validator invocation.

  6. Sends every recorded input to the Java CLI daemon in the same order and reads one Java ValidationResult per input.

  7. Compares the corresponding TypeScript and Java results. Up to ten mismatches are printed to the console. The complete mismatch report is written to:

    .cache/java-validation-sdk/parity-check-runs/<date>__<unix-timestamp>/mismatches.json
    

The temporary .cache/recorded-validation-cases/latest-run.json file connects the E2E recorder to the parity runner and is removed when the command finishes. A successful parity check also removes its recorded validation cases. If E2E execution or parity comparison fails, the recorded cases are preserved for investigation. A parity-check run directory is created only when mismatches need to be reported.

3. Comparison rules

The raw ValidationResult objects are not compared directly. Each result is reduced to this shape:

{
    ok: boolean;
    violations: Array<{
        code: string;
        path: string;
        expected?: unknown;
        actual?: unknown;
    }>;
}

The comparison includes:

  • the top-level ok value;
  • the number of violations, including duplicate violations;
  • each violation's code and path;
  • the presence and JSON value of expected and actual;
  • nested value types, string casing, and array element order inside expected and actual.

Before comparison:

  • violations are sorted, so the order in which the two SDKs report violations does not matter;
  • object keys are sorted recursively, so object property order does not matter;
  • arrays are not sorted, so their element order remains significant.

The comparison intentionally ignores:

  • violation message text;
  • violation details;
  • any other violation fields;
  • any other top-level result fields.

After normalization, the two result objects are serialized and compared exactly. Any remaining difference is reported as a parity mismatch.

License

BUSL-1.1

版本与发布记录

@debridge-finance/borderless-validation-sdk 共发布 31 个版本,首次发布于 2026/04/17;过去 12 个月发布了 31 个版本。

版本发布日期距今
0.6.0latest2026/11/12今天
0.5.22026/11/111 天前
0.5.12026/11/066 天前
0.5.02026/09/251 个月前
0.4.12026/09/141 个月前
0.4.02026/09/082 个月前

其他发布通道:dee2389 → 0.0.0-dev-dee2389,25d2153 → 0.0.0-dev-25d2153,58fb7d3 → 0.0.0-dev-58fb7d3,3dc1a82 → 0.0.0-dev-3dc1a82,4a73f49 → 0.0.0-dev-4a73f49。

关于 @debridge-finance/borderless-validation-sdk 的常见问题

@debridge-finance/borderless-validation-sdk 是什么?

Validation SDK for deBridge borderless intents API responses

如何安装 @debridge-finance/borderless-validation-sdk?

在项目目录运行 npm install @debridge-finance/borderless-validation-sdk,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:zod(^3.0.0 || ^4.0.0)、bs58(>=5.0.0)、viem(>=2.0.0)、@solana/web3.js(>=1.90.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@debridge-finance/borderless-validation-sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@debridge-finance/borderless-validation-sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@debridge-finance/borderless-validation-sdk 可以商用吗?

@debridge-finance/borderless-validation-sdk 使用 BUSL-1.1 许可。声明的许可为 BUSL-1.1,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@debridge-finance/borderless-validation-sdk 的下载量有多少?

根据 npm 官方下载统计,@debridge-finance/borderless-validation-sdk 在 2026/10/12 – 2026/11/10 这 30 天内被下载 2,600 次,日均约 87 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@debridge-finance/borderless-validation-sdk 还在维护吗?

最新版本 0.6.0 发布于 2026/11/12(今天);至今共发布 31 个版本,其中过去 12 个月发布了 31 个;首次发布于 2026/04/17。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。