Pular para o conteúdo principal

@cactus-agents/country-config

Registry de configuracoes por pais: validacao de documentos, mascaras de telefone, formatos de endereco, metodos de pagamento, requisitos legais e operadores KYC.

Instalacao

pnpm add @cactus-agents/country-config

Uso basico

import { getCountryConfig, hasCountryConfig } from "@cactus-agents/country-config";

const config = getCountryConfig("BRA");

// Validar documento
config.document.validate("123.456.789-09"); // true/false
config.document.format("12345678909"); // "123.456.789-09"
config.document.strip("123.456.789-09"); // "12345678909"

// Informacoes do pais
config.currency; // "BRL"
config.currencySymbol; // "R$"
config.phone.ddi; // "55"
config.phone.masks; // ["(00) 0000-0000", "(00) 00000-0000"]
config.legal.dataProtectionName; // "LGPD"

API publica

Funcoes do Registry

FuncaoDescricao
getCountryConfig(code)Retorna CountryConfig pelo codigo alpha-3. Fallback para BRA com warning.
getAllCountryCodes()Retorna todos os codigos registrados: ["BRA", "CHL", "MEX", "PER", "FIN", "XYZ"]
hasCountryConfig(code)Verifica se um codigo esta registrado

Catalogo global de paises

Funcoes para consultar o catalogo mundial de paises (250+ entradas, incluindo territorios, geradas a partir de dados ISO). Util para resolucao de alpha2/alpha3, moeda, DDI e outros metadados sem depender de maps hardcoded no template.

import {
getCountryCatalog,
getCountryByAlpha2,
getCountryByAlpha3,
getCountryByCode,
getCountriesByCurrency,
getCountryName,
getLocalizedCountryName,
getCurrencyByCountry,
getCurrentDdiByCountry,
} from "@cactus-agents/country-config";
FuncaoDescricao
getCountryCatalog()Retorna o array completo de CountryCatalogEntry[] (250+ paises)
getCountryByAlpha2(code)Busca por alpha-2 (ex: "BR" → entry do Brasil)
getCountryByAlpha3(code)Busca por alpha-3 (ex: "BRA" → entry do Brasil)
getCountryByCode(code)Busca por alpha-2 ou alpha-3 (detecta automaticamente pelo tamanho)
getCountriesByCurrency(currency)Retorna todos os paises que usam a moeda (ex: "USD"[USA, ECU, ...])
getCountryName(code)Retorna nome padrao em ingles do pais (ex: "BRA""Brazil")
getLocalizedCountryName(code, locale)Retorna nome localizado via Intl.DisplayNames com fallback para ingles
getCurrencyByCountry(alpha3)Retorna a primeira moeda do pais (ex: "BRA""BRL")
getCurrentDdiByCountry(alpha3)Retorna o primeiro DDI do pais (ex: "BRA""55")

Exemplo de uso no template:

// Antes: map hardcoded em app/config/payments/deposit.ts
const CURRENCY_COUNTRY_MAP = { BRL: "BRA", MXN: "MEX", ... };

// Agora: via SDK
import { getCountriesByCurrency, getCountryByAlpha3 } from "@cactus-agents/country-config";
const byCurrency = getCountriesByCurrency("BRL"); // → [{ alpha2: "BR", alpha3: "BRA", ... }]
const country = getCountryByAlpha3("BRA"); // → { alpha2: "BR", name: "Brazil", ... }

Helpers de telefone / DDI

Funcoes para listar DDIs mundiais, buscar DDI por pais, aplicar mascaras de telefone. Antes estavam em app/config/phone.config.ts no template — agora vivem no SDK.

import {
getDdiList,
findDdiByCountry,
findDdiByNumber,
applyPhoneMask,
getBestMask,
type DdiEntry,
} from "@cactus-agents/country-config";
FuncaoDescricao
getDdiList()Retorna DdiEntry[] com todos os DDIs mundiais (gerado a partir do catalogo)
findDdiByCountry(alpha3)Busca DdiEntry pelo codigo alpha-3 do pais
findDdiByNumber(ddi, countryCode?)Busca DdiEntry por DDI exato (ex: "55"). countryCode e opcional para desambiguar DDI compartilhado
applyPhoneMask(value, mask)Aplica mascara de telefone (ex: "11999990000" + "(##) #####-####""(11) 99999-0000")
getBestMask(masks, digitsLength)Seleciona a melhor mascara para o tamanho dos digitos informados

Exemplo de uso no template:

import { getDdiList, findDdiByCountry, applyPhoneMask, getBestMask } from "@cactus-agents/country-config";

const allDdis = getDdiList(); // lista completa para DdiSelect
const brazil = findDdiByCountry("BRA"); // { code: "BRA", ddi: "55", masks: [...] }
const mask = getBestMask(brazil.masks, 11); // "(##) #####-####"
const formatted = applyPhoneMask("11999990000", mask); // "(11) 99999-0000"

