Pular para o conteúdo principal

API

Cada nó OpenFiat expõe um único endpoint JSON-RPC 2.0 modelado diretamente na própria API JSON-RPC da Solana — nomes de método em camelCase getX/sendX sobre um único endpoint POST, em vez de uma hierarquia de recursos REST. É implementado pelos crates rpc e api em openfiat-core.

Endpoint

POST /rpc
Content-Type: application/json

Cada requisição é um envelope JSON-RPC 2.0 padrão:

{ "jsonrpc": "2.0", "id": 1, "method": "getAdvertisement", "params": { "id": "ad-1" } }

e cada resposta é ou um result ou um error, nunca ambos:

{ "jsonrpc": "2.0", "id": 1, "result": { "id": "ad-1", "status": "Active", "..." : "..." } }

O nó devnet público está em https://openfiat.allenhark.com — o mesmo host também publica um multiaddr de entrypoint para nós, que é um endereço diferente para um trabalho diferente (veja getting started). Qualquer nó que você execute serve a superfície idêntica em :7080.

Chaves, peer ids e assinaturas são base58

Cada chave pública, identificador de peer, assinatura e identificador de evento é uma string base58:

{
"service_id": "node-ALLENLMtV1zEAHT3xpVryqcbdPCB8c9JhM1Jdbe5XHg5",
"provider": "12D3KooWK9hQ7TwbfvFiaAxUbRFCkdhS7iEpAJDnewNL1anyREQ1",
"provider_public_key": "ALLENLMtV1zEAHT3xpVryqcbdPCB8c9JhM1Jdbe5XHg5"
}

Até há pouco eram arranjos de inteiros. Se você vê "provider_public_key": [192, 74, 15, ...], está falando com um nó anterior à mudança — e nada nessa resposta distingue uma chave pública publicada de uma privada vazada, porque um segredo Ed25519 também tem trinta e dois bytes. Essa ambiguidade é o motivo da mudança. A forma base58 é também a única usável: 12D3KooW… é o que um --entrypoint recebe e o que se pode buscar em um log.

Isto não é apenas uma mudança de exibição. Uma carga sendX é assinada sobre o JSON de seu struct interno, então um cliente que escreve uma chave numa carga como um arranjo produz uma transcrição que o nó não reproduz. A assinatura então falha na verificação — o que aparece como uma mutação rejeitada, não como um erro de parsing. Use um SDK e isso é tratado por você; ao construir o formato de fio à mão, codifique os identificadores como base58.

Os campos de bytes que não são identificadores continuam arranjos. O commitment de um voto de disputa e seu secret de revelação são valores opacos de trinta e dois bytes, não identidades, e são enviados como arranjos. A distinção é pelo que o campo é, não pelo seu comprimento.

Nomenclatura de métodos

Os métodos de leitura começam com get e nunca alteram o estado:

{ "method": "getReservation", "params": { "id": "res-1" } }
{ "method": "getReservations", "params": {} }

Um método getMyX ainda é uma leitura, mas responde apenas pela carteira que o chamador prova possuir — veja leituras com prova de carteira.

As mutações começam com send e recebem um campo — data, uma carga de fio codificada em base64 e já assinada que a própria carteira do chamador produziu localmente. Isto espelha o sendTransaction da Solana: o nó nunca constrói nem assina nada em nome do chamador, apenas decodifica a carga e a aplica pelo mesmo caminho de verificação de assinatura por onde passa um evento recebido por gossip.

{ "method": "sendReservationRequest", "params": { "data": "<base64 wire bytes>" } }

O Client tipado de cada SDK constrói e assina essa carga por você — é o ponto de integração recomendado, em vez de construir o formato de fio à mão.

Categorias de métodos

