Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Repo layout

A map of dead-pool-aka-wilson/apyx-sdk. The repo is a small pnpm workspace: one publishable package (the SDK), one in-tree playground (the example app), one mdBook (this manual).

Top level

apyx-sdk/
├── abis/                # JSON ABIs vendored from apyx-labs/subquery
├── book/                # mdBook user manual (this site)
├── example/             # browser playground (Vite + React 19 + Tailwind)
├── scripts/             # tsx generators (gen:abis, etc.)
├── src/                 # SDK + CLI source
├── test/                # vitest unit + e2e specs
├── package.json         # publishable package — @koed_jang/apyx-sdk
├── pnpm-workspace.yaml  # workspace: root + example/
├── rollup.config.mjs    # ESM (browser) + CJS (Node) + CLI bundles
├── tsconfig.json
├── vitest.config.ts     # unit tests
└── vitest.e2e.config.ts # fork + packaging tests

src/ — what gets published

src/
├── addresses.ts         # APYX_ADDRESSES + getAddresses + UnsupportedChainError
├── client.ts            # createApyxClient — the single public factory
├── errors.ts            # WalletClientRequiredError + InvalidAddressError
├── index.ts             # re-export barrel
├── contracts/
│   ├── apxUSD.ts        # ERC-20 + permit + supply views
│   ├── apyUSD.ts        # ERC-4626 + share-token ERC-20 surface
│   └── apyUSDRateView.ts# apy / annualizedYield / vault / precision
├── generated/           # `as const` ABI tuples (see `pnpm gen:abis`)
└── cli/                 # apyx CLI (Node-only)
    ├── cli.ts           # entry — argv parsing, dispatch
    ├── config.ts        # config schema, resolution rules, validation
    ├── repl.ts          # Node REPL with injected globals
    ├── signer.ts        # key + ledger dispatch (resolveSigner)
    ├── ledger.ts        # @ledgerhq/hw-app-eth dynamic import
    └── commands/        # contract-registry.ts (the 18-command source of truth)

The factory createApyxClient in src/client.ts is the gateway. Every consumer either calls it directly (programmatic) or via the CLI (which calls it under the hood).

example/ — playground

example/
├── src/                 # React app
├── e2e/smoke.spec.ts    # Playwright smoke (CI-runnable)
├── package.json         # @apyx-labs/sdk-playground (private)
├── playwright.config.ts
├── tailwind.config.js
├── vite.config.ts
└── README.md            # → see book/src/playground/*

The playground depends on the SDK via the workspace protocol ("@koed_jang/apyx-sdk": "workspace:*"). Edits to src/** reflect without re-publishing.

test/ — vitest

test/
├── *.spec.ts            # unit tests (run via `pnpm test`)
└── e2e/
    ├── fixtures/        # anvil + funded-account helpers
    ├── sdk/             # SDK module tests against an anvil mainnet fork
    ├── cli/             # CLI tests (config, repl, methods, session-flags, ledger)
    └── packaging/       # tarball install + CJS/ESM consumer smoke

Two vitest configs — vitest.config.ts for the unit suite, vitest.e2e.config.ts for fork + packaging. The split keeps the unit run under a few seconds and the e2e run isolated to PRs that touch src/** or test/e2e/** (path-filtered in CI).

book/ — this manual

Already familiar.

book/
├── book.toml          # mdBook config (mermaid + toc preprocessors)
├── src/SUMMARY.md     # chapter map
└── src/**/*.md

CI builds via mdbook build book and lychee-checks all intra-book links — see .github/workflows/docs.yml.

CI workflows

.github/workflows/
├── ci.yml          # lint + typecheck + unit tests on every push
├── e2e.yml         # fork tests (anvil via foundry-toolchain action) on src/** + test/e2e/** changes
├── packaging.yml   # nightly tarball install smoke
├── release.yml     # npm publish on `v*` tags
└── docs.yml        # mdbook build on book/** + src/** changes

Naming conventions

  • Files: kebab-case for everything user-facing (apyx-sdk, apyx.config.json, apxusd-balance-of.md); camelCase for TypeScript identifiers (createApyxClient, apxUSD.balanceOf); PascalCase for types and classes (ApyxClient, UnsupportedChainError).
  • Contract names: apxUSD (lowercase ‘a’), apyUSD (lowercase ‘a’), apyUSDRateView. The same casing is used in code, the CLI command tree, and the docs.
  • Imports: ESM-style from './x.js' (with .js extension) throughout src/ because the CJS bundle is built via Rollup with the same source.