Pular para o conteúdo principal

Migração para accounts

Três pacotes do SDK — @cactus-agents/auth, @cactus-agents/user e @cactus-agents/wallet — foram removidos e unificados em um único pacote, @cactus-agents/accounts.

Se o seu fork ainda declara qualquer um dos três no package.json, o pnpm install não consegue resolvê-los: eles não existem mais no registry. Esta página é o caminho de saída.

:::info Quem precisa desta página Só quem está em um fork anterior à unificação. Se o seu package.json já declara @cactus-agents/accounts e nenhum dos três pacotes antigos, não há nada a fazer aqui. :::

O que mudou

Os três pacotes cobriam fatias do mesmo domínio — sessão, dados cadastrais e saldo do mesmo usuário — e compartilhavam tipos entre si (o user, por exemplo, reexportava tipos do wallet). A unificação eliminou essa dependência cruzada.

A boa notícia: a esmagadora maioria dos nomes exportados foi preservada sem alteração. Na prática a migração é uma troca de caminho de import, com quatro exceções pontuais descritas abaixo.

O pacote novo tem dois entry points:

ImportO que expõe
@cactus-agents/accountsServiços, transforms, helpers puros e todos os tipos. Não depende de React.
@cactus-agents/accounts/reactHooks e a store reativa (useAccountsStore). Requer React e Zustand.

react (>=18) e zustand (>=4) são peer dependencies opcionais: se você usar só o entry point raiz, não precisa instalá-las por causa do accounts.

Passo 1 — trocar a dependência

Remova os três pacotes antigos e adicione o novo:

pnpm remove @cactus-agents/auth @cactus-agents/user @cactus-agents/wallet
pnpm add @cactus-agents/accounts

A versão mínima que cobre todo o conteúdo desta página é a 2.9.0. Confirme o range que ficou no seu package.json depois do comando.

Passo 2 — trocar os caminhos de import

Todo import que apontava para um dos três pacotes passa a apontar para @cactus-agents/accounts:

- import { createAuthService, type AuthUser } from "@cactus-agents/auth";
- import { createUserService, type UpdateUserPayload } from "@cactus-agents/user";
- import { createWalletService, type WalletData } from "@cactus-agents/wallet";
+ import {
+ createAuthService,
+ createUserService,
+ createWalletService,
+ type AuthUser,
+ type UpdateUserPayload,
+ type WalletData,
+ } from "@cactus-agents/accounts";

Para varrer o projeto de uma vez (macOS/BSD sed — no Linux use sed -i sem o ''):

grep -rl '@cactus-agents/\(auth\|user\|wallet\)' app/ workers/ \
| xargs sed -i '' -E 's#@cactus-agents/(auth|user|wallet)#@cactus-agents/accounts#g'

Ajuste a lista de diretórios ao seu fork — se você tem código em scripts/ ou em plugins de build, inclua também. Confirme no fim que não sobrou nada:

grep -rn '@cactus-agents/\(auth\|user\|wallet\)' . --exclude-dir=node_modules

Depois disso você provavelmente terá imports duplicados do mesmo módulo no mesmo arquivo. pnpm check:write (Biome) resolve a formatação; a consolidação dos blocos é manual.

Nomes preservados

Não precisam de nenhuma alteração além do caminho. Todos os nomes abaixo existem em @cactus-agents/accounts exatamente como existiam antes:

  • Do auth: todos, sem exceção — createAuthService, createAuthFromClient, createRecoveryService, createRecoveryFromClient, shouldRefreshToken, markRefreshStarted, markRefreshCompleted, markTokenSaved, initialRefreshState, e os tipos AuthUser, AuthUserInfo, AuthService, LoginPayload, LoginResponse, RegisterSimplifiedPayload, ValidateDocumentPayload, TokenRefreshState, RecoveryService etc.
  • Do user: createUserService, createUserFromClient, getAccountRestriction, isAccountRestricted, getRestrictionType, filterSelfExclusionOptions, filterTimeoutOptions, getMinSelfExclusionMonths, getMinTimeoutDays, isLimitChangeBlocked, getLimitChangeUnblocksAt, isPermanentExclusion, isoDurationToHours, hoursToIsoDuration, parseLimitPeriod, transformLoginHistoryItem, transformLoginHistoryResponse, e as constantes LIMIT_PERIOD, SELF_EXCLUSION_MONTHS_OPTIONS, TIMEOUT_DAYS_OPTIONS, SPA_EXCLUSION_CODES.
  • Do wallet: createWalletService, createWalletFromClient, fetchWalletData, aggregateWalletData, transformWalletResponse, transformTransaction, transformTransactionResponse, transformRollover, e os tipos Wallet, WalletData, RealWallet, BonusWallet, CashbackWallet, Rollover, Transaction, TransactionFilter, TransactionStatus etc.

Passo 3 — corrigir os quatro símbolos renomeados

Estes são os únicos que não compilam depois da troca de caminho:

Nome antigoPacote antigoNome novo
PostalCodeLookupResponseuserPostalCodeLookupResult
RawPostalCodeLookupResponseuserRawPostalCodeLookup
RolloverDatauserRolloverRaw
TransactionTypewalletTransactionFilterType ou TransactionCategory — veja abaixo

Sobre os três primeiros:

  • PostalCodeLookupResult tem a mesma forma que o tipo antigo (street, city, state) — é só o nome.
  • RawPostalCodeLookup perdeu o campo opcional state?. Os demais (street?, logradouro?, city?, cidade?, uf?) continuam iguais. Se o seu código lia raw.state, passe a ler raw.uf.
  • RolloverData era apenas um alias que o user publicava para o RolloverRaw do wallet. Use RolloverRaw direto.

TransactionType virou dois tipos

O antigo TransactionType acumulava dois papéis. Ele foi separado:

Novo tipoPapel
TransactionFilterTypeO valor que você envia no campo type ao listar o extrato
TransactionCategoryA categoria semântica que a UI recebe, derivada da resposta

Isso importa porque dois valores mudaram no lado do filtro:

Antes (TransactionType)Agora (TransactionFilterType)
"casino_bet""casino"
"sports_bet""sports"
"deposit", "withdraw", "coupon", "bonus", "cashback", "clubevip"iguais
"full" (era passado à parte do tipo)"full", agora parte do próprio tipo

:::caution Falha silenciosa Mandar "casino_bet" ou "sports_bet" como filtro não dá erro — o backend simplesmente devolve o extrato inteiro, sem filtro. O usuário vê uma lista que parece certa e não é. Se o seu fork monta filtros de extrato à mão, revise esses dois valores explicitamente; o typecheck pega o caso quando o valor é literal, mas não quando vem de uma string dinâmica. :::

TransactionCategory é mais granular que o tipo antigo: separa aposta de prêmio (casino_bet / casino_win, sports_bet / sports_win) e tem um "other" de fallback. Use-o para escolher título e ícone do card, não para montar a requisição.

TransactionStatus ganhou três valores

TransactionStatus manteve o nome e todos os valores antigos (approved, denied, expired, pending, processing, credit, debit, transfer), mas ganhou três: failed, integration_failure e provider_rejected. São variantes de falha distintas de denied, que passa a significar só rejeição manual.

Como a mudança é aditiva, código que apenas consome o tipo continua compilando. O que quebra é código exaustivo sobre ele:

  • Record<TransactionStatus, ...> — passa a faltar três chaves e o typecheck acusa
  • switch com default inalcançável ou checagem de exaustividade via never
  • mapas de label, cor ou ícone por status

Nesses pontos, decida o rótulo das três novas variantes de falha em vez de deixá-las cair em um fallback genérico — o objetivo delas é justamente permitir que a UI diferencie a causa.

Passo 4 — a camada React (opcional)

Os três pacotes removidos publicavam um único entry point, sem subpath ./react: eles não traziam hooks nem store. Se o seu fork mantém o estado de sessão/carteira em uma store própria, ela continua funcionando — nada obriga você a trocar.

O que o pacote novo oferece, e que antes não existia, é uma camada React pronta em @cactus-agents/accounts/react:

  • Store reativa: useAccountsStore — expõe user, userInfo, isAuthenticated, wallet, transactions, authHydrated e as ações correspondentes (setAuthUser, clearAuth, refetchWallet, fetchTransactions…). Além de hydrateAccounts e useAccountsHydration para o boot em SSR.
  • Hooks de auth: useCurrentUser, useLogin, useLogout, useRegister, useRecovery, useValidateDocument, useRefreshProfile.
  • Hooks de carteira: useWallet, useRealBalance, useBonusBalance, useCashbackBalance, useTransactions, useRollover, useTransferBonus, useTransferCashback, useWithdrawReceipt, useWalletFlags, useRefreshWallet.
  • Formatação de dinheiro: useFormatMoney e formatMoney.
  • Perfil: useProfile.

A camada precisa ser inicializada uma vez, com locale, moeda e casas decimais. O template faz isso em um componente dedicado que não renderiza nada, alimentado pelo ambiente e pela configuração de país — não por valores fixos:

import { useAccountsInit } from "@cactus-agents/accounts/react";
import { useCountry } from "~/context/country";
import { useClientEnv } from "~/context/env";

export function AccountsBootstrap() {
const env = useClientEnv();
const country = useCountry();

useAccountsInit({
locale: env.BRAND_LANGUAGE,
currency: env.BRAND_CURRENCY,
displayDecimalDigits: country.displayDecimalDigits,
});

return null;
}

BRAND_LANGUAGE chega em minúsculas (pt-br). O Intl casa tags de idioma sem diferenciar caixa, então passar o valor direto funciona; o template ainda assim normaliza para a forma canônica (pt-BR) antes de repassar, e vale imitar isso se você comparar o locale como string em algum ponto.

:::caution displayDecimalDigits não é sempre 2 Passe sempre o displayDecimalDigits da configuração de país, nunca um literal: Nigéria e Chile exibem valores sem casas decimais, os demais países com duas. Um 2 fixo quebra a exibição de saldo nesses dois mercados. Veja a nota em Installation. :::

Passando essa configuração, useFormatMoney, useTransactions e os hooks de saldo derivam a formatação sozinhos — você não precisa montar Intl.NumberFormat à mão.

AccountsConfig aceita ainda callbacks opcionais para você substituir qualquer chamada HTTP que a camada faz por padrão (fetchTransactions, refetchWallet, login, transferBonus…). Só passe os que precisar sobrescrever.

Passo 5 — verificar

pnpm install
pnpm typecheck

O typecheck é o que efetivamente prova a migração: qualquer import não resolvido ou símbolo renomeado aparece aqui. Depois:

pnpm dev

E teste manualmente os fluxos que atravessam os três domínios unificados:

  1. Login e logout — inclusive recuperação de senha
  2. Cadastro — com validação de documento, se a sua marca usa
  3. Saldo no header — real, bônus e cashback, com o número de casas decimais correto para o seu país
  4. Extrato — e cada filtro por tipo, um a um (é onde o casino_betcasino se manifesta)
  5. Transferência de bônus/cashback para a carteira real

Próximos passos

Com a migração fechada, volte ao fluxo normal de atualização em Updating SDK Packages. Se algum símbolo que o seu fork usa não aparece em nenhuma das listas acima, fale com o time Cactus antes de reimplementá-lo localmente.