feat: 1:1 stablecoin demo toggle (V2-207)#54
Conversation
Add a "1:1 demo" toggle that, when enabled, sends the X-Integrator-Key header on quote requests and forces order exclusivity to the LI.FI demo solver so it fills 1:1 via the quick fallback. Lets the 1:1 stablecoin flow be demoed to partners/prospects with verifiable on-chain output. - Bump @lifi/intent to 0.1.3 (adds integratorKey -> X-Integrator-Key header) - Add use11Demo + integratorKey state and a UI toggle/key field - Extract resolveDemoQuoteParams() helper with unit tests Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR migrates wallet integration from ChangesLI.FI Intent Migration & Config Refactoring
🎯 4 (Complex) | ⏱️ ~60 minutes Possibly Related PRs
Suggested Reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🚀 Preview deployed! Worker: |
There was a problem hiding this comment.
Actionable comments posted: 14
🧹 Nitpick comments (7)
.lintstagedrc.json (1)
2-2: ⚡ Quick winAdd ESLint to staged TS/JS/Svelte checks.
This config only formats files; it skips the required lint pass for staged
ts/js/sveltechanges.Suggested update
{ - "*.{js,ts,svelte,css,md,json,html}": "prettier --write" + "*.{js,ts,svelte,css,md,json,html}": "prettier --write", + "*.{js,ts,svelte}": "eslint --max-warnings=0" }As per coding guidelines: "
**/*.{ts,js,svelte}: Use ESLint with Svelte support for linting; runbun run lintto check lint rules".🤖 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 @.lintstagedrc.json at line 2, Update the .lintstagedrc.json so staged TypeScript/JavaScript/Svelte files are linted, not just prettier-formatted: add or replace the glob "**/*.{ts,js,svelte}" to run the ESLint-based lint command (per guidelines use "bun run lint") so that staged files matching "*.{ts,js,svelte}" are checked by ESLint with Svelte support; keep the existing prettier entry for other globs or chain both commands if you want formatting plus linting for the same file types.src/lib/libraries/compactLib.ts (2)
35-58: 💤 Low valueInconsistent await pattern with
writeContract.In
compactDeposit,writeContractis awaited immediately (lines 37, 47), makingtransactionHasha resolved string. However, incompactWithdraw(line 102) andcompactApprove(line 141),writeContractis not awaited, makingtransactionHasha promise. This inconsistency could confuse future maintainers. Also, on line 57,await transactionHashis redundant since it's already a string.♻️ Consistent pattern (prefer awaiting immediately)
- let transactionHash: `0x${string}`; if (token.address === ADDRESS_ZERO) { - transactionHash = await walletClient.writeContract({ + const transactionHash = await walletClient.writeContract({ chain: getChain(token.chainId), ... }); + await getClient(token.chainId).waitForTransactionReceipt({ hash: transactionHash }); + if (postHook) await postHook(); + return transactionHash; } else { - transactionHash = await walletClient.writeContract({ + const transactionHash = await walletClient.writeContract({ ... }); + await getClient(token.chainId).waitForTransactionReceipt({ hash: transactionHash }); + if (postHook) await postHook(); + return transactionHash; } - await getClient(token.chainId).waitForTransactionReceipt({ - hash: await transactionHash - }); - if (postHook) await postHook(); - return transactionHash;🤖 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/lib/libraries/compactLib.ts` around lines 35 - 58, The code in compactDeposit uses await on walletClient.writeContract so transactionHash is a string, but compactWithdraw and compactApprove leave it as a Promise, and then caller does await transactionHash later; make the pattern consistent by always awaiting writeContract immediately in compactDeposit, compactWithdraw, and compactApprove (i.e., assign transactionHash = await walletClient.writeContract(...)), and remove redundant await when calling getClient(...).waitForTransactionReceipt({ hash: transactionHash }); reference the functions compactDeposit, compactWithdraw, compactApprove, the transactionHash variable, walletClient.writeContract, and getClient(...).waitForTransactionReceipt when making the changes.
14-15: ⚡ Quick winReplace
anywith proper types for hooks.ESLint flags
anyonpreHookandpostHookreturn types. Since these hooks are for side effects (UI updates, logging),voidorunknownwould be more appropriate.♻️ Proposed fix
static compactDeposit( walletClient: WC, opts: { - preHook?: (chainId: number) => Promise<any>; - postHook?: () => Promise<any>; + preHook?: (chainId: number) => Promise<void>; + postHook?: () => Promise<void>; inputToken: AppTokenContext; ... } )Apply the same change to
compactWithdrawandcompactApprove.Also applies to: 67-68, 121-122
🤖 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/lib/libraries/compactLib.ts` around lines 14 - 15, Replace the loose any return types on the hook signatures with a more specific side-effect type: change preHook?: (chainId: number) => Promise<any> and postHook?: () => Promise<any> to use Promise<void> (or Promise<unknown> if you prefer unknown) so the hooks are clearly for side effects; make the identical change to the same hook types declared for compactWithdraw and compactApprove (ensure you update the signatures for preHook and postHook in each of those functions/classes: preHook, postHook, compactWithdraw, compactApprove).src/lib/config.ts (1)
383-386: 💤 Low valueSimplify address normalization logic.
The current slicing logic
address.length - 42is confusing and relies on assumptions about input length. For standard hex addresses (42 chars including0x), consider using a clearer approach.♻️ Clearer approach
- const concatedAddress = - "0x" + address?.replace("0x", "")?.slice(address.length - 42, address.length); + // Normalize to lowercase 0x-prefixed address, taking last 40 hex chars + const concatedAddress = address + ? (`0x${address.replace("0x", "").slice(-40).toLowerCase()}` as `0x${string}`) + : undefined;🤖 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/lib/config.ts` around lines 383 - 386, The current address normalization that builds concatedAddress is brittle; change it to strip any leading "0x" from address, take the last 40 hex chars (e.g., via slice(-40)), left-pad with zeros if shorter, and then prefix with "0x" (optionally lowercasing) so concatedAddress is always a valid 20-byte hex string; update the code that assigns concatedAddress (the variable named concatedAddress in src/lib/config.ts) to use this clear sequence instead of address.length - 42 slicing.src/app.d.ts (1)
11-13: RuntimeBigInt.prototype.toJSONimplementation is present
src/app.d.ts’sBigIntaugmentation is backed by a runtime patch:BigInt.prototype.toJSON = function () { return this.toString(); };insrc/routes/+page.svelte(lines 17-19), soJSON.stringifywon’t throw forbigintvalues due to this missing implementation.- Prototype mutation is currently done in a page module; move it to a dedicated global/polyfill/entry to avoid unexpected SSR/client side effects.
🤖 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/app.d.ts` around lines 11 - 13, The runtime patch BigInt.prototype.toJSON currently implemented inside src/routes/+page.svelte should be moved to a dedicated global/polyfill entry to avoid unexpected SSR/client side effects; create a single initialization module (e.g., a polyfills or runtime-init file) that checks typeof BigInt !== 'undefined' and whether BigInt.prototype.toJSON already exists before assigning, import that module from a top-level entry (client and/or server bootstrap such as your app entry or hooks file) so it runs once for both environments, and keep the TypeScript augmentation in src/app.d.ts to match the runtime behavior; remove the mutation from src/routes/+page.svelte to prevent per-page side effects.src/lib/libraries/intentFactory.ts (1)
124-125: ⚡ Quick winReplace
anytypes with specific types for hooks.The linter flags
anyusage. Consider usingvoidorunknownfor hook return types since the return values aren't used.Proposed fix
- preHook?: (chainId: number) => Promise<any>; - postHook?: () => Promise<any>; + preHook?: (chainId: number) => Promise<void>; + postHook?: () => Promise<void>;Apply the same change in the constructor options type and
escrowApproveopts.Also applies to: 133-134, 298-299
🤖 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/lib/libraries/intentFactory.ts` around lines 124 - 125, The hook signatures use `any`; change them to more specific types (e.g., replace `preHook?: (chainId: number) => Promise<any>` with `preHook?: (chainId: number) => Promise<void | unknown>` and `postHook?: () => Promise<any>` with `postHook?: () => Promise<void | unknown>` or simply `Promise<void>` if no return value is expected) and apply the same replacement in the constructor options type and the `escrowApprove` opts declarations (update the corresponding types referenced in intentFactory.ts for the constructor options and escrowApprove opts to use `Promise<void>` or `Promise<unknown>` instead of `Promise<any>`).src/lib/libraries/intentExecution.ts (1)
167-192: 💤 Low valueLoop structure with early return only processes first component.
The
forloop iterates overcomponentsbut returns or throws on the first iteration, making subsequent components unreachable. If only the first component should be processed, the loop is misleading; if all components should be processed, the logic needs restructuring.If only first component is intended, clarify without loop
- for (const { orderComponent } of components) { + const { orderComponent } = components[0]; + { if (intent.inputSettler.toLowerCase() === MULTICHAIN_INPUT_SETTLER_ESCROW.toLowerCase()) { return walletClient.writeContract({ // ... }); } if (intent.inputSettler.toLowerCase() === MULTICHAIN_INPUT_SETTLER_COMPACT.toLowerCase()) { // ... return walletClient.writeContract({ // ... }); } throw new Error(`Could not detect settler type ${intent.inputSettler}`); } - - throw new Error(`Failed to finalise multichain order on chain ${actionChain.id}.`);🤖 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/lib/libraries/intentExecution.ts` around lines 167 - 192, The for-loop over components returns or throws on the first iteration, so either remove the loop and operate on the first element (use components[0] / orderComponent) if only the first component should be finalised, or process all components by iterating and collecting the results (e.g., build an array of walletClient.writeContract promises for each orderComponent, using intent.inputSettler checks with MULTICHAIN_INPUT_SETTLER_ESCROW and MULTICHAIN_INPUT_SETTLER_COMPACT, calling combineSignatures(signatures) where needed) and await Promise.all, and ensure you do not throw inside the loop (handle per-component errors or aggregate them and throw after the loop with context including actionChain.id and failed components).
🤖 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 `@drizzle/0000_brief_corsair.sql`:
- Around line 1-8: The baseline migration contains destructive DROP TABLE IF
EXISTS statements for transaction_receipts, tokens, intents, and
fill_transactions which can irreversibly delete persisted user data; remove
those DROP statements from 0000_brief_corsair.sql and make the migration
non-destructive by either replacing them with idempotent CREATE TABLE IF NOT
EXISTS statements (or no-op existence checks) for transaction_receipts, tokens,
intents, and fill_transactions, or move the DROP operations into a clearly
labeled, separate destructive migration that requires explicit opt-in during
upgrades.
In `@drizzle/meta/_journal.json`:
- Around line 4-12: The journal rewrite replaces previous migration history with
a single baseline in _journal.json (the "entries" array with idx 0 and tag
"0000_brief_corsair"), which will cause persistent client DBs like idb://orders
to be replayed and tables dropped; instead preserve existing entries and append
a forward-only migration entry (increment idx and set a new timestamp/tag) or,
if you truly intend a reset, explicitly change the client DB name/version (e.g.,
bump the idb://orders namespace) so consumers know this is a deliberate reset
rather than silently rewriting history.
In `@src/lib/abi/escrow.ts`:
- Around line 1231-1262: Remove the duplicated ABI error object for
FillDeadlineAfterExpiry so only a single error definition remains; locate the
two identical entries named "FillDeadlineAfterExpiry" in the ABI array and
delete one of the objects (the one that repeats the same inputs:
fillDeadline:uint32 and expires:uint32), leaving one canonical definition and
ensuring no other duplicate error entries remain in the same exported ABI
structure (e.g., the escrow ABI list).
In `@src/lib/components/BalanceField.svelte`:
- Line 2: The import toBigIntWithDecimals from "`@lifi/intent`" in
BalanceField.svelte is unused; remove the unused import to clean up the file and
avoid lint warnings by deleting the line that imports toBigIntWithDecimals (the
import statement referencing toBigIntWithDecimals) so the component only imports
and uses props it needs.
In `@src/lib/components/Introduction.svelte`:
- Around line 7-11: The introduction copy in Introduction.svelte contains
grammar and typos; update the text fragments so they read correctly: change
"support" to "supports" in the sentence mentioning "resource lock flow", change
"transaction are" to "transactions are", change "configured different" to
"configured differently", and fix "Learm" to "Learn" wherever these exact
strings appear in the component's markup so the displayed intro text is
grammatically correct.
In `@src/lib/config.ts`:
- Around line 491-497: The polygon public client is mistakenly configured with
chain: base; update the createPublicClient call that constructs polygon to use
chain: polygon instead (replace chain: base with chain: polygon) so the polygon
client uses the correct chain context (chain ID, explorers, etc.); locate the
polygon variable/entry where createPublicClient is invoked and change the chain
argument accordingly.
- Around line 288-293: The native ETH entry in the token list currently sets
decimals: 6 for the object with address: ADDRESS_ZERO, name: "eth", chainId:
arbitrumSepolia.id; update that object's decimals value to 18 so native ETH on
Arbitrum Sepolia uses 18 decimals (fix formatting/calculation errors) and ensure
no other native-token entries for arbitrumSepolia still use 6.
In `@src/lib/libraries/assetSelection.ts`:
- Line 63: The comparator in the values.sort calls currently casts a bigint
difference to Number (values.sort((a, b) => Number(b[0] - a[0]))) which can
overflow and misorder large token amounts; replace the Number(...) conversion
with a bigint-safe comparator that returns -1/0/1 based on comparing the bigint
fields directly (e.g. compare b[0] and a[0] with conditional branches or by
testing b[0] - a[0] > 0 / < 0) so sorting for largest()/smallest() works
correctly; update both occurrences (the comparator at the shown values.sort
lines) to use this bigint-safe comparison.
In `@src/lib/libraries/coreDeps.ts`:
- Around line 31-35: The code inconsistently validates addresses:
POLYMER_ORACLE[key] (variable polymer) is only checked for truthiness while
WORMHOLE_ORACLE[key] uses isNonZeroAddress; change the polymer push to use the
same validation by calling isNonZeroAddress(polymer) before
allowed.push(polymer) so the zero address is rejected; update any related type
assumptions if needed and keep the same allowed: `0x${string}`[] typing.
- Around line 43-47: In allowedOutputOracles, the checks for oracle addresses
are inconsistent: polymer is pushed on a simple truthy check while wormhole uses
isNonZeroAddress; change the polymer check to use isNonZeroAddress as well so
both POLYMER_ORACLE[key] and WORMHOLE_ORACLE[key] are validated the same way
before pushing into the allowed array (refer to allowedOutputOracles,
POLYMER_ORACLE, WORMHOLE_ORACLE, isNonZeroAddress, and the allowed variable).
In `@src/lib/libraries/flowProgress.ts`:
- Around line 157-168: The code can access flattenedInputs[0][0] when
flattenedInputs[0] is an empty array; update the check in the function that uses
flattenedInputs (the block that calls inputChainClient.readContract with COMPACT
and getLockDetails) to ensure the first nested array actually has an element
before using [0][0] — either find the first non-empty entry in flattenedInputs
(e.g., iterate flattenedInputs to pick the first sub-array with length>0) or add
an explicit guard like if (!flattenedInputs[0] || flattenedInputs[0].length ===
0) return false; so you never pass undefined into getLockDetails via
inputChainClient.readContract.
In `@src/lib/libraries/intentExecution.ts`:
- Around line 29-32: The ABI encoding call is inconsistent:
sponsorSignature.payload is defaulted but allocatorSignature.payload is not;
update the encodeAbiParameters call (using encodeAbiParameters and
parseAbiParameters) to provide a safe fallback for allocatorSignature.payload as
well (e.g., allocatorSignature.payload ?? "0x") so both signature payloads are
always a hex string and avoid undefined being passed to encodeAbiParameters.
In `@src/lib/libraries/intentFactory.ts`:
- Around line 231-235: Change transactionHash to a const since it is never
reassigned (assign the result of depositAndRegisterCompact to const
transactionHash) and remove the unused receipt variable created from
getClient(...).waitForTransactionReceipt or, if the receipt is needed, use it;
specifically update the code around the depositAndRegisterCompact call and the
subsequent getClient(...).waitForTransactionReceipt call (which currently
assigns to receipt) so that either the receipt line is deleted or its value is
consumed, keeping symbols transactionHash, depositAndRegisterCompact, account(),
this.walletClient, getClient, and inputTokens intact.
- Around line 63-67: The loop that sets exclusivity currently skips outputs
whose output.context === "0x", so the exclusivity override never applies for the
test-fixture sentinel; change the guard in the block that iterates order.outputs
so that it replaces the sentinel instead of skipping it (i.e., set
output.context = newContext when output.context === "0x", or alternatively
remove the conditional to always assign if intended), targeting the loop that
references order.outputs and the output.context/newContext variables so
exclusivityFor is correctly applied.
---
Nitpick comments:
In @.lintstagedrc.json:
- Line 2: Update the .lintstagedrc.json so staged TypeScript/JavaScript/Svelte
files are linted, not just prettier-formatted: add or replace the glob
"**/*.{ts,js,svelte}" to run the ESLint-based lint command (per guidelines use
"bun run lint") so that staged files matching "*.{ts,js,svelte}" are checked by
ESLint with Svelte support; keep the existing prettier entry for other globs or
chain both commands if you want formatting plus linting for the same file types.
In `@src/app.d.ts`:
- Around line 11-13: The runtime patch BigInt.prototype.toJSON currently
implemented inside src/routes/+page.svelte should be moved to a dedicated
global/polyfill entry to avoid unexpected SSR/client side effects; create a
single initialization module (e.g., a polyfills or runtime-init file) that
checks typeof BigInt !== 'undefined' and whether BigInt.prototype.toJSON already
exists before assigning, import that module from a top-level entry (client
and/or server bootstrap such as your app entry or hooks file) so it runs once
for both environments, and keep the TypeScript augmentation in src/app.d.ts to
match the runtime behavior; remove the mutation from src/routes/+page.svelte to
prevent per-page side effects.
In `@src/lib/config.ts`:
- Around line 383-386: The current address normalization that builds
concatedAddress is brittle; change it to strip any leading "0x" from address,
take the last 40 hex chars (e.g., via slice(-40)), left-pad with zeros if
shorter, and then prefix with "0x" (optionally lowercasing) so concatedAddress
is always a valid 20-byte hex string; update the code that assigns
concatedAddress (the variable named concatedAddress in src/lib/config.ts) to use
this clear sequence instead of address.length - 42 slicing.
In `@src/lib/libraries/compactLib.ts`:
- Around line 35-58: The code in compactDeposit uses await on
walletClient.writeContract so transactionHash is a string, but compactWithdraw
and compactApprove leave it as a Promise, and then caller does await
transactionHash later; make the pattern consistent by always awaiting
writeContract immediately in compactDeposit, compactWithdraw, and compactApprove
(i.e., assign transactionHash = await walletClient.writeContract(...)), and
remove redundant await when calling getClient(...).waitForTransactionReceipt({
hash: transactionHash }); reference the functions compactDeposit,
compactWithdraw, compactApprove, the transactionHash variable,
walletClient.writeContract, and getClient(...).waitForTransactionReceipt when
making the changes.
- Around line 14-15: Replace the loose any return types on the hook signatures
with a more specific side-effect type: change preHook?: (chainId: number) =>
Promise<any> and postHook?: () => Promise<any> to use Promise<void> (or
Promise<unknown> if you prefer unknown) so the hooks are clearly for side
effects; make the identical change to the same hook types declared for
compactWithdraw and compactApprove (ensure you update the signatures for preHook
and postHook in each of those functions/classes: preHook, postHook,
compactWithdraw, compactApprove).
In `@src/lib/libraries/intentExecution.ts`:
- Around line 167-192: The for-loop over components returns or throws on the
first iteration, so either remove the loop and operate on the first element (use
components[0] / orderComponent) if only the first component should be finalised,
or process all components by iterating and collecting the results (e.g., build
an array of walletClient.writeContract promises for each orderComponent, using
intent.inputSettler checks with MULTICHAIN_INPUT_SETTLER_ESCROW and
MULTICHAIN_INPUT_SETTLER_COMPACT, calling combineSignatures(signatures) where
needed) and await Promise.all, and ensure you do not throw inside the loop
(handle per-component errors or aggregate them and throw after the loop with
context including actionChain.id and failed components).
In `@src/lib/libraries/intentFactory.ts`:
- Around line 124-125: The hook signatures use `any`; change them to more
specific types (e.g., replace `preHook?: (chainId: number) => Promise<any>` with
`preHook?: (chainId: number) => Promise<void | unknown>` and `postHook?: () =>
Promise<any>` with `postHook?: () => Promise<void | unknown>` or simply
`Promise<void>` if no return value is expected) and apply the same replacement
in the constructor options type and the `escrowApprove` opts declarations
(update the corresponding types referenced in intentFactory.ts for the
constructor options and escrowApprove opts to use `Promise<void>` or
`Promise<unknown>` instead of `Promise<any>`).
🪄 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: e685f060-bab0-42d0-8636-3f83f11b415a
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (111)
.env.e2e.example.github/workflows/deploy.yml.github/workflows/test.yml.gitignore.lintstagedrc.json.prettierrcREADME.mddrizzle.config.tsdrizzle/0000_absent_moonstone.sqldrizzle/0000_brief_corsair.sqldrizzle/0001_nifty_mephisto.sqldrizzle/0002_expand_intent_created_at.sqldrizzle/0003_unique_intent_order_id.sqldrizzle/0004_store_transaction_receipts.sqldrizzle/meta/0000_snapshot.jsondrizzle/meta/0001_snapshot.jsondrizzle/meta/_journal.jsoneslint.config.jspackage.jsonplaywright.config.tssrc/app.d.tssrc/app.htmlsrc/lib/abi/compact.tssrc/lib/abi/erc20.tssrc/lib/abi/escrow.tssrc/lib/abi/multichain_compact.tssrc/lib/abi/multichain_escrow.tssrc/lib/abi/outputsettler.tssrc/lib/abi/polymeroracle.tssrc/lib/abi/settlercompact.tssrc/lib/abi/wormholeoracle.tssrc/lib/appTypes.tssrc/lib/components/AwaitButton.sveltesrc/lib/components/BalanceField.sveltesrc/lib/components/GetQuote.sveltesrc/lib/components/InputTokenModal.sveltesrc/lib/components/IntentListDetailRow.sveltesrc/lib/components/Introduction.sveltesrc/lib/components/OutputTokenModal.sveltesrc/lib/components/ui/ChainActionRow.sveltesrc/lib/components/ui/FieldRow.sveltesrc/lib/components/ui/FlowProgressList.sveltesrc/lib/components/ui/FlowStepTracker.sveltesrc/lib/components/ui/FormControl.sveltesrc/lib/components/ui/InlineMetaField.sveltesrc/lib/components/ui/ScreenFrame.sveltesrc/lib/components/ui/SectionCard.sveltesrc/lib/components/ui/SegmentedControl.sveltesrc/lib/components/ui/TokenAmountChip.sveltesrc/lib/config.tssrc/lib/db.tssrc/lib/libraries/assetSelection.tssrc/lib/libraries/compactLib.tssrc/lib/libraries/coreDeps.tssrc/lib/libraries/demoQuote.tssrc/lib/libraries/flowProgress.tssrc/lib/libraries/intent.tssrc/lib/libraries/intentExecution.tssrc/lib/libraries/intentFactory.tssrc/lib/libraries/intentList.tssrc/lib/libraries/orderServer.tssrc/lib/libraries/rpcCache.tssrc/lib/libraries/solver.tssrc/lib/libraries/token.tssrc/lib/migrations.jsonsrc/lib/schema.tssrc/lib/screens/ConnectWallet.sveltesrc/lib/screens/FillIntent.sveltesrc/lib/screens/Finalise.sveltesrc/lib/screens/IntentDescription.sveltesrc/lib/screens/IntentList.sveltesrc/lib/screens/IssueIntent.sveltesrc/lib/screens/ManageDeposit.sveltesrc/lib/screens/ReceiveMessage.sveltesrc/lib/state.svelte.tssrc/lib/utils/convert.tssrc/lib/utils/idLib.tssrc/lib/utils/intent.tssrc/lib/utils/interopableAddresses.tssrc/lib/utils/orderLib.tssrc/lib/utils/typedMessage.tssrc/lib/utils/wagmi.tssrc/lib/utils/walletClient.tssrc/lib/utils/walletClientRuntime.tssrc/lib/utils/web3-onboard.tssrc/routes/+layout.sveltesrc/routes/+page.sveltesrc/routes/allocator/+server.tssrc/routes/health/+server.tssrc/routes/polymer/+server.tssrc/routes/polymer/health/+server.tssrc/types/index.tssvelte.config.jstests/db.test.tstests/e2e/escrow-standard-blackbox.spec.tstests/e2e/escrow-standard-live.spec.tstests/e2e/helpers/bootstrap.tstests/e2e/issuance.spec.tstests/fixtures/mockQuote.tstests/fixtures/orderFixtures.tstests/unit/assetSelection.test.tstests/unit/demoQuote.test.tstests/unit/intentList.test.tstests/unit/orderLib.test.tstests/unit/orderServer.test.tstests/unit/orderValidationDeps.test.tstests/unit/recipientField.test.tstests/unit/walletClientSwitch.test.tstsconfig.jsonvite.config.tswrangler.toml
💤 Files with no reviewable changes (8)
- drizzle/0000_absent_moonstone.sql
- src/lib/libraries/intent.ts
- drizzle/meta/0001_snapshot.json
- src/lib/libraries/orderServer.ts
- drizzle/0002_expand_intent_created_at.sql
- drizzle/0003_unique_intent_order_id.sql
- drizzle/0004_store_transaction_receipts.sql
- drizzle/0001_nifty_mephisto.sql
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 14
🧹 Nitpick comments (7)
.lintstagedrc.json (1)
2-2: ⚡ Quick winAdd ESLint to staged TS/JS/Svelte checks.
This config only formats files; it skips the required lint pass for staged
ts/js/sveltechanges.Suggested update
{ - "*.{js,ts,svelte,css,md,json,html}": "prettier --write" + "*.{js,ts,svelte,css,md,json,html}": "prettier --write", + "*.{js,ts,svelte}": "eslint --max-warnings=0" }As per coding guidelines: "
**/*.{ts,js,svelte}: Use ESLint with Svelte support for linting; runbun run lintto check lint rules".🤖 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 @.lintstagedrc.json at line 2, Update the .lintstagedrc.json so staged TypeScript/JavaScript/Svelte files are linted, not just prettier-formatted: add or replace the glob "**/*.{ts,js,svelte}" to run the ESLint-based lint command (per guidelines use "bun run lint") so that staged files matching "*.{ts,js,svelte}" are checked by ESLint with Svelte support; keep the existing prettier entry for other globs or chain both commands if you want formatting plus linting for the same file types.src/lib/libraries/compactLib.ts (2)
35-58: 💤 Low valueInconsistent await pattern with
writeContract.In
compactDeposit,writeContractis awaited immediately (lines 37, 47), makingtransactionHasha resolved string. However, incompactWithdraw(line 102) andcompactApprove(line 141),writeContractis not awaited, makingtransactionHasha promise. This inconsistency could confuse future maintainers. Also, on line 57,await transactionHashis redundant since it's already a string.♻️ Consistent pattern (prefer awaiting immediately)
- let transactionHash: `0x${string}`; if (token.address === ADDRESS_ZERO) { - transactionHash = await walletClient.writeContract({ + const transactionHash = await walletClient.writeContract({ chain: getChain(token.chainId), ... }); + await getClient(token.chainId).waitForTransactionReceipt({ hash: transactionHash }); + if (postHook) await postHook(); + return transactionHash; } else { - transactionHash = await walletClient.writeContract({ + const transactionHash = await walletClient.writeContract({ ... }); + await getClient(token.chainId).waitForTransactionReceipt({ hash: transactionHash }); + if (postHook) await postHook(); + return transactionHash; } - await getClient(token.chainId).waitForTransactionReceipt({ - hash: await transactionHash - }); - if (postHook) await postHook(); - return transactionHash;🤖 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/lib/libraries/compactLib.ts` around lines 35 - 58, The code in compactDeposit uses await on walletClient.writeContract so transactionHash is a string, but compactWithdraw and compactApprove leave it as a Promise, and then caller does await transactionHash later; make the pattern consistent by always awaiting writeContract immediately in compactDeposit, compactWithdraw, and compactApprove (i.e., assign transactionHash = await walletClient.writeContract(...)), and remove redundant await when calling getClient(...).waitForTransactionReceipt({ hash: transactionHash }); reference the functions compactDeposit, compactWithdraw, compactApprove, the transactionHash variable, walletClient.writeContract, and getClient(...).waitForTransactionReceipt when making the changes.
14-15: ⚡ Quick winReplace
anywith proper types for hooks.ESLint flags
anyonpreHookandpostHookreturn types. Since these hooks are for side effects (UI updates, logging),voidorunknownwould be more appropriate.♻️ Proposed fix
static compactDeposit( walletClient: WC, opts: { - preHook?: (chainId: number) => Promise<any>; - postHook?: () => Promise<any>; + preHook?: (chainId: number) => Promise<void>; + postHook?: () => Promise<void>; inputToken: AppTokenContext; ... } )Apply the same change to
compactWithdrawandcompactApprove.Also applies to: 67-68, 121-122
🤖 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/lib/libraries/compactLib.ts` around lines 14 - 15, Replace the loose any return types on the hook signatures with a more specific side-effect type: change preHook?: (chainId: number) => Promise<any> and postHook?: () => Promise<any> to use Promise<void> (or Promise<unknown> if you prefer unknown) so the hooks are clearly for side effects; make the identical change to the same hook types declared for compactWithdraw and compactApprove (ensure you update the signatures for preHook and postHook in each of those functions/classes: preHook, postHook, compactWithdraw, compactApprove).src/lib/config.ts (1)
383-386: 💤 Low valueSimplify address normalization logic.
The current slicing logic
address.length - 42is confusing and relies on assumptions about input length. For standard hex addresses (42 chars including0x), consider using a clearer approach.♻️ Clearer approach
- const concatedAddress = - "0x" + address?.replace("0x", "")?.slice(address.length - 42, address.length); + // Normalize to lowercase 0x-prefixed address, taking last 40 hex chars + const concatedAddress = address + ? (`0x${address.replace("0x", "").slice(-40).toLowerCase()}` as `0x${string}`) + : undefined;🤖 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/lib/config.ts` around lines 383 - 386, The current address normalization that builds concatedAddress is brittle; change it to strip any leading "0x" from address, take the last 40 hex chars (e.g., via slice(-40)), left-pad with zeros if shorter, and then prefix with "0x" (optionally lowercasing) so concatedAddress is always a valid 20-byte hex string; update the code that assigns concatedAddress (the variable named concatedAddress in src/lib/config.ts) to use this clear sequence instead of address.length - 42 slicing.src/app.d.ts (1)
11-13: RuntimeBigInt.prototype.toJSONimplementation is present
src/app.d.ts’sBigIntaugmentation is backed by a runtime patch:BigInt.prototype.toJSON = function () { return this.toString(); };insrc/routes/+page.svelte(lines 17-19), soJSON.stringifywon’t throw forbigintvalues due to this missing implementation.- Prototype mutation is currently done in a page module; move it to a dedicated global/polyfill/entry to avoid unexpected SSR/client side effects.
🤖 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/app.d.ts` around lines 11 - 13, The runtime patch BigInt.prototype.toJSON currently implemented inside src/routes/+page.svelte should be moved to a dedicated global/polyfill entry to avoid unexpected SSR/client side effects; create a single initialization module (e.g., a polyfills or runtime-init file) that checks typeof BigInt !== 'undefined' and whether BigInt.prototype.toJSON already exists before assigning, import that module from a top-level entry (client and/or server bootstrap such as your app entry or hooks file) so it runs once for both environments, and keep the TypeScript augmentation in src/app.d.ts to match the runtime behavior; remove the mutation from src/routes/+page.svelte to prevent per-page side effects.src/lib/libraries/intentFactory.ts (1)
124-125: ⚡ Quick winReplace
anytypes with specific types for hooks.The linter flags
anyusage. Consider usingvoidorunknownfor hook return types since the return values aren't used.Proposed fix
- preHook?: (chainId: number) => Promise<any>; - postHook?: () => Promise<any>; + preHook?: (chainId: number) => Promise<void>; + postHook?: () => Promise<void>;Apply the same change in the constructor options type and
escrowApproveopts.Also applies to: 133-134, 298-299
🤖 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/lib/libraries/intentFactory.ts` around lines 124 - 125, The hook signatures use `any`; change them to more specific types (e.g., replace `preHook?: (chainId: number) => Promise<any>` with `preHook?: (chainId: number) => Promise<void | unknown>` and `postHook?: () => Promise<any>` with `postHook?: () => Promise<void | unknown>` or simply `Promise<void>` if no return value is expected) and apply the same replacement in the constructor options type and the `escrowApprove` opts declarations (update the corresponding types referenced in intentFactory.ts for the constructor options and escrowApprove opts to use `Promise<void>` or `Promise<unknown>` instead of `Promise<any>`).src/lib/libraries/intentExecution.ts (1)
167-192: 💤 Low valueLoop structure with early return only processes first component.
The
forloop iterates overcomponentsbut returns or throws on the first iteration, making subsequent components unreachable. If only the first component should be processed, the loop is misleading; if all components should be processed, the logic needs restructuring.If only first component is intended, clarify without loop
- for (const { orderComponent } of components) { + const { orderComponent } = components[0]; + { if (intent.inputSettler.toLowerCase() === MULTICHAIN_INPUT_SETTLER_ESCROW.toLowerCase()) { return walletClient.writeContract({ // ... }); } if (intent.inputSettler.toLowerCase() === MULTICHAIN_INPUT_SETTLER_COMPACT.toLowerCase()) { // ... return walletClient.writeContract({ // ... }); } throw new Error(`Could not detect settler type ${intent.inputSettler}`); } - - throw new Error(`Failed to finalise multichain order on chain ${actionChain.id}.`);🤖 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/lib/libraries/intentExecution.ts` around lines 167 - 192, The for-loop over components returns or throws on the first iteration, so either remove the loop and operate on the first element (use components[0] / orderComponent) if only the first component should be finalised, or process all components by iterating and collecting the results (e.g., build an array of walletClient.writeContract promises for each orderComponent, using intent.inputSettler checks with MULTICHAIN_INPUT_SETTLER_ESCROW and MULTICHAIN_INPUT_SETTLER_COMPACT, calling combineSignatures(signatures) where needed) and await Promise.all, and ensure you do not throw inside the loop (handle per-component errors or aggregate them and throw after the loop with context including actionChain.id and failed components).
🤖 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 `@drizzle/0000_brief_corsair.sql`:
- Around line 1-8: The baseline migration contains destructive DROP TABLE IF
EXISTS statements for transaction_receipts, tokens, intents, and
fill_transactions which can irreversibly delete persisted user data; remove
those DROP statements from 0000_brief_corsair.sql and make the migration
non-destructive by either replacing them with idempotent CREATE TABLE IF NOT
EXISTS statements (or no-op existence checks) for transaction_receipts, tokens,
intents, and fill_transactions, or move the DROP operations into a clearly
labeled, separate destructive migration that requires explicit opt-in during
upgrades.
In `@drizzle/meta/_journal.json`:
- Around line 4-12: The journal rewrite replaces previous migration history with
a single baseline in _journal.json (the "entries" array with idx 0 and tag
"0000_brief_corsair"), which will cause persistent client DBs like idb://orders
to be replayed and tables dropped; instead preserve existing entries and append
a forward-only migration entry (increment idx and set a new timestamp/tag) or,
if you truly intend a reset, explicitly change the client DB name/version (e.g.,
bump the idb://orders namespace) so consumers know this is a deliberate reset
rather than silently rewriting history.
In `@src/lib/abi/escrow.ts`:
- Around line 1231-1262: Remove the duplicated ABI error object for
FillDeadlineAfterExpiry so only a single error definition remains; locate the
two identical entries named "FillDeadlineAfterExpiry" in the ABI array and
delete one of the objects (the one that repeats the same inputs:
fillDeadline:uint32 and expires:uint32), leaving one canonical definition and
ensuring no other duplicate error entries remain in the same exported ABI
structure (e.g., the escrow ABI list).
In `@src/lib/components/BalanceField.svelte`:
- Line 2: The import toBigIntWithDecimals from "`@lifi/intent`" in
BalanceField.svelte is unused; remove the unused import to clean up the file and
avoid lint warnings by deleting the line that imports toBigIntWithDecimals (the
import statement referencing toBigIntWithDecimals) so the component only imports
and uses props it needs.
In `@src/lib/components/Introduction.svelte`:
- Around line 7-11: The introduction copy in Introduction.svelte contains
grammar and typos; update the text fragments so they read correctly: change
"support" to "supports" in the sentence mentioning "resource lock flow", change
"transaction are" to "transactions are", change "configured different" to
"configured differently", and fix "Learm" to "Learn" wherever these exact
strings appear in the component's markup so the displayed intro text is
grammatically correct.
In `@src/lib/config.ts`:
- Around line 491-497: The polygon public client is mistakenly configured with
chain: base; update the createPublicClient call that constructs polygon to use
chain: polygon instead (replace chain: base with chain: polygon) so the polygon
client uses the correct chain context (chain ID, explorers, etc.); locate the
polygon variable/entry where createPublicClient is invoked and change the chain
argument accordingly.
- Around line 288-293: The native ETH entry in the token list currently sets
decimals: 6 for the object with address: ADDRESS_ZERO, name: "eth", chainId:
arbitrumSepolia.id; update that object's decimals value to 18 so native ETH on
Arbitrum Sepolia uses 18 decimals (fix formatting/calculation errors) and ensure
no other native-token entries for arbitrumSepolia still use 6.
In `@src/lib/libraries/assetSelection.ts`:
- Line 63: The comparator in the values.sort calls currently casts a bigint
difference to Number (values.sort((a, b) => Number(b[0] - a[0]))) which can
overflow and misorder large token amounts; replace the Number(...) conversion
with a bigint-safe comparator that returns -1/0/1 based on comparing the bigint
fields directly (e.g. compare b[0] and a[0] with conditional branches or by
testing b[0] - a[0] > 0 / < 0) so sorting for largest()/smallest() works
correctly; update both occurrences (the comparator at the shown values.sort
lines) to use this bigint-safe comparison.
In `@src/lib/libraries/coreDeps.ts`:
- Around line 31-35: The code inconsistently validates addresses:
POLYMER_ORACLE[key] (variable polymer) is only checked for truthiness while
WORMHOLE_ORACLE[key] uses isNonZeroAddress; change the polymer push to use the
same validation by calling isNonZeroAddress(polymer) before
allowed.push(polymer) so the zero address is rejected; update any related type
assumptions if needed and keep the same allowed: `0x${string}`[] typing.
- Around line 43-47: In allowedOutputOracles, the checks for oracle addresses
are inconsistent: polymer is pushed on a simple truthy check while wormhole uses
isNonZeroAddress; change the polymer check to use isNonZeroAddress as well so
both POLYMER_ORACLE[key] and WORMHOLE_ORACLE[key] are validated the same way
before pushing into the allowed array (refer to allowedOutputOracles,
POLYMER_ORACLE, WORMHOLE_ORACLE, isNonZeroAddress, and the allowed variable).
In `@src/lib/libraries/flowProgress.ts`:
- Around line 157-168: The code can access flattenedInputs[0][0] when
flattenedInputs[0] is an empty array; update the check in the function that uses
flattenedInputs (the block that calls inputChainClient.readContract with COMPACT
and getLockDetails) to ensure the first nested array actually has an element
before using [0][0] — either find the first non-empty entry in flattenedInputs
(e.g., iterate flattenedInputs to pick the first sub-array with length>0) or add
an explicit guard like if (!flattenedInputs[0] || flattenedInputs[0].length ===
0) return false; so you never pass undefined into getLockDetails via
inputChainClient.readContract.
In `@src/lib/libraries/intentExecution.ts`:
- Around line 29-32: The ABI encoding call is inconsistent:
sponsorSignature.payload is defaulted but allocatorSignature.payload is not;
update the encodeAbiParameters call (using encodeAbiParameters and
parseAbiParameters) to provide a safe fallback for allocatorSignature.payload as
well (e.g., allocatorSignature.payload ?? "0x") so both signature payloads are
always a hex string and avoid undefined being passed to encodeAbiParameters.
In `@src/lib/libraries/intentFactory.ts`:
- Around line 231-235: Change transactionHash to a const since it is never
reassigned (assign the result of depositAndRegisterCompact to const
transactionHash) and remove the unused receipt variable created from
getClient(...).waitForTransactionReceipt or, if the receipt is needed, use it;
specifically update the code around the depositAndRegisterCompact call and the
subsequent getClient(...).waitForTransactionReceipt call (which currently
assigns to receipt) so that either the receipt line is deleted or its value is
consumed, keeping symbols transactionHash, depositAndRegisterCompact, account(),
this.walletClient, getClient, and inputTokens intact.
- Around line 63-67: The loop that sets exclusivity currently skips outputs
whose output.context === "0x", so the exclusivity override never applies for the
test-fixture sentinel; change the guard in the block that iterates order.outputs
so that it replaces the sentinel instead of skipping it (i.e., set
output.context = newContext when output.context === "0x", or alternatively
remove the conditional to always assign if intended), targeting the loop that
references order.outputs and the output.context/newContext variables so
exclusivityFor is correctly applied.
---
Nitpick comments:
In @.lintstagedrc.json:
- Line 2: Update the .lintstagedrc.json so staged TypeScript/JavaScript/Svelte
files are linted, not just prettier-formatted: add or replace the glob
"**/*.{ts,js,svelte}" to run the ESLint-based lint command (per guidelines use
"bun run lint") so that staged files matching "*.{ts,js,svelte}" are checked by
ESLint with Svelte support; keep the existing prettier entry for other globs or
chain both commands if you want formatting plus linting for the same file types.
In `@src/app.d.ts`:
- Around line 11-13: The runtime patch BigInt.prototype.toJSON currently
implemented inside src/routes/+page.svelte should be moved to a dedicated
global/polyfill entry to avoid unexpected SSR/client side effects; create a
single initialization module (e.g., a polyfills or runtime-init file) that
checks typeof BigInt !== 'undefined' and whether BigInt.prototype.toJSON already
exists before assigning, import that module from a top-level entry (client
and/or server bootstrap such as your app entry or hooks file) so it runs once
for both environments, and keep the TypeScript augmentation in src/app.d.ts to
match the runtime behavior; remove the mutation from src/routes/+page.svelte to
prevent per-page side effects.
In `@src/lib/config.ts`:
- Around line 383-386: The current address normalization that builds
concatedAddress is brittle; change it to strip any leading "0x" from address,
take the last 40 hex chars (e.g., via slice(-40)), left-pad with zeros if
shorter, and then prefix with "0x" (optionally lowercasing) so concatedAddress
is always a valid 20-byte hex string; update the code that assigns
concatedAddress (the variable named concatedAddress in src/lib/config.ts) to use
this clear sequence instead of address.length - 42 slicing.
In `@src/lib/libraries/compactLib.ts`:
- Around line 35-58: The code in compactDeposit uses await on
walletClient.writeContract so transactionHash is a string, but compactWithdraw
and compactApprove leave it as a Promise, and then caller does await
transactionHash later; make the pattern consistent by always awaiting
writeContract immediately in compactDeposit, compactWithdraw, and compactApprove
(i.e., assign transactionHash = await walletClient.writeContract(...)), and
remove redundant await when calling getClient(...).waitForTransactionReceipt({
hash: transactionHash }); reference the functions compactDeposit,
compactWithdraw, compactApprove, the transactionHash variable,
walletClient.writeContract, and getClient(...).waitForTransactionReceipt when
making the changes.
- Around line 14-15: Replace the loose any return types on the hook signatures
with a more specific side-effect type: change preHook?: (chainId: number) =>
Promise<any> and postHook?: () => Promise<any> to use Promise<void> (or
Promise<unknown> if you prefer unknown) so the hooks are clearly for side
effects; make the identical change to the same hook types declared for
compactWithdraw and compactApprove (ensure you update the signatures for preHook
and postHook in each of those functions/classes: preHook, postHook,
compactWithdraw, compactApprove).
In `@src/lib/libraries/intentExecution.ts`:
- Around line 167-192: The for-loop over components returns or throws on the
first iteration, so either remove the loop and operate on the first element (use
components[0] / orderComponent) if only the first component should be finalised,
or process all components by iterating and collecting the results (e.g., build
an array of walletClient.writeContract promises for each orderComponent, using
intent.inputSettler checks with MULTICHAIN_INPUT_SETTLER_ESCROW and
MULTICHAIN_INPUT_SETTLER_COMPACT, calling combineSignatures(signatures) where
needed) and await Promise.all, and ensure you do not throw inside the loop
(handle per-component errors or aggregate them and throw after the loop with
context including actionChain.id and failed components).
In `@src/lib/libraries/intentFactory.ts`:
- Around line 124-125: The hook signatures use `any`; change them to more
specific types (e.g., replace `preHook?: (chainId: number) => Promise<any>` with
`preHook?: (chainId: number) => Promise<void | unknown>` and `postHook?: () =>
Promise<any>` with `postHook?: () => Promise<void | unknown>` or simply
`Promise<void>` if no return value is expected) and apply the same replacement
in the constructor options type and the `escrowApprove` opts declarations
(update the corresponding types referenced in intentFactory.ts for the
constructor options and escrowApprove opts to use `Promise<void>` or
`Promise<unknown>` instead of `Promise<any>`).
🪄 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: e685f060-bab0-42d0-8636-3f83f11b415a
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (111)
.env.e2e.example.github/workflows/deploy.yml.github/workflows/test.yml.gitignore.lintstagedrc.json.prettierrcREADME.mddrizzle.config.tsdrizzle/0000_absent_moonstone.sqldrizzle/0000_brief_corsair.sqldrizzle/0001_nifty_mephisto.sqldrizzle/0002_expand_intent_created_at.sqldrizzle/0003_unique_intent_order_id.sqldrizzle/0004_store_transaction_receipts.sqldrizzle/meta/0000_snapshot.jsondrizzle/meta/0001_snapshot.jsondrizzle/meta/_journal.jsoneslint.config.jspackage.jsonplaywright.config.tssrc/app.d.tssrc/app.htmlsrc/lib/abi/compact.tssrc/lib/abi/erc20.tssrc/lib/abi/escrow.tssrc/lib/abi/multichain_compact.tssrc/lib/abi/multichain_escrow.tssrc/lib/abi/outputsettler.tssrc/lib/abi/polymeroracle.tssrc/lib/abi/settlercompact.tssrc/lib/abi/wormholeoracle.tssrc/lib/appTypes.tssrc/lib/components/AwaitButton.sveltesrc/lib/components/BalanceField.sveltesrc/lib/components/GetQuote.sveltesrc/lib/components/InputTokenModal.sveltesrc/lib/components/IntentListDetailRow.sveltesrc/lib/components/Introduction.sveltesrc/lib/components/OutputTokenModal.sveltesrc/lib/components/ui/ChainActionRow.sveltesrc/lib/components/ui/FieldRow.sveltesrc/lib/components/ui/FlowProgressList.sveltesrc/lib/components/ui/FlowStepTracker.sveltesrc/lib/components/ui/FormControl.sveltesrc/lib/components/ui/InlineMetaField.sveltesrc/lib/components/ui/ScreenFrame.sveltesrc/lib/components/ui/SectionCard.sveltesrc/lib/components/ui/SegmentedControl.sveltesrc/lib/components/ui/TokenAmountChip.sveltesrc/lib/config.tssrc/lib/db.tssrc/lib/libraries/assetSelection.tssrc/lib/libraries/compactLib.tssrc/lib/libraries/coreDeps.tssrc/lib/libraries/demoQuote.tssrc/lib/libraries/flowProgress.tssrc/lib/libraries/intent.tssrc/lib/libraries/intentExecution.tssrc/lib/libraries/intentFactory.tssrc/lib/libraries/intentList.tssrc/lib/libraries/orderServer.tssrc/lib/libraries/rpcCache.tssrc/lib/libraries/solver.tssrc/lib/libraries/token.tssrc/lib/migrations.jsonsrc/lib/schema.tssrc/lib/screens/ConnectWallet.sveltesrc/lib/screens/FillIntent.sveltesrc/lib/screens/Finalise.sveltesrc/lib/screens/IntentDescription.sveltesrc/lib/screens/IntentList.sveltesrc/lib/screens/IssueIntent.sveltesrc/lib/screens/ManageDeposit.sveltesrc/lib/screens/ReceiveMessage.sveltesrc/lib/state.svelte.tssrc/lib/utils/convert.tssrc/lib/utils/idLib.tssrc/lib/utils/intent.tssrc/lib/utils/interopableAddresses.tssrc/lib/utils/orderLib.tssrc/lib/utils/typedMessage.tssrc/lib/utils/wagmi.tssrc/lib/utils/walletClient.tssrc/lib/utils/walletClientRuntime.tssrc/lib/utils/web3-onboard.tssrc/routes/+layout.sveltesrc/routes/+page.sveltesrc/routes/allocator/+server.tssrc/routes/health/+server.tssrc/routes/polymer/+server.tssrc/routes/polymer/health/+server.tssrc/types/index.tssvelte.config.jstests/db.test.tstests/e2e/escrow-standard-blackbox.spec.tstests/e2e/escrow-standard-live.spec.tstests/e2e/helpers/bootstrap.tstests/e2e/issuance.spec.tstests/fixtures/mockQuote.tstests/fixtures/orderFixtures.tstests/unit/assetSelection.test.tstests/unit/demoQuote.test.tstests/unit/intentList.test.tstests/unit/orderLib.test.tstests/unit/orderServer.test.tstests/unit/orderValidationDeps.test.tstests/unit/recipientField.test.tstests/unit/walletClientSwitch.test.tstsconfig.jsonvite.config.tswrangler.toml
💤 Files with no reviewable changes (8)
- drizzle/0000_absent_moonstone.sql
- src/lib/libraries/intent.ts
- drizzle/meta/0001_snapshot.json
- src/lib/libraries/orderServer.ts
- drizzle/0002_expand_intent_created_at.sql
- drizzle/0003_unique_intent_order_id.sql
- drizzle/0004_store_transaction_receipts.sql
- drizzle/0001_nifty_mephisto.sql
🛑 Comments failed to post (14)
drizzle/0000_brief_corsair.sql (1)
1-8:
⚠️ Potential issue | 🔴 Critical | ⚡ Quick winRemove destructive table drops from the baseline migration.
Line 1-8 can irreversibly wipe persisted user data if this migration is replayed during upgrades. Baseline migrations should be non-destructive.
Suggested non-destructive adjustment
-DROP TABLE IF EXISTS "transaction_receipts"; ---> statement-breakpoint -DROP TABLE IF EXISTS "tokens"; ---> statement-breakpoint -DROP TABLE IF EXISTS "intents"; ---> statement-breakpoint -DROP TABLE IF EXISTS "fill_transactions"; ---> statement-breakpoint -CREATE TABLE "fill_transactions" ( +CREATE TABLE IF NOT EXISTS "fill_transactions" ( @@ -CREATE TABLE "intents" ( +CREATE TABLE IF NOT EXISTS "intents" ( @@ -CREATE TABLE "tokens" ( +CREATE TABLE IF NOT EXISTS "tokens" ( @@ -CREATE TABLE "transaction_receipts" ( +CREATE TABLE IF NOT EXISTS "transaction_receipts" (🤖 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 `@drizzle/0000_brief_corsair.sql` around lines 1 - 8, The baseline migration contains destructive DROP TABLE IF EXISTS statements for transaction_receipts, tokens, intents, and fill_transactions which can irreversibly delete persisted user data; remove those DROP statements from 0000_brief_corsair.sql and make the migration non-destructive by either replacing them with idempotent CREATE TABLE IF NOT EXISTS statements (or no-op existence checks) for transaction_receipts, tokens, intents, and fill_transactions, or move the DROP operations into a clearly labeled, separate destructive migration that requires explicit opt-in during upgrades.drizzle/meta/_journal.json (1)
4-12:
⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy liftDo not reset migration history to a new single baseline for persisted client databases.
Line 4-12 rewrites history to one new migration while
idb://ordersremains persistent. On upgrade paths, this can replay the baseline and, with the current SQL, drop/recreate user tables.A safer path is to preserve prior journal entries and append a forward-only migration, or explicitly version the client DB name and treat it as a deliberate reset.
🤖 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 `@drizzle/meta/_journal.json` around lines 4 - 12, The journal rewrite replaces previous migration history with a single baseline in _journal.json (the "entries" array with idx 0 and tag "0000_brief_corsair"), which will cause persistent client DBs like idb://orders to be replayed and tables dropped; instead preserve existing entries and append a forward-only migration entry (increment idx and set a new timestamp/tag) or, if you truly intend a reset, explicitly change the client DB name/version (e.g., bump the idb://orders namespace) so consumers know this is a deliberate reset rather than silently rewriting history.src/lib/abi/escrow.ts (1)
1231-1262:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove duplicated
FillDeadlineAfterExpiryABI error entry.
FillDeadlineAfterExpiryis declared twice (Line 1233 and Line 1249) with identical inputs. Keep a single definition to avoid ABI duplication noise and downstream confusion in interface/type generation.Suggested fix
- { - type: "error", - name: "FillDeadlineAfterExpiry", - inputs: [ - { - name: "fillDeadline", - type: "uint32", - internalType: "uint32" - }, - { - name: "expires", - type: "uint32", - internalType: "uint32" - } - ] - },📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.{ type: "error", name: "FillDeadlineAfterExpiry", inputs: [ { name: "fillDeadline", type: "uint32", internalType: "uint32" }, { name: "expires", type: "uint32", internalType: "uint32" } ] },🤖 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/lib/abi/escrow.ts` around lines 1231 - 1262, Remove the duplicated ABI error object for FillDeadlineAfterExpiry so only a single error definition remains; locate the two identical entries named "FillDeadlineAfterExpiry" in the ABI array and delete one of the objects (the one that repeats the same inputs: fillDeadline:uint32 and expires:uint32), leaving one canonical definition and ensuring no other duplicate error entries remain in the same exported ABI structure (e.g., the escrow ABI list).src/lib/components/BalanceField.svelte (1)
2-2:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove unused import.
The
toBigIntWithDecimalsimport is not used anywhere in this component. The component only displays the balance value that it receives as a prop.🧹 Proposed fix
<script lang="ts"> - import { toBigIntWithDecimals } from "`@lifi/intent`"; - let {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.<script lang="ts"> let {🧰 Tools
🪛 ESLint
[error] 2-2: 'toBigIntWithDecimals' is defined but never used.
(
@typescript-eslint/no-unused-vars)🤖 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/lib/components/BalanceField.svelte` at line 2, The import toBigIntWithDecimals from "`@lifi/intent`" in BalanceField.svelte is unused; remove the unused import to clean up the file and avoid lint warnings by deleting the line that imports toBigIntWithDecimals (the import statement referencing toBigIntWithDecimals) so the component only imports and uses props it needs.src/lib/components/Introduction.svelte (1)
7-11:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix user-facing copy typos/grammar in the intro text.
There are visible wording issues on Line 7 (“support” → “supports”), Line 38 (“transaction are” → “transactions are”), Line 76 (“configured different” → “configured differently”), and Line 77 (“Learm” → “Learn”).
Also applies to: 38-39, 75-77
🤖 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/lib/components/Introduction.svelte` around lines 7 - 11, The introduction copy in Introduction.svelte contains grammar and typos; update the text fragments so they read correctly: change "support" to "supports" in the sentence mentioning "resource lock flow", change "transaction are" to "transactions are", change "configured different" to "configured differently", and fix "Learm" to "Learn" wherever these exact strings appear in the component's markup so the displayed intro text is grammatically correct.src/lib/config.ts (2)
288-293:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winNative ETH has wrong decimals on arbitrumSepolia.
Native ETH should have 18 decimals, not 6. This will cause incorrect amount formatting and calculations for ETH on Arbitrum Sepolia.
🐛 Proposed fix
{ address: ADDRESS_ZERO, name: "eth", chainId: arbitrumSepolia.id, - decimals: 6 + decimals: 18 },📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.{ address: ADDRESS_ZERO, name: "eth", chainId: arbitrumSepolia.id, decimals: 18 },🤖 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/lib/config.ts` around lines 288 - 293, The native ETH entry in the token list currently sets decimals: 6 for the object with address: ADDRESS_ZERO, name: "eth", chainId: arbitrumSepolia.id; update that object's decimals value to 18 so native ETH on Arbitrum Sepolia uses 18 decimals (fix formatting/calculation errors) and ensure no other native-token entries for arbitrumSepolia still use 6.
491-497:
⚠️ Potential issue | 🔴 Critical | ⚡ Quick winPolygon client uses wrong chain configuration.
The polygon client is configured with
chain: baseinstead ofchain: polygon. This causes the client to use Base chain's context (chain ID, block explorer, etc.) while connecting to Polygon RPC endpoints, which will lead to incorrect transaction signing and chain ID mismatches.🐛 Proposed fix
polygon: createPublicClient({ - chain: base, + chain: polygon, transport: fallback([ http("https://polygon-bor-rpc.publicnode.com"), ...polygon.rpcUrls.default.http.map((v) => http(v)) ]) }),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.polygon: createPublicClient({ chain: polygon, transport: fallback([ http("https://polygon-bor-rpc.publicnode.com"), ...polygon.rpcUrls.default.http.map((v) => http(v)) ]) }),🤖 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/lib/config.ts` around lines 491 - 497, The polygon public client is mistakenly configured with chain: base; update the createPublicClient call that constructs polygon to use chain: polygon instead (replace chain: base with chain: polygon) so the polygon client uses the correct chain context (chain ID, explorers, etc.); locate the polygon variable/entry where createPublicClient is invoked and change the chain argument accordingly.src/lib/libraries/assetSelection.ts (1)
63-63:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid
Number(...)conversion in bigint sort comparators.Casting bigint differences to
numbercan lose precision for token-sized values and misorder assets, which breakslargest()/smallest()selection outcomes.Suggested fix
largest() { const values = AssetSelection.zip(this.values); - values.sort((a, b) => Number(b[0] - a[0])); + values.sort((a, b) => (b[0] > a[0] ? 1 : b[0] < a[0] ? -1 : 0)); AssetSelection.takeFromArray(this.goal, values); this.sortedValues = AssetSelection.unzip(values); return this; } smallest() { const values = AssetSelection.zip(this.values); - values.sort((a, b) => Number(a[0] - b[0])); + values.sort((a, b) => (a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0)); AssetSelection.takeFromArray(this.goal, values); this.sortedValues = AssetSelection.unzip(values); return this; }Also applies to: 73-73
🤖 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/lib/libraries/assetSelection.ts` at line 63, The comparator in the values.sort calls currently casts a bigint difference to Number (values.sort((a, b) => Number(b[0] - a[0]))) which can overflow and misorder large token amounts; replace the Number(...) conversion with a bigint-safe comparator that returns -1/0/1 based on comparing the bigint fields directly (e.g. compare b[0] and a[0] with conditional branches or by testing b[0] - a[0] > 0 / < 0) so sorting for largest()/smallest() works correctly; update both occurrences (the comparator at the shown values.sort lines) to use this bigint-safe comparison.src/lib/libraries/coreDeps.ts (2)
31-35:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winInconsistent address validation for
polymervswormhole.
polymeruses a simple truthy check whilewormholeusesisNonZeroAddress. IfPOLYMER_ORACLE[key]ever returns the zero address string"0x0000...", the truthy check passes and an invalid address gets pushed.Proposed fix for consistent validation
const polymer = POLYMER_ORACLE[key]; const wormhole = WORMHOLE_ORACLE[key]; const allowed: `0x${string}`[] = []; - if (polymer) allowed.push(polymer); + if (isNonZeroAddress(polymer)) allowed.push(polymer); if (isNonZeroAddress(wormhole)) allowed.push(wormhole);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const polymer = POLYMER_ORACLE[key]; const wormhole = WORMHOLE_ORACLE[key]; const allowed: `0x${string}`[] = []; if (isNonZeroAddress(polymer)) allowed.push(polymer); if (isNonZeroAddress(wormhole)) allowed.push(wormhole);🤖 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/lib/libraries/coreDeps.ts` around lines 31 - 35, The code inconsistently validates addresses: POLYMER_ORACLE[key] (variable polymer) is only checked for truthiness while WORMHOLE_ORACLE[key] uses isNonZeroAddress; change the polymer push to use the same validation by calling isNonZeroAddress(polymer) before allowed.push(polymer) so the zero address is rejected; update any related type assumptions if needed and keep the same allowed: `0x${string}`[] typing.
43-47:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winSame inconsistency in
allowedOutputOracles.Apply the same fix here for consistency.
Proposed fix
const polymer = POLYMER_ORACLE[key]; const wormhole = WORMHOLE_ORACLE[key]; const allowed: `0x${string}`[] = []; - if (polymer) allowed.push(polymer); + if (isNonZeroAddress(polymer)) allowed.push(polymer); if (isNonZeroAddress(wormhole)) allowed.push(wormhole);🤖 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/lib/libraries/coreDeps.ts` around lines 43 - 47, In allowedOutputOracles, the checks for oracle addresses are inconsistent: polymer is pushed on a simple truthy check while wormhole uses isNonZeroAddress; change the polymer check to use isNonZeroAddress as well so both POLYMER_ORACLE[key] and WORMHOLE_ORACLE[key] are validated the same way before pushing into the allowed array (refer to allowedOutputOracles, POLYMER_ORACLE, WORMHOLE_ORACLE, isNonZeroAddress, and the allowed variable).src/lib/libraries/flowProgress.ts (1)
157-168:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPotential out-of-bounds access on
flattenedInputs[0][0].Line 158 checks
flattenedInputs.length === 0but doesn't verify thatflattenedInputs[0]has elements. IfflattenedInputs[0]is an empty array, accessing[0][0]at line 167 will returnundefined, which may cause unexpected behavior when passed togetLockDetails.Proposed defensive check
const flattenedInputs = "originChainId" in order ? order.inputs : order.inputs[0]?.inputs; - if (!flattenedInputs || flattenedInputs.length === 0) return false; + if (!flattenedInputs || flattenedInputs.length === 0 || !flattenedInputs[0]?.[0]) return false;🤖 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/lib/libraries/flowProgress.ts` around lines 157 - 168, The code can access flattenedInputs[0][0] when flattenedInputs[0] is an empty array; update the check in the function that uses flattenedInputs (the block that calls inputChainClient.readContract with COMPACT and getLockDetails) to ensure the first nested array actually has an element before using [0][0] — either find the first non-empty entry in flattenedInputs (e.g., iterate flattenedInputs to pick the first sub-array with length>0) or add an explicit guard like if (!flattenedInputs[0] || flattenedInputs[0].length === 0) return false; so you never pass undefined into getLockDetails via inputChainClient.readContract.src/lib/libraries/intentExecution.ts (1)
29-32:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winInconsistent null-coalescing for signature payloads.
sponsorSignature.payloaduses?? "0x"fallback, butallocatorSignature.payloaddoesn't. IfallocatorSignature.payloadisundefined,encodeAbiParametersmay fail or produce unexpected results.Proposed fix
return encodeAbiParameters(parseAbiParameters(["bytes", "bytes"]), [ sponsorSignature.payload ?? "0x", - allocatorSignature.payload + allocatorSignature.payload ?? "0x" ]);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.return encodeAbiParameters(parseAbiParameters(["bytes", "bytes"]), [ sponsorSignature.payload ?? "0x", allocatorSignature.payload ?? "0x" ]);🤖 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/lib/libraries/intentExecution.ts` around lines 29 - 32, The ABI encoding call is inconsistent: sponsorSignature.payload is defaulted but allocatorSignature.payload is not; update the encodeAbiParameters call (using encodeAbiParameters and parseAbiParameters) to provide a safe fallback for allocatorSignature.payload as well (e.g., allocatorSignature.payload ?? "0x") so both signature payloads are always a hex string and avoid undefined being passed to encodeAbiParameters.src/lib/libraries/intentFactory.ts (2)
63-67:
⚠️ Potential issue | 🟠 Major | ⚡ Quick win🧩 Analysis chain
🏁 Script executed:
#!/bin/bash # Check how output.context is typically initialized and when it would be "0x" vs non-empty rg -n -B3 -A3 'context.*0x|\.context\s*=' --type=tsRepository: lifinance/lintent
Length of output: 3820
🏁 Script executed:
#!/bin/bash set -euo pipefail # Show surrounding code where output.context is modified sed -n '1,120p' src/lib/libraries/intentFactory.ts # Find where exclusivity override/newContext is computed or used rg -n "newContext|paddedExclusiveFor|SAME_CHAIN_EXCLUSIVITY_SECONDS|exclusiv" src/lib/libraries/intentFactory.ts src/lib/libraries/intentList.ts # Inspect context encoding/meaning in intentList sed -n '120,240p' src/lib/libraries/intentList.tsRepository: lifinance/lintent
Length of output: 10377
🏁 Script executed:
#!/bin/bash set -euo pipefail # Find where order outputs are created/mapped, focusing on context initialization rg -n "outputs\\b|outputTokens|context\\s*:" src/lib/libraries/intentFactory.ts # Show the sections around applyExclusivityOverride calls rg -n "applyExclusivityOverride\\(" -n src/lib/libraries/intentFactory.ts sed -n '140,320p' src/lib/libraries/intentFactory.ts # Check how intentFactory inputs map to order outputs (look for context usage) rg -n "TokenContext|outputTokens|context\\b" src/lib/libraries/intentFactory.ts # Search across src/lib for common context literals rg -n "context:\\s*\"0x(00)?\"|context:\\s*\"0x\"" src/lib -SRepository: lifinance/lintent
Length of output: 7333
🏁 Script executed:
#!/bin/bash set -euo pipefail # Find tests/fixtures referencing exclusivity context bytes or exclusiveFor behavior rg -n "exclusiveFor|exclusiveUntil|e0|e1|SAME_CHAIN_EXCLUSIVITY_SECONDS|0xe0|0xe1" src tests -S # Look specifically for context literals used in expected orders rg -n 'context:\s*"(0x|0x00)"' src tests -S # Inspect fixtures/orderFixtures and any helper that builds outputs with context ls -la tests/fixtures || true sed -n '1,120p' tests/fixtures/orderFixtures.ts # Find helper makeMandateOutput etc. to see what context they set rg -n "makeMandateOutput|make.*Output" tests -SRepository: lifinance/lintent
Length of output: 11170
🏁 Script executed:
#!/bin/bash set -euo pipefail # Search for IntentFactory usage in tests rg -n "new IntentFactory|IntentFactory\\b|applyExclusivityOverride\\b" tests src -S # Search for "context" assertions in tests related to intents/order outputs rg -n "output\\.?context|outputs\\s*\\[.*\\].*context|context\\s*:\\s*\"0x\"|context\\s*:\\s*\"0x00\"" tests -S # If any test targets intentFactory, inspect nearby lines rg -n "intentFactory\\.ts|intentFactory" tests -SRepository: lifinance/lintent
Length of output: 1023
🏁 Script executed:
#!/bin/bash set -euo pipefail sed -n '1,220p' tests/unit/intentList.test.ts sed -n '1,160p' tests/unit/orderValidationDeps.test.ts sed -n '1,120p' tests/fixtures/mockQuote.ts sed -n '1,120p' tests/unit/demoQuote.test.tsRepository: lifinance/lintent
Length of output: 8462
Exclusivity override doesn’t apply when
output.contextis exactly"0x"In
src/lib/libraries/intentFactory.ts(lines 63-67), this guard prevents the exclusivity context from being written for outputs whosecontextis"0x":for (const output of order.outputs) { if (output.context !== "0x") { output.context = newContext; } }Since this repo’s test/fixture orders use
context: "0x"for default (non-exclusive) outputs (tests/fixtures/orderFixtures.ts), this likely makes same-chainexclusiveForineffective in the common/default case; the condition is likely inverted (or should be unconditional) depending on the intended sentinel for “unset” context.🤖 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/lib/libraries/intentFactory.ts` around lines 63 - 67, The loop that sets exclusivity currently skips outputs whose output.context === "0x", so the exclusivity override never applies for the test-fixture sentinel; change the guard in the block that iterates order.outputs so that it replaces the sentinel instead of skipping it (i.e., set output.context = newContext when output.context === "0x", or alternatively remove the conditional to always assign if intended), targeting the loop that references order.outputs and the output.context/newContext variables so exclusivityFor is correctly applied.
231-235:
⚠️ Potential issue | 🟡 Minor | ⚡ Quick winStatic analysis:
transactionHashshould beconstandreceiptis unused.The linter correctly flags that
transactionHashis never reassigned (should useconst) andreceiptis assigned but never used.Proposed fix
- let transactionHash = await depositAndRegisterCompact(intent, account(), this.walletClient); + const transactionHash = await depositAndRegisterCompact(intent, account(), this.walletClient); - const receipt = await getClient(inputTokens[0].token.chainId).waitForTransactionReceipt({ + await getClient(inputTokens[0].token.chainId).waitForTransactionReceipt({ hash: transactionHash });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const transactionHash = await depositAndRegisterCompact(intent, account(), this.walletClient); await getClient(inputTokens[0].token.chainId).waitForTransactionReceipt({ hash: transactionHash });🧰 Tools
🪛 ESLint
[error] 231-231: 'transactionHash' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 233-233: 'receipt' is assigned a value but never used.
(
@typescript-eslint/no-unused-vars)🤖 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/lib/libraries/intentFactory.ts` around lines 231 - 235, Change transactionHash to a const since it is never reassigned (assign the result of depositAndRegisterCompact to const transactionHash) and remove the unused receipt variable created from getClient(...).waitForTransactionReceipt or, if the receipt is needed, use it; specifically update the code around the depositAndRegisterCompact call and the subsequent getClient(...).waitForTransactionReceipt call (which currently assigns to receipt) so that either the receipt line is deleted or its value is consumed, keeping symbols transactionHash, depositAndRegisterCompact, account(), this.walletClient, getClient, and inputTokens intact.
In 1:1 demo mode the quote request must not send metadata.exclusiveFor (the integrator key drives the 1:1 quote), but the on-chain intent must still be exclusive to the demo solver so it fills 1:1 via quick fallback. - demoQuote: demo mode returns exclusiveFor undefined (quote omits it) - IssueIntent: force DEMO_EXCLUSIVE_SOLVER on the order in demo mode - Update tests/comments accordingly Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🚀 Preview deployed! Worker: |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🚀 Preview deployed! Worker: |
Summary
Adds a "1:1 demo" toggle so the 1:1 stablecoin intent flow can be shown to partners/prospects with verifiable on-chain output, powered by LI.FI intents. When enabled, quote requests send the
X-Integrator-Keyheader and force order exclusivity to the LI.FI demo solver (0x94807fE4300D15909C1a4fd39f76c61D68aee11E) so it fills 1:1 via the solver's quick fallback. When off, behavior is unchanged.This branch is intended as the base for a polished Jumper-style UI built on top of it.
Linear: V2-207
Changes
@lifi/intentto 0.1.3 (addsintegratorKey→X-Integrator-Keyheader support ingetQuotes)use11Demo+integratorKeystate and a UI toggle + key field inIssueIntent.svelteGetQuote.sveltesends the header and forced exclusivity in demo moderesolveDemoQuoteParams()helper with unit testsDEMO_EXCLUSIVE_SOLVERinconfig.tsVerification
bun run check→ 0 errors, 0 warningsbun test tests/unit→ 28 pass, 0 failOut of scope
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Tests
Chores