From: Chris Duncan Date: Mon, 3 Aug 2026 06:42:24 +0000 (-0700) Subject: Refactor account refresh to validate RPC response. X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=ec77b8921d40cf573c2b372e5b25a65822ce7785;p=libnemo.git Refactor account refresh to validate RPC response. --- diff --git a/src/lib/account/refresh.ts b/src/lib/account/refresh.ts index c87e767..9888674 100644 --- a/src/lib/account/refresh.ts +++ b/src/lib/account/refresh.ts @@ -3,6 +3,7 @@ import { Account } from '.' import { Block } from '../block' +import { SCHEMA } from '../constants' import { Rpc } from '../rpc' export async function _refresh (account: Account, rpc: Rpc | string | URL): Promise @@ -21,16 +22,40 @@ export async function _refresh (account: Account, rpc: unknown): Promise { weight: true } const resAccountInfo = await rpc.post('account_info', reqAccountInfo) - if (resAccountInfo.frontier == null) { + if (resAccountInfo == null || typeof resAccountInfo !== 'object') { + throw new TypeError('Invalid account_info response') + } + const accountInfo = resAccountInfo as Record + if (accountInfo.frontier == null) { throw new Error('Account not found') } - Object.assign(account, resAccountInfo) + for (const [k, v] of Object.entries(accountInfo)) { + if (SCHEMA.account_info.fields.includes(k) && typeof v === 'string') { + account[k] = v + } + } - const reqConfirmedFrontier = { + const reqConfirmedFrontierBlockInfo = { json_block: true, hash: account.confirmed_frontier } - const { contents: confirmedFrontierContents, subtype: confirmedFrontierSubtype } = await rpc.post('block_info', reqConfirmedFrontier) + const resConfirmedFrontierBlockInfo = await rpc.post('block_info', reqConfirmedFrontierBlockInfo) + if (resConfirmedFrontierBlockInfo == null || typeof resConfirmedFrontierBlockInfo !== 'object') { + throw new TypeError('Invalid confirmed frontier block_info response') + } + if (!('subtype' in resConfirmedFrontierBlockInfo) || typeof resConfirmedFrontierBlockInfo.subtype !== 'string') { + throw new Error('Confirmed frontier block info subtype not found') + } + const confirmedFrontierSubtype = resConfirmedFrontierBlockInfo.subtype + if (!('contents' in resConfirmedFrontierBlockInfo) || resConfirmedFrontierBlockInfo.contents == null || !(typeof resConfirmedFrontierBlockInfo.contents !== 'object')) { + throw new Error('Confirmed frontier block info contents not found') + } + const confirmedFrontierContents: Record = {} + for (const [k, v] of Object.entries(resConfirmedFrontierBlockInfo.contents)) { + if (SCHEMA.block_info.contents.fields.includes(k) && typeof v === 'string') { + confirmedFrontierContents[k] = v + } + } const confirmedFrontierBlock = new Block(confirmedFrontierContents.account, confirmedFrontierContents.balance, confirmedFrontierContents.previous, confirmedFrontierContents.representative) if (typeof confirmedFrontierBlock[confirmedFrontierSubtype] !== 'function') { throw new TypeError('Unknown subtype of confirmed frontier block', { cause: confirmedFrontierSubtype }) @@ -38,11 +63,27 @@ export async function _refresh (account: Account, rpc: unknown): Promise { confirmedFrontierBlock[confirmedFrontierSubtype](confirmedFrontierContents.link, 0).signature = confirmedFrontierContents.signature account.confirmed_frontier_block = confirmedFrontierBlock - const reqFrontier = { + const reqFrontierBlockInfo = { json_block: true, hash: account.frontier } - const { contents: frontierContents, subtype: frontierSubtype } = await rpc.post('block_info', reqFrontier) + const resFrontierBlockInfo = await rpc.post('block_info', reqFrontierBlockInfo) + if (resFrontierBlockInfo == null || typeof resFrontierBlockInfo !== 'object') { + throw new TypeError('Invalid frontier block_info response') + } + if (!('subtype' in resFrontierBlockInfo) || typeof resFrontierBlockInfo.subtype !== 'string') { + throw new Error('Frontier block info subtype not found') + } + const frontierSubtype = resFrontierBlockInfo.subtype + if (!('contents' in resFrontierBlockInfo) || resFrontierBlockInfo.contents == null || !(typeof resFrontierBlockInfo.contents !== 'object')) { + throw new Error('Frontier block info contents not found') + } + const frontierContents: Record = {} + for (const [k, v] of Object.entries(resFrontierBlockInfo.contents)) { + if (SCHEMA.block_info.contents.fields.includes(k) && typeof v === 'string') { + frontierContents[k] = v + } + } const frontierBlock = new Block(frontierContents.account, frontierContents.balance, frontierContents.previous, frontierContents.representative) if (typeof frontierBlock[frontierSubtype] !== 'function') { throw new TypeError('Unknown subtype of frontier block', { cause: frontierSubtype })