Files
parser2/packages/ship-reader/src/rpc.ts
T
coopops 399496d51c [549-3][@ant] feat: реализован @coopenomics/coopos-ship-reader v0.1.0 — SHiP-транспортная основа для универсального индексера блокчейна
- ShipClient: connect()/handshake()/streamBlocks() AsyncIterable + ack(n)
- WharfkitDeserializer + AbieosDeserializer (optional, Linux, runtime fallback)
- 24 native-table типа с computeLookupKey() (портировано из Hyperion, MIT)
- RPC helpers getChainInfo()/getRawAbi() с retry
- tsup ESM+CJS build, tsconfig strict + noUncheckedIndexedAccess
- MIT LICENSE, NOTICE (EOS Rio + AntelopeIO attribution), LICENSE-THIRD-PARTY
- 26 unit-тестов: 26/26 pass; GitHub Actions CI pipeline
2026-04-21 17:28:45 +00:00

54 lines
1.6 KiB
TypeScript

import { ChainRpcError } from './errors.js'
import type { ChainInfo } from './types/ship.js'
const DEFAULT_RETRIES = 3
const RETRY_DELAYS_MS = [500, 1500, 3000] as const
async function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function postJson<T>(url: string, body: Record<string, unknown>): Promise<T> {
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
})
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`)
}
return res.json() as Promise<T>
}
async function withRetry<T>(fn: () => Promise<T>, retries = DEFAULT_RETRIES): Promise<T> {
let lastErr: unknown
for (let i = 0; i < retries; i++) {
try {
return await fn()
} catch (err) {
lastErr = err
const delay = RETRY_DELAYS_MS[i] ?? RETRY_DELAYS_MS[RETRY_DELAYS_MS.length - 1] ?? 3000
await sleep(delay)
}
}
throw new ChainRpcError('Chain RPC request failed after retries', lastErr)
}
export async function getChainInfo(chainUrl: string): Promise<ChainInfo> {
return withRetry(() => postJson<ChainInfo>(`${chainUrl}/v1/chain/get_info`, {}))
}
export async function getRawAbi(chainUrl: string, accountName: string): Promise<Uint8Array> {
interface GetRawAbiResponse {
account_name: string
abi_hash: string
abi: string
}
const res = await withRetry(() =>
postJson<GetRawAbiResponse>(`${chainUrl}/v1/chain/get_raw_abi`, { account_name: accountName }),
)
const b64 = res.abi
const binary = Buffer.from(b64, 'base64')
return new Uint8Array(binary)
}