Skip to content

Commit 97769ad

Browse files
github-actions[bot]matthappensbsiaotickchongpengyingcursoragent
authored
Updates to core, ui (#493)
* Restrict first and last name input fields to be more than 1 characters and to not contain digits (#22563) ## Reason closes PX-1302 Yellowcard does not allow names containing numbers, and I can't really think of a reason we should either? GitOrigin-RevId: e6fc9162d884d82256e3ee71c8330edeebb53983 * Revert "Restrict first and last name input fields to be more than 1 c… (#22867) …haracters and to not contain digits (#22563)" This reverts commit e6fc9162d884d82256e3ee71c8330edeebb53983. ## Reason there's an issue where sign up in mx is blocked, reverting this to be safe GitOrigin-RevId: 6ead3d065fd639bd7f7f1e309450801d0f794a90 * [ops] unify sparkcore and paycore searches into one (#22822) ## Reason The sparkcore vs paycore ent searches is kind of frustrating because it doesn't indicate if it exists in one or the other. So I wanted to combine both into a single search so you don't have to toggle the schema manually (and it'll show results for both schemas) ## Overview - deletes old searches for sparkcore and paycore - queries both schemas for results in new unified search input - search types are combined (defaults to auto if it doesn't exist for one of the schemas) - shows the schema on the actual ent! ## Test Plan works locally ![Screenshot 2025-12-24 at 6.08.51 PM.png](https://app.graphite.com/user-attachments/assets/58a9fb5e-b937-49eb-9f1e-ce2fb1d68e09.png) ![Screenshot 2025-12-24 at 6.08.56 PM.png](https://app.graphite.com/user-attachments/assets/8e456b16-b5a2-4910-8459-6cda78857ef2.png) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Unified search input consolidates results across schemas and shows schema on results. * CardPage header supports custom right-side content (used to show schema badges). * **Refactor** * Replaced two specialized search inputs with a single unified one for consistent behavior. * Inspector now uses a single link component for entity navigation for consistent styling. * **Chores** * Removed legacy per-schema search components and related query wiring. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> GitOrigin-RevId: 7ae439a34e2c04d40bf2163190a78179dfbf000a * Update OTP entry to move cursor to first unpopulated input (#22860) ## Reason This change fixes a bug in the `CodeInput` component (unified variant) where clicking in the middle of the input would place the cursor at that arbitrary position, preventing users from easily completing the code. ## Overview An `onMouseDown` handler has been added to the `UnifiedCodeInputContainer`. This handler intercepts clicks and, if the click occurs on an input position *after* the first empty one, it prevents the default focus behavior and redirects focus to the first available empty input field. If all inputs are filled, it focuses the last input. ## Test Plan - All existing tests pass. - Two new test cases have been added to `js/apps/examples/ui-test-app/src/tests/CodeInput.test.tsx` to specifically cover: - Redirecting focus to the first empty input when clicking on a later input. - Allowing normal focus when clicking on or before the first empty input. - Lint checks passed. --- [Slack Thread](https://lightsparkgroup.slack.com/archives/C0447HDL3LY/p1767211308856809?thread_ts=1767211308.856809&cid=C0447HDL3LY) <a href="https://cursor.com/background-agent?bcId=bc-5bceb9c9-4f25-4715-b3d7-d56146281eed"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/open-in-cursor-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/open-in-cursor-light.svg"><img alt="Open in Cursor" src="https://cursor.com/open-in-cursor.svg"></picture></a>&nbsp;<a href="https://cursor.com/agents?id=bc-5bceb9c9-4f25-4715-b3d7-d56146281eed"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/open-in-web-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/open-in-web-light.svg"><img alt="Open in Web" src="https://cursor.com/open-in-web.svg"></picture></a> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a configurable autoFocus option for modals (defaults to enabled); specific modals can opt out. * **Bug Fixes** * Improved unified code-input focus behavior: clicking empty areas redirects to the first empty input; clicks on filled inputs preserve focus; when all inputs are filled, focus stays on the last. * **Tests** * Added tests for unified code-input focus behavior covering empty, partially filled, and all-empty scenarios. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Brian Siao Tick Chong <bsiaotickchong@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> GitOrigin-RevId: ac96b2361390be252d2bfb994cce33852571c499 * [tazapay] fixes for link bank screen (#22900) ## Reason small fixes for tazapay link bank screen ## Overview - adds description to tazapay link bank screen - removes unused info icon from accountNumber input - fixes bank icon ## Test Plan ![Screenshot 2026-01-06 at 2.47.00 PM.png](https://app.graphite.com/user-attachments/assets/60b6b4c1-9b49-4c9b-8076-eb7f0cdf60de.png) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added multilingual descriptions for bank linking flow with support for English, Spanish, Portuguese, German, French, Italian, and other languages. * **Bug Fixes** * Removed unnecessary icon from account number input field. * **Style** * Updated bank icon to solid design throughout the bank linking interface. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> GitOrigin-RevId: 1e5f3efad1862c652b919583644e25b30439667f * Add YC region mapping for Zambia & the Zambian Kwacha to currencies (#22913) ## Reason closes PX-1310 Add Zambia as a YC integration. Zambia uses the Kwacha (ZMW) so add that as well 90% of this PR is files updated by adding ZMW currency ## Test go through onboarding flow for Zambian users <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Zambian Kwacha (ZMW) added across the platform and APIs. * Yellow Card onboarding now supports Zambia (ZMW) as an account option, including Zambia-specific mobile network choices and phone validation/masked display. * Feature gate introduced to control staged rollout of Yellow Card Zambia onboarding. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> GitOrigin-RevId: ffc4b510f63c9e5bbaed4ae9bcbba24be0a9a8f3 * [uma-bridge] fix most mobile cta buttons to bottom of screen, center login and create account content (#22814) ## Reason Fixes mobile cta buttons to bottom of bridge card form, and centers login and create account content. This will help prevent adding fixed heights such that the button is either too low or too high on the screen ## Overview - adds parameters to BridgeCardForm to handle centering content and fixing cta content to the bottom of the screen ## Test Plan Tested all onboarding flows manually ![Screenshot 2025-12-23 at 4.11.41 PM.png](https://app.graphite.com/user-attachments/assets/e4253f2c-97e7-46ab-bd5e-994cac13df34.png) ![Screenshot 2025-12-24 at 1.32.22 PM.png](https://app.graphite.com/user-attachments/assets/bd9f6430-4714-4972-a5ac-ab68ac0ea880.png) GitOrigin-RevId: 83b42641cfe9dc65f2521a3b6b4ef7776f79d30d * [site] Support filtering by payment hash in transactions table (#23014) Adding filtering by payment hash per request from Chivo: <img width="1500" height="1342" alt="Screenshot 2026-01-12 at 1 59 30 PM" src="https://github.com/user-attachments/assets/b7b888a6-90c5-4367-86a3-edcb5e731307" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a "Payment Hash" column to Transactions and a "Payment Hash" string filter (64-character hex) to search and filter transactions by payment hash. * **Style** * Consolidated filter action button layout into a shared component for consistent spacing, wrapping, and max-width across table filters. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> GitOrigin-RevId: 5c51f07e6a4bc347492fafd60e38aacb0a6cc107 * [Tazapay] Add AED support (#23189) ## Reason Added support for the United Arab Emirates Dirham (AED) as a new currency option in our payment system to expand our service offerings in the Middle East region. ## Overview - Added AED to the `CurrencyUnit` and `FiatCurrencyUnit` enums across all GraphQL schemas - Created a new `TazapayAedAccountIntegration` class to handle AED-specific banking operations - Implemented IBAN validation and BIC code extraction for AED bank accounts - Added support for creating AED bank destinations in the Tazapay client ## Test Plan - Verified AED IBAN validation logic works correctly with test IBANs from UAE banks - Confirmed the new currency appears correctly in all relevant GraphQL schemas - Tested the integration with Tazapay's API for AED transactions - Ensured proper BIC code extraction from UAE IBANs GitOrigin-RevId: 0ec9cc6b9a2101ac9dcbaabb02aa126e3ec00344 * Add GTQ - Guatamalan Quetzal currency (#23249) ## Reason Thunes onboarding commences! The first 2 countries we'll iterate on for the implementation are El Salvador and Guatemala, as they're both reasonably supported in the dev environment. El Salvador is USD, which is convenient. For Guatemala we'll need the Quetzal . Fun fact about the Quetzal, the currency notes display their value in Mayan numerals in the top right corner GitOrigin-RevId: e4e32220f64b0226e65d37da445784a5d00c47c0 * use agent-md-refactor skill to reduce the size and increase the effectiveness of our claude code md files (#23278) ## Reason Use the agents-md-refactor skill to tighten up our CLAUDE.md files in sparkcore more on the agents refactor md here : [link](https://skills.sh/softaworks/agent-toolkit/agent-md-refactor ) ## What Changed 1. Root CLAUDE.md - Cut from 73 to 37 lines. Removed setup prerequisites (not AI instructions), kept only essential commands and links. 2. sparkcore/CLAUDE.md - Cut from 160 to 68 lines. Removed redundant debugging tips, setup docs, and verbose explanations. Kept actionable patterns. 3. js/CLAUDE.md - Cut from 163 to 69 lines. Removed release process docs, React stack details, and configuration file explanations. Kept commands and patterns. 4. New linked files - Extracted cross-cutting concerns: - .claude/docs/graphql-workflow.md - Single source for GraphQL regeneration - .claude/docs/testing.md - Consolidated testing philosophy from your CLAUDE.local.md 5. Kept untouched: - sparkcore/sparkcore/spark/CLAUDE.md - Domain-specific, well-organized, essential for Spark protocol work - CLAUDE.local.md - Your personal overrides (git workflow with Graphite, Python commands) GitOrigin-RevId: 5db5c5e8a25f9dc3b48b83fcfd73e3374a81dadb * Tests for Secp256k1SigningKey (#23583) https://lightsparkgroup.slack.com/archives/C08T5ATQBBK/p1770617598579799?thread_ts=1770562711.801429&cid=C08T5ATQBBK --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> GitOrigin-RevId: 8d490d46961abd9a99c66cf40fbac67a0f48c0b0 * [core, lightspark-cli] Replace secp256k1 with @noble/curves (#23584) https://lightsparkgroup.slack.com/archives/C08T5ATQBBK/p1770617598579799?thread_ts=1770562711.801429&cid=C08T5ATQBBK --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> GitOrigin-RevId: 006a2b9a49e1acd2baa34d588108b1d07e508c6e * CI update lock file for PR * add changesets --------- Co-authored-by: Matt Davis <matthappens@gmail.com> Co-authored-by: Brian Siao Tick Chong <bsiaotickchong@gmail.com> Co-authored-by: Peng Ying <peng@lightspark.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Corey Martin <coreyn.martin@gmail.com> Co-authored-by: Aaryaman Bhute <35084309+AaryamanBhute@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Lightspark Eng <engineering@lightspark.com>
1 parent 856f026 commit 97769ad

File tree

21 files changed

+594
-218
lines changed

21 files changed

+594
-218
lines changed

.changeset/light-bars-visit.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@lightsparkdev/lightspark-cli": patch
3+
---
4+
5+
- Replace secp256k1 with @noble/curves: Same dependency swap — secp256k1 replaced with @noble/curves for key generation and validation. Removes native build
6+
requirement.

.changeset/spotty-yaks-lie.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@lightsparkdev/core": patch
3+
---
4+
5+
- Replace secp256k1 with @noble/curves: The native secp256k1 npm package (which requires native compilation/bindings) has been replaced with @noble/curves/secp256k1, a
6+
pure JS implementation. This removes native build dependencies, improving portability and install reliability. Secp256k1SigningKey.sign() now uses @noble/curves API
7+
internally (DER-encoded output is preserved).
8+
- Add 3 new currencies: ZMW (Zambian Kwacha), AED (UAE Dirham), GTQ (Guatemalan Quetzal) — added to CurrencyUnit, conversion maps, formatting, and CurrencyMap type.

.changeset/tender-jobs-call.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@lightsparkdev/ui": patch
3+
---
4+
5+
- CodeInput: Clicking the unified code input now moves the cursor to the first empty input field instead of wherever the user clicked, improving OTP entry UX.
6+
- CardForm: CardFormContentFull now sets width: 100% for proper full-width layout.
7+
- CardPage: New headerRightContent prop to render content on the right side of the card page header.
8+
- DataManagerTable filters: AppliedButtonsContainer extracted to a shared component with max-width: 100% on buttons (prevents overflow for long filter values).
9+
- New icon: BankSolid icon added (exported as CentralBankSolid).

CLAUDE.md

Lines changed: 41 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,68 @@
1-
# CLAUDE.md
1+
# JS Monorepo
22

3-
This file provides guidance to Claude Code when working in the js/ directory.
3+
TypeScript monorepo for Lightning Network SDKs and internal applications. Yarn workspaces + Turbo.
44

5-
## Overview
5+
## Quick Reference
66

7-
JavaScript/TypeScript monorepo for Lightspark's Lightning Network and UMA services. Public SDKs, internal applications, and shared packages using Yarn workspaces + Turbo.
7+
| Action | Command |
8+
|--------|---------|
9+
| Install | `yarn` |
10+
| Start apps | `yarn start site uma-bridge ops` |
11+
| Build | `yarn build` |
12+
| Test | `yarn test` |
13+
| Lint + format | `yarn lint && yarn format` |
14+
| Full checks | `yarn checks` |
15+
| GraphQL regen | `yarn gql-codegen` |
16+
| Clean all | `yarn clean-all` |
817

918
## Structure
1019

11-
- **packages/** - Shared libraries
12-
- **core/** - Auth, utilities
13-
- **lightspark-sdk/** - Public Lightning SDK
14-
- **ui/** - React components, design system
15-
- **private/** - Internal utilities, GraphQL clients
16-
- **apps/examples/** - Public examples and CLI tools
17-
- **apps/private/** - Internal apps (site, ops, uma-bridge)
18-
19-
## Essential Commands
20-
21-
### Setup
22-
```bash
23-
nvm use || nvm install # Match Node version
24-
corepack enable && corepack prepare --activate # Enable Yarn
25-
yarn # Install all workspace dependencies
2620
```
27-
28-
### Development Workflow
29-
```bash
30-
# Start applications
31-
yarn start site uma-bridge ops # Specific apps (@lightsparkdev/ prefix implied)
32-
yarn start private # All private apps
33-
yarn start examples # All examples
34-
35-
# Code quality
36-
yarn lint && yarn format # Lint + Prettier
37-
yarn checks # Full validation: deps, lint, format, test, circular-deps
38-
39-
# Building
40-
yarn build # Build all workspaces with Turbo caching
41-
yarn build --force # Rebuild without cache
42-
43-
# Testing
44-
yarn test # Run all tests
45-
yarn workspace @lightsparkdev/ui test # Test specific workspace
46-
47-
# GraphQL codegen
48-
yarn gql-codegen # Regenerate TypeScript types from schemas
21+
packages/
22+
core/ # Auth, utilities
23+
lightspark-sdk/ # Public Lightning SDK
24+
ui/ # React components
25+
private/ # Internal utilities
26+
apps/
27+
examples/ # Public examples
28+
private/ # Internal apps (site, ops, uma-bridge)
4929
```
5030

51-
### Workspace Targeting
31+
## Workspace Commands
32+
5233
```bash
53-
# From repo root
34+
# Target specific workspace
5435
yarn workspace @lightsparkdev/<name> <command>
5536

56-
# From workspace directory
57-
cd apps/private/uma-bridge && yarn start
37+
# Examples
38+
yarn workspace @lightsparkdev/uma-bridge start
39+
yarn workspace @lightsparkdev/ui test
5840
```
5941

60-
## Architecture & Patterns
42+
## Code Patterns
6143

62-
### Monorepo Management
63-
- **Yarn workspaces** with workspace protocol (`"@lightsparkdev/ui": "*"`)
64-
- **Turbo** orchestrates builds with caching and parallelization
44+
### Dependencies
45+
- Use workspace protocol for internal deps: `"@lightsparkdev/ui": "*"`
6546
- Shared configs: `@lightsparkdev/{tsconfig,eslint-config}`
66-
- Build artifacts in `dist/`, ignored by git
6747

6848
### GraphQL
69-
- TypeScript types auto-generated via GraphQL Code Generator
70-
- Schema variants per API surface (internal, third-party)
71-
- Fragments/operations defined per app
72-
- Real-time subscriptions for transaction updates
73-
- **After Python schema changes**: run `yarn gql-codegen` from root
74-
75-
### React Stack
76-
- **Vite** - Dev server and bundler
77-
- **Emotion** - CSS-in-JS styling
78-
- **React Router** - Navigation
79-
- **React Query** - Server state
80-
- **Zustand** - Client state
81-
82-
### Testing
83-
- **Jest** - Unit/integration tests
84-
- **React Testing Library** - Component tests
85-
- **Cypress** - E2E tests
86-
- Tests colocated with source (`.test.ts`, `.spec.ts`)
87-
88-
## Configuration Files
89-
90-
- **turbo.json** - Build pipeline, task dependencies, caching
91-
- **package.json** (root) - Workspace definitions, scripts
92-
- **packages/eslint-config/** - Shared linting rules
93-
- **packages/tsconfig/** - TypeScript presets
94-
95-
## Code Standards
96-
97-
- **TypeScript strict mode** enabled
98-
- **ESLint** extends shared configs
99-
- **Prettier** with import organization
100-
- **Circular dependency detection** via madge
101-
- **Prefer Edit tool** over inline rewrites for existing code
102-
103-
## Common Task Workflows
104-
105-
### Adding New Package
106-
1. Create directory in `packages/` or `apps/`
107-
2. Add workspace reference in root `package.json`
108-
3. Create `package.json` with dependencies (use workspace protocol for internal deps)
109-
4. Add build config to `turbo.json` if needed
110-
5. Run `yarn` to link workspace
111-
112-
### GraphQL Type Updates
113-
After Python backend schema changes:
114-
```bash
115-
yarn gql-codegen # All workspaces
116-
yarn workspace @lightsparkdev/uma-bridge gql-codegen # Specific app
117-
```
118-
119-
### Debugging Build Issues
120-
```bash
121-
yarn clean-all # Remove dist/ and caches
122-
yarn build --force # Bypass Turbo cache
123-
yarn clean-resolve # Nuclear option: reset lockfile
124-
```
125-
126-
### UMA Bridge Development
49+
After Python schema changes:
12750
```bash
128-
# Lint bridge + UI package
129-
yarn run lint --filter=@lightsparkdev/ui --filter=@lightsparkdev/uma-bridge
130-
131-
# Start with Vite dev server (proxy configured for backend)
132-
yarn workspace @lightsparkdev/uma-bridge start
51+
yarn gql-codegen # All workspaces
52+
yarn workspace @lightsparkdev/uma-bridge gql-codegen # Specific
13353
```
13454

135-
Integrates with: Plaid, Tazapay, Striga, other payment providers
136-
13755
### Adding Dependencies
13856
```bash
139-
# Workspace-specific
140-
yarn workspace @lightsparkdev/<name> add <package>
141-
142-
# Root-level (affects all workspaces)
143-
yarn add -W <package>
57+
yarn workspace @lightsparkdev/<name> add <package> # To workspace
58+
yarn add -W <package> # Root level
14459
```
14560

146-
## Release Process
147-
148-
**Public packages** (SDK, core utilities):
149-
- Changesets for version management
150-
- Copybara syncs to public repo on main merge
151-
- Release PR auto-created
152-
- Merge Release PR → npm publish
153-
154-
**Private packages** (`packages/private/`, `apps/private/`):
155-
- Not published to npm
156-
- Versioned internally only
157-
15861
## Troubleshooting
15962

160-
**Import errors**: Check workspace dependencies use `"*"` not version numbers
161-
**Type errors after GraphQL changes**: Run `yarn gql-codegen`
162-
**Stale build artifacts**: `yarn clean-all && yarn build`
163-
**Turbo cache issues**: Add `--force` flag to bypass cache
63+
| Issue | Fix |
64+
|-------|-----|
65+
| Import errors | Check deps use `"*"` not versions |
66+
| Type errors after GraphQL | `yarn gql-codegen` |
67+
| Stale builds | `yarn clean-all && yarn build` |
68+
| Cache issues | `yarn build --force` |

apps/examples/ui-test-app/src/tests/CodeInput.test.tsx

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import { jest } from "@jest/globals";
22
import { CodeInput } from "@lightsparkdev/ui/components/CodeInput/CodeInput";
33
import { fireEvent, screen, waitFor } from "@testing-library/react";
4+
import userEvent from "@testing-library/user-event";
45
import { render } from "./render";
56

67
describe("CodeInput", () => {
78
beforeEach(() => {
89
const mockClipboardReadWithoutNumbers = jest.fn(() =>
910
Promise.resolve("sdkjfnsd"),
1011
);
11-
Object.assign(navigator, {
12-
clipboard: {
12+
// `userEvent.setup()` may install `navigator.clipboard` as a getter-only prop.
13+
// Use `defineProperty` so this mock is resilient regardless of that setup.
14+
Object.defineProperty(navigator, "clipboard", {
15+
value: {
1316
readText: mockClipboardReadWithoutNumbers,
1417
},
18+
configurable: true,
1519
});
1620
});
1721

@@ -134,4 +138,61 @@ describe("CodeInput", () => {
134138
expect(inputFields[3]).toHaveValue(null);
135139
expect(inputFields[2]).toHaveFocus();
136140
});
141+
142+
it("redirects focus to first empty input when clicking on empty input in unified variant", async () => {
143+
const user = userEvent.setup();
144+
render(<CodeInput codeLength={6} variant="unified" />);
145+
const inputFields = screen.getAllByRole("textbox");
146+
expect(inputFields).toHaveLength(6);
147+
148+
// Enter some digits in the first two positions
149+
fireEvent.keyDown(inputFields[0], { key: "1" });
150+
fireEvent.keyDown(inputFields[1], { key: "2" });
151+
152+
// Now focus should be on the third input (index 2)
153+
expect(inputFields[2]).toHaveFocus();
154+
155+
// Simulate clicking on the 5th input (index 4) - an empty position
156+
// onMouseDown should redirect focus to the first empty input (index 2)
157+
await user.click(inputFields[4]);
158+
expect(inputFields[2]).toHaveFocus();
159+
});
160+
161+
it("allows clicking on any filled input in unified variant", async () => {
162+
const user = userEvent.setup();
163+
render(<CodeInput codeLength={6} variant="unified" />);
164+
const inputFields = screen.getAllByRole("textbox");
165+
166+
// Enter some digits
167+
fireEvent.keyDown(inputFields[0], { key: "1" });
168+
fireEvent.keyDown(inputFields[1], { key: "2" });
169+
fireEvent.keyDown(inputFields[2], { key: "3" });
170+
171+
// Focus should be on the 4th input (index 3)
172+
expect(inputFields[3]).toHaveFocus();
173+
174+
// Clicking on a filled input (index 1) should work normally - no redirect
175+
await user.click(inputFields[1]);
176+
expect(inputFields[1]).toHaveFocus();
177+
178+
// Can also click on index 0
179+
await user.click(inputFields[0]);
180+
expect(inputFields[0]).toHaveFocus();
181+
182+
// Can also click on index 2
183+
await user.click(inputFields[2]);
184+
expect(inputFields[2]).toHaveFocus();
185+
});
186+
187+
it("focuses first input when all inputs are empty in unified variant", () => {
188+
render(<CodeInput codeLength={6} variant="unified" />);
189+
const inputFields = screen.getAllByRole("textbox");
190+
191+
// Blur the auto-focused first input
192+
fireEvent.blur(inputFields[0]);
193+
194+
// Click on a middle input when all are empty
195+
fireEvent.mouseDown(inputFields[3]);
196+
expect(inputFields[0]).toHaveFocus();
197+
});
137198
});

packages/core/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@
6363
},
6464
"license": "Apache-2.0",
6565
"dependencies": {
66+
"@noble/curves": "^1.9.7",
6667
"dayjs": "^1.11.7",
6768
"graphql": "^16.6.0",
6869
"graphql-ws": "^5.11.3",
69-
"secp256k1": "^5.0.1",
7070
"ws": "^8.12.1",
7171
"zen-observable-ts": "^1.1.0"
7272
},
@@ -77,7 +77,6 @@
7777
"@types/crypto-js": "^4.1.1",
7878
"@types/jest": "^29.5.3",
7979
"@types/lodash-es": "^4.17.6",
80-
"@types/secp256k1": "^4.0.3",
8180
"@types/ws": "^8.5.4",
8281
"auto-bind": "^5.0.1",
8382
"eslint": "^8.3.0",

packages/core/src/crypto/SigningKey.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import secp256k1 from "secp256k1";
1+
import { secp256k1 } from "@noble/curves/secp256k1";
22
import { createSha256Hash } from "../utils/createHash.js";
33
import { hexToBytes } from "../utils/hex.js";
44
import type { CryptoInterface } from "./crypto.js";
@@ -46,7 +46,7 @@ export class Secp256k1SigningKey extends SigningKey {
4646
async sign(data: Uint8Array) {
4747
const keyBytes = new Uint8Array(hexToBytes(this.privateKey));
4848
const hash = await createSha256Hash(data);
49-
const signResult = secp256k1.ecdsaSign(hash, keyBytes);
50-
return secp256k1.signatureExport(signResult.signature);
49+
const sig = secp256k1.sign(hash, keyBytes);
50+
return sig.toBytes("der");
5151
}
5252
}

0 commit comments

Comments
 (0)