npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@codedartdev/coinsentry-sdk

v0.1.3

Published

Headless CoinSentry SDK for browser-safe Auth, Session, Entity, KYC, Brand, HTTP and Realtime contracts.

Readme

@codedartdev/coinsentry-sdk

Core headless do SDK CoinSentry. Este pacote define contratos publicos para frontends de clientes consumirem Auth, Session, Entity, KYC, Brand, HTTP, erros e Realtime sem depender de React, Next.js ou componentes da whitelabel.

Responsabilidade

  • Cliente HTTP same-origin com fetch, cookies, CSRF retry, FormData seguro e corpos URLSearchParams para endpoints form-urlencoded.
  • Servicos headless: auth, session, entity, kyc, brand e modulos de produto.
  • Tipos publicos, guards e codigos de erro estaveis.
  • Resolucao pura do KYC universal via @codedartdev/coinsentry-sdk/kyc.
  • Interface de realtime desacoplada do client WebSocket interno.

Fora Do Escopo

  • Segredos de assinatura do BFF.
  • Headers upstream X-Frontend-*.
  • React providers, hooks, modais, toasts ou redirects.
  • Chamada browser para /api/v1/kyc/requirements.
  • Decisao local de client_flow, jurisdicao, customer type ou proxima tela.

createCoinSentryClient() e browser-safe e nunca aceita segredo de assinatura. O segredo do proxy deve existir apenas em APIs server-only de @codedartdev/coinsentry-next.

Uso Basico

import { createCoinSentryClient } from '@codedartdev/coinsentry-sdk';

const cs = createCoinSentryClient({
  baseUrl: '/',
  locale: 'pt-BR',
  onError(error) {
    console.warn(error.code, error.status, error.reason);
  },
});

await cs.auth.login({ email, password, slideCaptchaToken });
const session = await cs.session.refresh();
const entities = await cs.entity.list();
const selected = await cs.entity.select({ entityUuid: entities[0].uuid });
const overview = await cs.kyc.getOverview();

O browser deve usar baseUrl: '/' para chamar somente o BFF same-origin. Nao passe WHITELABEL_PROXY_SIGNATURE_SECRET, FRONTEND_PROXY_SIGNATURE_SECRET ou qualquer segredo equivalente para este cliente.

Locale

O adapter fetch envia Accept-Language automaticamente.

cs.locale.set('pt-BR');
cs.locale.setKyc('es-AR');
await cs.kyc.getOverview();
cs.locale.clearKyc();

locale.setKyc() afeta apenas requests para /api/v1/kyc*. Isso preserva o comportamento da whitelabel atual sem colocar fallback de fluxo no browser.

Brand

client.brand.getConfig() consome o contrato publico GET /api/brand/theme. Ele aceita brandKey e etag, normaliza o payload canonico e retorna metadata de cache quando disponivel.

const response = await cs.brand.getConfig({
  brandKey: 'default',
  etag: previousEtag,
});

if (!response.notModified && response.config) {
  renderBrand(response.config);
}

O subpath @codedartdev/coinsentry-sdk/brand contem helpers puros para aplicar o contrato em qualquer framework:

import {
  buildBrandCss,
  getBrandCssVariables,
  normalizeBrandConfig,
} from '@codedartdev/coinsentry-sdk/brand';

const brand = normalizeBrandConfig(response.config);
const css = buildBrandCss(brand);
const darkVars = getBrandCssVariables(brand, 'dark');

Os tipos cobrem fonte base, tipografia, logo textual/imagem, favicon claro e escuro, tokens de mercado (rising/downing) e tokens opcionais de superficie, texto e estado enviados pelo backend.

Transporte HTTP

client.request<T>() e o transporte headless oficial. Use-o para endpoints same-origin do BFF em vez de fetch manual no browser. O adapter preserva FormData sem definir Content-Type e aceita URLSearchParams para casos form-urlencoded como autorizacao de canais realtime.

Para compatibilidade com Sanctum/Fortify, requests mutaveis same-origin leem o ultimo cookie XSRF-TOKEN disponivel e enviam X-XSRF-TOKEN decodificado automaticamente. O token nao e anexado a requests cross-origin.

O retry automatico de 419 continua ativo por padrao em client.request<T>(). Para endpoints sensiveis que ja inicializam CSRF antes do POST, use retryOnCsrf: false para evitar repetir a mesma acao:

await cs.request({
  method: 'POST',
  path: '/auth/login',
  retryOnCsrf: false,
  body: payload,
});

csrf.init() e deduplicado: chamadas concorrentes compartilham o mesmo request e chamadas recentes reaproveitam uma janela curta de inicializacao. Metodos de auth, como login, register e 2FA, continuam forçando CSRF fresco antes do POST para preservar a seguranca do fluxo Fortify/Sanctum.

Auth

auth.login() e auth.twoFactorChallenge() preservam os envelopes reais do backend:

  • CoinSentryLoginTwoFactor: { two_factor: true };
  • CoinSentryLoginIncomplete: { success: true, two_factor: false, needs_refresh: true };
  • CoinSentryLoginMultipleEntities: login autenticado sem entidade ativa;
  • CoinSentryLoginSingleEntity: login com entidade selecionada;
  • CoinSentryLoginSuccess: sucesso simples.

Os metodos de auth que chamam csrf.init() antes do POST nao repetem automaticamente o POST em 419. Isso evita duplicar a mesma tentativa de login, registro ou desafio 2FA, especialmente quando ha CAPTCHA envolvido.

Use guards publicos para reduzir branching inseguro:

import {
  isCoinSentryLoginIncomplete,
  isCoinSentryLoginMultipleEntities,
  isCoinSentryLoginTwoFactor,
} from '@codedartdev/coinsentry-sdk';

const response = await cs.auth.login({ email, password, slideCaptchaToken });

if (isCoinSentryLoginTwoFactor(response)) {
  showTwoFactorChallenge();
}

if (isCoinSentryLoginIncomplete(response)) {
  await cs.session.refresh();
}

if (isCoinSentryLoginMultipleEntities(response)) {
  openEntitySelector(response.entities);
}

Session E Entity

session.refresh() retorna a sessao autenticada. entity.select() retorna um contrato tipado com usuario, balances, entidades e kyc_required quando o BFF responde com esse envelope.

Guards uteis:

  • isCoinSentrySession(value);
  • hasCoinSentryActiveEntity(session);
  • isCoinSentryEntityMinimal(value);
  • requiresCoinSentryEntitySelection(value).

Modulos De Produto

Alem de Auth, Session, Entity e KYC, o client expoe dominios usados pela whitelabel atual. Todos usam client.request<T>(), retornam payload de dominio normalizado e aceitam { signal } quando aplicavel.

  • account.twoFactor: enable, QR code, confirmacao, recovery codes, regeneracao, disable e status.
  • contacts: contatos bancarios, bancos e contatos de wallet.
  • deposits: dados de deposito e intent de deposito.
  • withdrawals: dados de saque, saque fiat, saque crypto e taxa de rede.
  • payments: moedas, historico, PIX receive/status/lookup/pay.
  • affiliate: codigo, status, referrals, payouts e rankings.
  • market: market data, orderbook, criar/cancelar ordens e cancelar todas.
  • otc: pares, quote/execute/history, ativar/desativar quote e planos recorrentes.
const depositData = await cs.deposits.get('BRL');
const fee = await cs.withdrawals.networkFee({ currency: 'BTC', network: 'BTC' });
const quote = await cs.otc.createQuote({
  symbol: 'USDT_BRL',
  from_currency: 'BRL',
  to_currency: 'USDT',
  from_amount: '100',
});

Esses modulos continuam headless: nao exibem toast, nao redirecionam e nao conhecem componentes da whitelabel.

Market E Orderbook

O modulo market tambem expoe helpers puros para consumers que precisam de orderbook realtime sem conhecer o formato interno de canais:

import {
  buildCreateOrderPayload,
  getOrderbookChannel,
  normalizeMarketSymbol,
  normalizeOrderbookSnapshot,
} from '@codedartdev/coinsentry-sdk/market';

