Skip to content

feat: implement issues #73, #74, #99, #472 — storage, UI components, wallet orchestration, rate-limiting#955

Merged
wheval merged 4 commits into
ancore-org:mainfrom
gregemax:feat/issues-73-74-99-472
Jul 5, 2026
Merged

feat: implement issues #73, #74, #99, #472 — storage, UI components, wallet orchestration, rate-limiting#955
wheval merged 4 commits into
ancore-org:mainfrom
gregemax:feat/issues-73-74-99-472

Conversation

@gregemax

@gregemax gregemax commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR resolves four independent issues across the monorepo in a single batch. Every commit is independently scoped and all relevant tests pass.


Changes

#73 — Implement Secure Storage Manager for Browser Extension

Commit: ec384b8

Files changed:

  • packages/core-sdk/src/storage/__tests__/chrome-compat.test.ts (new)
  • apps/extension-wallet/src/background/storage.ts (new)

SecureStorageManager with PBKDF2 + AES-256-GCM encryption already existed. This commit adds the two missing deliverables:

  • chrome-compat.test.ts — 13 smoke tests verifying createStorageAdapter() selects the correct adapter (Chrome/Firefox/localStorage fallback) based on runtime globals, and that the full unlock → save → lock → re-unlock → get round-trip works for each adapter.
  • background/storage.ts — Canonical import path for background service-worker code; re-exports getSharedStorageManager as getStorageManager from the shared security singleton, eliminating import scatter.

#74 — Create Address and QR Code Display Components

Commit: 46afaf1

Files changed:

  • packages/ui-kit/src/components/address-display.tsx (modified)
  • packages/ui-kit/src/components/address-display.test.tsx (modified, 22 tests)
  • packages/ui-kit/src/components/address-display.stories.tsx (modified)
  • packages/ui-kit/src/components/Identicon.stories.tsx (new)
  • packages/ui-kit/src/components/QRCode.stories.tsx (new)

AddressDisplay additions:

  • showIdenticon — renders a 24 px deterministic Identicon avatar alongside the address
  • isValidfalse applies a destructive border + AlertCircle icon; undefined (default) shows nothing
  • Full-address Tooltip on hover/focus-within (via existing ui/tooltip.tsx, no new deps)
  • aria-live="polite" region announces "Address copied to clipboard"; copy-button aria-label toggles between "Copy address" and "Copied!"

New Storybook stories: Identicon (Default, Small, Large, UniquePerAddress, SizeScale) and QRCode (Default, PaymentURI, SizeScale, ReceiveCard).

All 190 ui-kit tests pass.


#99 — Core SDK Create Wallet (mnemonic → keypair → encrypted output)

Commit: 8220efd

Files changed:

  • packages/core-sdk/src/create-wallet.ts (new)
  • packages/core-sdk/src/ancore-client.ts (modified)
  • packages/core-sdk/src/index.ts (modified)
  • packages/core-sdk/jest.config.cjs (modified)
  • packages/core-sdk/src/__tests__/create-wallet.test.ts (new, 21 tests)

create-wallet.ts orchestrates: generateMnemonic()deriveKeypairFromMnemonic(mnemonic, accountIndex) → optional encryptSecretKey(mnemonic, password). Returns a typed CreateWalletResultpublicKey and contractId are safe to persist; mnemonic, secretKey, and encryptedMnemonic must be handled in-memory only.

AncoreClient.createWallet(params?) is a thin delegation to the orchestration layer.

Adding @ancore/crypto to moduleNameMapper in jest.config.cjs also fixes the previously failing wallet.test.ts suite as a side-effect. All 31 core-sdk test suites (463 tests) pass.


#472 — [RELAYER] Add per-route rate-limit config map and tests

Commit: f173ace

Files changed:

  • services/relayer/src/middleware/routeRateLimiter.ts (new)
  • services/relayer/src/middleware/__tests__/routeRateLimiter.test.ts (new, 24 tests)

Central ROUTE_RATE_LIMIT_CONFIG map:

Route rpm Rationale
/relay/execute 30 Baseline
/relay/validate 60 Read-only, more permissive
/relay/session-key 10 Sensitive mutation — stricter
/relay/revoke-session-key 10 Sensitive mutation — stricter
/relay/status 120 Monitoring — very permissive
/health 120 Monitoring — very permissive

DEFAULT_ROUTE_CONFIG (20 rpm) is a fail-safe for unconfigured routes. createRouteRateLimiter(route, override?) wires express-rate-limit with standardHeaders: true / legacyHeaders: false (RateLimit-* draft spec). 429 body: { error, route, retryAfter }.

Tests cover: config map values, stricter session-key defaults, DEFAULT fallback, enforcement, per-account isolation, per-route isolation, RateLimit draft headers, no legacy X-RateLimit headers, override precedence.


