@delvoux/oplab
v0.1.1
Published
SDK TypeScript independente, completo e tipado para a API REST v3 da OpLab.
Maintainers
Readme
@delvoux/oplab
Biblioteca para integrar aplicações JavaScript e TypeScript à API REST v3 da OpLab. O SDK oferece métodos prontos para consultar dados de mercado e acessar recursos da sua conta, cuidando da autenticação por token, da montagem das requisições HTTP e do tratamento de respostas e erros.
Você pode usá-lo em scripts, serviços e backends que precisam de cotações, cadeias de opções, históricos, portfólios e outros recursos disponibilizados pela OpLab.
- Mercado: instrumentos, cotações, opções, dados históricos, rankings, taxas de juros e status do mercado.
- Conta e operações: usuário, portfólios, posições, ordens, estratégias, watchlists e outros recursos do domínio da API.
- Cobertura do contrato: 115 operações e 65 modelos nomeados, com entradas e respostas tipadas para TypeScript.
- Transporte: timeout, cancelamento, tratamento de erros e novas tentativas controladas para consultas seguras.
- Compatibilidade: ESM e CommonJS,
fetchnativo e zero dependências em runtime.
Este SDK é independente e não é um produto oficial da OpLab. A cobertura se refere à especificação incluída no projeto; não significa que todos os endpoints tenham sido validados na API real. As correções aplicadas e os limites conhecidos estão em Notas do OpenAPI.
Requisitos
- Node.js 22 ou superior.
- Token de acesso à API da OpLab, com permissão para os recursos que sua aplicação utilizará. Consulte Acesso à API OpLab.
- Execução no servidor ou em um script local. Mantenha o token fora do código enviado ao navegador e não o inclua no repositório.
O SDK é gratuito e distribuído sob MPL-2.0. Ele não fornece token, assinatura ou acesso gratuito à API: os dados e recursos disponíveis dependem da conta, do plano e das condições da OpLab.
Instalação
npm install @delvoux/oplabO pacote inclui o JavaScript compilado e as declarações de tipos. Não é necessário instalar TypeScript para utilizá-lo em JavaScript.
Primeiro uso em JavaScript
Na pasta da sua aplicação, crie um arquivo .env com seu token e inclua .env no .gitignore:
OPLAB_ACCESS_TOKEN=seu_token_da_oplabCrie exemplo.mjs na mesma pasta:
import { OplabClient } from "@delvoux/oplab";
const accessToken = process.env.OPLAB_ACCESS_TOKEN;
if (!accessToken) {
throw new Error("Configure OPLAB_ACCESS_TOKEN antes de iniciar a aplicação.");
}
const oplab = new OplabClient({ accessToken });
const quotes = await oplab.market.instruments.quote({
query: { tickers: ["PRIO3", "PETR4"] },
});
console.table(quotes ?? []);
const options = await oplab.market.options.list({
path: { symbol: "PRIO3" },
});
for (const option of (options ?? []).slice(0, 5)) {
console.log(option.symbol, option.strike, option.bid, option.ask);
}Execute com o carregamento de variáveis de ambiente do próprio Node.js:
node --env-file=.env exemplo.mjsO exemplo faz duas consultas de leitura: cotações e opções. O SDK envia o token no header Access-Token. Os símbolos apenas demonstram as chamadas; os resultados vêm da API e dependem do ativo e das permissões da conta.
Se preferir uma função factory, o pacote também exporta createOplabClient(options), que retorna uma instância equivalente. Outros recursos seguem a mesma organização, por exemplo await oplab.domain.portfolios.list() para listar portfólios.
TypeScript
Os parâmetros e as respostas são inferidos automaticamente. O pacote também exporta modelos e tipos de operação para anotar o código da sua aplicação:
import type { OptionInfo } from "@delvoux/oplab";
const options: OptionInfo[] | undefined = await oplab.market.options.list({
path: { symbol: "PRIO3" },
});O trecho acima usa a instância oplab criada no exemplo anterior. Veja Tipos e formato das respostas para os detalhes do contrato.
CommonJS
const { OplabClient } = require("@delvoux/oplab");
const oplab = new OplabClient({
accessToken: process.env.OPLAB_ACCESS_TOKEN,
});Organização da API
A fachada acompanha as duas categorias da documentação oficial:
| Categoria | Recursos |
| --- | --- |
| client.domain | Usuário, portfólios, posições, ordens, estratégias, compartilhamentos, corretoras, contas de trade, watchlists, robôs, notificações e dias úteis. |
| client.market | Opções, instrumentos, taxas de juros, status de mercado, companhias, ações, rankings, dados históricos e bolsas. |
Por exemplo, client.market.options oferece list, get, covered, blackScholes e powders. Todos os métodos recebem um objeto de entrada com path, query e/ou body, conforme a operação. Métodos sem entrada obrigatória podem ser chamados sem argumentos.
O Catálogo da API relaciona cada um dos 115 métodos ao verbo HTTP, à rota e ao operationId original. Os nomes originais das propriedades da API, incluindo snake_case e chaves como "access-token", são preservados.
Acesso por operationId
A interface genérica tem a mesma tipagem da fachada e permite integrar o SDK a serviços, ferramentas ou roteadores que já usam os identificadores do OpenAPI:
const options = await oplab.request("GetInstrumentOptions", {
path: { symbol: "PRIO3" },
});
const result = await oplab.requestWithResponse("GetInstrumentOptions", {
path: { symbol: "PRIO3" },
});
console.log(result.status);
console.log(result.headers.get("content-type"));
console.log(result.requestId);
console.log(result.data);requestWithResponse retorna { data, status, headers, requestId }. Respostas HTTP de erro continuam lançando OplabApiError; esse método acrescenta metadados às respostas de sucesso.
Tipos e formato das respostas
O pacote exporta os 65 modelos, os tipos de entrada e resposta de cada operação, além dos utilitários OperationId, OperationInput<K> e OperationResponse<K>:
import type {
OptionInfo,
OperationInput,
OperationResponse,
} from "@delvoux/oplab";
const input: OperationInput<"GetInstrumentOptions"> = {
path: { symbol: "PRIO3" },
};
type OptionList = OperationResponse<"GetInstrumentOptions">;
type IndividualOption = OptionInfo;As garantias de tipagem acompanham o contrato disponível:
- Propriedades sem
requiredno OpenAPI permanecem opcionais. Ter um campo no exemplo oficial não o torna obrigatório no tipo. - Operações que documentam sucesso com JSON e também
204 No Contentretornam uma união comundefined. Operações de sucesso sem conteúdo retornamundefined. - Datas são strings no formato da API. O SDK não converte automaticamente para
Datenem altera unidades ou casas decimais. - Objetos e arrays sem estrutura documentada usam
unknown, evitandoany. - Enums documentados são uniões literais. Parâmetros CSV conhecidos aceitam valor único ou array de valores válidos e são serializados com vírgulas.
- Há validação em runtime da presença de parâmetros de path/query e de corpo exigidos, além da serialização. A estrutura dos campos do corpo é verificada estaticamente pelo TypeScript. Corpos e respostas não passam por validação automática do schema completo em runtime. Adicione a validação de negócio da sua aplicação quando precisar de garantias além da tipagem estática.
O SDK exige explicitamente o argumento body nas 27 operações que declaram corpo, embora o OpenAPI original omita requestBody.required em todas elas. Essa é uma decisão do SDK para tornar as chamadas previsíveis; os campos internos continuam respeitando a obrigatoriedade do schema. Um corpo cujas propriedades são todas opcionais pode ser informado como {}. Veja todas as decisões em Notas do OpenAPI.
Particularidades do contrato
PostUserSettings recebe preferences como string contendo JSON:
await oplab.request("PostUserSettings", {
body: {
preferences: JSON.stringify({ interest_rate_type: "SELIC" }),
},
});GetRobotLog retorna texto. PostOrdersExport usa GET e retorna 202 sem corpo: ele inicia a geração de um CSV, cujo link é enviado posteriormente por notificação da OpLab. O método não retorna diretamente o arquivo.
Configuração, timeout e novas tentativas
const oplab = new OplabClient({
accessToken,
timeoutMs: 30_000,
retry: {
maxRetries: 2,
baseDelayMs: 250,
maxDelayMs: 5_000,
},
headers: {
"X-Application-Name": "meu-servico",
},
});| Configuração | Comportamento |
| --- | --- |
| accessToken | String ou função que resolve a chave, inclusive de forma assíncrona. |
| baseUrl | Base HTTP(S), por padrão https://api.oplab.com.br/v3. Permite apontar para um proxy ou ambiente de testes sob seu controle. |
| timeoutMs | Limite total da chamada lógica; padrão de 30 segundos. Abrange resolução do token, requisição, leitura da resposta e espera entre tentativas. Use 0 para desativar. |
| retry.maxRetries | Até duas tentativas adicionais por padrão, somente em GETs classificados como seguros. Use 0 para desativar. |
| retry.baseDelayMs / maxDelayMs | Controle da espera entre tentativas; padrões de 250 ms e 5.000 ms. |
| headers | Headers adicionais do cliente ou da chamada. |
| fetch | Implementação de fetch injetável, útil para testes ou transporte customizado compatível. |
Falhas de rede e status 429, 500, 502, 503 e 504 podem receber nova tentativa em GETs seguros. POST, PUT e DELETE não recebem novas tentativas automáticas. A exportação de ordens também não recebe, porque inicia um processamento apesar de usar GET.
Quando a resposta inclui Retry-After válido, o SDK respeita a espera informada. Se ela exceder maxDelayMs, encerra com o erro HTTP original, sem repetir a chamada antes do momento permitido.
Cancelamento e opções por chamada
O segundo argumento dos métodos da fachada aceita { signal, timeoutMs, headers, retry }:
const controller = new AbortController();
const pending = oplab.market.options.list(
{ path: { symbol: "PRIO3" } },
{
signal: controller.signal,
timeoutMs: 10_000,
retry: { maxRetries: 0 },
},
);
// O chamador pode executar controller.abort() quando cancelar a operação.
const options = await pending;Para métodos sem parâmetros, use undefined como primeiro argumento quando quiser fornecer opções:
await oplab.domain.portfolios.list(undefined, {
timeoutMs: 10_000,
});Token dinâmico e autenticação
O resolver de token é executado uma vez por chamada lógica, e seu resultado é reutilizado nas tentativas dessa chamada:
const oplab = new OplabClient({
accessToken: async () => {
const token = process.env.OPLAB_ACCESS_TOKEN;
if (!token) throw new Error("Token OpLab indisponível.");
return token;
},
});setAccessToken(token) substitui a chave/resolver configurado; clearAccessToken() remove essa configuração. A chave permanece na memória da instância e não é persistida pelo SDK. Autenticação e recuperação de senha não avaliam o resolver accessToken nem adicionam um token a partir dessa opção, pois o OpenAPI declara essas operações públicas.
Se optar por autenticar com e-mail e senha, confira a presença da chave antes de armazená-la:
const unauthenticated = new OplabClient();
const auth = await unauthenticated.request("PostAuthenticate", {
body: {
email: "[email protected]",
password: "substitua-pela-senha-obtida-com-seguranca",
},
});
if (
auth &&
"access-token" in auth &&
typeof auth["access-token"] === "string"
) {
unauthenticated.setAccessToken(auth["access-token"]);
} else {
throw new Error("A resposta de autenticação não contém um access-token.");
}O exemplo usa credenciais fictícias. Em uma aplicação, obtenha segredos do ambiente ou do seu gerenciador de segredos e mantenha o cliente autenticado no servidor.
Tratamento de erros
import { OplabClient, isOplabApiError } from "@delvoux/oplab";
const oplab = new OplabClient({ accessToken });
try {
await oplab.market.options.list({ path: { symbol: "PRIO3" } });
} catch (error) {
if (isOplabApiError(error)) {
console.error({
status: error.status,
operation: error.operationId,
requestId: error.requestId,
message: error.message,
});
} else {
throw error;
}
}OplabApiError também é exportada para uso com instanceof. Ela oferece status, body, headers, operationId, method, url e requestId. O corpo de erro não ganha uma estrutura fictícia: faça refinamento antes de acessar propriedades específicas. Use os metadados necessários à observabilidade da sua aplicação e trate timeout, cancelamento e falhas de transporte conforme a política do serviço.
Os helpers isOplabError e isOplabApiError também reconhecem erros que atravessam as entradas ESM e CommonJS do pacote. Prefira esses helpers quando a aplicação mistura os dois formatos, porque o instanceof direto depende da identidade da classe importada.
| Classe exportada | Situação |
| --- | --- |
| OplabApiError | Resposta HTTP de erro da API. |
| OplabAuthError | Token ausente, inválido ou falha ao resolvê-lo. |
| OplabValidationError | Entrada/configuração de transporte inválida. |
| OplabTimeoutError | Prazo total da chamada excedido. |
| OplabAbortError | Cancelamento pelo AbortSignal. |
| OplabNetworkError | Falha no transporte ou leitura da resposta. |
| OplabDecodeError | JSON inválido ou status de sucesso não documentado. |
Todas derivam de OplabError, também identificável com isOplabError.
Integração com NestJS
O SDK não depende do NestJS. Registre uma instância como provider usando as dependências que sua aplicação já possui:
import { Module } from "@nestjs/common";
import { OplabClient } from "@delvoux/oplab";
@Module({
providers: [
{
provide: OplabClient,
useFactory: () => {
const accessToken = process.env.OPLAB_ACCESS_TOKEN;
if (!accessToken) throw new Error("Configure OPLAB_ACCESS_TOKEN.");
return new OplabClient({ accessToken });
},
},
],
exports: [OplabClient],
})
export class OplabModule {}Depois, injete OplabClient nos serviços normalmente. Em aplicações com várias contas, crie instâncias por credencial/contexto ou forneça um resolver ligado ao contexto correto; uma mudança de token em uma instância compartilhada afeta suas chamadas futuras.
Desenvolvimento e atualização do contrato
| Comando | Finalidade |
| --- | --- |
| npm ci | Instalar as versões registradas no lockfile. |
| npm run generate | Gerar contrato normalizado, tipos, fachada, metadados e catálogo a partir da especificação original. |
| npm run generate:check | Verificar se os arquivos gerados correspondem à especificação e ao gerador. |
| npm run typecheck | Verificar o projeto TypeScript sem emitir código. |
| npm test | Executar os testes de comportamento e contrato. |
| npm run test:types | Verificar os contratos de tipagem, incluindo entradas inválidas esperadas. |
| npm run build | Compilar as distribuições ESM e CommonJS e suas declarações. |
| npm run test:package | Verificar o pacote distribuível e seu consumo. |
| npm run check | Executar a verificação integrada do projeto. |
| npm pack --dry-run | Inspecionar o conteúdo previsto para o pacote npm. |
Arquivos centrais:
| Caminho | Conteúdo |
| --- | --- |
| src/ | Cliente, transporte, erros e código gerado. |
| dist/ | Distribuição compilada pronta para consumo. |
| spec/openapi.original.json | Cópia preservada da especificação recebida. |
| spec/openapi.normalized.json | Contrato utilizado na geração após as correções explícitas. |
| spec/normalization-report.json | Registro das decisões de normalização. |
| scripts/ | Geração, compilação e verificações reproduzíveis. |
| docs/API.md | Catálogo completo de operações. |
| docs/OPENAPI-NOTES.md | Inconsistências do contrato e tratamento adotado. |
Para atualizar a API, substitua a especificação original por uma nova versão obtida da OpLab, execute npm run generate, revise o diff e execute npm run check. Não edite os arquivos gerados para introduzir ajustes permanentes: registre a alteração no gerador e nas notas correspondentes.
As verificações automatizadas usam respostas simuladas, checagem de tipos, cobertura do contrato e consumo do pacote. A passagem desses testes não confirma permissões de plano, comportamento atual do servidor nem semântica de operações financeiras em produção. O teste com token real descrito abaixo cobre somente as três consultas que executa.
O registro de validação detalha os testes da versão inicial do projeto.
Uso local a partir do ZIP ou dos fontes
Para desenvolver a biblioteca ou gerar um pacote local, extraia o ZIP ou obtenha os fontes e execute na raiz do projeto:
npm ci
npm run check
npm packO comando npm pack informa o nome do arquivo .tgz gerado. Na aplicação que vai consumir o SDK, instale esse arquivo; por exemplo, para a versão 0.1.0:
npm install /caminho/para/delvoux-oplab-0.1.0.tgzSe você recebeu um ZIP com um .tgz já gerado em artifacts/, também pode instalar esse arquivo diretamente. Para publicar uma versão da biblioteca, consulte Publicação no npm.
Testar com seu token real
Na cópia local deste projeto, preencha OPLAB_ACCESS_TOKEN no .env da raiz e execute:
npm run build
npm run test:api
# Opcional: escolher outro ativo (padrão: PETR4)
npm run test:api -- VALE3O arquivo JavaScript scripts/test-api.js carrega o .env automaticamente e usa o SDK compilado em dist/ para consultar status do mercado, cotação e opções. Exibe até cinco registros por consulta e um resumo com duração, sem imprimir o token. As três chamadas são GET de leitura, com timeout de 15 segundos cada e sem novas tentativas automáticas.
Também é possível rodar diretamente com node scripts/test-api.js depois de compilar. Falhas encerram o processo com código 1. Respostas vazias aparecem como SEM DADOS; os dados e recursos disponíveis dependem do ativo e das permissões da conta/plano. Este teste valida somente as três consultas executadas.
Licença e atribuição
Distribuído sob Mozilla Public License 2.0, a licença declarada pela especificação fornecida. As fontes e a especificação estão incluídas na distribuição; preserve a licença e as atribuições ao redistribuir o projeto. Consulte NOTICE.md.
A licença do SDK e da especificação é distinta das condições de acesso à API e de uso dos dados de mercado, definidas pela OpLab em sua documentação e nos termos de serviço.
