Skip to content

Fix SDK acknowledgement before home channel creation#734

Merged
ihsraham merged 3 commits into
mainfrom
feat/ts-sdk-ack-offchain-funds
May 12, 2026
Merged

Fix SDK acknowledgement before home channel creation#734
ihsraham merged 3 commits into
mainfrom
feat/ts-sdk-ack-offchain-funds

Conversation

@ihsraham
Copy link
Copy Markdown
Collaborator

@ihsraham ihsraham commented May 8, 2026

Summary

  • Fixes Client.acknowledge(asset) so received off-chain funds can be acknowledged before a home channel is open.
  • Routes latest states without homeChannelId through the existing channel creation acknowledgement path.
  • Bumps @yellow-org/sdk to 1.2.2 and adds unit coverage for acknowledgement path selection.

Context

While adding channel-readiness UX to the Nitrolite Store example, we found that the app can detect received off-chain funds, but the browser SDK needs to acknowledge those funds through channel creation when no home channel exists yet. This aligns the TS SDK behavior with the Go SDK path for state exists but no HomeChannelID.

Validation

  • npm --prefix sdk/ts run typecheck
  • npm --prefix sdk/ts test -- --runTestsByPath test/unit/client.test.ts
  • npm --prefix sdk/ts test
  • npm --prefix sdk/ts run lint
  • npm --prefix sdk/ts run build:ci
  • git diff --check

Summary by CodeRabbit

  • Bug Fixes

    • Broadened handling for cases where an on-chain channel is not present, improving acknowledgement and transfer flows.
  • Tests

    • Expanded unit tests to cover acknowledgement and transfer edge cases and state transitions.
  • Chores

    • Package version bumped to 1.2.2.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

Warning

Rate limit exceeded

@ihsraham has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 42 minutes and 12 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 64970497-5799-4438-bb30-841b9eaaf891

📥 Commits

Reviewing files that changed from the base of the PR and between 2052e6a and 97d904f.

⛔ Files ignored due to path filters (2)
  • sdk/mcp/package-lock.json is excluded by !**/package-lock.json
  • sdk/ts-compat/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • sdk/mcp/package.json
  • sdk/mcp/server.json
  • sdk/ts-compat/package.json
📝 Walkthrough

Walkthrough

transfer and acknowledge now treat states missing homeChannelId as "no open channel" and route them to channel creation; acknowledge adds an early user-acknowledged guard. Unit tests cover creation vs submission and rejection paths. Package version bumped to 1.2.2.

Changes

Client transfer & acknowledge flow

Layer / File(s) Summary
Core logic updates
sdk/ts/src/client.ts
Updated docs and branching: transfer and acknowledge treat `!state
Unit tests
sdk/ts/test/unit/client.test.ts
Added shared test helpers and suites for Client.acknowledge and Client.transfer covering channel-creation, submission, and already-acknowledged rejection scenarios.
Version bump
sdk/ts/package.json
Version updated from 1.2.1 to 1.2.2.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • dimast-x
  • philanton
  • nksazonov

Poem

🐰 I hop through code with ears held high,
Missing channels no longer pass by,
If homeId's gone, I build the way,
Tests clap softly—ready for play,
Version bumped, the rabbits cheer 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix SDK acknowledgement before home channel creation' accurately describes the main change: fixing the Client.acknowledge() method to handle states without homeChannelId before home channel creation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ts-sdk-ack-offchain-funds

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sdk/ts/src/client.ts`:
- Around line 667-670: The branch that handles "no open channel" currently
checks if (!state || !state.homeChannelId) before testing whether the state was
already acknowledged, so states with userSig but no homeChannelId fall into
creation/acknowledgement flow and can be double-acknowledged; move the "already
acknowledged" guard (the check for state.userSig / existing acknowledgement) to
run before the branch selection that starts with if (!state ||
!state.homeChannelId) so that any state with a userSig is immediately
rejected/returned as already-acknowledged; apply the same reordering fix to the
other occurrence around the code referenced at lines ~716-718 to ensure both
code paths reject already-acknowledged states instead of attempting channel
creation/ack.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fbf74e98-bee6-4fdb-8f78-988790251510

📥 Commits

Reviewing files that changed from the base of the PR and between c5581cf and 7526152.

⛔ Files ignored due to path filters (1)
  • sdk/ts/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • sdk/ts/package.json
  • sdk/ts/src/client.ts
  • sdk/ts/test/unit/client.test.ts

Comment thread sdk/ts/src/client.ts
Copy link
Copy Markdown
Contributor

@nksazonov nksazonov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good fix!

Two things to be aware of beyond the inline comments:

transfer() has the same pre-fix pattern (client.ts:576 still uses if (!state) without a !state.homeChannelId guard). The Go SDK's Transfer() already handles state.HomeChannelID == nil by routing to channel creation. In the TS SDK, a user with received off-chain funds calling transfer() before acknowledge() will reach signAndSubmitState — and the node will reject with "user has no open channel" (submit_state.go:56–58). The existing comment at client.ts:572 saying "homeChannelId is intentionally not checked here" is now misleading given this PR's rationale. Consider either fixing transfer() the same way or updating the comment to document that acknowledge() must be called first.

The fix to the aforementioned issue should probably be done in a separate PR. Let's wait for @philanton to decide together.

Comment thread sdk/ts/test/unit/client.test.ts
Comment thread sdk/ts/test/unit/client.test.ts Outdated
@nksazonov
Copy link
Copy Markdown
Contributor

@ihsraham , after speaking to @philanton , could you please make the same change for transfer(...) logic in the TS SDK?

@ihsraham ihsraham force-pushed the feat/ts-sdk-ack-offchain-funds branch from 7526152 to 2052e6a Compare May 11, 2026 13:29
@ihsraham
Copy link
Copy Markdown
Collaborator Author

@nksazonov done in 2052e6af. transfer() now uses the same no-home-channel creation path as acknowledge().

@ihsraham ihsraham requested a review from nksazonov May 11, 2026 14:43
@ihsraham ihsraham merged commit 8449372 into main May 12, 2026
16 checks passed
@ihsraham ihsraham deleted the feat/ts-sdk-ack-offchain-funds branch May 12, 2026 06:53
nksazonov pushed a commit that referenced this pull request May 13, 2026
- MF-L01: fix(contracts/ChannelHub): cap ERC20 transfer returndata copy to 32 bytes (#726)                                                
- MF-H01: fix(nitronode): paginate get_last_key_states endpoints (#724)                                                                   
- MF-I01-I02: fix(contracts): address security audit findings I-01 and I-02 (#728)                                                        
- MF-C01: rpc: cap inbound WebSocket frame size and rate-limit per connection (#723)                                                      
- MF-L02: docs(protocol): qualify enforcement guarantee for intent-specific execution paths (#737)                                        
- MF-L02-I03-I04_I05: fix(contracts): add more Node trust assumptions and requirements (#738)                                             
- MF-M01: backfill state user_sig from on-chain events (#731)               
- MF-M02: fix(rpc): release Serve wait group on processSink overflow (#732)                                                               
- Fix SDK acknowledgement before home channel creation (#734)               
- MF-I06: fix(nitronode): gate escrow transitions on home channel onchain materialization (#730)                                          
- MF-M05: fix(nitronode): enforce TLS by default for Postgres (#733)                                                                      
- MF-M07: Unblock receiver states after finalized escrow operations (#735)
- MF-M04: feat: provide tooling for and enhance docs on ValidatorRegistered event (#744)                                                  
- MF-L04: fix(contracts): reject redundant native value (#741)              
- MF-H02: bind session key registration to a single owner per kind (#739)                                                                 
- MF-I07: fix(contracts): enforce max challenge duration (#752)             
- MF-M08: fix(rpc): replace Origin label with application_id on connection gauge (#745)                                                   
- MF-C02: fix(core): add ChannelStatusClosing to gate post-finalize state transitions (#746)                                              
- MF-L06: fix(contracts): clear stale challengeExpireAt on cooperative escrow finalization (#754)
- MF-I08: docs: document ChannelClosed event orientation ambiguity during abandoned migration (#755)                                      
- MF-M09: fix(nitronode): auto-challenge home channel on withheld escrow finalize (#753)
- MF-L09: fix(nitronode): validate parsed app session nonce (#751)                                                                        
- MF-L05: docs(contracts): document informational events not guaranteed to emit (#756)
- MF-L08: fix(nitronode/api): default get_last_key_states to active-only with include_inactive opt-in (#749)                              
- MF-L10: fix: emit escrowIds array in EscrowDepositsPurged event and handle it in Nitronode (#757)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants