From d5a02de036e1c2f5145a8ecae8cef753246e2964 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Fri, 7 Aug 2026 09:23:17 -0700 Subject: [PATCH] More RPC refactoring. --- src/lib/account/index.ts | 6 +- src/lib/account/refresh.ts | 26 ++------ src/lib/block/index.ts | 3 +- src/lib/rpc/account_info.ts | 106 ++++++++++++++++++++++++------ src/lib/rpc/accounts_frontiers.ts | 2 +- src/lib/rpc/process.ts | 1 - src/lib/rpc/schema.ts | 2 +- 7 files changed, 99 insertions(+), 47 deletions(-) diff --git a/src/lib/account/index.ts b/src/lib/account/index.ts index 2247b9a..adcd901 100644 --- a/src/lib/account/index.ts +++ b/src/lib/account/index.ts @@ -34,7 +34,7 @@ export class Account { #balance?: bigint #block_count?: number - #frontier?: string + #frontier?: Hex #frontier_block?: Block #open_block?: string #receivable?: bigint @@ -59,7 +59,7 @@ export class Account { get balance (): bigint | undefined { return this.#balance } get block_count (): number | undefined { return this.#block_count } - get frontier (): string | undefined { return this.#frontier } + get frontier (): Hex | undefined { return this.#frontier } get frontier_block (): Block | undefined { return this.#frontier_block } get open_block (): string | undefined { return this.#open_block } get receivable (): bigint | undefined { return this.#receivable } @@ -84,7 +84,7 @@ export class Account { set balance (v: bigint | number | string) { this.#balance = BigInt(v) } set block_count (v: number | undefined) { if (v !== undefined) this.#block_count = v | 0 } - set frontier (v: string | undefined) { this.#frontier = v } + set frontier (v: Hex | undefined) { this.#frontier = v } set frontier_block (v: Block | undefined) { this.#frontier_block = v } set open_block (v: string | undefined) { this.#open_block = v } set receivable (v: bigint | number | string) { this.#receivable = BigInt(v) } diff --git a/src/lib/account/refresh.ts b/src/lib/account/refresh.ts index 3fc558c..09dbc2a 100644 --- a/src/lib/account/refresh.ts +++ b/src/lib/account/refresh.ts @@ -3,7 +3,8 @@ import { Account } from '.' import { Block } from '../block' -import { Rpc, Schema } from '../rpc' +import { Rpc } from '../rpc' +import { AccountInfoRequest } from '../rpc/account_info' export async function _refresh (account: Account, rpc: Rpc | string | URL): Promise export async function _refresh (account: Account, rpc: unknown): Promise { @@ -13,25 +14,16 @@ export async function _refresh (account: Account, rpc: unknown): Promise { if (!(rpc instanceof Rpc)) { throw new TypeError('RPC must be a valid node') } - const reqAccountInfo = { + const reqAccountInfo: AccountInfoRequest = { account: account.address, include_confirmed: true, receivable: true, representative: true, weight: true } - const resAccountInfo = await rpc.post('account_info', reqAccountInfo) - 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') - } + const accountInfo = await rpc.post('account_info', reqAccountInfo) for (const [k, v] of Object.entries(accountInfo)) { - if (Schema.account_info.fields.includes(k) && typeof v === 'string') { - account[k] = v - } + account[k] = v } const reqConfirmedFrontierBlockInfo = { @@ -54,9 +46,7 @@ export async function _refresh (account: Account, rpc: unknown): Promise { } 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 - } + confirmedFrontierContents[k] = v } const confirmedFrontierBlock = new Block(confirmedFrontierContents.account, confirmedFrontierContents.balance, confirmedFrontierContents.previous, confirmedFrontierContents.representative) if (typeof confirmedFrontierBlock[confirmedFrontierSubtype] !== 'function') { @@ -85,9 +75,7 @@ export async function _refresh (account: Account, rpc: unknown): Promise { } 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 - } + frontierContents[k] = v } const frontierBlock = new Block(frontierContents.account, frontierContents.balance, frontierContents.previous, frontierContents.representative) if (typeof frontierBlock[frontierSubtype] !== 'function') { diff --git a/src/lib/block/index.ts b/src/lib/block/index.ts index a214faf..85deedd 100644 --- a/src/lib/block/index.ts +++ b/src/lib/block/index.ts @@ -7,6 +7,7 @@ import { DIFFICULTY_RECEIVE, DIFFICULTY_SEND, PREAMBLE } from '../constants' import { bytes, dec, hex } from '../convert' import { Blake2b } from '../crypto' import { Rpc } from '../rpc' +import { ProcessRequest } from '../rpc/process' import { convert } from '../tools' import { Wallet } from '../wallet' import { _change } from './change' @@ -204,7 +205,7 @@ export class Block { throw new Error('Block is missing signature. Use sign() and try again.') } if (this.work == null) await this.pow() - const data = { + const data: ProcessRequest = { subtype: this.subtype, json_block: true, block: this.toJSON() diff --git a/src/lib/rpc/account_info.ts b/src/lib/rpc/account_info.ts index df63a2e..6931cd1 100644 --- a/src/lib/rpc/account_info.ts +++ b/src/lib/rpc/account_info.ts @@ -1,24 +1,88 @@ //! SPDX-FileCopyrightText: 2026 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -export const account_info = Object.freeze({ - fields: [ - 'account_version', - 'balance', - 'block_count', - 'confirmation_height', - 'confirmation_height_frontier', - 'confirmed_balance', - 'confirmed_frontier', - 'confirmed_height', - 'confirmed_receivable', - 'confirmed_representative', - 'frontier', - 'modified_timestamp', - 'open_block', - 'receivable', - 'representative', - 'representative_block', - 'weight', - ], -}) +import { RpcError } from '../errors' + +export type AccountInfoRequest = { + account: string + include_confirmed: true + receivable: true + representative: true + weight: true +} + +export type AccountInfoResponse = { + account_version: string + balance: string + block_count: string + confirmation_height: string + confirmation_height_frontier: string + confirmed_balance: string + confirmed_frontier: string + confirmed_height: string + confirmed_pending?: string + confirmed_receivable: string + confirmed_representative: string + frontier: string + modified_timestamp: string + open_block: string + pending?: string + receivable: string + representative: string + representative_block: string + weight: string +} + +export function account_info (body: unknown): AccountInfoResponse { + if (body != null && typeof body === 'object') { + if ('account_version' in body && typeof body.account_version === 'string' + && 'balance' in body && typeof body.balance === 'string' + && 'block_count' in body && typeof body.block_count === 'string' + && 'confirmation_height' in body && typeof body.confirmation_height === 'string' + && 'confirmation_height_frontier' in body && typeof body.confirmation_height_frontier === 'string' + && 'confirmed_balance' in body && typeof body.confirmed_balance === 'string' + && 'confirmed_frontier' in body && typeof body.confirmed_frontier === 'string' + && 'confirmed_height' in body && typeof body.confirmed_height === 'string' + && 'confirmed_receivable' in body && typeof body.confirmed_receivable === 'string' + && 'confirmed_representative' in body && typeof body.confirmed_representative === 'string' + && 'frontier' in body && typeof body.frontier === 'string' + && 'modified_timestamp' in body && typeof body.modified_timestamp === 'string' + && 'open_block' in body && typeof body.open_block === 'string' + && 'receivable' in body && typeof body.receivable === 'string' + && 'representative' in body && typeof body.representative === 'string' + && 'representative_block' in body && typeof body.representative_block === 'string' + && 'weight' in body && typeof body.weight === 'string' + ) { + const response: AccountInfoResponse = { + account_version: body.account_version, + balance: body.balance, + block_count: body.block_count, + confirmation_height: body.confirmation_height, + confirmation_height_frontier: body.confirmation_height_frontier, + confirmed_balance: body.confirmed_balance, + confirmed_frontier: body.confirmed_frontier, + confirmed_height: body.confirmed_height, + confirmed_receivable: body.confirmed_receivable, + confirmed_representative: body.confirmed_representative, + frontier: body.frontier, + modified_timestamp: body.modified_timestamp, + open_block: body.open_block, + receivable: body.receivable, + representative: body.representative, + representative_block: body.representative_block, + weight: body.weight, + } + if ('confirmed_pending' in body && typeof body.confirmed_pending === 'string') { + response.confirmed_pending = body.confirmed_pending + } + if ('pending' in body && typeof body.pending === 'string') { + response.pending = body.pending + } + return response + } + if ('error' in body && typeof body.error === 'string') { + throw new RpcError(body.error) + } + } + throw new RpcError('Invalid account_info response') +} diff --git a/src/lib/rpc/accounts_frontiers.ts b/src/lib/rpc/accounts_frontiers.ts index dce1ee0..01df9ba 100644 --- a/src/lib/rpc/accounts_frontiers.ts +++ b/src/lib/rpc/accounts_frontiers.ts @@ -8,7 +8,7 @@ import { hex } from '../convert' type AccountsFrontiers = { frontiers?: { - [address: string]: string + [address: string]: Hex } errors?: { [address: string]: string diff --git a/src/lib/rpc/process.ts b/src/lib/rpc/process.ts index 99b62ba..450399a 100644 --- a/src/lib/rpc/process.ts +++ b/src/lib/rpc/process.ts @@ -6,7 +6,6 @@ import { RpcError } from '../errors' import { BlockInfoContents } from './block_info' export type ProcessRequest = { - action: 'process' block: BlockInfoContents async: boolean force: boolean diff --git a/src/lib/rpc/schema.ts b/src/lib/rpc/schema.ts index 295a92b..a3b46f6 100644 --- a/src/lib/rpc/schema.ts +++ b/src/lib/rpc/schema.ts @@ -12,7 +12,7 @@ import { process } from './process' export const Schema = Object.freeze({ account_balance, - // account_info, + account_info, // account_representative, accounts_balances, accounts_frontiers, -- 2.52.0