Helpers de nacionalidade (registro)

Funcoes para obter lista completa de nacionalidades (alpha-3 + OTHER) e default por pais da brand.

import {
getRegistrationNationalityCodes,
getDefaultRegistrationNationalityCode,
isRegistrationNationalityCode,
} from "@cactus-agents/country-config";
FuncaoDescricao
getRegistrationNationalityCodes()Retorna lista completa de codigos alpha-3 (prioriza BRA/CHL/MEX/ARG/COL/PER/URY no topo) + OTHER
getDefaultRegistrationNationalityCode(countryCode)Retorna default de nacionalidade para o pais da brand ("CHL""CHL", desconhecido → "OTHER")
isRegistrationNationalityCode(value)Valida se o valor e um codigo aceito

No template, os labels da lista devem vir do namespace countries no SDK de i18n (countries.nationalities.<ISO3>).

Validadores (uso direto)

Cada país tem funções validate, format e strip para seu tipo de documento ou campo bancário:

País / CampoExports
Brasil (CPF)validateCpf, formatCpf, stripCpf, CPF_MASK
Chile (RUT)validateRut, formatRut, stripRut, RUT_MASK
México (CURP)validateCurp, formatCurp, stripCurp, CURP_MASK
Peru (DNI)validateDni, formatDni, stripDni, DNI_MASK
México (CLABE)validateClabe, stripClabe, CLABE_LENGTH
GenericvalidateGeneric, formatGeneric, stripGeneric

CLABE (México)

A CLABE é o identificador bancário padrão mexicano — 18 dígitos numéricos.

import { validateClabe, stripClabe, CLABE_LENGTH } from "@cactus-agents/country-config";

validateClabe("032180000118359719") // → true
validateClabe("123") // → false (menos de 18 dígitos)
stripClabe("032-180-0001183-59719") // → "032180000118359719"
CLABE_LENGTH // → 18

Regra: Validadores bancários (CLABE, etc.) ficam no @cactus-agents/country-config, não no componente de UI. O template importa e usa — nunca redefine a regex.

Configs individuais (tree-shakeable)

braConfig, chlConfig, mexConfig, perConfig, finConfig, xyzConfig

Tipos

CountryConfig

interface CountryConfig {
code: string; // ISO 3166-1 alpha-3 (ex: "BRA")
alpha2: string; // ISO 3166-1 alpha-2 (ex: "BR")
currency: string; // ISO 4217 (ex: "BRL")
timezone: string; // IANA (ex: "America/Sao_Paulo")
languages: string[]; // Idiomas suportados
currencySymbol: string; // Simbolo (ex: "R$")
intlLocale: string; // BCP 47 (ex: "pt-BR")
displayDecimalDigits: number; // Casas decimais em valores monetarios (0 ou 2)
document: DocumentConfig;
address: AddressConfig;
phone: PhoneConfig;
payments: PaymentFeatures;
legal: LegalConfig;
kycOperators: string[];
}

DocumentConfig

type DocumentStoreEndpoint = "store-user-document" | "store-mex-document";

interface DocumentConfig {
name: string; // Label (ex: "CPF")
mask?: string; // Mascara (ex: "000.000.000-00")
placeholder?: string;
maxLength?: number;
validate: (value: string) => boolean;
format: (value: string) => string; // Raw → formatado
strip: (value: string) => string; // Formatado → raw
storeEndpoint: DocumentStoreEndpoint; // API endpoint para salvar documento
canRegisterFromAccount: boolean; // Se o usuario pode cadastrar documento na pagina de conta
}
  • storeEndpoint: Define qual endpoint da API usar para salvar o documento. "store-user-document" para CPF (BRA), "store-mex-document" para todos os outros (RUT, CURP, DNI, Generic).
  • canRegisterFromAccount: Controla se o formulario de cadastro de documento aparece na pagina de dados da conta. Todos os paises atualmente tem true.

CountryCatalogEntry

interface CountryCatalogEntry {
name: string; // Nome comum em ingles (ex: "Brazil")
officialName: string; // Nome oficial (ex: "Federative Republic of Brazil")
alpha2: string; // ISO 3166-1 alpha-2 (ex: "BR")
alpha3: string; // ISO 3166-1 alpha-3 (ex: "BRA")
numericCode: string; // ISO 3166-1 numerico (ex: "076")
ddis: string[]; // Codigos de discagem sem "+" (ex: ["55"])
currencies: string[]; // ISO 4217 (ex: ["BRL"])
timezones: string[]; // IANA (ex: ["America/Sao_Paulo", ...])
region?: string; // Regiao (ex: "Americas")
subregion?: string; // Sub-regiao (ex: "South America")
emoji?: string; // Emoji da bandeira (ex: "🇧🇷")
}

