@finatic/client

中文文档
1.1.6发布于 2026/10/17PROPRIETARYTypeScriptESM + CJS构建来源已验证近 30 天下载 2129

Finatic Client SDK for browser integration

原始使用文档
文档目录10 节
  1. Install
  2. Quick start
  3. Portal authentication and connection readiness
  4. Exact instrument descriptors
  5. Event Contract capability and order types
  6. Token handoff
  7. Migrating from beta
  8. Environments
  9. Common commands
  10. Documentation

Finatic Client SDK

Browser SDK for embedding Finatic Connect and account-first data into your frontend. The company API key never belongs in this package. Your backend (Server SDK) mints a one-time token; the browser only receives that token.

Install

npm install @finatic/client

Quick start

import { FinaticConnect, isPortalLifecycleEventPayload } from '@finatic/client';

const finatic = await FinaticConnect.init('one-time-token', undefined, {
  apiEnvironment: 'sandbox', // or 'live'
});

await finatic.openPortal({
  mode: 'dark',
  onSuccess: (userId) => {
    // OTP / session ready. The user has not necessarily granted an account yet.
    console.log('Portal user linked:', userId);
  },
  onEvent: async (eventName, payload) => {
    if (eventName !== 'account.grant.created') return;
    const grant = payload as { accountId?: string };
    const accounts = await finatic.v1.listAccounts({ includeSyncStatus: true });
    const ready = accounts.success?.data ?? [];
    console.log('Grant created for', grant.accountId, 'accounts', ready);
  },
});

openPortal must use the object form to receive onEvent. The positional overload has no grant events.

The embedding app controls when Connect is dismissed. Call closePortal() from host UI or after handling an optional portal event; repeated calls are safe and do nothing when no portal is open:

await finatic.openPortal({
  onEvent: (eventName) => {
    if (eventName === 'account.grant.created') {
      finatic.closePortal();
    }
  },
  onClose: () => {
    // Runs once for either the portal close control or closePortal().
  },
});

Portal authentication and connection readiness

onSuccess(userId) means the portal session authenticated. It does not mean a broker connection exists or that connector data is ready. Connect schema v1 publishes those later transitions through the typed portal.lifecycle event:

await finatic.openPortal({
  onEvent: (eventName, payload) => {
    if (eventName !== 'portal.lifecycle' || !isPortalLifecycleEventPayload(payload)) return;

    switch (payload.stage) {
      case 'portal_authenticated':
        console.log('Portal authenticated', payload.userId);
        break;
      case 'broker_connection_created':
        console.log('Connection persisted', payload.connectionId);
        break;
      case 'push_agent_state_changed':
        // Only LIVE_DATA and STALE_LIVE_DATA can report dataReady: true.
        console.log(payload.state, payload.dataReady ?? 'not asserted');
        break;
    }
  },
});

The SDK accepts lifecycle messages only when they match schema version 1 and the exported stage/state allowlists. Unsupported versions, malformed payloads, unexpected fields (including secret-bearing fields), and invalid readiness claims are dropped. Existing broad (eventName: string, payload?: unknown) handlers remain assignable, and non-lifecycle events continue to be forwarded.

Client data methods return the wire envelope { success, error, warning } (not { data, errors }).

Exact instrument descriptors

Account orders, order fills and events, positions, position lots, and lot fills expose the API-generated FDXInstrumentDescriptor from the package root. Exact futures keep their full contract identity (MGCZ6 and MGCG7 remain distinct); root-only symbols such as MGC are marked with future.identityQuality === 'ROOT_ONLY'. Optional expiry, exchange, provider symbol, and provenance fields stay absent when the API cannot verify them—the browser SDK does not infer or normalize instrument identity.

import {
  FDXFutureInstrumentDetailsIdentityQualityEnum,
  type FDXBrokerPosition,
} from '@finatic/client';

const result = await finatic.v1.listPositions({ accountId: 'account-id' });
const position: FDXBrokerPosition | undefined = result.success?.data[0];

if (
  position?.instrument?.future?.identityQuality ===
  FDXFutureInstrumentDetailsIdentityQualityEnum.Exact
) {
  console.log(position.instrument.finaticInstrumentId, position.instrument.future.contractCode);
}

await finatic.v1.createAccountOrder({
  accountId: 'account-id',
  idempotencyKey: crypto.randomUUID(),
  body: {
    order: {
      symbol: 'MGCZ6',
      finaticInstrumentId: 'fininst_mgcz6',
      instrumentId: 'provider-native-id',
    },
  },
});

Legacy symbol-only order bodies and existing flat identity fields remain supported. When both identity fields are supplied, the API validates that they agree in the authorized account scope.

Event Contract capability and order types

The package root exports FDXAssetType.EventContract, EventContractCapabilityResponse, AccountOrderSchemaResponse, and FinaticAPIErrorResponse from the approved public OpenAPI artifact. Capability axes are independent: provider offering and implementation evidence do not imply public write enablement or account entitlement. Treat publicEnabled !== true, accountEntitled !== true, or closingOnly === true as a reason not to submit an opening order.

import {
  FDXAssetType,
  type AccountOrderSchemaResponse,
} from '@finatic/client';

const response = await finatic.v1.getAccountOrderSchema<AccountOrderSchemaResponse>({
  accountId: 'account-id',
  action: 'place',
});
const capability = response.success?.data.eventContract;

if (
  capability?.publicEnabled === true &&
  capability.accountEntitled === true &&
  capability.closingOnly !== true
) {
  await finatic.v1.createAccountOrder({
    accountId: 'account-id',
    idempotencyKey: crypto.randomUUID(),
    body: { order: { assetType: FDXAssetType.EventContract, symbol: 'EVENT-SYMBOL' } },
  });
}

EVENT_CONTRACT is the public asset enum value. Provider-native payload fields such as asset_type: 'event_contract' pass through unchanged. Unknown public assetType values fail locally instead of being omitted or mapped to equity. Authenticated Event Contract writes and public enablement still require provider/account evidence; this SDK release does not claim them.

Call FinaticConnect.reset() before init when you need a new session boundary.

Token handoff

// Backend (@finatic/server-node) — keep FINATIC_API_KEY here
const token = await finatic.v1.getToken();
// 90 seconds. Send token to the browser only.

Never set an API key in Vite/NEXT_PUBLIC_ env vars for production.

Migrating from beta

Beta route familyv1 replacement
/api/beta/session/initBackend v1.getToken() / session/init
/api/beta/session/startFinaticConnect.init(oneTimeToken)
/api/beta/session/portalfinatic.openPortal(...) or backend v1.getPortalUrl()
/api/beta/brokers/data/accountsfinatic.v1.listAccounts(...)
/api/beta/brokers/data/balancesfinatic.v1.listBalances({ accountId })
/api/beta/brokers/data/positionsfinatic.v1.listPositions({ accountId })
/api/beta/brokers/data/ordersfinatic.v1.listOrders({ accountId })
/api/beta/brokers/data/transactionsfinatic.v1.listTransactions({ accountId })
/api/beta/brokers/ordersfinatic.v1.createAccountOrder({ accountId, body, idempotencyKey })
/api/beta/brokers/connectionsfinatic.v1.listAccounts() plus finatic.v1.listAccountGrants()

Connect owns portal institution/auth/consent UX. Those flows are not published methods on finatic.v1. Position lots are not on the v1 façade — use listPositions. Do not pass beta connectionId as {accountId}.

Environments

apiEnvironment is live | sandbox (X-Finatic-Environment). URL presets (environment: 'staging' | 'production' | ...) are separate from sandbox vs live data.

Common commands

TaskCommand
Buildnpm run build
Testnpm test
Lintnpm run lint

Documentation

This README is the Client SDK contract. Fetch the rest before writing a full integration:

版本与发布记录

@finatic/client 共发布 36 个版本,首次发布于 2025/07/17;过去 12 个月发布了 24 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.1.6latest2026/10/1728 天前
1.1.52026/10/111 个月前
1.1.42026/09/201 个月前
1.1.32026/09/181 个月前
1.1.22026/09/151 个月前
1.1.12026/09/151 个月前

关于 @finatic/client 的常见问题

@finatic/client 是什么?

Finatic Client SDK for browser integration

如何安装 @finatic/client?

在项目目录运行 npm install @finatic/client,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=16.8.0)、react-dom(>=16.8.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@finatic/client 支持 TypeScript 吗?

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

@finatic/client 支持 ESM 还是 CommonJS?

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

@finatic/client 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@finatic/client 可以商用吗?

@finatic/client 使用 PROPRIETARY 许可。声明的许可为 PROPRIETARY,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@finatic/client 的下载量有多少?

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

@finatic/client 还在维护吗?

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