Read Juplend positions via Borrow API#115
Conversation
|
Warning Review limit reached
Next review available in: 24 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis PR migrates the Juplend adapter from an on-chain ChangesJuplend Borrow REST Migration
Trellis Trae Platform Support and Workflow Docs
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant PrivateAdapter as JuplendPrivateAdapter
participant BorrowAPI as readJuplendPositions
participant JupAPI as api.jup.ag
Client->>PrivateAdapter: bootstrapAccount/mapAccount
PrivateAdapter->>BorrowAPI: readJuplendPositions({walletAddress, vaultId, positionId})
BorrowAPI->>JupAPI: GET /lend/v1/borrow/positions?users=wallet
JupAPI-->>BorrowAPI: raw positions JSON
BorrowAPI-->>PrivateAdapter: filtered JuplendReadPosition[]
PrivateAdapter-->>Client: mapped balances/risk
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/adapters/juplend/private-adapter.ts (1)
217-284: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winInclude
position.dustBorrowAmountin Juplend debt totals.readJuplendPositionsexposes it separately, butmapAccountonly foldsposition.borrowAmountintoaccumulator.borrowedandtotalDebtUsd, so positions with dust debt will underreportborrowed,totalDebtUSD, and the resulting risk metrics. Add the dust amount with the borrow token decimals alongsideborrowAmount.🤖 Prompt for 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. In `@src/adapters/juplend/private-adapter.ts` around lines 217 - 284, `mapAccount` is missing `position.dustBorrowAmount` in Juplend debt aggregation, so debt and risk metrics can be understated. Update the debt handling inside `mapAccount` to combine `position.borrowAmount` with `position.dustBorrowAmount` using the borrow token decimals before calculating `borrowedQuantity`, then use that combined amount for both `accumulator.borrowed` and `totalDebtUsd` while leaving the rest of the position mapping logic unchanged.
🧹 Nitpick comments (2)
.claude/hooks/inject-workflow-state.py (1)
310-340: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueNarrow the stdin reader exception handler Catch
Exceptioninstead ofBaseExceptionin the daemon reader so shutdown signals aren’t swallowed.🤖 Prompt for 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. In @.claude/hooks/inject-workflow-state.py around lines 310 - 340, The stdin reader in _load_hook_input is catching too broadly by using BaseException inside the _read daemon helper, which can swallow shutdown/control-flow signals. Update the exception handling in _read to catch Exception only, while keeping the existing queue-based read and the fallback-to-empty-dict behavior in _load_hook_input unchanged. Use the _load_hook_input and _read symbols to locate the handler.Source: Linters/SAST tools
src/adapters/juplend/private-adapter.ts (1)
217-231: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate
getJupApiKeyimplementation across two files.
private-adapter.tsdefines its owngetJupApiKey(used at bootstrapAccount's call site) whileborrow-api.tsalso defines agetJupApiKeywith the sameexplicitApiKey || process.env.JUP_APIfallback logic, andreadJuplendPositionsre-resolves the key a second time internally. Consider exporting a singlegetJupApiKeyfromborrow-api.tsand reusing it here to avoid the two implementations silently diverging over time.Also applies to: 341-353
🤖 Prompt for 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. In `@src/adapters/juplend/private-adapter.ts` around lines 217 - 231, The Juplend API key resolution logic is duplicated in both private-adapter.ts and borrow-api.ts, and readJuplendPositions is resolving it again internally; consolidate this by exporting and reusing the existing getJupApiKey from borrow-api.ts in bootstrapAccount/mapAccount so there is only one fallback path. Update the call sites around mapAccount and readJuplendPositions to accept the already-resolved key instead of recomputing it, keeping the explicitApiKey || process.env.JUP_API behavior in one shared place.
🤖 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 `@src/adapters/juplend/borrow-api.ts`:
- Around line 78-80: The asString helper currently only guards against
undefined, so null values from the Juplend borrow API can still reach toString()
and fail mapping. Update asString in borrow-api.ts to treat null the same as
undefined before conversion, and keep the existing behavior for StringLike,
string, and number inputs used by the supply/borrow/dustBorrow mapping.
In `@src/adapters/juplend/private-adapter.ts`:
- Around line 205-215: The token decimal handling in tokenDecimals and
divideTokenAmount currently falls back to 0 when JuplendTokenMetadata.decimals
is missing or invalid, which can silently skew amounts. Update the
JuplendTokenMetadata parsing path to treat missing/malformed decimals as an
error condition or skip the affected position instead of defaulting to zero, and
ensure the caller that uses divideTokenAmount handles that failure explicitly.
---
Outside diff comments:
In `@src/adapters/juplend/private-adapter.ts`:
- Around line 217-284: `mapAccount` is missing `position.dustBorrowAmount` in
Juplend debt aggregation, so debt and risk metrics can be understated. Update
the debt handling inside `mapAccount` to combine `position.borrowAmount` with
`position.dustBorrowAmount` using the borrow token decimals before calculating
`borrowedQuantity`, then use that combined amount for both
`accumulator.borrowed` and `totalDebtUsd` while leaving the rest of the position
mapping logic unchanged.
---
Nitpick comments:
In @.claude/hooks/inject-workflow-state.py:
- Around line 310-340: The stdin reader in _load_hook_input is catching too
broadly by using BaseException inside the _read daemon helper, which can swallow
shutdown/control-flow signals. Update the exception handling in _read to catch
Exception only, while keeping the existing queue-based read and the
fallback-to-empty-dict behavior in _load_hook_input unchanged. Use the
_load_hook_input and _read symbols to locate the handler.
In `@src/adapters/juplend/private-adapter.ts`:
- Around line 217-231: The Juplend API key resolution logic is duplicated in
both private-adapter.ts and borrow-api.ts, and readJuplendPositions is resolving
it again internally; consolidate this by exporting and reusing the existing
getJupApiKey from borrow-api.ts in bootstrapAccount/mapAccount so there is only
one fallback path. Update the call sites around mapAccount and
readJuplendPositions to accept the already-resolved key instead of recomputing
it, keeping the explicitApiKey || process.env.JUP_API behavior in one shared
place.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 53aaa119-6158-4c8d-9201-b87bedfb935e
⛔ Files ignored due to path filters (7)
.trellis/tasks/archive/2026-07/07-03-ws-periodic-business-liveness/check.jsonlis excluded by!.trellis/tasks/**.trellis/tasks/archive/2026-07/07-03-ws-periodic-business-liveness/design.mdis excluded by!.trellis/tasks/**.trellis/tasks/archive/2026-07/07-03-ws-periodic-business-liveness/implement.jsonlis excluded by!.trellis/tasks/**.trellis/tasks/archive/2026-07/07-03-ws-periodic-business-liveness/implement.mdis excluded by!.trellis/tasks/**.trellis/tasks/archive/2026-07/07-03-ws-periodic-business-liveness/prd.mdis excluded by!.trellis/tasks/**.trellis/tasks/archive/2026-07/07-03-ws-periodic-business-liveness/task.jsonis excluded by!.trellis/tasks/**package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (38)
.agents/skills/trellis-brainstorm/SKILL.md.agents/skills/trellis-meta/references/customize-local/change-hooks.md.agents/skills/trellis-meta/references/local-architecture/generated-files.md.agents/skills/trellis-meta/references/platform-files/hooks-and-settings.md.agents/skills/trellis-meta/references/platform-files/overview.md.agents/skills/trellis-meta/references/platform-files/platform-map.md.changeset/juplend-borrow-api-reader.md.claude/hooks/inject-workflow-state.py.claude/hooks/session-start.py.claude/skills/trellis-brainstorm/SKILL.md.claude/skills/trellis-meta/references/customize-local/change-hooks.md.claude/skills/trellis-meta/references/local-architecture/generated-files.md.claude/skills/trellis-meta/references/platform-files/hooks-and-settings.md.claude/skills/trellis-meta/references/platform-files/overview.md.claude/skills/trellis-meta/references/platform-files/platform-map.md.codex/hooks/inject-workflow-state.py.trellis/.template-hashes.json.trellis/.version.trellis/scripts/common/active_task.py.trellis/scripts/common/cli_adapter.py.trellis/scripts/common/task_store.py.trellis/spec/sdk/adapters.md.trellis/spec/sdk/architecture.md.trellis/spec/sdk/venues/juplend.md.trellis/workflow.mddocs/managers.mddocs/quickstart.mddocs/types.mdpackage.jsonscripts/live-juplend-account-smoke.tssrc/adapters/juplend/borrow-api.tssrc/adapters/juplend/lend-read.tssrc/adapters/juplend/private-adapter.tssrc/client/runtime.tssrc/types/shared.tstests/integration/account.test.tstests/support/exchanges/juplend.tstests/type/register-account-input.ts
💤 Files with no reviewable changes (1)
- src/adapters/juplend/lend-read.ts
Summary
@jup-ag/lend-readreader with Jupiter Lend Borrow RESTGET /lend/v1/borrow/positions?users=....options.walletAddressfor Juplend accounts and treatvaultId/positionIdas local filters over returned wallet positions.Validation
bun run lintbun run type-checkbun test --max-concurrency=1 tests/integration/account.test.tsbun run testSummary by CodeRabbit
New Features
Bug Fixes
Documentation