const symbol = normalizeMarketSymbol('btc-brl'); // BTC_BRL
const markets = await cs.market.listMarkets();
const ticker = await cs.market.getTicker(symbol);
const details = await cs.market.getMarketDetails(symbol);
const snapshot = await cs.market.getOrderbookSnapshot('BTC_USDT', 50);
const trades = await cs.market.getTrades('BTC_USDT', { limit: 50 });
const channel = getOrderbookChannel('BTC_USDT'); // orderbook.btc-usdt

await cs.market.createOrder(buildCreateOrderPayload({
  symbol: 'BTC_USDT',
  side: 'BUY',
  type: 'LIMIT',
  price: '67000',
  quantity: '0.01',
}));

O book publico e tratado como snapshot-only: o client deve carregar GET /api/v1/orderbook/{symbol} e substituir o estado local em .orderbook.updated. O SDK nao expoe diffs incrementais publicos porque o backend atual nao publica sequencia nem delta canonico.

Endpoints publicos de mercado:

  • market.listMarkets() -> GET /api/v1/market;
  • market.getTicker(symbol) -> GET /api/v1/ticker/{symbol};
  • market.getOrderbookSnapshot(symbol, depth?) -> GET /api/v1/orderbook/{symbol};
  • market.getTrades(symbol, { limit? }) -> GET /api/v1/trades/{symbol}.

market.getMarketDetails(symbol) e o agregado autenticado GET /api/v1/market/{symbol} para saldos, ordens do usuario e enriquecimento privado. market.getMarket(symbol) continua como alias por compatibilidade, mas orderbook e trades publicos nao dependem desse agregado.

KYC Headless

import {
  hasKycClientFlow,
  isKycFlowSnapshotConfigured,
  resolveKycFlowSnapshot,
} from '@codedartdev/coinsentry-sdk/kyc';

const overview = await cs.kyc.getOverview();
const flow = resolveKycFlowSnapshot({ overview });

if (!isKycFlowSnapshotConfigured(flow)) {
  throw new Error('KYC flow is not configured.');
}

if (flow.activeStep?.screen === 'document_upload') {
  await cs.kyc.upload({ step: flow.activeStep, formData });
}

O core falha fechado quando nao existe client_flow. Ele nao cria fallback local para fluxo legado, jurisdicao, customer type ou proxima tela.

Guards KYC publicos:

  • hasKycClientFlow(requirements);
  • hasResolvedKycRequirements(requirements);
  • isKycFlowSnapshotConfigured(snapshot);
  • isKycOverviewFlowConfigured(overview).

Erros Publicos

O SDK normaliza falhas em CoinSentryApiError:

import {
  isCoinSentryAbortError,
  normalizeCoinSentryError,
} from '@codedartdev/coinsentry-sdk';

try {
  await cs.kyc.getOverview();
} catch (error) {
  if (isCoinSentryAbortError(error)) return;

  const normalized = normalizeCoinSentryError(error);
  if (normalized.code === 'kyc_required') {
    openKyc();
  }
}

Codigos estaveis:

  • unauthenticated
  • csrf_expired
  • kyc_required
  • entity_required
  • invalid_signature
  • origin_not_allowed
  • missing_signature_headers
  • validation_failed
  • rate_limited
  • forbidden
  • network_error
  • server_error
  • unknown_error

Cancelamentos iniciados pelo caller via request.signal sao repropagados como abort e nao chamam onError. Use isCoinSentryAbortError(error) para ignorar esse caso. Timeout interno continua sendo falha de rede normalizada.

Realtime

createCoinSentryRealtime(adapter) define a interface publica. A implementacao concreta pode ser o Reverb/Pusher client interno da whitelabel ou outro adapter compativel.

const realtime = createCoinSentryRealtime(adapter);
realtime.connect();
realtime.subscribeToEntity(entityUuid, 'balance.updated', onBalance);
realtime.subscribeStatus?.((status) => {
  if (status === 'connected') {
    // reancore snapshots locais se necessario
  }
});

O payload recomendado para saldo e CoinSentryBalanceUpdate:

type CoinSentryBalanceUpdate = {
  currency: string;
  available: string | number;
  locked: string | number;
  total?: string | number;
};

Estado Atual

Beta npm (0.1.2, dist-tag latest). O pacote gera dist, .d.ts, .d.ts.map e sourcemaps. O pacote permanece UNLICENSED enquanto os contratos publicos seguem em beta.