DomínioMétodos de exemplo
AnúnciosgetAdvertisement, getAdvertisements, sendAdvertisementCreate, sendAdvertisementPriceUpdate, sendAdvertisementDisable
ReservasgetReservation, getReservations, getMyReservations, sendReservationRequest
LiquidaçãogetSettlement, getSettlements, getMySettlements, sendSettlementInitiate, sendPaymentSubmitted, sendSettlementApproved
Negociação (junção só de leitura)getTrade, getTrades
DisputasgetDispute, getDisputes, getMyDisputes, sendDisputeOpen, sendArbitratorJoin, sendVoteCommit, sendVoteReveal
Provas de carteiragetWalletChallenge, getCounterpartiesChallenge, getCounterparties, getProviderEarningsChallenge
VolumegetSettledVolume
Anexos e conteúdogetSettlementAttachments, getHeldContent, sendAttachmentPublish
IdentidadegetIdentityClaim, getIdentityClaimsByWallet, sendClaimPublish
Reputação (só leitura)getReputation
GovernançagetProposal, getProposals, sendProposalCreate, sendVoteCast
Provedores de serviçogetProvider, getProviders, sendProviderRegister, sendProviderHealthUpdate, getProviderEarnings, sendProviderWithdraw
NotificaçõesgetSubscription, getNotificationDispatch, sendSubscriptionUpdate, sendDeliveryReport
OráculosgetOracleRecord, getExchangeRate, getMedianExchangeRate, sendOraclePublish
Inteligência de riscogetWalletScreening, sendRiskPublish
RecompensasgetRewardObservations
SnapshotsgetLatestSnapshot, getSnapshots, getCheckpointSlot, sendSnapshotAnnounce
SessõesgetSession, sendSessionEstablish, sendSessionRenew, sendSessionRevoke, sendSessionMigrate
Ponte de cadeia (Solana, OFS-4300)getChainStatus, getLatestBlockhash, sendTransaction
getVersion, getHealth, getPeers

Leituras que não nomeiam as partes

getSettlement(s), getReservation(s) e getDispute(s) retornam registros com a identidade das partes removida. É uma mudança deliberada, motivada pela segurança, e não um descuido, e tem uma página própria: o que uma leitura pública retorna. Uma parte lê seus próprios registros por completo via leituras com prova de carteira.

As disputas são decididas na cadeia, não pelo nó que te responde

Uma resposta de getDispute carrega as revelações que um nó coletou, e não carrega um desfecho derivado delas. Uma resolução aparece só depois que este nó observou a transação de execução confirmar e leu o que ela decidiu — veja como uma disputa se resolve. Um cliente que conta ele mesmo as revelações reintroduziu exatamente a divergência que o nó parou de produzir.

Dois métodos de taxa de câmbio, e qual usar

getMedianExchangeRate retorna um número nu ou null, que é a forma correta quando tudo o que você quer é um preço ou nada.

getExchangeRate recebe os mesmos { base, quote } e responde com um status etiquetado, porque null colapsa dois fatos distintos:

{ "status": "current", "rate": 129.5, "expiresAt": 1753800000000 }
{ "status": "stale" }
{ "status": "noData" }

A distinção não é acadêmica. Stale significa que um provedor de fato publica este par e cada registro expirou (OFS-7000 §12: dados expirados não são dados atuais, por mais recente que seja o lapso) — o feed provavelmente voltará, então esperar é sensato. NoData significa que ninguém precifica este corredor e esperar é inútil. Nenhum é um número, e um chamador não deve mostrar nenhum como tal.

Use getExchangeRate a menos que você tenha um motivo para não fazê-lo. getMedianExchangeRate permanece porque os clientes dependem dele.

Service ids

Um nó se registra sob node-<sua chave pública base58>, e um provedor de snapshots sob snapshot-<a mesma chave> — o prefixo é o que permite a um nó manter vários registros do registro sem que colidam.

O id é derivado em vez de aleatório para que um nó que reinicia atualize seu registro existente em vez de deixar uma entrada morta para trás. Derivá-lo da chave inteira importa: um esquema anterior usava os primeiros oito bytes do peer id como hexadecimal, o que parece dezesseis dígitos de identidade mas são dois, já que cada peer id Ed25519 abre com o mesmo preâmbulo de seis bytes. Dois nós colidiram em poucas centenas de registros, e o segundo a registrar deslocou o primeiro.

O que um nó sabe sobre a rede

getPeers reporta os peers que este nó descobriu, os endereços que ele anuncia sobre si mesmo e seu próprio self_peer_id na forma 12D3Koo… que vai em um --entrypoint. Veja descoberta de peers para a visão do operador disso.

Erros

Os códigos de erro JSON-RPC 2.0 padrão (-32700 erro de parsing, -32601 método não encontrado, -32602 parâmetros inválidos, -32603 erro interno) cobrem falhas de nível de transporte. Cada falha de domínio — liquidez insuficiente, um evento duplicado, um signatário não autorizado — volta como um único erro de aplicação -32000, com o código numérico próprio do protocolo e o nome simbólico (de OFS-8000) em data:

{ "error": { "code": -32000, "message": "INSUFFICIENT_AVAILABLE_LIQUIDITY", "data": { "ofsErrorCode": 4004, "ofsErrorName": "INSUFFICIENT_AVAILABLE_LIQUIDITY" } } }

