Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 150 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,153 @@
# LI.FI Intent Demo

The LI.FI intent demo is hosted at lintent.org. It demonstrates the entire intent flow from resource lock mangement, intent issuance, and solving intents.

## Project

This project uses SvelteKit and `bun`. It is configured for a deployment to Cloudflare workers, to change the deployment target modify [/svelte.config.js](/svelte.config.js) with another [adapter](https://svelte.dev/docs/kit/adapters).

### Development

To start development:

1. Copy `.env.example` to `.env`.
2. Then fill in the `env` variables by creating a [WalletConnect](https://walletconnect.com) project
3. Also create an [account](https://accounts.polymerlabs.org/) with Polymer to generation [Polymer](https://polymerlabs.org) API keys.
4. Install dependencies `bun install`.
5. Start `bun run dev`.

### Testing

The project now uses a two-layer automated test suite:

1. Unit and integration tests with `bun test`
2. Browser UI-state tests with Playwright

Run:

- `bun run test:unit` for library/unit/integration tests with coverage output
- `bun run test:e2e` for deterministic browser tests
- `bun run test:all` to run both

For local Playwright setup:

1. `bun install`
2. `bunx playwright install chromium`

## Structure

Lintent is built around a single page [/src/routes/+page.svelte](/src/routes/+page.svelte).

The app consists of a series of screens that are displayed in a scrollable container. Each screen can be found in [/src/lib/screens/](/src/lib/screens/).

### Libraries

Several helper classes that acts as wrappers for external endpoints can be found in [/src/lib/libraries/](/src/lib/libraries/).
# Lintent

Lintent is LI.FI's interactive demo for the [Open Intents Framework (OIF)](https://openintents.xyz). It walks through the full cross-chain intent lifecycle, from resource lock management and intent issuance to solving, proof submission, and finalisation. The live app is hosted at [lintent.org](https://lintent.org).

The app handles both sides of an intent: the user (intent issuer) and the solver. Each step maps to a dedicated screen so you can follow the entire flow in sequence.

## Architecture

```mermaid
flowchart TD
subgraph Browser["Browser (SvelteKit SPA)"]
direction TB
Page["+page.svelte"]
S0["Connect Wallet"]
S1["Manage Deposit"]
S2["Issue Intent"]
S3["Intent List"]
S4["Fill Intent"]
S5["Receive Message"]
S6["Finalise"]

Store["Svelte 5 runes store\nbalances, allowances, orders"]
DB["PGlite via IndexedDB\nintents, fills, receipts"]

Page --> S0 & S1 & S2 & S3 & S4 & S5 & S6
Store --> DB
end

subgraph Worker["Cloudflare Worker"]
API_P["POST /polymer\nproof proxy"]
API_A["POST /allocator\nallocator proxy"]
API_H["GET /health"]
end

subgraph External["External Services"]
OS["LI.FI Order Server\nREST + WebSocket"]
POL["Polymer API\ncross-chain proofs"]
RPC["EVM RPC Nodes"]
end

subgraph Contracts["Smart Contracts"]
COMPACT["The Compact\nresource lock registry"]
ESC["Input Settler\nescrow + multichain"]
CSETT["Input Settler\ncompact + multichain"]
CF["CoinFiller\noutput settlement"]
PORACLE["Polymer Oracle\nproof verifier"]
end

S2 -->|"getQuotes / submitOrder"| OS
S3 -->|"WebSocket + REST"| OS
S4 -->|"fillOrderOutputs"| CF
S5 -->|"proof request"| API_P
S5 -->|"receiveMessage"| PORACLE
S5 -->|"setAttestation"| CF
S6 -->|"finalise"| ESC
S6 -->|"finalise"| CSETT
S1 -->|"deposit / withdraw"| COMPACT
S2 -->|"open escrow"| ESC
S2 -->|"sign compact"| COMPACT
API_P -->|"requestProof / queryProof"| POL
API_A -->|"attestCommit"| POL
Store -->|"balance / allowance reads"| RPC
```

## Intent Lifecycle

The app exposes six sequential screens, each representing one step in the OIF flow.

- **Connect Wallet** connects via Web3-Onboard (injected wallets, Coinbase, WalletConnect, Zeal)
- **Manage Deposit** lets you choose between escrow and compact locking, then deposit or withdraw tokens from The Compact
- **Issue Intent** configures the intent (input/output tokens, chains, amounts, verifier), fetches a quote from the LI.FI order server, and submits the order on-chain (escrow) or via EIP-712 signature (compact)
- **Intent List** shows open intents from the order server WebSocket and local DB, with the option to import by on-chain order ID
- **Fill Intent** is the solver side, where output tokens are delivered to recipients via the CoinFiller contract on each output chain
- **Receive Message** fetches a cross-chain proof from Polymer and submits it to the Polymer Oracle on the source chain (or calls `setAttestation` for same-chain fills)
- **Finalise** calls `finalise()` on the appropriate input settler, releasing the locked input tokens to the solver

## Tech Stack

- **Framework** SvelteKit 2 with Svelte 5 runes
- **Language** TypeScript
- **Styling** Tailwind CSS v4
- **EVM** viem ~2.45
- **Wallet** Web3-Onboard
- **Local DB** PGlite (WASM Postgres) + Drizzle ORM, persisted to IndexedDB
- **Deployment** Cloudflare Workers via `@sveltejs/adapter-cloudflare`
- **Runtime** Bun
- **Testing** Bun test (unit/integration) and Playwright (E2E)

## Supported Chains

**Mainnet** Ethereum, Base, Arbitrum, Polygon, BSC, MegaETH, Katana

**Testnet** Sepolia, Base Sepolia, Arbitrum Sepolia, Optimism Sepolia

## Smart Contracts

The app interacts with the following deployed contracts (ABIs are inlined in `src/lib/abi/`).

| Contract | Purpose |
|---|---|
| The Compact | ERC-6909 resource lock registry for compact-based intents |
| Input Settler (Escrow) | Opens and finalises escrow-based intents (single-chain and multichain variants) |
| Input Settler (Compact) | Finalises compact-based intents using combined sponsor and allocator signatures |
| CoinFiller | Output settlement where solvers deliver tokens, also handles same-chain attestations |
| Polymer Oracle | Verifies cross-chain fill proofs submitted via Polymer |

## Project Structure

```
src/
lib/
abi/ # contract ABIs (Compact, Escrow, CoinFiller, Polymer Oracle, etc.)
libraries/ # core logic (Intent, IntentFactory, OrderServer, Solver, CompactLib)
screens/ # SvelteKit components for each step in the flow
utils/ # helpers (EIP-712 typed data, order validation, address encoding)
config.ts # contract addresses, chain config, token lists, RPC clients
state.svelte.ts # global reactive store (Svelte 5 runes)
db.ts # PGlite + Drizzle init with IndexedDB persistence
schema.ts # Drizzle table definitions
routes/
+page.svelte # single-page entry point (renders all six screens)
polymer/ # server route proxying to Polymer API
allocator/ # server route proxying to Polymer Allocator
health/ # liveness check
tests/
unit/ # order validation, intent list, order server parsing, asset selection
e2e/ # Playwright browser tests for issuance flow
db.test.ts # PGlite integration test
```

## Getting Started

1. Copy `.env.example` to `.env`
2. Create a [WalletConnect](https://walletconnect.com) project and add the project ID
3. Create an account with [Polymer](https://accounts.polymerlabs.org/) and generate API keys for mainnet and testnet
4. Install dependencies with `bun install`
5. Start the dev server with `bun run dev`

## Testing

- `bun run test:unit` runs library and unit tests with coverage
- `bun run test:e2e` runs Playwright browser tests (requires `bunx playwright install chromium`)
- `bun run test:all` runs both suites

## Deployment

Production deploys happen on push to `main` via GitHub Actions. The workflow builds with Bun and deploys to the `lintent-worker` Cloudflare Worker. PR preview environments are created and cleaned up automatically.

Required secrets for CI: `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID`, `PRIVATE_POLYMER_MAINNET_ZONE_API_KEY`, `PRIVATE_POLYMER_TESTNET_ZONE_API_KEY`, `PUBLIC_WALLET_CONNECT_PROJECT_ID`.

## License

This project is licensed under the **[MIT License](/LICENSE)**. Any contributions to this repository is provided with a MIT License.
This project is licensed under the [MIT License](/LICENSE).
Loading