Integrate new DEX aggregators, swappers, or bridge protocols (like Bebop, Portals, Jupiter, 0x, 1inch, etc.) into ShapeShift Web. Activates when user wants to add, integrate, or implement support for a new swapper. Guides through research, implementation, and testing following established patterns.
You are helping integrate a new DEX aggregator, swapper, or bridge into ShapeShift Web. This skill guides you through the complete process from research to testing.
Use this skill when the user wants to:
ShapeShift Web supports multiple swap aggregators through a unified swapper interface located in packages/swapper/src/swappers/. Each swapper follows consistent patterns, but has variations based on its type (EVM, Solana, cross-chain, gasless, etc.).
Your task: Research existing swappers to understand patterns, then adapt them for the new integration.
Before starting implementation, collect ALL required information from the user.
Use the AskUserQuestion tool to interactively gather this information with structured prompts.
Ask the user for:
API Documentation
.env.baseSupported Networks
API Behavior
Brand Assets
Reference Materials (helpful but optional)
Action: Stop and gather this information before proceeding. Missing details cause bugs later.
IMPORTANT: Don't guess at implementation details. Research thoroughly before coding.
Before looking at code, understand the swapper's API:
Read the official docs (link from Phase 1)
Study the Swagger/OpenAPI spec (if available)
Key things to verify:
Try making a test curl request if possible to see real responses.
Now that you understand the API, see how existing swappers work:
# List all existing swappers
ls packages/swapper/src/swappers/
You'll see swappers like:
Based on what you gathered in Phase 1, determine which swapper type yours is:
EVM Single-Hop (most common):
Gasless / Order-Based:
Solana-Only:
Cross-Chain / Multi-Hop:
Bridge-Specific:
Pick 2-3 similar swappers and read their implementations:
# Example: If building an EVM aggregator, study these:
@packages/swapper/src/swappers/BebopSwapper/BebopSwapper.ts
@packages/swapper/src/swappers/BebopSwapper/endpoints.ts
@packages/swapper/src/swappers/BebopSwapper/types.ts
@packages/swapper/src/swappers/BebopSwapper/INTEGRATION.md
@packages/swapper/src/swappers/ZrxSwapper/ZrxSwapper.ts
@packages/swapper/src/swappers/PortalsSwapper/PortalsSwapper.ts
Pay attention to:
Consult the skill's reference materials:
@reference.md - General swapper architecture and patterns@common-gotchas.md - Critical bugs to avoid@examples.md - Code templatesFollow the pattern established by similar swappers. Don't reinvent the wheel.
Create packages/swapper/src/swappers/[SwapperName]Swapper/
For most EVM swappers, create:
[SwapperName]Swapper/
├── index.ts
├── [SwapperName]Swapper.ts
├── endpoints.ts
├── types.ts
├── get[SwapperName]TradeQuote/
│ └── get[SwapperName]TradeQuote.ts
├── get[SwapperName]TradeRate/
│ └── get[SwapperName]TradeRate.ts
└── utils/
├── constants.ts
├── [swapperName]Service.ts
├── fetchFrom[SwapperName].ts
└── helpers/
└── helpers.ts
Check @examples.md for structure templates.
Order (follow this sequence):
types.ts: Define TypeScript interfaces based on API responsesutils/constants.ts: Supported chains, default slippage, native token markersutils/helpers/helpers.ts: Helper functions (validation, rate calculation)utils/[swapperName]Service.ts: HTTP service wrapperutils/fetchFrom[SwapperName].ts: API fetch functionsget[SwapperName]TradeQuote.ts: Quote logicget[SwapperName]TradeRate.ts: Rate logicendpoints.ts: Wire up SwapperApi interface[SwapperName]Swapper.ts: Main swapper classindex.ts: ExportsRefer to @examples.md for code templates. Copy patterns from similar existing swappers.
When is metadata needed?
When is metadata NOT needed?
If your swapper doesn't need async status polling or deposit addresses, skip this step!
Three places to add metadata:
a. Define types (packages/swapper/src/types.ts):
Add to TradeQuoteStep type:
export type TradeQuoteStep = {
// ... existing fields
[swapperName]Specific?: {
depositAddress: string
swapId: number
// ... other swapper-specific fields
}
}
Add to SwapperSpecificMetadata type (for swap storage):
export type SwapperSpecificMetadata = {
chainflipSwapId: number | undefined
nearIntentsSpecific?: {
depositAddress: string
depositMemo?: string
timeEstimate: number
deadline: string
}
// Add your swapper's metadata here
[swapperName]Specific?: {
// ... fields needed for status polling
}
// ... other fields
}
b. Populate in quote (packages/swapper/src/swappers/[Swapper]/swapperApi/getTradeQuote.ts):
Store metadata in the TradeQuoteStep:
const tradeQuote: TradeQuote = {
// ... other fields
steps: [{
// ... step fields
[swapperName]Specific: {
depositAddress: response.depositAddress,
swapId: response.id,
// ... other data needed later
}
}]
}
c. Extract into swap (TWO places required!):
Place 1: src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeButtonProps.tsx
Add to metadata object around line 114-126: