Skip to content
Closed
Show file tree
Hide file tree
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
43 changes: 43 additions & 0 deletions .cursor/BUGBOT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Bugbot Review Rules

## Swap plugin conventions

### Shared Guards Required (`shared-guards-required`)

In a central swap plugin, `fetchSwapQuote` must call `checkInvalidTokenIds` from `src/util/swapHelpers.ts` (it carries the same-asset guard and the default invalid-token list), even with an empty plugin-specific map. Flag any plugin that skips it, and any token-identity check that matches on Edge currency code instead of contract address.

### Native Amount Rounding (`native-amount-rounding`)

Any `denominationToNative` result used in an order, limit, or quote must be rounded to integer atomic units (`round(x, 0)`). Provider amounts carry more decimals than asset denominations; a plain `mul` yields fractional native values.

### Error Classification (`error-classification`)

`SwapCurrencyError` is only for genuinely unsupported pairs. Flag code that maps auth failures, rate limits, region refusals, or 5xx responses into it, and flag the same provider error kind mapped differently across the estimate, exchange, and range paths.

### Per-Endpoint Auth (`per-endpoint-auth`)

Flag authenticated headers sent to provider endpoints that reject them (some public catalog endpoints return 401 for ANY `X-API-KEY` value). Credentials go only to endpoints that require them.

### Empty Memo Is Absent (`empty-memo-absent`)

An empty-string memo / extra-id from a provider must be treated as absent, never emitted as an `EdgeMemo`.

### Catalog Cache Expiry (`catalog-cache-expiry`)

Provider catalog caches (supported assets, rate types) need an expiry or re-fetch-on-miss path. Flag lifetime-of-the-plugin caching justified by "these do not change"; providers rename and relist assets.

## Error handling

### Typed Catch Clauses (`typed-catch`)

Use `catch (error: unknown)`, never a bare `catch (error)`.

## Known-good patterns (do not flag)

### Cleaners `asOptional` Accepts Null (`asoptional-accepts-null`)

`asOptional` in the `cleaners` library tests `raw == null`, which covers JSON `null` as well as a missing key; a `null` value cleans to `undefined` without throwing. Do not flag `asOptional(...)` fields as rejecting `null`.

### Raw Error Logging Follows The Template (`template-error-logging`)

Logging cleaned upstream error payloads in `fetchSwapQuoteInner` follows `src/swap/central/template.ts` (step 8 of `docs/CREATING_AN_EXCHANGE_PLUGIN.md`), the repo-wide convention. Flag only secrets or PII in logs, not the pattern itself.
30 changes: 30 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# AGENTS.md

Swap-plugin library for Edge: every provider integration (centralized in `src/swap/central/`, on-chain DeFi in `src/swap/defi/`) plus the chain/token mapping layer in `src/mappings/`. Consumed by `edge-react-gui`; clone as a peer to it for integration testing.

## Commands

| Task | Command |
|---|---|
| Install | `npm install && npm run prepare` |
| Full verification (prepare, lint, types, test) | `npm run verify` |
| Mapping fixtures | `npm run mapctl` (see `docs/CHAIN_MAPPING_SYNCHRONIZERS.md`) |

## Integration invariants

These fail silently or only under production traffic, and every one has caused review findings on past plugin PRs:

- New central plugins start from `src/swap/central/template.ts` and follow `docs/CREATING_AN_EXCHANGE_PLUGIN.md`. Read `docs/API_REQUIREMENTS.md` before writing code.
- Call the shared guards in `src/util/swapHelpers.ts`: `fetchSwapQuote` must run `checkInvalidTokenIds` (same-asset guard plus the default invalid-token list) even with an empty plugin-specific map, matching the sibling central plugins.
- Token identity resolves by CONTRACT ADDRESS, never by Edge currency code. A native asset (no Edge contract address) requires the provider side to also have none; a provider listing must never be matched on ticker alone.
- Round every `denominationToNative` result to integer atomic units (`round(x, 0)`) before it reaches an order, limit, or quote. Provider amounts carry arbitrary decimals.
- Map provider failures to the typed swap errors precisely: `SwapCurrencyError` means "this pair is genuinely unsupported", never a bucket for auth failures, rate limits, region refusals, or 5xx. Map the same provider error kind identically across the estimate, exchange, and range paths.
- Empty-string memo / extra-id from a provider is absent; never emit an empty `EdgeMemo`.
- Send credentials per endpoint, not globally: some provider endpoints reject requests that carry the API key. Verify each endpoint's auth expectation against the live API.
- Provider catalog caches (supported assets, rate types) need an expiry or re-fetch-on-miss path; providers rename and relist assets.

## Docs index

- `docs/CREATING_AN_EXCHANGE_PLUGIN.md`: the end-to-end plugin walkthrough; open when adding a provider.
- `docs/API_REQUIREMENTS.md`: what a provider's API must support before integration starts.
- `docs/CHAIN_MAPPING_SYNCHRONIZERS.md`: how `src/mappings/` fixtures are generated and refreshed.
Loading