Assinaturas

GET /ws

transmite cada mutação bem-sucedida à medida que acontece — {"method": "sendX", "result": ...} — para que um cliente possa reagir à atividade do mercado sem sondagem. Filtre no lado do cliente pelos métodos que lhe interessam.

Os snapshots são etiquetados por slot, não por uma altura

getCheckpointSlot retorna o slot da Solana em relação ao qual o estado do último snapshot importado estava atual, ou null em um nó que não importou nenhum.

Era getCheckpointHeight, e a renomeação não é cosmética. O valor antigo era a própria contagem de eventos de gossip do nó produtor, que é por produtor: dois nós com estado idêntico reportam números diferentes, e um nó que entrou na semana passada reporta um mais baixo que um nó em operação desde a gênese. Comparar os números de dois produtores não comparava nada.

Um slot é o único relógio que cada participante já compartilha. Ele também torna uma afirmação verificável — um nó pode comparar um slot anunciado com sua própria visão da cadeia e recusar um de um futuro implausível, o que é impossível contra um número que só o anunciante pode ver.

O que um slot afirma é mais estreito do que parece. Ele diz quando o estado foi capturado, não o que ele contém: dois nós que fazem snapshot no mesmo slot podem ter estados de gossip ligeiramente diferentes, porque a propagação não é instantânea. Trate-o como uma âncora de recência, não como uma prova de que um snapshot contém outro — o mesmo que os próprios snapshots da Solana significam com ele.

Um nó que nunca observou um slot não produz snapshots e diz isso. Isso não é uma exigência de executar uma conexão RPC: um nó só-gossip aprende slots pela ponte de cadeia.

Volume liquidado, e por que é por ativo

getSettledVolume responde com uma linha por ativo, nunca um total:

{
"assets": [
{ "asset_mint": "2bHPi…RRU", "asset_symbol": "USDC", "decimals": 6,
"base_units": 4500000, "settlements": 12 },
{ "asset_mint": "So111…112", "asset_symbol": "wSOL", "decimals": 9,
"base_units": 2000000000, "settlements": 3 }
],
"unattributed_settlements": 1,
"settlements_known": 16,
"scope": "settlements this node has replicated and observed confirmed"
}

Quatro coisas que um cliente não deve fazer com isto:

Não some entre ativos. São tokens diferentes em escalas diferentes; uma cifra combinada soma SOL a USDC e não significa nada.

Não adivinhe decimals. É null, junto com um asset_symbol null, quando este nó não tem um nome para aquele mint. Mostre o endereço e as unidades base brutas. Assumir 6 é exatamente como wSOL — que tem nove — sai mil vezes grande demais.

Não esconda unattributed_settlements. São liquidações reais confirmadas cujo anúncio foi apagado desde então, então seu ativo é irrecuperável. Omiti-las faz os totais parecerem completos quando estão faltando exatamente essas.

Não descarte scope. Ele diz que estas são as liquidações que este nó replicou e confirmou — não toda a história da rede. Uma cifra de volume apresentada sem seu escopo se lê como um total global. settlements_known ao lado das linhas contadas faz o restante ser lido como negociações em curso, e não como uma discrepância.

Referência interativa

Explore cada método →

Um documento OpenRPC 1.2.6 (o equivalente JSON-RPC de uma spec OpenAPI/Swagger) — /api/openrpc.json — mais uma página interativa autônoma para explorar cada método. A lista de métodos é gerada diretamente da própria tabela de despacho ao vivo do openfiat-rpc (cargo run -p openfiat-api --example dump_openrpc), então não pode desviar para um método que um nó real não executa; é publicada aqui como um snapshot estático já que este site de docs não tem um nó próprio para servi-la ao vivo. Aponte o painel «Try it» da página de referência para um nó que você esteja executando (padrão http://localhost:7080) para chamar um método de verdade.

Os esquemas por método nesse documento são uma aproximação deliberadamente simplificada, baseada em convenções — cada getX(id) recebe {id}, cada sendX recebe {data} — em vez de um JSON Schema derivado dos tipos Rust concretos de cada método. Onde um método se afasta dessas convenções, este site é a forma autoritativa: as leituras com prova de carteira, getExchangeRate e getPeers recebem todos parâmetros que a convenção não descreve.

Um nó em execução também serve a referência idêntica ao vivo e de mesma origem que seu próprio /rpc: GET /openrpc.json e GET /docs. GET /metrics expõe contadores de requisição em formato Prometheus para operadores.