From 702625e419eadc5750033dd5a91955d220e7cac5 Mon Sep 17 00:00:00 2001 From: joshglogau Date: Tue, 21 Jul 2026 15:07:39 -0400 Subject: [PATCH] fix(sdk-core): accept accounts without created timestamp --- CLAUDE.md | 1 + packages/sdk-core/README.md | 3 +++ packages/sdk-core/src/api/v1/Types.ts | 4 ++-- packages/sdk-core/tests/api/v1/Chain.test.ts | 25 ++++++++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4da2648..6c0b526 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -207,6 +207,7 @@ All generated or modified code **must** include JSDoc comments (`/** ... */`), c - `pnpm test` runs `npm run build` first (not `pnpm build`), then jest — the build must succeed before tests run - protoc-gen packages have `postinstall` scripts that trigger `pnpm dist` — this can be slow on first install - The `fix-hybrid-output.mjs` script must run after every build of hybrid packages or ESM imports will break in Node +- Keep `AccountObject.created` optional: valid system-account responses may omit it. - `packages/sdk-core/src/contracts/sysio/authex` owns `sysio.authex` action builders, link table reads, and create-link proof helpers. Consumers should not duplicate the `createlink` message/signature rules locally. - AuthEx `links` reads use wire-sysio KV `index_name` queries with JSON-encoded bounds. Preserve KV row unwrapping, generated enum-name normalization, and compressed/uncompressed EM key equivalence. - `packages/sdk-core/src/contracts/sysio/reserv` owns public `sysio.reserv` registry reads, normalized rows, matching, rewards, and read-only quote helpers. External-chain reserve custody belongs in the ABI/IDL-owning chain SDK. diff --git a/packages/sdk-core/README.md b/packages/sdk-core/README.md index 5975217..66fbb58 100644 --- a/packages/sdk-core/README.md +++ b/packages/sdk-core/README.md @@ -2,6 +2,9 @@ JavaScript library for working with Wire powered blockchains (formerly EOSIO, still compatible with EOSIO). +The v1 account decoder accepts valid system-account responses that omit the +optional `created` timestamp. + Available on npm: ## Multisig diff --git a/packages/sdk-core/src/api/v1/Types.ts b/packages/sdk-core/src/api/v1/Types.ts index a5c734d..7c467cf 100644 --- a/packages/sdk-core/src/api/v1/Types.ts +++ b/packages/sdk-core/src/api/v1/Types.ts @@ -152,8 +152,8 @@ export class AccountObject extends Struct { @Struct.field("bool") declare privileged: boolean /** Last update to accounts contract as unix timestamp. */ @Struct.field("time_point") declare last_code_update: TimePoint - /** Account created as unix timestamp. */ - @Struct.field("time_point") declare created: TimePoint + /** Account creation timestamp, omitted by some valid system-account responses. */ + @Struct.field("time_point", { optional: true }) declare created: TimePoint | null /** Account core token balance */ @Struct.field("asset?") core_liquid_balance?: Asset @Struct.field("int64") declare ram_quota: Int64 diff --git a/packages/sdk-core/tests/api/v1/Chain.test.ts b/packages/sdk-core/tests/api/v1/Chain.test.ts index eeaca24..6d15c45 100644 --- a/packages/sdk-core/tests/api/v1/Chain.test.ts +++ b/packages/sdk-core/tests/api/v1/Chain.test.ts @@ -112,6 +112,31 @@ describe("ChainAPI.get_block", () => { }) }) +describe("ChainAPI.get_account", () => { + test("decodes system accounts that omit the creation timestamp", async () => { + const client = makeClient({ + "/v1/chain/get_account": { + account_name: "sysio", + head_block_num: 729126, + head_block_time: "2026-07-21T19:06:21.000", + privileged: true, + last_code_update: "2026-07-16T21:03:45.500", + ram_quota: 464220502, + net_weight: -1, + cpu_weight: -1, + net_limit: { used: -1, available: -1, max: -1 }, + cpu_limit: { used: -1, available: -1, max: -1 }, + ram_usage: 1745389, + permissions: [] + } + }), + account = await client.v1.chain.get_account("sysio") + + expect(account.account_name.toString()).toBe("sysio") + expect(account.created).toBeNull() + }) +}) + describe("ChainAPI.get_table_rows — wire-sysio KV row shape", () => { test("forwards named KV secondary-index bounds", async () => { const provider = new CapturingProvider(),