DdiEntry

interface DdiEntry {
code: string; // ISO 3166-1 alpha-3 (ex: "BRA")
alpha2: string; // ISO 3166-1 alpha-2 (ex: "BR")
name: string; // Nome do pais (ex: "Brazil")
ddi: string; // DDI sem "+" (ex: "55")
masks: string[]; // Mascaras de telefone onde "#" = digito
}

Outros tipos

TipoDescricao
AddressConfigLabel/mascara do CEP, lista de estados, statesRequired
StateEntry{ code: string; name: string }
PhoneConfigDDI e array de mascaras
PaymentFeaturesFlags booleanas: pix, spei, oxxo, cryptoWallet, redirect, bankAccountSection
LegalConfigLei de protecao de dados, termos obrigatorios, flag IRPF

Paises suportados

PaisCodigoDocumentoMascaraDDIPagamentosEstadosProtecaoDecimais
BrasilBRACPF000.000.000-0055PIX, Redirect27 (obrigatorio)LGPD2
ChileCHLRUT00.000.000-X56Redirect0
MexicoMEXCURPAAAA000000AAAAAA0052SPEI, OXXO, Redirect32 (obrigatorio)Ley de Datos2
PeruPERDNI0000000051Redirect25 (opcional)Ley de Datos2
FinlandiaFINPassport/ID358RedirectGDPR2
NigeriaNGANIN00000000000234Crypto, Redirect37 (obrigatorio)NDPA0
FilipinasPHLPassport/ID63Redirect2
PortugalPRTNIF000000000351RedirectGDPR2
XYZ (generico)XYZPassport/ID971Crypto, Redirect2

A coluna Decimais corresponde ao novo campo displayDecimalDigits: define quantas casas decimais aparecem em valores monetarios renderizados pelo formatMoney e pelos hooks useFormatMoney / useTransactions / useBalance do @cactus-agents/accounts/react. Backend continua armazenando em unidades menores (kobo para NGN, centavos para CLP/BRL, etc.) — a mudanca eh apenas de display. Nigeria e Chile usam 0 porque na pratica esses paises nao mostram subunidades; demais paises usam 2.

Algoritmos de validacao

CPF (Brasil)

Validacao modulo-11 com dois digitos verificadores. Pesos 10-2 para o primeiro digito e 11-2 para o segundo. Rejeita sequencias com todos os digitos iguais.

RUT (Chile)

Modulo-11 com multiplicadores ciclicos 2-7. Digito verificador pode ser 0-9 ou K. Aceita 7 a 9 caracteres (sem pontuacao).

CURP (Mexico)

Regex: ^[A-Z]{4}\d{6}[HM][A-Z]{2}[B-DF-HJ-NP-TV-Z]{3}[A-Z0-9]\d$

Estrutura: 4 letras (iniciais) + 6 digitos (nascimento YYMMDD) + sexo (H/M) + 2 letras (estado) + 3 consoantes + homoclave + digito verificador.

DNI (Peru)

Exatamente 8 digitos. Rejeita todos zeros.

Generic (Finlandia, XYZ)

Aceita qualquer valor nao vazio. Validacao real delegada ao backend/KYC.

Geracao do catalogo mundial

O arquivo src/world-catalog.data.ts contem os dados de 250+ paises e e gerado automaticamente a partir de fontes ISO:

pnpm generate:world-catalog

O script gera alpha2, alpha3, numericCode, DDIs, moedas, timezones, regiao e emoji para cada pais. Nao edite o arquivo manualmente — rode o script para regenerar.

Adicionando um novo país

  1. Criar src/countries/xxx.ts com a CountryConfig completa
  2. (Opcional) Criar validador em src/validators/xxx.ts — ex: validador de conta bancária local
  3. Registrar no src/registry.ts
  4. Re-exportar no src/index.ts

O restante do sistema (front-web-base, validations, payments) pega automaticamente.

Arquivos relevantes

ArquivoConteudo
src/index.tsExports publicos (registry, catalog, phone, validators)
src/registry.tsRegistry de CountryConfig por alpha-3
src/catalog.tsFuncoes de busca no catalogo mundial
src/phone.tsHelpers de DDI e mascaras de telefone
src/world-catalog.data.tsDados do catalogo mundial (gerado automaticamente)
src/types.tsInterfaces: CountryConfig, CountryCatalogEntry, DdiEntry, etc.
src/countries/*.tsConfigs individuais por pais (BRA, CHL, MEX, PER, FIN, XYZ)
src/validators/*.tsValidadores de documentos (CPF, RUT, CURP, DNI, generic)
scripts/generate-world-catalog.mjsScript de geracao do catalogo