Skip to content
Merged
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
1 change: 1 addition & 0 deletions content/evm/_meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default {
title: 'Sei Global Wallet'
},
'building-a-frontend': 'Building a Frontend',
'in-app-swaps': 'In-App Swaps',

'-- Smart Contracts': {
type: 'separator',
Expand Down
213 changes: 213 additions & 0 deletions content/evm/in-app-swaps.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
---
title: 'In-App Swaps - Symphony Integration Guide'
description: 'Guide to integrating the Symphony swap widget into your Sei application for seamless token exchanges.'
keywords: ['swap widget', 'in-app swaps', 'token exchange', 'dex integration', 'symphony']
---

import { Callout, Tabs } from 'nextra/components';

# In-App Swaps Integration Guide

Integrating in-app swap functionality into your Sei application enables users to exchange tokens directly within your platform, enhancing user experience and engagement.

## Overview

Swap widgets are embeddable UI components that abstract the complexity of interacting with decentralized exchanges (DEXs) and liquidity aggregators. They provide:

- **Seamless UX**: Users can swap tokens without leaving your app
- **Reduced Friction**: No need to redirect users to external DEX interfaces
- **Revenue Opportunities**: Many providers offer fee-sharing mechanisms
- **Cross-Chain Support**: Some widgets enable bridging assets from other chains

## Symphony Swap Widget

[Symphony](https://symph.ag) is a native DEX aggregator on Sei, offering the simplest integration via iframe embedding.

### Quick Start

```html
<iframe src="https://symph.ag/embed"></iframe>
```

### Live Demo

<div style={{ display: 'flex', justifyContent: 'center' }}>
<iframe src="https://symph.ag/embed" style={{ width: '100%', maxWidth: '420px', minWidth: '377px', minHeight: '680px', border: 'none', borderRadius: '12px' }} title="Symphony Swap Widget Demo" />
</div>

### Size Requirements

- **Minimum Width**: `377px`
- **Minimum Height**: `650px` (recommended to prevent wallet modal scrolling)
- **Optimal Height**: `680-685px`

### URL Parameters

Customize the widget by appending query parameters:

#### Token Selection

| Parameter | Description | Example |
| ---------- | ----------------------------- | ----------------------------------------------------- |
| `tokenIn` | Input token contract address | `tokenIn=0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392` |
| `tokenOut` | Output token contract address | `tokenOut=0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7` |

<Callout type="info">Tokens can be changed by the user after the widget loads.</Callout>

#### Appearance

| Parameter | Description | Supported Formats |
| --------- | ------------------------- | -------------------------------------------------------------------------------------------- |
| `bgColor` | Background color | Hex (`%23FFFFFF`), Named (`white`), RGB (`rgb(255,255,255)`), RGBA (`rgba(255,255,255,0.9)`) |
| `theme` | Color theme of the widget | `light` or `dark` (defaults to `dark` if not specified) |

<Callout type="warning">For hex colors, use `%23` instead of `#` in the URL (e.g., `%23FFFFFF` for white).</Callout>

#### Features

| Parameter | Description | Values |
| --------------- | ---------------------------- | --------------------------- |
| `notifications` | Show/hide notification cards | `true` (default) or `false` |

### Complete Example

<Tabs items={['HTML', 'React', 'Next.js']}>
<Tabs.Tab>
```html
<iframe
src="https://symph.ag/embed?tokenIn=0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392&tokenOut=0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7&bgColor=white&theme=light&notifications=false"
style="width: 100%; min-height: 650px; border: none; border-radius: 12px;"
title="Symphony Swap Widget"
></iframe>
```
</Tabs.Tab>
<Tabs.Tab>
```jsx
function SwapWidget() {
const tokenIn = "0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392";
const tokenOut = "0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7";

return (
<iframe
src={`https://symph.ag/embed?tokenIn=${tokenIn}&tokenOut=${tokenOut}&theme=dark`}
style={{
width: '100%',
minHeight: '650px',
border: 'none',
borderRadius: '12px'
}}
title="Symphony Swap Widget"
/>
);
}
```
</Tabs.Tab>
<Tabs.Tab>
```tsx
'use client';

export default function SwapPage() {
const params = new URLSearchParams({
tokenIn: '0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392',
tokenOut: '0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7',
theme: 'dark',
notifications: 'true'
});

return (

<div className="max-w-md mx-auto">
<iframe src={`https://symph.ag/embed?${params.toString()}`} className="w-full min-h-[650px] border-0 rounded-xl" title="Symphony Swap" />
</div>
); }

````
</Tabs.Tab>
</Tabs>

### Popular Sei Token Addresses (Mainnet)

| Token | Address |
| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
| WSEI | [`0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7`](https://seiscan.io/address/0xE30feDd158A2e3b13e9badaeABaFc5516e95e8C7) |
| USDC (native) | [`0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392`](https://seiscan.io/address/0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392) |
| USDT0 | [`0x9151434b16b9763660705744891fA906F660EcC5`](https://seiscan.io/address/0x9151434b16b9763660705744891fA906F660EcC5) |

---

## Best Practices

### Security Considerations

<Callout type="warning">
**Security Checklist**

- ✅ Validate that iframe sources match official domains
- ✅ Implement Content Security Policy (CSP) headers
</Callout>

### Performance Optimization

```tsx
// Lazy load swap widgets to improve initial page load
import dynamic from 'next/dynamic';

const SwapWidget = dynamic(() => import('./SwapWidget'), {
loading: () => <div className="animate-pulse h-[650px] bg-gray-800 rounded-xl" />,
ssr: false
});
````

### Responsive Design

```css
/* Ensure swap widgets are responsive */
.swap-container {
width: 100%;
max-width: 420px;
margin: 0 auto;
}

.swap-container iframe {
width: 100%;
min-height: 650px;
border: none;
border-radius: 12px;
}

@media (max-width: 480px) {
.swap-container {
max-width: 100%;
padding: 0 16px;
}
}
```

### Error Handling

```tsx
import { useState } from 'react';

function SwapWidgetWithFallback() {
const [error, setError] = useState(false);

if (error) {
return (
<div className="p-6 bg-red-900/20 rounded-xl text-center">
<p>Swap widget failed to load.</p>
<a href="https://symph.ag" target="_blank" rel="noopener noreferrer" className="text-blue-400 underline">
Open Symphony directly →
</a>
</div>
);
}

return <iframe src="https://symph.ag/embed" onError={() => setError(true)} style={{ width: '100%', minHeight: '650px', border: 'none' }} title="Swap Widget" />;
}
```

---

## Additional Resources

- [Symphony Swap Widget Documentation](https://docs.symph.ag/widget/symphony-swap-widget)