Test summary

Package Suites Tests
@ancore/core-sdk 31 ✅ 463 ✅
@ancore/ui-kit 18 ✅ 190 ✅
@ancore/relayer 20 ✅ 235 ✅

Closes #73
Closes #74
Closes #99
Closes #472

gregemax added 4 commits July 2, 2026 16:40
…ncore-org#73)

- Add SecureStorageManager with unlock/lock/save/get/export/import API
- Wire storage payload format + AES-GCM encryption via PBKDF2 key derivation
- Ensure lock() clears in-memory CryptoKey and auto-lock timer
- Add chrome-compat.test.ts: smoke tests for Chrome, Firefox (browser),
  and localStorage fallback adapter wiring + lock/unlock lifecycle
- Add background/storage.ts: re-exports getStorageManager and
  resetSharedStorageManagerForTests from the shared security module

Security checklist:
- Encryption key never stored (in-memory only, cleared on lock())
- Unique IV + per-payload salt generated for each encryption (AES-256-GCM)
- Master salt generated on first use and persisted (non-sensitive)
- PBKDF2 with 100,000 iterations + SHA-256
- Auto-lock timer resets on activity via touch()
- Wrong password returns false, leaves manager locked

Closes ancore-org#73
AddressDisplay enhancements:
- showIdenticon prop: renders deterministic Identicon avatar alongside address
- Full-address Tooltip on hover and focus-within (existing ui/tooltip.tsx)
- isValid prop: destructive border + AlertCircle icon for invalid addresses
- aria-live polite region announces 'Address copied to clipboard' to screen readers
- Copy button aria-label toggles between 'Copy address' and 'Copied!'
- aria-label on <code> element exposes full untruncated address

New Storybook stories:
- Identicon.stories.tsx: Default, Small, Large, CustomLabel, UniquePerAddress, SizeScale
- QRCode.stories.tsx: Default, Small, Large, CustomLabel, PaymentURI, SizeScale, ReceiveCard
- address-display.stories.tsx: updated with WithIdenticon, ValidAddress, InvalidAddress,
  InvalidWithIdenticon, MultipleAddresses, InCard compound examples

Tests (address-display.test.tsx):
- 22 tests covering all props: truncation, label, copy, clipboard, aria-live, onCopy,
  controlled copied, tooltip aria-label, identicon rendering, isValid feedback, className

All 190 tests pass across 18 test files.

Closes ancore-org#74
…core-org#99)

- Add create-wallet.ts: CreateWalletParams, CreateWalletResult types and
  createWallet() function that orchestrates generateMnemonic →
  deriveKeypairFromMnemonic → encryptSecretKey (optional, password-gated)
- Add AncoreClient.createWallet(params?) delegating to the orchestration layer
- Export createWalletOrchestration, CreateWalletParams, CreateWalletResult
  from index.ts
- Add @ancore/crypto moduleNameMapper to jest.config.cjs, fixing the
  previously failing wallet.test.ts suite as a side-effect
- Add create-wallet.test.ts: 21 unit tests with all @ancore/crypto dependencies
  mocked, covering both the standalone createWallet() function and the
  AncoreClient.createWallet() delegation path

All 31 test suites (463 tests) pass.

Closes ancore-org#99
…org#472)

- Add ROUTE_RATE_LIMIT_CONFIG: central map keyed by Express route path
    /relay/execute          → 30 rpm  (baseline)
    /relay/validate         → 60 rpm  (read-only, more permissive)
    /relay/session-key      → 10 rpm  (sensitive mutation, stricter)
    /relay/revoke-session-key → 10 rpm (sensitive mutation, stricter)
    /relay/status           → 120 rpm (monitoring, very permissive)
    /health                 → 120 rpm (monitoring, very permissive)
- Add DEFAULT_ROUTE_CONFIG (20 rpm) as a fail-safe for unconfigured routes
- createRouteRateLimiter(route, override?): factory that looks up the map,
  applies optional override, and wires express-rate-limit with
  standardHeaders:true / legacyHeaders:false (RateLimit-* draft spec)
- 429 body includes { error, route, retryAfter } for client-side handling
- resolveRouteConfig() helper for test-time introspection without
  constructing a middleware instance
- 24 unit tests covering: config map values, stricter session-key defaults,
  DEFAULT_ROUTE_CONFIG fallback, resolveRouteConfig, enforcement (allows N,
  blocks N+1), correct 429 body, per-account isolation, per-route isolation,
  RateLimit draft headers, no legacy X-RateLimit headers, override precedence

Closes ancore-org#472
@drips-wave

drips-wave Bot commented Jul 2, 2026

Copy link
Copy Markdown

@gregemax Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@wheval
wheval merged commit 764fa5d into ancore-org:main Jul 5, 2026
12 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants