# Blockend Labs

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

Web3 is fragmented, with hundreds of chains creating isolated pools of liquidity. Users struggle with multiple dexes, complex bridges, and scattered liquidity. \
\
**BlockEnd Labs** builds infrastructure to unify and simplify crypto liquidity across multiple blockchain networks, enabling seamless cross-chain transactions.\
\
*Two Products, One Mission:*  To become the central nervous system of all crypto liquidity.\
\ <img src="https://a.slack-edge.com/production-standard-emoji-assets/14.0/apple-medium/0031-fe0f-20e3@2x.png" alt=":one:" data-size="line">  **COMPASS** (Live with 80+ Chains)

*Enables one-click transactions across any chain, simplifying the user experience.*\
\
A web3 GPS for dApps. Onboard users from any chain or token without leaving your platform. Aggregates all existing liquidity, including bridges, DEXes, RFQ, and intent protocols, transforming complex cross-chain, multi-step transactions into one-click actions.\
\
Compass is a cross-chain liquidity aggregator  that enables seamless token transfers across 80+ blockchains. By aggregating liquidity from multiple sources including DEXs, bridges, aggregators, and intent protocols, Compass finds the optimal path for users to move assets between chains.

Whether you're building a DeFi protocol, NFT marketplace, or Web3 platform, Compass can be integrated through our widget (single line of code), APIs, or SDK to enable cross-chain functionality without users ever leaving your application. When a user needs to pay with a token from one chain but your application requires a different token on another chain, Compass handles the entire routing and bridging process automatically.

Currently supports all major EVM chains, Cosmos chains, and Solana, with built-in wallet adapters and optimized routing to ensure the best rates and fastest transaction times for your users.<br>

#### [Integrate Compass Widget in One Line of Code](/compass/compass-widget)  [Use our API for Comprehensive Integrations](/compass/api-v1-overview)  <br>

<img src="https://a.slack-edge.com/production-standard-emoji-assets/14.0/apple-medium/0032-fe0f-20e3@2x.png" alt=":two:" data-size="line"> **LEX** (In Development)\
\
A Liquidity Engine bringing instant capital to underserved chains and enabling efficient liquidity for protocols to build on top of.\
\
A TransferWise-like liquidity engine for crypto, bringing instant capital to underserved chains. Uses micro liquidity pools, Coincidence of Wants, Intelligent rebalancing, and USDC-pegged stable-coins.\
Built on the *Solana Virtual Machine* for high throughput, scalable, and efficient cross-chain transactions.\ <br>


# API v1 Overview

Compass is a cross-chain liquidity aggregation protocol enabling seamless token transfers across 80+ blockchains. This documentation covers the core API endpoints for executing cross-chain transaction

[![Run In Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/25193308-9db7ddc1-c22f-44f1-bcc4-badae4796dfb?action=collection%2Ffork\&source=rip_markdown\&collection-url=entityId%3D25193308-9db7ddc1-c22f-44f1-bcc4-badae4796dfb%26entityType%3Dcollection%26workspaceId%3D996072e7-23dc-4dc5-abe3-a4351f3abba1)

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

### Getting Started <a href="#getting-started" id="getting-started"></a>

Base URL `https://api2.blockend.com/v1/` \
All type definitions can be found [here](/compass/type-definations)

### Core Transaction Flow

#### 1. Fetching quotes <a href="#id-1.-fetching-quotes" id="id-1.-fetching-quotes"></a>

User flow begins with fetching quotes, which returns a list of quotes for the given input and output assets, along with the steps involved in the transaction. Quotes are by default sorted via best output and contains a scores object and tags to determine fastest/cheapest/best output routes.

[Get Quotes Documentation](/compass/fetching-quotes)

#### 2. Creating a transaction <a href="#id-2.-creating-a-transaction" id="id-2.-creating-a-transaction"></a>

After fetching quotes, you can create a transaction using the selected quote by passing in the `routeId` of the quote.

[Create Transaction Documentation](/compass/create-transaction)

#### 3. Getting transaction data to execute <a href="#id-3.-getting-transaction-data-to-execute" id="id-3.-getting-transaction-data-to-execute"></a>

Call this api with `routeId` and `stepId` of individual steps to get the transaction data to execute.

[Get Transaction Data Documentation](/compass/getting-transaction-data-to-execute)

#### 4. Check status of a transaction <a href="#id-4.-check-status-of-a-transaction" id="id-4.-check-status-of-a-transaction"></a>

After user signs and submits the transaction on chain, check the status of the transaction by passing in the signature hash of the transaction.

[Check Transaction Status Documentation](/compass/check-transaction-status)

#### 5. Using WebSockets for realtime updates (in active development) <a href="#id-5.-using-websockets-for-realtime-updates" id="id-5.-using-websockets-for-realtime-updates"></a>

You can also check the status of a transaction using WebSockets. This can provide faster and almost realtime updates on the status of a transaction.

> Note: this feature is in active development and will be generally available soon. Contact us to get access to this feature.

#### 6. Single  API for simple flow execution (in active development) <a href="#meta-endpoints" id="meta-endpoints"></a>

A simple 1 step endpoint is being worked on where a request directly gives you a single quote in response along with array of transaction data to execute to complete the transaction&#x20;

> Note: this feature is in active development and will be generally available soon. Contact us to get access to this feature.

### Meta Endpoints <a href="#meta-endpoints" id="meta-endpoints"></a>

#### [Tokens](/compass/supported-tokens) <a href="#tokens" id="tokens"></a>

Get a list of supported tokens and their details.

```
curl -X GET "https://api2.blockend.com/v1/tokens"
```

#### [Chains](/compass/supported-chains) <a href="#chains" id="chains"></a>

Get a list of supported chains and their details.

```
curl -X GET "https://api2.blockend.com/v1/chains"
```


# Rate Limits and Authentication

### &#x20;<a href="#rate-limiting" id="rate-limiting"></a>

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

### Rate Limiting <a href="#rate-limiting" id="rate-limiting"></a>

Without authentication:  20 requests per minute\
With authentication: 200 requests per minute

### Authentication <a href="#authentication" id="authentication"></a>

While Compass API can be accessed without authentication, it is recommended to authenticate to get access to more features and higher rate limits.

To authenticate, you need to pass in the api-key in the request header.

```
const headers = {
    'x-api-key': 'YOUR_API_KEY'
};

fetch('https://api2.blockend.com/v1/tokens', { headers })
    .then(response => response.json())
    .then(data => console.log(data));
```

```
curl -X GET "https://api2.blockend.com/v1/tokens" \
    -H "x-api-key: YOUR_API_KEY"
```


# Fetching Quotes

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

Flow of a transaction starts with fetching quotes for it.

### Endpoint: `GET /quotes`&#x20;

```url
/quotes
    ?fromChainId=
    &fromAssetAddress=
    &toChainId=
    &toAssetAddress=
    &inputAmountDisplay=
    &userWalletAddress=
    &recipient=
```

### Query params <a href="#example" id="example"></a>

<table><thead><tr><th width="221">Field</th><th width="143">Type</th><th>Description</th></tr></thead><tbody><tr><td>fromChainId*</td><td>string</td><td>Source blockchain identifier</td></tr><tr><td>fromAssetAddress*</td><td>string</td><td>Token address on source chain</td></tr><tr><td>toChainId*</td><td>string</td><td>Destination blockchain identifier</td></tr><tr><td>toAssetAddress*</td><td>string</td><td>Token address on destination chain</td></tr><tr><td>inputAmountDisplay*</td><td>string</td><td>Human-readable input amount (e.g., “1.5”) <br><strong>Note:</strong> Either inputAmountDisplay or inputAmount should be passed</td></tr><tr><td>inputAmount*</td><td>string</td><td>Input amount in decimals units<br><strong>Note:</strong> Either inputAmountDisplay or inputAmount should be passed</td></tr><tr><td>userWalletAddress*</td><td>string</td><td>User’s wallet address</td></tr><tr><td>recipient</td><td>string</td><td>Final recipient of the tokens. If not provided userWalletAddress is used by default </td></tr><tr><td>slippage</td><td>number</td><td>Slippage tolerance in basis points (100 = 1%)</td></tr><tr><td>solanaOptions</td><td>SolanaOptions</td><td>Solana-specific parameters</td></tr><tr><td>evmOptions</td><td>EvmOptions</td><td>EVM-specific parameters</td></tr><tr><td>skipChecks</td><td>boolean</td><td>Skip validation checks</td></tr><tr><td>include</td><td>string</td><td>Comma-separated list of providers to include</td></tr><tr><td>exclude</td><td>string</td><td>Comma-separated list of providers to exclude</td></tr><tr><td>recommendedProvider</td><td>boolean</td><td>Use only recommended providers</td></tr></tbody></table>

**Solana Options**

<table><thead><tr><th width="187">Field</th><th width="198">Type</th><th>Description</th></tr></thead><tbody><tr><td>solanaPriorityFee</td><td>number | PriorityLevel</td><td>Priority fee in micro lamports or priority level</td></tr><tr><td>solanaJitoTip</td><td>number | PriorityLevel</td><td>Jito MEV tip in lamports or priority level</td></tr></tbody></table>

**Evm Options**

<table><thead><tr><th width="185">Field</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>evmPriorityFee</td><td>number | PriorityLevel</td><td>Priority fee in wei or priority level</td></tr></tbody></table>

```typescript
PriorityLevel = 'low' | 'medium' | 'high' | 'ultra' | 'degen'
```

### Response <a href="#example" id="example"></a>

A Route represents a complete path for token transfer, including all necessary steps and fee information.

<table><thead><tr><th width="243">Field</th><th width="146">Type</th><th>Description</th></tr></thead><tbody><tr><td>requestId</td><td>string</td><td>Unique identifier for the quote request</td></tr><tr><td>routeId</td><td>string</td><td>Unique identifier for this specific route</td></tr><tr><td>from</td><td>Asset</td><td>Source token details including chain and token information</td></tr><tr><td>to</td><td>Asset</td><td>Destination token details</td></tr><tr><td>steps</td><td>Steps[]</td><td>Array of execution steps (approval, swap, bridge, etc.)</td></tr><tr><td>fee</td><td>Fee[]</td><td>Breakdown of all fees involved</td></tr><tr><td>provider</td><td>Providers</td><td>Liquidity provider identifier</td></tr><tr><td>providerDetails</td><td>ProviderDetails</td><td>Additional provider information</td></tr><tr><td>protocolsUsed</td><td>string[]</td><td>List of protocols used in this route</td></tr><tr><td>inputAmount</td><td>string</td><td>Input amount in wei/native units</td></tr><tr><td>inputAmountDisplay</td><td>string</td><td>Human-readable input amount</td></tr><tr><td>outputAmount</td><td>string</td><td>Expected output in wei/native units</td></tr><tr><td>outputAmountDisplay</td><td>string</td><td>Human-readable output amount</td></tr><tr><td>minOutputAmount</td><td>string</td><td>Minimum output amount after slippage</td></tr><tr><td>minOutputAmountDisplay</td><td>string</td><td>Human-readable minimum output</td></tr><tr><td>slippage</td><td>number</td><td>Applied slippage tolerance in basis points</td></tr><tr><td>userWalletAddress</td><td>string</td><td>User's wallet address</td></tr><tr><td>recipient</td><td>string</td><td>Final recipient address</td></tr><tr><td>createdAt</td><td>number</td><td>Unix timestamp of quote creation</td></tr><tr><td>deadline</td><td>number</td><td>Unix timestamp when quote expires</td></tr><tr><td>estimatedTimeInSeconds</td><td>number</td><td>Estimated execution time</td></tr><tr><td>tags</td><td>string[]</td><td>Route classification tags</td></tr></tbody></table>

### Example <a href="#example" id="example"></a>

The following example shows how to get quotes for a cross-chain swap transaction from Ethereum to Solana. We'll be fetching quotes for ETH on Ethereum to USDC on Solana.

**Request:**

```url
https://api2.blockend.com/v1/quotes
    ?fromChainId=1
    &fromAssetAddress=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
    &toChainId=sol
    &toAssetAddress=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
    &inputAmountDisplay=0.420
    &userWalletAddress=0x17e7c3DD600529F34eFA1310f00996709FfA8d5c
    &recipient=7zSa114U45nJ8b8ALsuhszS2Kxto8grgedh65Q7xJYii
```

**Response:**

```json
{
    "status": "success",
    "data": {
        "quotes": [
            {
                "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
                "from": {
                    "networkType": "evm",
                    "chainId": "1",
                    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                    "decimals": 18,
                    "name": "Ethereum",
                    "symbol": "ETH",
                    "isNative": true,
                    "isPopular": true,
                    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                    "priceId": "ethereum",
                    "blockchain": "Ethereum",
                    "lastPrice": 3480.62
                },
                "to": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Solana",
                    "decimals": 6,
                    "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                    "networkType": "sol",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "sol",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "steps": [
                    {
                        "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
                        "stepType": "bridge",
                        "protocolsUsed": [
                            "Auction"
                        ],
                        "provider": "mayan",
                        "from": {
                            "networkType": "evm",
                            "chainId": "1",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Ethereum",
                            "symbol": "ETH",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                            "priceId": "ethereum",
                            "blockchain": "Ethereum",
                            "lastPrice": 3480.62
                        },
                        "to": {
                            "symbol": "USDC",
                            "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                            "priceId": "usd-coin",
                            "blockchain": "Solana",
                            "decimals": 6,
                            "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                            "networkType": "sol",
                            "isNative": false,
                            "isPopular": false,
                            "chainId": "sol",
                            "name": "USDC",
                            "lastPrice": 1.002
                        },
                        "fee": [
                            {
                                "token": {
                                    "networkType": "evm",
                                    "chainId": "1",
                                    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                                    "decimals": 18,
                                    "name": "Ethereum",
                                    "symbol": "ETH",
                                    "isNative": true,
                                    "isPopular": true,
                                    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                                    "priceId": "ethereum",
                                    "blockchain": "Ethereum",
                                    "lastPrice": 3480.62
                                },
                                "amount": "1380475027400000",
                                "amountInEther": "1380475027400000",
                                "amountInUSD": "4.804908989868988",
                                "type": "network"
                            }
                        ],
                        "inputAmount": "420000000000000000",
                        "outputAmount": "1459244847",
                        "estimatedTimeInSeconds": 900
                    }
                ],
                "fee": [
                    {
                        "token": {
                            "networkType": "evm",
                            "chainId": "1",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Ethereum",
                            "symbol": "ETH",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                            "priceId": "ethereum",
                            "blockchain": "Ethereum",
                            "lastPrice": 3480.62
                        },
                        "amount": "1380475027400000",
                        "amountInEther": "1380475027400000",
                        "amountInUSD": "4.804908989868988",
                        "type": "network"
                    }
                ],
                "provider": "mayan",
                "providerDetails": {
                    "id": "mayan",
                    "name": "Mayan",
                    "logoUrl": "https://blockend-widget.s3.ap-south-1.amazonaws.com/mayan.svg",
                    "websiteUrl": "https://mayan.finance/"
                },
                "protocolsUsed": [
                    "Auction"
                ],
                "inputAmount": "420000000000000000",
                "inputAmountDisplay": "0.420",
                "outputAmount": "1459244847",
                "outputAmountDisplay": "1459.244847",
                "minOutputAmount": "1459.098923",
                "minOutputAmountDisplay": "1459.098923",
                "slippage": 0,
                "recipient": "7zSa114U45nJ8b8ALsuhszS2Kxto8grgedh65Q7xJYii",
                "createdAt": 1721085515718,
                "deadline": 60,
                "estimatedTimeInSeconds": 900,
                "requestId": "01J2WB1K2D769PJRBMPNX1SKJT",
                "score": {
                    "outputScore": 1,
                    "speedScore": 0.0011111111111111111,
                    "feeScore": 1,
                    "slipparageScore": 0,
                    "stepScore": 1,
                    "outputDiffPercent": 0
                },
                "tags": [
                    "BEST_OUTPUT",
                    "CHEAP"
                ]
            },
            {
                "routeId": "01J2WB1MX7ZDHNB71GH3R52189",
                "from": {
                    "networkType": "evm",
                    "chainId": "1",
                    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                    "decimals": 18,
                    "name": "Ethereum",
                    "symbol": "ETH",
                    "isNative": true,
                    "isPopular": true,
                    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                    "priceId": "ethereum",
                    "blockchain": "Ethereum",
                    "lastPrice": 3480.62
                },
                "to": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Solana",
                    "decimals": 6,
                    "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                    "networkType": "sol",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "sol",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "steps": [
                    {
                        "stepId": "01J2WB1MX7BJA7ZSN8K4KXF1VA",
                        "stepType": "bridge",
                        "protocolsUsed": [
                            "deBridge"
                        ],
                        "provider": "dln",
                        "from": {
                            "networkType": "evm",
                            "chainId": "1",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Ethereum",
                            "symbol": "ETH",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                            "priceId": "ethereum",
                            "blockchain": "Ethereum",
                            "lastPrice": 3480.62
                        },
                        "to": {
                            "symbol": "USDC",
                            "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                            "priceId": "usd-coin",
                            "blockchain": "Solana",
                            "decimals": 6,
                            "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                            "networkType": "sol",
                            "isNative": false,
                            "isPopular": false,
                            "chainId": "sol",
                            "name": "USDC",
                            "lastPrice": 1.002
                        },
                        "fee": [
                            {
                                "type": "network",
                                "token": {
                                    "networkType": "evm",
                                    "chainId": "1",
                                    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                                    "decimals": 18,
                                    "name": "Ethereum",
                                    "symbol": "ETH",
                                    "isNative": true,
                                    "isPopular": true,
                                    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                                    "priceId": "ethereum",
                                    "blockchain": "Ethereum",
                                    "lastPrice": 3480.62
                                },
                                "amount": "5141425082200000",
                                "amountInEther": "5141425082200000",
                                "amountInUSD": "17.895346969606965"
                            }
                        ],
                        "inputAmount": "420000000000000000",
                        "outputAmount": "1449243299",
                        "estimatedTimeInSeconds": 1
                    }
                ],
                "fee": [
                    {
                        "type": "network",
                        "token": {
                            "networkType": "evm",
                            "chainId": "1",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Ethereum",
                            "symbol": "ETH",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                            "priceId": "ethereum",
                            "blockchain": "Ethereum",
                            "lastPrice": 3480.62
                        },
                        "amount": "5141425082200000",
                        "amountInEther": "5141425082200000",
                        "amountInUSD": "17.895346969606965"
                    }
                ],
                "provider": "dln",
                "providerDetails": {
                    "id": "dln",
                    "name": "DLN",
                    "logoUrl": "https://dln.trade/assets/images/favicon/apple-touch-icon.png",
                    "websiteUrl": "https://dln.trade/"
                },
                "protocolsUsed": [
                    "deBridge"
                ],
                "inputAmount": "420000000000000000",
                "inputAmountDisplay": "0.420",
                "outputAmount": "1449243299",
                "outputAmountDisplay": "1449.243299",
                "minOutputAmount": "1449.243299",
                "minOutputAmountDisplay": "1449.243299",
                "slippage": 0.3,
                "recipient": "7zSa114U45nJ8b8ALsuhszS2Kxto8grgedh65Q7xJYii",
                "createdAt": 1721085514664,
                "deadline": 30,
                "estimatedTimeInSeconds": 1,
                "requestId": "01J2WB1K2D769PJRBMPNX1SKJT",
                "score": {
                    "outputScore": 0.9932454038279075,
                    "speedScore": 1,
                    "feeScore": 0.26850046540195793,
                    "slipparageScore": 0,
                    "stepScore": 1,
                    "outputDiffPercent": 0.00677748576178394
                },
                "tags": [
                    "BEST",
                    "FAST"
                ]
            }
        ]
    }
}
```


# Create Transaction

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

Once user selects a quote fetched from `/quotes` api, start the transaction by sending a request to `/createTx` api with the `routeId` of the selected quote. Response will contain updated steps for the transaction. These updated steps include any additional steps required to complete the transaction such as, but not limited to, ERC20 approvals.

### Endpoint: `GET /createTx`&#x20;

### Query params

```
/createTx?
    routeId=
```

### Response

```typescript
{
    "steps": Steps[];
}
```

### Example <a href="#exmaple" id="exmaple"></a>

Continuing example from `/quotes` api, let's start the transaction by sending a request to `/createTx` api with the `routeId` of the selected quote.

**Request:**

```
https://api2.bloclend.com/v1/createTx
    ?routeId=01J2WB2ZTWAWXN9K48899CSSVN
```

**Response:** The response for the selected quote now contains 2 steps. Additonal step being the approval step for USDC on Polygon chain.

```json
{
    "status": "success",
    "data": {
        "routeId": "01J2WB2ZTWAWXN9K48899CSSVN",
        "steps": [
            {
                "stepId": "01J2WB3JEB34B0A1SXHT1E3B63",
                "protocolsUsed": [
                    "Blockend"
                ],
                "stepType": "approval",
                "from": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Polygon",
                    "decimals": 6,
                    "address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
                    "networkType": "evm",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "137",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "to": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Polygon",
                    "decimals": 6,
                    "address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
                    "networkType": "evm",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "137",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "inputAmount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
                "outputAmount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
                "fee": [
                    {
                        "type": "network",
                        "token": {
                            "networkType": "evm",
                            "chainId": "137",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Matic",
                            "symbol": "MATIC",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
                            "priceId": "matic-network",
                            "blockchain": "Polygon",
                            "lastPrice": 0.546532
                        },
                        "amount": "1800000001440000",
                        "amountInEther": "1800000001440000",
                        "amountInUSD": "0.0009837576007870061"
                    }
                ]
            },
            {
                "stepId": "01J2WB2ZTWXW6D39KJN7AAB3VV",
                "stepType": "bridge",
                "protocolsUsed": [
                    "deBridge"
                ],
                "provider": "dln",
                "from": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Polygon",
                    "decimals": 6,
                    "address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
                    "networkType": "evm",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "137",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "to": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Solana",
                    "decimals": 6,
                    "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                    "networkType": "sol",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "sol",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "fee": [
                    {
                        "type": "network",
                        "token": {
                            "networkType": "evm",
                            "chainId": "137",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Matic",
                            "symbol": "MATIC",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
                            "priceId": "matic-network",
                            "blockchain": "Polygon",
                            "lastPrice": 0.546483
                        },
                        "amount": "518000000014400000",
                        "amountInEther": "518000000014400000",
                        "amountInUSD": "0.28307819400786943"
                    }
                ],
                "inputAmount": "3000000",
                "outputAmount": "1523800",
                "estimatedTimeInSeconds": 1
            }
        ]
    }
}
```


# Getting transaction data to execute

The TxnData type combines transaction metadata with network-specific transaction details for different blockchain networks (EVM, Solana, Cosmos, Tron)

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

Call this api with `routeId` and `stepId` of individual steps to get the transaction data to execute. Once the transaction is executed, check the status of the transaction using `/status` api and proceed to the next step of the transaction.

> Note: you can ignore status check and skip to next step of the txn if `skipTxn` field is set to `true` in the response. Also, when `skipTxn` is set to `true`, `txnData` will be `null`.

### Endpoint: `GET /nextTx`&#x20;

### Query params

```
/nextTx?
    routeId=
    &stepId=
```

### Response

```typescript
{
    routeId: string;
    stepId: string;
    txnData: TxnData | null;
    skipTxn?: boolean;
}
```

<table><thead><tr><th width="184">Field</th><th width="172">Type</th><th>Description</th></tr></thead><tbody><tr><td>requestId</td><td>string</td><td>Associated request identifier</td></tr><tr><td>routeId</td><td>string</td><td>Associated route identifier</td></tr><tr><td>stepId</td><td>string</td><td>Current step identifier</td></tr><tr><td>networkType</td><td>NetworkType</td><td>Blockchain network type</td></tr><tr><td>deadline</td><td>number</td><td>Transaction expiration timestamp</td></tr><tr><td>skipTxn</td><td>boolean</td><td>This step's associated txn can be skipped</td></tr><tr><td>txnEvm</td><td>TxnEvm | null</td><td>Either of one is present depending on network type</td></tr><tr><td>txnSol</td><td>TxnSol | null</td><td></td></tr><tr><td>txnTron</td><td>TxnTron | null</td><td></td></tr><tr><td>txnCosmos</td><td>TxnCosmos | null</td><td></td></tr></tbody></table>

Network-Specific Transaction Data:

EVM Transaction (TxnEvm)

| Field    | Type   | Required | Description                  |
| -------- | ------ | -------- | ---------------------------- |
| from     | string | No       | Sender address               |
| to       | string | Yes      | Recipient contract/address   |
| value    | string | No       | Native token amount (in wei) |
| data     | string | No       | Transaction calldata         |
| gasPrice | string | No       | Gas price in wei             |
| gasLimit | string | No       | Maximum gas limit            |

Solana Transaction (TxnSol)

| Field | Type   | Required | Description              |
| ----- | ------ | -------- | ------------------------ |
| data  | string | Yes      | Encoded transaction data |

Cosmos Transaction (TxnCosmos)

| Field        | Type   | Required | Description              |
| ------------ | ------ | -------- | ------------------------ |
| data         | string | Yes      | Transaction data         |
| value        | string | Yes      | Transaction value        |
| gasLimit     | string | Yes      | Gas limit                |
| gasPrice     | string | Yes      | Gas price                |
| maxFeePerGas | string | Yes      | Maximum fee per gas unit |

Tron Transaction (txnTron)

| Field          | Type    | Required | Description            |
| -------------- | ------- | -------- | ---------------------- |
| raw\_data      | any     | No       | Raw transaction data   |
| raw\_data\_dex | string  | No       | DEX-specific data      |
| txID           | string  | Yes      | Transaction ID         |
| visible        | boolean | Yes      | Transaction visibility |

### Example <a href="#example" id="example"></a>

Lets now fetch the transaction data for the first step of the transaction we created in `/createTx` api.

**Request:**

```
https://api2.blockend.com/v1/nextTx
    ?routeId=01J2WB2ZTWAWXN9K48899CSSVN
    &stepId=01J2WB3JEB34B0A1SXHT1E3B63
```

**Response:** As the

```json
{
    "status": "success",
    "data": {
        "routeId": "01J2WB2ZTWAWXN9K48899CSSVN",
        "stepId": "01J2WB3JEB34B0A1SXHT1E3B63",
        "txnData": {
            "id": "01J2WD2YRTT6AN4450NKX9H1WB",
            "routeId": "01J2WB2ZTWAWXN9K48899CSSVN",
            "stepId": "01J2WB3JEB34B0A1SXHT1E3B63",
            "isCompleted": false,
            "networkType": "evm",
            "txnEvm": {
                "from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
                "to": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
                "data": "0x095ea7b3000000000000000000000000ef4fb24ad0916217251f553c0596f8edc630eb66ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
                "gasPrice": "30000000030",
                "gasLimit": 56167
            },
            "createdAt": 1721087654682,
            "status": "not-started",
            "fetchedAt": 1721087654682,
            "requestId": "01J2WB2ZBWNW0M0CJEYV415HPZ"
        }
    }
}
```


# Check transaction status

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

After user signs and submits the transaction on chain, check the status of the transaction by passing in the signature hash of the transaction. You need to keep polling this api to get the `status` of the transaction. Once the status response is `success`, you can proceed to the next step of the transaction (if any).

### Endpoint: `GET /status`&#x20;

### Query params

```
/status?
    routeId=
    &stepId=
    &txnHash=
```

### Response:

```typescript
{
    routeId: string;
    stepId: string;
    status: TxnStatus;
    srcTxnHash?: string;
    srcTxnUrl?: string;
    destTxnHash?: string;
    destTxnUrl?: string;
    points?: number;
}
```

### Example <a href="#example" id="example"></a>

Now, let check the status of the transaction we fetched in the previous step.

**Request:**

```url
https://api2.blockend.com/v1/status
    ?routeId=01J2WB2ZTWAWXN9K48899CSSVN
    &stepId=01J2WB3JEB34B0A1SXHT1E3B63
    &txnHash=0x3d7bdcfac0062b3c9ae1e4045bc43600c2c55c560dde7eebd2a15afb5ba1c390
```

**Response:**

```json
{
    "status": "success",
    "data": {
        "routeId": "01J2WB2ZTWAWXN9K48899CSSVN",
        "stepId": "01J2WB3JEB34B0A1SXHT1E3B63",
        "status": "success",
        "srcTxnHash": "0x3d7bdcfac0062b3c9ae1e4045bc43600c2c55c560dde7eebd2a15afb5ba1c390",
        "srcTxnUrl": "https://polygonscan.com/tx/0x3d7bdcfac0062b3c9ae1e4045bc43600c2c55c560dde7eebd2a15afb5ba1c390"
    }
}
```


# Supported Tokens

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

Blockend Widget supports a whole array of token which would be difficult to list here, so we have built a handy API just for that

```
curl -X GET "https://api2.blockend.com/v1/tokens" \
  -H "accept: application/json"
```

You can also pass `chainId` as query parameter to get tokens for a specific chain

```
curl -X GET "https://api2.blockend.com/v1/tokens?chainId=sol" \
  -H "accept: application/json"
```


# Liquidity Sources

###

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

### Dexes

* [Jupiter](https://jup.ag/)
* [0x](https://0x.org/)
* [1Inch](https://1inch.io/)
* [Paraswap](https://paraswap.io/)
* [ODOS](https://www.odos.xyz/)
* [Virtuals](https://www.virtuals.io/)
* [Pump.fun](https://pump.fun/)

### Bridges

* [Mayan Finance](https://mayan.finance/)
* [DLN (deBridge)](https://dln.trade/)
* [LiFi](https://li.fi/)
* [Socket](https://socket.tech/)
* [Squid Router](https://www.squidrouter.com/)
* [LayerSwap](https://layerswap.io/)
* [Across](https://across.to/)


# Supported Chains

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

You can get list of supported chains from the following endpoint

```
curl -X GET "https://api2.blockend.com/v1/chains" \
  -H "accept: application/json"
```

### List of chains supported

<table><thead><tr><th width="106">Sr. No</th><th>Chain Name</th><th>Chain ID</th></tr></thead><tbody><tr><td>1</td><td>Ethereum</td><td>1</td></tr><tr><td>2</td><td>Solana</td><td>sol</td></tr><tr><td>3</td><td>BSC</td><td>56</td></tr><tr><td>4</td><td>Base</td><td>8453</td></tr><tr><td>5</td><td>Arbitrum</td><td>42161</td></tr><tr><td>6</td><td>Avalanche</td><td>43114</td></tr><tr><td>7</td><td>Polygon</td><td>137</td></tr><tr><td>8</td><td>Optimism</td><td>10</td></tr><tr><td>9</td><td>Cronos</td><td>25</td></tr><tr><td>10</td><td>Blast</td><td>81457</td></tr><tr><td>11</td><td>Mantle</td><td>5000</td></tr><tr><td>12</td><td>Linea</td><td>59144</td></tr><tr><td>13</td><td>dYdX</td><td>dydx-mainnet-1</td></tr><tr><td>14</td><td>Gnosis</td><td>100</td></tr><tr><td>15</td><td>Scroll</td><td>534352</td></tr><tr><td>16</td><td>Rootstock</td><td>30</td></tr><tr><td>17</td><td>Sei</td><td>pacific-1</td></tr><tr><td>18</td><td>Mode</td><td>34443</td></tr><tr><td>19</td><td>Osmosis</td><td>osmosis-1</td></tr><tr><td>20</td><td>CELO</td><td>42220</td></tr><tr><td>21</td><td>Fantom</td><td>250</td></tr><tr><td>22</td><td>zkSync Era</td><td>324</td></tr><tr><td>23</td><td>Neutron</td><td>neutron-1</td></tr><tr><td>24</td><td>Injective</td><td>injective-1</td></tr><tr><td>25</td><td>Kujira</td><td>kaiyo-1</td></tr><tr><td>26</td><td>Aurora</td><td>1313161554</td></tr><tr><td>27</td><td>Moonbeam</td><td>1284</td></tr><tr><td>28</td><td>Secret</td><td>secret-4</td></tr><tr><td>29</td><td>Polygon zkEVM</td><td>1101</td></tr><tr><td>30</td><td>Moonriver</td><td>1285</td></tr><tr><td>31</td><td>Dymension</td><td>dymension_1100-1</td></tr><tr><td>32</td><td>Carbon</td><td>carbon-1</td></tr><tr><td>33</td><td>Harmony</td><td>1666600000</td></tr><tr><td>34</td><td>Archway</td><td>archway-1</td></tr><tr><td>35</td><td>Boba</td><td>288</td></tr><tr><td>36</td><td>OKXChain</td><td>66</td></tr><tr><td>37</td><td>Cosmos Hub</td><td>cosmoshub-4</td></tr><tr><td>38</td><td>Fuse</td><td>122</td></tr><tr><td>39</td><td>Terra Classic</td><td>columbus-5</td></tr><tr><td>40</td><td>Heco</td><td>128</td></tr><tr><td>41</td><td>Evmos</td><td>9001</td></tr><tr><td>42</td><td>Chihuahua</td><td>chihuahua-1</td></tr><tr><td>43</td><td>Juno</td><td>juno-1</td></tr><tr><td>44</td><td>Migaloo</td><td>migaloo-1</td></tr><tr><td>45</td><td>Nolus</td><td>pirin-1</td></tr><tr><td>46</td><td>Nibiru</td><td>cataclysm-1</td></tr><tr><td>47</td><td>Stargaze</td><td>stargaze-1</td></tr><tr><td>48</td><td>Comdex</td><td>comdex-1</td></tr><tr><td>49</td><td>Crescent</td><td>crescent-1</td></tr><tr><td>50</td><td>Agoric</td><td>agoric-3</td></tr><tr><td>51</td><td>Akash</td><td>akashnet-2</td></tr><tr><td>52</td><td>AssetMantle</td><td>mantle-1</td></tr><tr><td>53</td><td>Axelar</td><td>axelar-dojo-1</td></tr><tr><td>54</td><td>BandChain</td><td>band-laozi-mainnet1</td></tr><tr><td>55</td><td>BitCanna</td><td>bitcanna-1</td></tr><tr><td>56</td><td>BitSong</td><td>bitsong-2b</td></tr><tr><td>57</td><td>Celestia</td><td>celestia</td></tr><tr><td>58</td><td>Chain4Energy</td><td>perun-1</td></tr><tr><td>59</td><td>Cheqd</td><td>cheqd-mainnet-1</td></tr><tr><td>60</td><td>Coreum</td><td>coreum-mainnet-1</td></tr><tr><td>61</td><td>Decentr</td><td>mainnet-3</td></tr><tr><td>62</td><td>Desmos</td><td>desmos-mainnet</td></tr><tr><td>63</td><td>Gravity Bridge</td><td>gravity-bridge-3</td></tr><tr><td>64</td><td>Humans.ai</td><td>humans_1089-1</td></tr><tr><td>65</td><td>IRISnet</td><td>irishub-1</td></tr><tr><td>66</td><td>Impacts Hub</td><td>ixo-5</td></tr><tr><td>67</td><td>Jackal</td><td>jackal-1</td></tr><tr><td>68</td><td>Kava IBC</td><td>kava_2222-10</td></tr><tr><td>69</td><td>Lava</td><td>lava-mainnet-1</td></tr><tr><td>70</td><td>LikeCoin</td><td>likecoin-mainnet-2</td></tr><tr><td>71</td><td>Lum Network</td><td>lum-network-1</td></tr><tr><td>72</td><td>Mars Hub</td><td>mars-1</td></tr><tr><td>73</td><td>Noble</td><td>noble-1</td></tr><tr><td>74</td><td>OmniFlix</td><td>omniflixhub-1</td></tr><tr><td>75</td><td>Persistence</td><td>core-1</td></tr><tr><td>76</td><td>Quasar</td><td>quasar-1</td></tr><tr><td>77</td><td>Quicksilver</td><td>quicksilver-2</td></tr><tr><td>78</td><td>Regen</td><td>regen-1</td></tr><tr><td>79</td><td>Saga</td><td>ssc-1</td></tr><tr><td>80</td><td>Sentinel</td><td>sentinelhub-2</td></tr><tr><td>81</td><td>Sommelier</td><td>sommelier-3</td></tr><tr><td>82</td><td>Stride</td><td>stride-1</td></tr><tr><td>83</td><td>Teritori</td><td>teritori-1</td></tr><tr><td>84</td><td>Umee</td><td>umee-1</td></tr></tbody></table>


# Type Definations

###

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

### Basic Types

```typescript
type NetworkType = "evm" | "sol" | "cosmos" | "tron";

type Asset = {
  networkType?: NetworkType;
  chainId: string;
  address: string;
  decimals: number;

  symbol: string;
  name?: string;
  isNative?: boolean;
  isPopular?: boolean;
  image?: string;

  blockchain: string;
  lastPrice: number;
  marketCap?: number;
};

type Chain = {
  chainId: string;
  symbol: string;
  name: string;
  networkType: NetworkType;

  image: string;
  isPopular?: boolean;
  isEnabled: boolean;

  explorer: {
    token: string; // https://polygonscan.com/token/{tokenAddress}
    txn: string; // https://polygonscan.com/tx/{txnHash}
    address?: string; // https://polygonscan.com/address/{address}
  };
  rpcUrls: string[];
  tokenCount: number;
};

enum FeeType {
  NETWORK = "NETWORK", // gas fee
  PROVIDER = "PROVIDER", // fee charged by the provider
  BLOCKEND = "BLOCKEND", // fee charged by blockend
  INTEGRATOR = "INTEGRATOR", // custom fee someone want to charge via blockend integration
};

enum FeeSource {
  FROM_SOURCE_WALLET = "FROM_SOURCE_WALLET",
  FROM_OUTPUT_AMOUNT = "FROM_OUTPUT_AMOUNT",
  FROM_INPUT_AMOUNT = "FROM_INPUT_AMOUNT",
};

type Fee = {
  type: FeeType;
  token: Asset;
  source: FeeSource;
  amountInToken: string;
  amountInUSD: number | string;
};

type ProviderDetails = {
  name: string;
  logoUrl: string;
};

type StepType = "approval" | "swap" | "bridge" | "sign" | "claim";
type TxnStatus = "not-started" | "in-progress" | "success" | "failed" | "cancelled";
```

### Quote Request

```typescript
type QuoteRequest = {
  fromChainId: string; // chainId of the asset to swap from
  fromAssetAddress: string; // address of the asset to swap from

  toChainId: string; // chainId of the asset to swap to
  toAssetAddress: string; // address of the asset to swap to

  // send either inputAmountDisplay or inputAmount
  inputAmountDisplay: string; // 3.2
  inputAmount: string; // 3.2*10^18

  userWalletAddress: string; // address of the user who will perform the swap
  recipient?: string; // address of the recipient (in case recipient is different)
  
  slippage: number; // in bps, 100bps = 1%
  solanaOptions?: SolanaOptions;
  evmOptions?: EvmOptions;
  skipChecks?: boolean;
};

type QuoteResponse = {
  quotes: Routes[];
};

export type Route = {
  requestId?: string;
  routeId: string;

  from: Asset;
  to: Asset;
  steps: Steps[];
  fee: Fee[];

  provider: Providers;
  providerDetails: ProviderDetails;
  protocolsUsed: string[];

  inputAmount: string; // 3.2*10^18
  inputAmountDisplay: string; // 3.2

  outputAmount: string; // 4.56*10^18
  outputAmountDisplay: string; // 4.56
  minOutputAmount: string; // 4.32*10^18
  minOutputAmountDisplay?: string; // 4.32
  slippage: number;

  userWalletAddress: string;
  recipient?: string;

  createdAt: number; // time when quote is created
  deadline: number; // deadline (in seconds) for quote to be used
  estimatedTimeInSeconds: number;
  tags?: string[];
};

type Steps = {
  stepId: string;
  stepType: StepType;
  protocolsUsed: string[];
  provider?: Providers;

  from: Asset;
  to: Asset;
  txnHash?: string;
  status?: TxnStatus;

  inputAmount: string;
  outputAmount: string;
  fee: Fee[];
  estimatedTimeInSeconds?: number;
};
```

### Create a transaction

```typescript
type CreateTxnRequest = {
  routeId: string;
};

type CreateTxnResponse = {
  routeId: string;
  steps: Steps[];
};
```

### Transaction Data

```typescript
type NextTxnRequest = {
  routeId: string;
  stepId: string;
};

type NextTxnResponse = {
  routeId: string;
  stepId: string;
  txnData: TxnData | null;
  skipTxn?: boolean;
};

type TxnData = TxnMetaData & {
  txnEvm?: TxnEvm;
  txnSol?: TxnSol;
  txnTron?: TxnTron;
  txnCosmos?: TxnCosmos;
};

type TxnEvm = {
  from: string | null;
  to: string;
  value?: string | null;
  data?: string | null;

  gasPrice?: string | null;
  gasLimit?: string | null;
};

type TxnSol = {
  data: string;
};

type TxnTron = {
  raw_data?: any | null;
  raw_data_dex?: string | null;
  txID: string;
  visible: boolean;
};

type TxnCosmos = {
  data: string; 
  value: string;
  gasLimit: string;
  gasPrice: string;
  maxFeePerGas: string;
};

type TxnMetaData = {
  requestId: string;
  routeId: string;
  stepId: string;
  networkType: NetworkType;

  deadline?: number;
  skipTxn?: boolean;
};
```

### Check status of a transaction

```typescript
type StatusCheckRequest = {
  routeId: string;
  stepId: string;
  txnHash: string;
};

type StatusCheckResponse = {
  routeId: string;
  stepId: string;
  status: TxnStatus;
  srcTxnHash?: string;
  srcTxnUrl?: string;
  destTxnHash?: string;
  destTxnUrl?: string;
  points?: number;
};
```


# Compass Widget

{% hint style="danger" %}
This is an outdated version of our documentation.

Please visit the latest version at <https://docs.blockend.com/> for up-to-date and accurate information.
{% endhint %}

```sh
npm install blockend
```

**yarn:**

```sh
yarn add blockend
```

## Getting started with Blockend Widget

Integrating widget to your dapp or webiste is very easy. It takes a full 3 line of code to integrate and start using Blockend Widget, now that's a lot of work for a human dev.

### 1. Import Widget dependencies

In your react app, start by importing the Blockend Widget and its styles

```jsx
import Blockend from "blockend";
import "blockend/dist/main.css";
```

You may encounter Server Error... ReferenceError: self is not defined in your Next JS app, this is because blockend requires web apis to work and the web apis are not available on the server side when next js renders a page, in order to avoid this you can start by importing the Blockend Widget like below

```jsx
import dynamic from "next/dynamic";
const Blockend = dynamic(() => import("blockend"), {
  ssr: false,
});
import "blockend/dist/main.css";
```

### 2. Initialize the Widget

Add the widget component to your app

```jsx
<Blockend />
```

### Integrator Id (Required)

Unique identifier assigned to each integration partner. It is used to track and manage various integrations within our system.Error will be thrown if this field is empty.

```jsx
const configuration = {
  integratorId:""
  ...
};
<Blockend  configuration={configuration} />
```

This id will be added in the request header of api calls that is made by the widget.

And that is it, you have successfully integrated the Blockend Widget.

### 3. (optional) Customizing the Widget

As an optional step, you can also customize the look and feel of the widget. This can be done by passing a configuration object as prop when initializing the widget.

```jsx
const configuration = {
    gradientStyle: {
    background: "linear-gradient(#E66465, #9198E5)",
    spinnerColor: "#E66465",
    stopColor: "#9198E5",
  },
  containerStyle:{
    background:"#000000",
    border:"1px solid #fff",
    boxShadow:"1px 1px 7px 5px rgb(255,255,255,0.1)" ,
  },
  theme:"light",
  customTheme: {
    text: {
      primary: "#808080",
      secondary: "rgba(128, 128, 128, 0.75)",
      placeholder: "#cccccc",
      success: "#49AD71",
      error: "#FD5868",
    },
    background: {
      container: "#FFFFFF",
      secondary: "#E9E9E9",
      card:"#FFFFFF",
      networkCard: "#F6F6F6",
      loaderbar: "#E9E9E9",
      coin:"#E0E0E0",
      rewards:"#eaeaeb33"
    },
    border: {
      primary: "#E0E0E0",
      inputHighlight: "#9FC966",
    },
    fontFamily:'"micro 5 charted"', sans-serif, lato;
    shadow: {
      boxShadow: "1px 1px 7px 5px rgb(255,255,255,0.1)",
    },
  },
};

<Blockend configuration={configuration} />;
```

Full list of configuration options can be found [here](#configuration-options)

## Configuration Options

### Customizing gradient colors

You can customize the gradient colors of the widget by passing `gradientStyle` object in configuration.

```jsx
const configuration = {
  gradientStyle: {
    background: "linear-gradient(#E66465, #9198E5)",
    spinnerColor: "#E66465",
    stopColor: "#9198E5",
  },
  ...
};
```

You can customize the theme of the widget by passing `customTheme` object in configuration.

```jsx
const configuration = {
  // containerStyle will override the styles written for the widget container, containerStyle accepts all the inline style properties.
  containerStyle:{
    background:"#000000", // changes the background color of the widget to black
    border:"1px solid #fff", //adds border to the widget container
    boxShadow:"1px 1px 7px 5px rgb(255,255,255,0.1)" // for adding desired shadow effect to the container.
  },
  theme:"light",  // light or dark, if custom theme is applied then custom theme will override light/dark theme
  customTheme: {
    text: {
      primary: "#808080", // primary color of the theme, this applies to headings, main text, svgs, etc..,
      secondary: "rgba(128, 128, 128, 0.75)",  //secondary color of the theme, this applies to secondary headings, network names, route info ,etc..,
      placeholder: "#cccccc",// to update  placeholder colors like input placeholder,date picker heading etc.,
      success: "#49AD71", // view all routes Higher output color
      error: "#FD5868", // error messages and lower output.
    },
    background: {
      container: "#FFFFFF", // can be used to update the bg color of the widget container, input amount container and routes container.
      secondary: "#E9E9E9", // can be used to update the table cell background on portfolio page.
      card:"#FFFFFF", //can be used to update the card color of the widget
      networkCard: "#F6F6F6", // used as background color for top main networks cards and transaction hash container in tokens section.
      loaderbar: "#E9E9E9", // loader bar color accross the widget.
      coin:"#E0E0E0", // used to update th default background color of the coin and chain icons.
      rewards:"#eaeaeb33" // can be used to update the rewards section background color on history page
    },
    border: {
      primary: "#E0E0E0",// primary border color of the widget, can be used to update the container border,border of coin and chain icons, cards border of the widget.
      inputHighlight: "#9FC966", //inputHighlight is used to update the border color of search tokens input field on select chains page when there are more than 0 results.
    },
    fontFamily:'"micro 5 charted"', sans-serif, lato; // can be used to update the font family of the widget to match the parent site, add the fonts to your site and just pass the font name to the widget.
    shadow: {
      boxShadow: "1px 1px 7px 5px rgb(255,255,255,0.1)", // to add shadow effect to the container and cards.
    },
  },
};
```

### Setting Default Chains and Tokens

Widget gives you the option to set default chains and tokens to be shown to the user. This can be done by passing `defaultChains` and `defaultTokens` in configuration when initializing the widget.\
See list of [supported chains](#supported-chains) and [tokens](#supported-tokens) below.

```jsx
const configuration = {
  defaultChains: {
    from: { chainId: "10" }, // optimism
    to: { chainId: "sol" }, // solana
  },
  defaultTokens: {
    from: { tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" }, // eth on optimism
    to: { tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }, // usdc on solana
  },
  ...
};
```

> Note: token address for native tokens is set to 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

<br>

Here is what a integration of widget on your frontend might look like:

```jsx
import Blockend from "blockend";
import "blockend/dist/main.css";

const configuration = {
  gradientStyle: {
    background: "linear-gradient(#e66465, #9198e5)",
    spinnerColor: "#e66465",
    stopColor: "#9198e5",
  },
  defaultChains: {
    from: { chainId: "10" }, // optimism
    to: { chainId: "sol" }, // solana
  },
  defaultTokens: {
    from: { tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" }, // eth on optimism
    to: { tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }, // usdc on solana
  },
};

export const Home = () => {
  return <Blockend configuration={configuration} />;
};
```

## Supported Chains

| Chain         | Chain Id   |
| ------------- | ---------- |
| Solana        | sol        |
| Ethereum      | 1          |
| Optimism      | 10         |
| BSC           | 56         |
| Polygon       | 137        |
| FUSE          | 122        |
| Gnosis        | 100        |
| Fantom        | 250        |
| Base          | 8453       |
| Arbitrum      | 42161      |
| zkSync Era    | 324        |
| Polygon zkEVM | 1101       |
| Avalanche     | 43114      |
| Boba          | 288        |
| OKXChain      | 66         |
| Moonbeam      | 1284       |
| Moonriver     | 1285       |
| Cronos        | 25         |
| Heco          | 128        |
| Aurora        | 1313161554 |
| Harmony       | 1666600000 |
| Evmos         | 9001       |

## Supported Tokens

Blockend Widget supports a whole array of token which would be difficult to list here, so we have built a handy API just for that

```bash
curl -X GET "https://api.blockend.com/v1/tokens" \
  -H "accept: application/json"
```

<br>

You can also pass `chainId` as query parameter to get tokens for a specific chain

```bash
curl -X GET "https://api.blockend.com/v1/tokens?chainId=sol" \
  -H "accept: application/json"
```

<br>

You can also get list of supported chains by calling the following endpoint

```bash
curl -X GET "https://api.blockend.com/v1/chains" \
  -H "accept: application/json"
```


# Overview

**BlockEnd** makes value transfer across web3 simple, fast, and scalable with two products and one mission:

**One Web3: any token, any chain, no barriers.**

***

## :compass: COMPASS (Live on 140+ Chains)

Compass is a liquidity Super-Aggregator that unifies every Web3 liquidity source including DEXs, Bridges, RFQs, Intent Protocols and more, into a single reliable layer.

* **Onboard More Users, Reduce Drop-Offs**\
  Enable users to pay with any token across all chains and start using your dApp instantly.\
  Install our Custom Widgets in your Frontend with one line of code.

{% content-ref url="/pages/CNUb9FXtQ5otfHVTjHVM" %}
[Compass Widgets](/compass-widgets/widget-pro)
{% endcontent-ref %}

* **Execute Complex Transactions With Best Execution**\
  Build Disruptive AI-Agents, Payments, DeFi or Consumer Apps with Instant & optimized liquidity.\
  Integrate our Comprehensive API/SDK to unlock the full power of Web3 liquidity.

{% content-ref url="/pages/MOcEIQFGNJVxLQbuFyDV" %}
[Compass API](/compass-api/api-reference)
{% endcontent-ref %}

#### Dive Deeper:

{% content-ref url="/pages/6hz90pdWMWaLHW68NSNh" %}
[Compass ](/about-blockend/compass)
{% endcontent-ref %}

***

## :ocean:Liquidity Exchange (LEX)

LEX solves the inefficiencies of traditional intent-based protocols by offering a scalable, cost-effective, and infrastructure-light solution for omnichain liquidity. Built on the **Solana Virtual Machine (SVM)**, LEX can power seamless liquidity movement for **an inevitable future of a million chains**.\
\
With the introduction of **Intents 2.0**, LEX eliminates the need for complex infrastructure, significantly **reducing costs for users, solvers, and validators**. Its design **scales effortlessly to the latest chains**, including those with unique architectures or unconventional technical stacks, ensuring compatibility without compromise.

## Scale To Any Chain Without Infrastructure Bottlenecks

* **Infrastructure-Light Design**: Eliminates the need for smart contracts on source and destination chains and cross-chain messaging layers. This significantly reduces time-to-market and removes scaling bottlenecks when integrating new chains.
* **Support for Non-Standard Chains**: Seamlessly integrates chains with unique architectures or tech stacks, including EVM, Non-EVM, Modular, or unconventional protocols, ensuring compatibility without compromising efficiency.
* **Efficient Operations for Solvers and Validators**: The simplified design minimizes operational overhead, lowering costs and enabling streamlined processes for all participants.

### Low Cost Transactions, Faster and Capital Efficient Settlements

* **Unified Execution:** LEX consolidates all critical components of intent bridges including Escrow, Fulfillment, Validation, and Settlement into a single, decentralized ledger built on the SVM, optimized for seamless liquidity movement across chains.
* **Unparalleled Efficiency:** Solver and validator interactions occur directly on the LEX chain, enabling unprecedented speed and cost efficiency throughout the intent protocol lifecycle.
* **Enhanced Capital Utilization:** Faster settlements allow liquidity to be rapidly reused, maximizing solver capital efficiency while minimizing delays.

**LEX Is Currently In Development, Click Below To Dive Deeper:**

{% content-ref url="/pages/B4wMlTdPAhhcrZiEHg3G" %}
[LEX Protocol](/about-blockend/lex-protocol)
{% endcontent-ref %}


# Thesis Old

### Thesis

At its core, 99% of Web3 activity revolves around transferring value, whether between parties or across assets.

There 300+ active chains, and the overall web3 ecosystem is fragmented and liquidity is stuck in silos. Even Web3 OGs have to figure out a lot of things using a dApp on a new chain. A typical user manages 100s of tokens across 10s of chains not to mention Gas tokens for each chain. Launching a dApp on a specific blockchain and attracting users from other chains is quite challenging for developers. Several protocols aim to address these issues, achieving limited success so far.  The aim is to solve for the current 300 chains right now, but with the rapid expansion of Layer 2s, Layer 3s, app chains launching, everyone is playing catchup. We envision that in the future we'll have a million chains. As today we think of a chain as a really big, architectural, giant, monolithic thing. But in the future, chains may be similar to how we have billions of websites right now. On chains, we will have specific requirements based on specific infrastructures. We may use different index packs. All different requirements. So that's how we envision it. So someone has to solve the liquidity fragmentation issues. We may in the future have a standard protocol like we had in Layer 2 to replicate across websites. Or we'll have standards like TCPIP and DNS and all of that. But that is far off in Layer 3 right now. So we believe that this is the moment to actually build a liquidity layer which can enable liquidity movements seamlessly across millions of chains in Web 3 in the near future.

So, the way we can do it... The first problem is, there are a lot of protocols or solutions trying to solve the GPT fragmentation issue. But let's say we bring an innovative solution. We don't get enough traction or discovery because the average user or app is not aware about the unique solution. When this unique solution comes in, there is another unique solution which is coming up for cross-chain liquidity or liquidity on the same day itself. And there are hundreds of new protocols and solutions coming up. This creates, again, more fragmentation in terms of just the solution itself. So, even if someone actually solves this issue, it would be very long before they become the standard across... and able to use them. Because there are so many different types of even solutions. So, the important part is for us to bring them together. For a developer or a user to be able to find these and interact with them and gain the benefit, it helps the performance, speed, or cost. So, that is the aggregating part. The other side of this point is, these protocols, because there are so many, for them to actually gain any traction, they need order flow. And that is very difficult to gain in the current landscape with so many solutions. So, our aim with the first part of building Compass is to capture the order flow directly from the tabs. And by aggregating all of the new, unique, old, all of the liquidity solutions, and giving the best output to the user. So, the user gets the best output, the latest innovations in liquidity, and is able to seamlessly transfer value or transfer assets across chains and use their protocols on any chain and token. The protocols, in turn, get order flow directly from the source, because all liquidity in that queue is technically to use a decentralized application. And this activity does not happen on the tab right now. So, we capture the order flow directly from the tab by integrating Compass directly with the tabs, and we enable discoverability for the protocol itself. So, in the end, it's a win-win for the users, the protocols, and for us, because we actually got the flow directly. So, then we become the single source of a good amount of order flow, and a massive amount of liquidity.

Now after aggregating liquidity and maintaining the order flow, the problem is all of these different protocols are running, all of them are limited by their own innovation and stack, support of chain, and all of that. It's difficult for them to work together. So then comes a layer of execution, where Comcast Pathfinder handles the execution, works with all of these different protocols, merges them, finds the best routes, figures out efficient ways to execute the user's intent, in some sense, of giving one token and getting another token on a chain and actually execute an action, depending on the use case of, let's say, buying an NFT or putting money into a liquidity pool or anything else. So this is the execution part, where Comcast Pathfinder handles the execution, makes it streamlined, makes it efficient. Because even if you aggregate all of the solution, and if you give it to the user or the developer, they still have a lot to decide and execute and do. That also creates one more layer of complexity. So to reduce or remove, eliminate all of that, Comcast Pathfinder handles the execution. So your stack is aggregation, distribution, in some sense, for the protocols, for the end-to-end order flow, and then for the end-to-end stack, execution. So all of this is part of Compass.

Now in terms of, even if you have all of the existing protocols and liquidity aggregated, even if you are able to execute, find the best option, mix and match all of these puzzles, handle them to an execution, even then, you won't be able to support even the Lite, the active pre-embedding right now, because simply all of these protocols are limited in terms of scalability, high amount of infrastructure overhead, and a lot of different issues and different tech requirements on top of that. So then comes the requirement of building a comprehensive liquidity layer, which can take in all of these different liquidity avenues and enable them to interact across chains and seamlessly hold money from any source to any destination. And the main part of this is because all of the existing protocols are not even able to scale between other chains. There is literally not a single protocol or solution which works across all chains. So either they work across 10 chains, 15, 20, 50, maximum 100, and apart from that, if there are 300 chains, they won't be able to work. Even if, let's say, a particular solution is working, supports 100 chains, they will not support liquidity for more than top 3, 4, 5, or 10 assets on the chain. They won't be able to support all the liquidity across all these chains. So that's where Lex protocol comes in. Lex builds upon the growth of intent-based bridges and protocols and improves it further for scalability. The main objective of Lex is to improve the intent-based mechanisms and make them scalable. The current intent-based mechanisms have solved the user experience issue.

And are able to get the user a specific asset for whatever their intent is, fulfilled by pushing it on to third parties who execute this on their own. The problem with this is the overall, the thought and the logic is good, and the problem is with the overall infrastructure requirements. Intent-based widgets work because they fulfill the user's intent regardless of the underlying entity, provider, or liquidity, whoever that is, and get this done. But the problem lies wherein, once the user's intent is fulfilled, the liquidity provider or the solver who may be involved, they have to go through a learning process which is infrastructure-ready, costly after multiple transactions, and time consuming because they have to prove to the protocol that they fulfilled the user's intent. There are validators who verify the request for fulfillment, then there is a settlement process which takes a lot of time, sometimes a few days, sometimes a few hours, and that makes the guaranteed intent protocols inefficient. So the next protocol improves the intent-based engines and removes all the unnecessary complexities and infrastructure requirements and fulfilling a single goal of enabling users to access liquidity on any new chain, solvers for them to be able to solve liquidity regardless of the architecture or smart contract by the protocol and for validators to efficiently and at speed and low cost verify all of these transactions across any chain, regardless of whether the chain is linear, non-linear, modular, or whatever in the near future. So by overall, if you consider the stack, it solves for aggregation, distribution, order flow, execution, and settlement. By adding all of this together, you combine all of this stack and then comes the full end-to-end life cycle of liquidity moving across chains for the future of enabling chains.

####

#### Rethinking Web3 From First Principles

**Users** \
Most user interactions with a dApp involve a transfer of value.. Does a user care what consensus mechanism or VM the dApp is deployed on? No.

**Developers** \
When building dApps, developers choose blockchains that best fit their technical needs - for speed, cost, or innovation. Should these technical decisions become a barrier for potential users holding assets on other chains? No.

**Intermediaries** \
Intermediaries bridge one gap: matching asset conversion needs with the best available liquidity source. If the conversion is fast, secure, and maximised, does it require complex infrastructure? No.

### *By going back to basics, BlockEnd addresses Web3’s core need: seamless value transfer.*


# Extra data

### [Explore Compass Use-Cases](/compass-usecases/onboards-users-from-any-chain-and-token-right-on-your-dapp)

### **Why It Matters**

• **One Integration for All**: No more juggling multiple protocols. Connect once and automatically tap into 80+ chains with ease.

• **Abstracts Complexity**: Compass manages all behind-the-scenes logic for seamless end-to-end asset conversions, so you don’t have to.

• **Scales Effortlessly**: A simple front-end widget or a back-end API—both designed to grow with your dApp.

#### **Bottom Line**

Compass empowers users to seamlessly spend their assets on any dApp, regardless of the underlying chain, while allowing developers to freely choose the optimal blockchain without losing users to cross-chain complexities.


# Thesis

## Unifying Web3: The Future of Borderless Liquidity

<figure><img src="https://3263726620-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FqarB7qiMcyzczIQFNGu5%2Fuploads%2Fnkl4TYVWkg427WcdfrGl%2Fimage.png?alt=media&amp;token=bf8d8bc2-333a-4d6e-9611-45ad08a923a9" alt=""><figcaption><p>Source: <a href="https://thirdweb.com/chainlist">https://thirdweb.com/chainlist</a></p></figcaption></figure>

Today, launching a new chain is as easy as ordering food on a delivery app. Every day, new Layer 3s, Layer 4s, rollups, and app chains are cropping up. **The future of a million chains is inevitable.**

### ***A chain is not an island - neither is your dApp.*** <a href="#block-1aead3a0895f80e4b281c595c8071d69" id="block-1aead3a0895f80e4b281c595c8071d69"></a>

We believe founders should leverage native blockchain ecosystems for their launch, go-to-market strategy, and the technology stack of a particular chain. At the same time, they must enable users from other ecosystems to access their dApps, maximizing their Total Addressable Market (TAM) and reaching a broader audience. Liquidity should be accessible across all ecosystems, regardless of the underlying infrastructure. **Users want the best apps, not a PhD in figuring out which tokens work where.**

Imagine if Gmail users couldn’t email Outlook users. That’s the reality of Web3 today.

* **Users Get Stuck at the Door** – Developers struggle to onboard users who lack the right assets on the right chain.
* **Liquidity is Trapped in Silos** – Assets can’t move freely, making cross-chain activity expensive and inefficient.
* **Expanding Across Chains is a Nightmare** – Cross-chain deployment is slow, costly, and distracts developers from innovation.

### **The Endgame? A Liquidity Marketplace Without Borders.** <a href="#block-1aead3a0895f804a9849fcfeb25638e1" id="block-1aead3a0895f804a9849fcfeb25638e1"></a>

A marketplace thrives by connecting supply and demand, eliminating inefficiencies. Consumers gain choice, competition, and better prices, while providers get instant access to a broader market without the overhead of customer acquisition. This model has dominated Web2, from Amazon to Uber. However, building a marketplace isn’t easy - most fail due to the classic **chicken-and-egg problem**: supply won’t come without demand, and demand won’t exist without supply. So, how do we build a thriving marketplace?

### **First: Bootstrap the supply side** <a href="#block-1aead3a0895f800a8061e900a6e41050" id="block-1aead3a0895f800a8061e900a6e41050"></a>

We build the supply side first by aggregating existing DEXs, bridges, and intent protocols into a unified liquidity layer, abstracting away their quirks. Instead of forcing developers to troubleshoot integrations for years, we make liquidity accessible in one place, instantly.

### **Second: Capture demand at the source** <a href="#block-1aead3a0895f805786a6c6c3d6a99d1c" id="block-1aead3a0895f805786a6c6c3d6a99d1c"></a>

Demand originates **at the application level**. Users don’t start with a liquidity problem. They start with an **application problem,** they want to use a dApp but need specific assets. Instead of forcing users to **search for external liquidity sources**, we **bring liquidity directly into the applications -** capturing **order flow at the source**, **exactly where it’s needed.**

### **Next: Make it convenient at scale** <a href="#block-1aead3a0895f8075a2c8c67c5b781da0" id="block-1aead3a0895f8075a2c8c67c5b781da0"></a>

*Just aggregation isn't cool, you know what's cool? **Convenience*****.** Amazon scaled beyond its marketplace by making transactions effortless, one-click checkout, Prime delivery and seamless payments. In Web3, liquidity access must evolve the same way.

**Building for the future: Intents based protocols are the next evolution in liquidity movement.**

Instead of manually navigating steps, users simply express what they want. The protocol then broadcasts this intent to a network of solvers, who compete to find the best liquidity path and fulfill the request.

The winning solver fronts their own capital, delivers assets to the user instantly, and later claims reimbursement from the protocol after fulfillment.

***If intent protocols are the future, why haven’t they solved everything yet?***

1. **Infrastructure Overhead** – Protocols must deploy and audit smart contracts on every chain, while validators manage nodes, event monitoring, and messaging. This adds complexity and limits support for non-EVM chains.
2. **High Costs** – Frequent cross-chain smart contract calls result in high gas fees. Validator infrastructure and cross-chain messaging further drive up costs, reducing solver margins and increasing user fees.
3. **Locked Liquidity** – Settlement delays due to validation steps and messaging lock solver funds, reducing capital efficiency and restricting liquidity expansion across chains.

*With this foundational understanding, we establish the first layer of our liquidity stack:*

### **Layer 1: Compass Aggregator – Unified Liquidity** <a href="#block-1aead3a0895f806e8096f6e3daad184d" id="block-1aead3a0895f806e8096f6e3daad184d"></a>

A **single integration** that provides access to all liquidity sources across chains. Developers save **months, even years**, of integration overhead. They can onboard more users from any chain, and any token directly through our front-end widgets. While powering advanced use-cases like chain-agnostic trading, DeFi strategies, and AI agents through our comprehensive backend APIs.

### **Layer 2: Pathfinder – One-Click Execution** <a href="#block-1aead3a0895f802a86b3d55375666231" id="block-1aead3a0895f802a86b3d55375666231"></a>

Pathfinder is an **execution engine** that simplifies transactions by abstracting away complexities.

* **One-click execution** – No more signing multiple transactions.
* **Gas abstraction** – No need to manage gas tokens for different chains.
* **Unrestricted liquidity** – No longer limited by a single liquidity provider; Pathfinder combines multiple sources for the best execution.

By leveraging **Compass** to find optimal liquidity routes, even when no single provider can fulfill a request. Pathfinder **unlocks liquidity pathways that wouldn’t otherwise be possible.**

Pathfinder acts as a **solver**, handling order flow exclusively from Compass. While it improves execution and fills gaps in the short term, the expanding landscape demands **more solvers** with diverse execution capabilities. To ensure **optimal pricing and efficiency**, we need an **open marketplace** where solvers compete for order flow.

That’s why we’re building LEX Protocol - an open marketplace that eliminates bottlenecks and scales seamlessly across all chains, regardless of architecture.

### **Layer 3: LEX Protocol – The Open Liquidity Infrastructure** <a href="#block-1aead3a0895f800686bcf0d276879fdb" id="block-1aead3a0895f800686bcf0d276879fdb"></a>

LEX is an **intent-based liquidity protocol** that functions across **all virtual machines**, removing dependencies on smart contracts and cross-chain messaging. It is designed to be:

• **Infrastructure-light**: Works on any chain, regardless of tech architecture.

• **Permissionless**: Any Solver, Chain, liquidity provider can plug in.

• **Capital and cost-efficient**: Faster settlements, cheaper transactions for all participants.

All core functions of LEX protocol execute on a dedicated **high-speed, low-cost settlement layer built on** the **Solana Virtual Machine (SVM),** enabling seamless liquidity movement across chains without constraints. Pathfinder will eventually transition into one of the solvers on LEX competing in the open liquidity marketplace.

### Why Solana? <a href="#block-1aead3a0895f8038ac9efcd4ef827059" id="block-1aead3a0895f8038ac9efcd4ef827059"></a>

While Blockend is a chain-agnostic liquidity infrastructure, Solana was the clear choice for our base layer due to:

• **Scalability & Speed** – Solana’s high-throughput architecture ensures fast, cost-efficient settlements.

• **Strong Community & Ecosystem** – A thriving culture of builders, founders, and innovators committed to long-term growth.

• **Security & Settlement** – LEX runs as an app chain on SVM, executing transactions on the SVM while eventually settling batches on Solana L1.

### Why Blockend? <a href="#block-1aead3a0895f80699292d8ad85989a27" id="block-1aead3a0895f80699292d8ad85989a27"></a>

With 8+ years of experience running a centralized exchange with 250k+ users, and building multiple Web2, Web2.5, and Web3 products, we understand both sides of the equation - the challenges developers face in building applications and the friction users experience when interacting with them.

Our mission is simple: remove inefficiencies so builders can focus on innovation, not infrastructure bottlenecks.

We are building a full-stack open liquidity marketplace - Compass (discovery), Pathfinder (execution), and LEX (scalability) - to power frictionless liquidity movement across all chains, assets, and virtual machines.

One Web3. Any token. Any chain. No barriers.

<br>


# Compass&#x20;

When a user visits a new dApp, their first thought is : **“Which token do I need, and on which chain, to use this dApp?”**

This forces them into a complex journey of researching, swapping, and transferring assets across platforms **often resulting in drop-offs and lost revenue for the dApp**.

If, by some miracle, a dev decides to tackle this friction and improve the user experience (a rarity among Web3 devs), they face the daunting task of:

* Integrating a colossal number of chains, wallets, providers, and liquidity sources.
* Deciphering wildly different mechanisms and tech across platforms because, well, Web3.
* Undertaking a journey so complex it can take years and demand significant resources.

#### *There has to be a better way! (* :shark: *Shark Tank Style)*

### Introducing :compass: Compass

Compass discovers, stress-tests, and aggregates the best liquidity sources across all of Web3, bringing them together into a single, streamlined liquidity layer.\
As a meta-aggregator Compass integrates top **Dexes, Bridges, RFQ Mechanisms, Intent protocols and even top aggregators**, delivering unmatched prices, speed, and execution directly to your dApp.\
\
Compass leverages deep analytics, onchain data and ranks routes based on maximum output, minimum gas costs, fastest execution and reliability of the liquidity source, ensuring a seamless user experience.\
\
The power of Compass can be added to your dApp frontend today in just one line of code, using our retail-tested, user-friendly widgets.

{% content-ref url="/pages/CNUb9FXtQ5otfHVTjHVM" %}
[Compass Widgets](/compass-widgets/widget-pro)
{% endcontent-ref %}

Add Compass to your frontend today in just one line of code, using our retail-tested, user-friendly widgets.

### OR

{% content-ref url="/pages/MOcEIQFGNJVxLQbuFyDV" %}
[Compass API](/compass-api/api-reference)
{% endcontent-ref %}

Use our comprehensive APIs and SDKs in your backend utilizing all of web3 liquidity to build Innovative applications that would previously would not have been possible!

### But thats not all, Wait for it,

### Compass goes beyond aggregation with 'Pathfinder'

PathFinder is our proprietary execution engine designed to handle complex, end-to-end transactions, transforming multi-step processes into seamless one-click magic. It executes all steps with maximum efficiency in just seconds.

* **Figures Out Unique Paths**: Combines multiple providers for optimal execution, even when no single provider can handle the entire transaction journey.
* **Automates Execution**: Handles every step- approval, swap, bridge, requiring only one user transaction.
* **Manages Gas Fees**: Automatically calculates and manages gas tokens across chains for complex transactions.

*"Pathfinder is currently in beta and being rolled out to our early integrators in phases, bringing us closer to realizing our vision of Any Token, Any Chain."*

### Why Choose Compass?

* **Boost User Conversion:** Compass eliminates friction for your users by enabling seamless one-click transactions. Users don’t need to research, swap, or transfer assets across chains, it’s all handled automatically, keeping them engaged and reducing drop-offs.
* **Save Development Time:** Integrating multiple chains, wallets, and liquidity providers can take years. With Compass, all of this complexity is streamlined into a single integration, saving you time and resources.
* **Optimize Performance:** Compass delivers the best value, speed, and gas efficiency for every transaction by leveraging advanced analytics and routing algorithms, making your dApp more competitive.
* **Effortless Compatibility:** Access support for 140+ chains, including EVM and non-EVM ecosystems, with no additional infrastructure required. Plus, as Compass continues integrating new chains at a rapid pace, your dApp will automatically support them—no extra work needed.


# LEX OLD

Lex is Intents 2.0, removing the limitations that hold back legacy and intent-based bridges. It enables faster, cheaper, and truly scalable cross-chain liquidity, unlocking the full potential of Web3.\
\
LEX Protocol (In Developement

*While building Compass, we realized that aggregating and connecting existing liquidity is a crucial foundation, but current solutions cannot scale for a future with a thousand chains.*

*This inspired us to reimagine the base infrastructure for cross-chain liquidity and build Lex.*

### **Why a New Protocol?**

Intent-based protocols solve the user experience problem by letting users state, ‘I have X, I want Y,’ and instantly receive assets on another chain.

However they still rely on legacy infrastructure like, cross-chain messaging, smart contracts on each chain and traditional bridging mechanisms behind the scenes for core components. This reliance on legacy infrastructure lead to high fees, locked capital, limited scalability, and slower settlements.

### **LEX: Intents 2.0**

Lex redefines intent-based bridging by moving all core processes—escrow, fulfillment, validation, and settlement—to a single, high-speed SVM chain. No more per-chain smart contracts or cross-chain messaging overhead, which dramatically lowers costs, boosts speed, and reduces complexity.

### **Why Is LEX Better?**

• **Reduced Infrastructure:** Eliminates the need for Smart Contracts on each chain plus less infrastructure costs for validators and solvers.

• **Lower Fees:** Consolidating everything on one chain slashes transaction, validation and settlements costs, making even small transfers feasible.

• **Instant Scalability:** Adding a new chain is as simple as a solver providing liquidity—no heavy setup required.

• **Faster Settlement:** Near-instant finalization on the SVM chain frees up solver liquidity quickly, driving higher capital efficiency.

#### Lex rethinks intent-based bridging in a single, high-speed layer—enabling near-instant, cost-effective transfers that can quickly scale to any chain.

### Learn More About LEX Protocol:

#### LEX is an Omnichain liquidity protocol designed to enable seamless liquidity movement across millions of chains: an inevitable future by reinventing Intent based bridges and introducing intents 2.0 which eliminates the need for complex infrastructure and reduces cost for validators and solvers by orders of magnitude.

### • **Minimized Infrastructure Overhead For Validators & Solvers:**&#x20;

Eliminates the need for Smart Contracts on each chain plus less infrastructure costs for validators and solvers.

### • Lower Costs Enable High Frequency Low Value Transactions Possible

Consolidating everything on one chain slashes transaction, validation and settlements costs, making even small transfers feasible.

### • **Infinite Scalability Even With Never Unique Architecture chains:**&#x20;

Adding a new chain is as simple as a solver providing liquidity—no heavy setup required.

### • **Faster Settlements Improve Capital Efficiency & Utilisation:**&#x20;

Near-instant finalization on the SVM chain frees up solver liquidity quickly, driving higher capital efficiency.

LEX is an omnichain intent protocol designed to enable seamless liquidity movement across millions of chains: an inevitable future.

By reimagining cross-chain liquidity movement, LEX consolidates all core processes of current intent protocols—escrow, fulfillment, validation, and settlement—into a single high-speed SVM chain. \
It eliminates the need for smart contracts on every chain and cross-chain messaging overhead, dramatically reducing costs, increasing speed, and simplifying integration with new chains.\
\
LEX consolidates all core components of Intent Bridges including Escrow, Fulfillment, Validation, and Settlement, into a single, high-speed SVM chain, purpose-built for fast, cost-effective liquidity movement across chains.

\
All solver and validator interactions with the core components occur directly on the LEX chain, delivering unprecedented speed and significantly reducing costs throughout the intent protocol lifecycle. This enables faster settlements, maximizes solver capital efficiency, and ensures liquidity is rapidly reusable.

### Why?

By reimagining intent-based bridges and introducing **Intents 2.0**, LEX eliminates the need for complex infrastructure, dramatically reducing costs and simplifying processes for solvers and validators.

Best Price, Speed & Liquidity\
Single Integration, No Infrastructure Overhead\
Robust Transaction Landing, Tracking & Analytics

Build Innovative Apps With Instant & optimized liquidity


# LEX Protocol

### The Cross-Chain Challenge

Aggregators like Compass have transformed how users move assets across chains, making complex transfers feel seamless with a single interface. Yet even the most sophisticated aggregation can't overcome the fundamental limitations of today's bridging infrastructure. While Compass can discover routes that other aggregators miss, it's still constrained by bridges that support only the most popular assets, require multiple validation layers, and rely on slow cross-chain messaging.

This means even optimal routes often involve multiple steps and intermediaries, with each hop accumulating its own gas fees, bridge fees, and validator costs. What should be a simple transfer becomes prohibitively expensive, especially for smaller transactions where fees can exceed the transfer amount itself. The problem extends far beyond the top 10-15 chains and tokens, there's massive user demand across hundreds of emerging chains and tokens that current bridge infrastructure simply cannot serve efficiently. With an ecosystem already spanning 300+ chains and potentially growing to thousands, these infrastructure limitations aren't just inconvenient they're becoming a critical bottleneck for cross-chain liquidity.

### **The Rise of Intent-Based Bridges**

Intent-based bridges revolutionize cross-chain transactions by focusing on a simple principle: users say what they want, and get it within seconds. Instead of navigating complex technical steps, users express straightforward intents like "I have DAI on Base and want BONK on Solana."

Behind the scenes, specialized participants called solvers compete to fulfill these intents. The key innovation? Solvers front their own liquidity on destination chains. Rather than waiting for a long bridging process or complex multi-step transactions with multiple gas fees, users receive their desired tokens almost immediately because solvers front the liquidity and optimize execution across available liquidity sources – including DEXs, bridges, and other venues.

Intent-based bridging transforms complex cross-chain transactions into a seamless two-phase process that separates user experience from solver settlement.

**Phase 1: User Intent Flow:**\
The user expresses intent, solvers compete, and the winning solver delivers the desired tokens to the user instantly on the destination chain.

1. **Intent Expression**\
   The user submits their intent via a simple interface, triggering an auction where solvers compete to offer the best terms.
2. **Escrow**\
   The user’s funds are escrowed in a smart contract on the source chain, involving smart contract interactions and event monitoring by validators to ensure proper fund locking.
3. **Fulfillment**\
   The winning solver fulfills the user’s request by delivering the desired asset on the destination chain.

**Phase 2: Solver Settlement Flow:**

After fulfillment, the solver’s fronted liquidity is repaid through a settlement process handled by the intent protocol.

4. **Submit Claim**\
   The solver submits a claim with proof of the fulfilled intent to the protocol’s smart contract on the destination chain.
5. **Validation**\
   Validators verify the relevant events on both the source and destination chains, utilizing cross-chain messaging, smart contract interactions, and forming consensus.
6. **Reimbursement**\
   &#x20;After successful validation and consensus, a signature verifying the intent’s completion is posted to the protocol’s smart contract, and the solver is reimbursed from the locked funds on the source chain.

This two-phase design achieves a critical goal: users get instant results while the system maintains rigorous security through thorough settlement procedures. The complexity of cross-chain messaging, validator consensus, and settlement logistics remains invisible to users, who experience only the seamless front-end transaction.

***

### **The Settlement Bottleneck**

While intent-based bridges have streamlined the user experience, their back-end settlement process still relies on legacy bridge infrastructure. Though critical for ensuring secure and accurate transactions, this process creates significant bottlenecks that hinder scalability, drive up costs, and introduce operational inefficiencies.

**Three main bottlenecks in the settlement process:**

1. :office: **Infrastructure Overhead**\
   Protocols must deploy and audit smart contracts for every supported chain, while validators manage full nodes, event monitoring, cross-chain messaging, and contract interactions. Since protocols rely on smart contracts, they cannot support chains without such capabilities, like Bitcoin, or those with different virtual machine architectures. These demands increase complexity and limit scaling to more chains.
2. :moneybag: **High Costs**\
   Settlement requires frequent smart contract calls across multiple chains, including deposits, fill events, validation, and claims, which lead to high gas fees. Cross-chain messaging and validator infrastructure further increase costs, especially on chains with expensive gas fees. These expenses reduce solver and validator margins and are ultimately passed on to the user, ultimately increasing end user fees.
3. :unlock:**Locked Liquidity**\
   Settlement delays caused by multi-step validation, cross-chain messaging, and challenge periods lock solver liquidity. Solvers, who operate on thin margins and rely on high transaction frequency, face reduced capital efficiency due to these delays. Locked funds limit their ability to handle new transactions, making it harder to expand liquidity to additional chains and impacting overall profitability.

***For intent-based bridges to fully replace traditional bridges and unlock their potential, these bottlenecks must be addressed.***

***

### Introducing Intents 2.0

LEX takes the core components of intent protocols such as escrow, fulfillment, validation, and settlement—and moves all of them to a purpose-built SVM chain on Solana. This chain is optimized for speed and cost, tailored specifically to the intent protocol lifecycle. While the core components remain the same, LEX eliminates the need for smart contracts on every supported chain and reduces dependency on legacy infrastructure like cross-chain messaging. By redefining who does what, how it happens, and where these processes are executed, LEX streamlines operations, lowers costs, and introduces the next evolution: Intents 2.0.

#### *Three Key Changes in LEX: From Intent 1.0 to Intent 2.0*

1. **Streamlined Solver and Validator Operations on a Single Chain**\
   All solver and validator-related operations and actions are consolidated onto a single, dedicated, fast, and cost-effective SVM chain. This reduces complexity and significantly lowers costs.
2. **Elimination of Smart Contracts on Source and Destination Chains**\
   By removing smart contracts from both source and destination chains, LEX simplifies operations for users and solvers. Asset transfers are reduced to simple token transactions, improving scalability and minimizing overhead.
3. **Infrastructure-Free Validators with Economic Incentives**\
   LEX removes the need for validators to maintain complex infrastructure across multiple chains. A robust reward and slashing mechanism ensures security and accuracy, making the system both scalable and secure.\\

\
LEX streamlines the core components of escrow, fulfillment, validation, and settlement by implementing these three key changes. The following sections break down each stage in detail to highlight the specific innovations driving these improvements.

### Escrow: Secure Collateral Without Source Chain Smart Contracts

Instead of users locking funds in source chain smart contracts, LEX requires winning solvers to escrow collateral on the SVM chain. This seemingly simple change has profound implications. Users now make basic token transfers directly to solver addresses a transaction that costs dramatically less in gas than smart contract interactions, especially on high-fee chains like Ethereum. The solver’s escrowed collateral on the SVM chain provides bulletproof security without the overhead of cross-chain smart contracts.

Consider how this improves upon traditional systems: In current intent protocols, users must interact with smart contracts that need deployment, auditing, and maintenance on every supported chain. Each interaction involves multiple transaction layers: first to approve tokens, then to deposit them, each incurring gas costs. LEX reduces this to a single standard token transfer while maintaining equivalent security through solver collateral.

### **Fulfillment: Reducing Infrastructure by Focusing on Intent Completion**

The end goal of an intent protocol is to ensure that the user’s intent is fulfilled and that the solver is appropriately compensated. If this critical aspect can be completed and verified, then there is no need for extensive infrastructure that monitors every specific event, including the source chain deposit.

Solvers already take on finality risk in traditional protocols, they routinely fulfill intents before source chain transactions fully finalize, occasionally losing funds to block reorganizations. Since solvers have already priced in and accepted this risk, LEX eliminates the need for costly cross-chain validation infrastructure. By focusing on verifying the fulfillment of the user’s intent on the destination chain, the system becomes far more efficient.

However, there may be instances where the source chain transaction needs to be validated, such as when the intent is canceled by the user, the source transaction fails, or other issues arise. In such cases, the escrow of the solver must be released. LEX accommodates these scenarios by enabling validators to verify source chain transactions when required, but without the need for full-scale infrastructure. These mechanisms ensure that the system remains robust while avoiding unnecessary overhead.

### **Validation: Flexible and Incentivized Verification for Scalability**

The current infrastructure requirements maintaining nodes, monitoring smart contracts, and verifying cross-chain events add complexity without providing meaningful benefits to solvers and validators. The end goal of validators in LEX is to ensure that the user’s intent is fulfilled, verified, and that solvers are repaid for their efforts on time.

The broader objective of the protocol is to capture a user’s intent, find the best possible execution path for solver liquidity, and ensure that the intent is fulfilled. How this happens doesn’t need to be rigid or overly complex, as long as the process is verified by actors with skin in the game and proven on-chain. With this approach, LEX avoids dictating specific infrastructure requirements, offering validators flexibility in how they verify transactions.

The protocol’s robust reward and slashing mechanism ensures security: validators stake assets as skin in the game, incentivizing them to maintain perfect accuracy regardless of their chosen verification approach. When a validator submits a signature confirming a transaction’s validity, it carries weight because their staked assets back that claim. Incorrect validations result in penalties, creating strong economic pressure for validators to develop reliable verification systems.

### **Settlement: Fast, Cost-Effective Finalization on the SVM Chain**

The settlement process showcases even more dramatic efficiency gains. Validators only need to monitor SVM chain events in real-time and run a full node for the SVM chain. They receive transaction data for destination chain verification, streamlining their operations. This consolidation eliminates the need for validators to interact with or track dozens of different smart contracts and run nodes for all other chains.

Consensus becomes remarkably efficient because validators do not need to collaborate to reach consensus in real-time. Instead, they individually verify transactions and submit their signatures to the SVM chain smart contract. Once a sufficient majority (typically 15 out of 20 validators) confirms a transaction, the solver’s escrowed funds are automatically released minus protocol fees. The entire process occurs on the high-performance SVM chain, where 50-millisecond block times enable near-instant settlement.

This architecture delivers unprecedented improvements in capital efficiency. Traditional intent protocols often lock solver funds for 24-48 hours during settlement. Even “optimistic” protocols typically impose 4-hour challenge periods. LEX’s streamlined settlement completes in minutes—up to 100 times faster than traditional systems. This speed allows solvers to reuse capital more frequently, handling higher transaction volumes with less locked collateral.

#### Bottom Line

Looking at the end-to-end process, LEX's innovations multiply: User intents are fulfilled faster through direct transfers. Settlement happens almost immediately on the optimized SVM chain. Validation is streamlined yet secure through economic incentives. And the entire system scales effortlessly to new chains without additional infrastructure overhead. Each component has been carefully redesigned to maximize efficiency while maintaining security, creating a protocol that's both more performant and more practical than traditional alternatives.

***

*This overview is intended to provide a broad, high-level summary, deliberately avoiding in-depth technical details or discussions on handling adversarial scenarios. These aspects, including the technical specifics and strategies for addressing potential challenges, will be explored comprehensively in an upcoming posts.*


# Widget Pro

## Compass Widget Pro: The Full-Featured Widget of Compass

### Onboard users from any chain, any token, at the best prices, directly on your DApp.

Widget Pro is a fully-featured solution designed to simplify cross-chain interactions and streamline user onboarding. It supports all major wallets across ecosystems, including EVM, Solana, Cosmos, and more, ensuring seamless compatibility with diverse blockchain networks.

The widget handles end-to-end execution, removing the need for additional front-end integrations. With advanced capabilities like provider selection, cost and speed filters, portfolio management, and historical transaction access, Widget Pro empowers your users with an intuitive, efficient, and complete cross-chain experience, all integrated directly into your DApp.<br>

### Give it a try at our demo interface

### LAZY.Exchange

{% embed url="<https://www.lazy.exchange/>" %}

<div align="left"><figure><img src="https://3263726620-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FqarB7qiMcyzczIQFNGu5%2Fuploads%2FrsoyYLoXMNLYm9CUQfEt%2FGroup%201171277023.png?alt=media&amp;token=ad75d74b-96f2-4b67-bd13-253babde5fda" alt="" width="188"><figcaption></figcaption></figure> <figure><img src="https://3263726620-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FqarB7qiMcyzczIQFNGu5%2Fuploads%2FRElCJCbdu4wf4zQ9wQ99%2FGroup%201171277024.png?alt=media&amp;token=888b9d63-6ca8-45a7-ba8e-5b831aad08b2" alt="" width="188"><figcaption></figcaption></figure> <figure><img src="https://3263726620-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FqarB7qiMcyzczIQFNGu5%2Fuploads%2FtPjZF3b5xnHkAhyUyY41%2FGroup%201171277025.png?alt=media&amp;token=5797c5a3-6917-4f2b-bd78-ff18b29b2eaf" alt="" width="188"><figcaption></figcaption></figure> <figure><img src="https://3263726620-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FqarB7qiMcyzczIQFNGu5%2Fuploads%2Fk1clj9EoaURpNMFRdBBv%2FGroup%201171277026.png?alt=media&amp;token=c504d0a7-d1fc-4658-9e53-9235f1e18025" alt="" width="188"><figcaption></figcaption></figure></div>

Widget Pro is built to handle all complexities of cross-chain interactions so your users can focus on what matters most.

{% content-ref url="/pages/Q93EpYCETEQn8kwB397D" %}
[Install Widget Pro](/compass-widgets/widget-pro/install-widget-pro)
{% endcontent-ref %}


# Install Widget Pro

## Getting started with Blockend Widget

Blockend Widget is available as an [npm package](https://www.npmjs.com/package/blockend) along with several required dependencies for full functionality.

**Package Dependencies Overview**

The widget requires the following dependency packages:<br>

* **@dynamic-labs**: Provides wallet connection for Solana blockchain.
* **@cosmjs**: Enables interaction with Cosmos-based blockchains
* graz: Provides react hooks for Cosmos wallet interaction.
* wagmi,viem: Enables interaction with EVM blockchain

**Installation Commands**

Choose your preferred package manager:

**npm:**

```sh
npm install @blockend/widget @blockend/compass-sdk wagmi viem @tanstack/react-query @dynamic-labs/sdk-react-core @dynamic-labs/solana @dynamic-labs/bitcoin graz graz-sh/types @cosmjs/cosmwasm-stargate @cosmjs/proto-signing @cosmjs/stargate
```

**yarn:**

```sh
yarn add @blockend/widget @blockend/compass-sdk wagmi viem @tanstack/react-query @dynamic-labs/sdk-react-core @dynamic-labs/solana @dynamic-labs/bitcoin graz graz-sh/types @cosmjs/cosmwasm-stargate  @cosmjs/proto-signing @cosmjs/stargate 
```

> **Note**: All dependencies are required for full functionality of the widget across different blockchain networks and wallet types.

Integrating widget to your dapp or webiste is very easy. It takes a full 3 line of code to integrate and start using Blockend Widget, now that's a lot of work for a human dev.

### 1. Import Widget dependencies

In your react app, start by importing the Blockend Widget and its styles

```jsx
import Blockend from "@blockend/widget";
import "@blockend/widget/dist/style.css";
```

You may encounter Server Error... ReferenceError: self is not defined in your Next JS app, this is because blockend requires web apis to work and the web apis are not available on the server side when next js renders a page, in order to avoid this you can start by importing the Blockend Widget like below

```jsx
import dynamic from "next/dynamic";
const Blockend = dynamic(() => import("@blockend/widget"), {
  ssr: false,
});
import "blockend/dist/style.css";
```

### 2. Initialize the Widget

Add the widget component to your app

```jsx
<Blockend />
```

### Integrator Id (Required)

Unique identifier assigned to each integration partner. It is used to track and manage various integrations within our system.Error will be thrown if this field is empty.

```jsx
const configuration = {
  integratorId:""
  ...
};
<Blockend  configuration={configuration} />
```

This id will be added in the request header of api calls that is made by the widget.

And that is it, you have successfully integrated the Blockend Widget.

### 3. (optional) Customizing the Widget

As an optional step, you can also customize the look and feel of the widget. This can be done by passing a configuration object as prop when initializing the widget.

```jsx
const configuration = {
    gradientStyle: {
    background: "linear-gradient(#E66465, #9198E5)",
    spinnerColor: "#E66465",
    stopColor: "#9198E5",
  },
  containerStyle:{
    background:"#000000",
    border:"1px solid #fff",
    boxShadow:"1px 1px 7px 5px rgb(255,255,255,0.1)" ,
  },
  theme:"light",
  customTheme: {
    text: {
      primary: "#808080",
      secondary: "rgba(128, 128, 128, 0.75)",
      placeholder: "#cccccc",
      success: "#49AD71",
      error: "#FD5868",
    },
    background: {
      container: "#FFFFFF",
      secondary: "#E0E0E0",
      networkCard: "#F7F7F7",
    },
    border: {
      primary: "#E0E0E0",
    },
    fontFamily:'"micro 5 charted"', sans-serif, lato;
    shadow: {
      boxShadow: "1px 1px 7px 5px rgb(255,255,255,0.1)",
    },
  },
};

<Blockend configuration={configuration} />;
```

Full list of configuration options can be found here:

{% content-ref url="/pages/STVyE2K7cUqqaMRbpNey" %}
[Customise Widget Pro](/compass-widgets/widget-pro/customise-widget-pro)
{% endcontent-ref %}

### Code Example

Here is what a integration of widget on your frontend might look like:

```jsx
import Blockend from "@blockend/widget";
import "@blockend/widget/dist/style.css";

const configuration = {
  gradientStyle: {
    background: "linear-gradient(#e66465, #9198e5)",
    spinnerColor: "#e66465",
    stopColor: "#9198e5",
  },
  defaultChains: {
    from: { chainId: "10" }, // optimism
    to: { chainId: "sol" }, // solana
  },
  defaultTokens: {
    from: { tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" }, // eth on optimism
    to: { tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }, // usdc on solana
  },
};

export const Home = () => {
  return <Blockend configuration={configuration} />;
};
```

### Supported Tokens

Widget supports a whole array of token which would be difficult to list here, so we have built a handy API just for that

```bash
curl -X GET "https://api2.blockend.com/v1/tokens" \
  -H "accept: application/json"
```

\
You can also pass `chainId` as query parameter to get tokens for a specific chain

```bash
curl -X GET "https://api2.blockend.com/v1/tokens?chainId=sol" \
  -H "accept: application/json"
```

\
You can also get list of supported chains by calling the following endpoint

```bash
curl -X GET "https://api2.blockend.com/v1/chains" \
  -H "accept: application/json"
```


# Customise Widget Pro

## Widget Customization Guide

### Customizing gradient colors

You can customize the gradient colors of the widget by passing `gradientStyle` object in configuration.

```jsx
const configuration = {
  gradientStyle: {
    background: "linear-gradient(#E66465, #9198E5)",
    spinnerColor: "#E66465",
    stopColor: "#9198E5",
  },
  ...
};
```

You can customize the theme of the widget by passing `customTheme` object in configuration.

```jsx
const configuration = {
  // containerStyle will override the styles written for the widget container, containerStyle accepts all the inline style properties.
  containerStyle:{
    background:"#000000", // changes the background color of the widget to black
    border:"1px solid #fff", //adds border to the widget container
    boxShadow:"1px 1px 7px 5px rgb(255,255,255,0.1)" // for adding desired shadow effect to the container.
  },
  theme:"light",  // light or dark, if custom theme is applied then custom theme will override light/dark theme
  customTheme: {
    text: {
      primary: "#808080", // primary color of the theme, this applies to headings, main text, svgs, etc..,
      secondary: "rgba(128, 128, 128, 0.75)",  //secondary color of the theme, this applies to secondary headings, network names, route info ,etc..,
      placeholder: "#cccccc",// to update  placeholder colors like input placeholder,date picker heading etc.,
      success: "#49AD71", // view all routes Higher output color
      error: "#FD5868", // error messages and lower output.
    },
    background: {
      container: "#FFFFFF", // can be used to update the bg color of the widget container and card color of the widget.
      secondary: "#E9E9E9", // can be used to update the table cell,loaderbar,skeleton and assets background on portfolio page.
      networkCard: "#F6F6F6", // used as background color for top main networks cards and transaction hash container in tokens section.
  
    },
    border: {
      primary: "#E0E0E0",// primary border color of the widget, can be used to update the container border,border of coin and chain icons, cards border of the widget.
    },
    fontFamily:'"micro 5 charted"', sans-serif, lato; // can be used to update the font family of the widget to match the parent site, add the fonts to your site and just pass the font name to the widget.
    shadow: {
      boxShadow: "1px 1px 7px 5px rgb(255,255,255,0.1)", // to add shadow effect to the container and cards.
    },
  },
};
```

### Setting Default Chains and Tokens

Widget gives you the option to set default chains and tokens to be shown to the user. This can be done by passing `defaultChains` and `defaultTokens` in configuration when initializing the widget.\
See list of supported chains and tokens below.

{% content-ref url="/pages/FIOBdT70ECwvChUfPKda" %}
[Supported Chains](/compass-api/supported-chains)
{% endcontent-ref %}

{% content-ref url="/pages/zGsOamwv5gouUJwe8QQ7" %}
[Get Supported Chains & Tokens](/compass-api/api-reference/get-supported-chains-and-tokens)
{% endcontent-ref %}

```jsx
const configuration = {
  defaultChains: {
    from: { chainId: "10" }, // optimism
    to: { chainId: "sol" }, // solana
  },
  defaultTokens: {
    from: { tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" }, // eth on optimism
    to: { tokenAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }, // usdc on solana
  },
  ...
};
```

Note: token address for native tokens is set to 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

### Add custom widget heading

There is an option to customise the widget heading, here is how to do it,

```javascript
const configuration={
   headingText: "", // Text to display as the widget heading - pass the heading as string to display your own heading, default text is LAZY.exchange.
      headingContainerStyles: {// Styles to customize the container that wraps the heading,
        transform: "skewX(0deg)", // Supports all valid CSS style properties.
        left: "0px",
        top: "0px",
      },
      // Styles to customize the heading text itself,
      // Supports all valid CSS style properties.
      headingStyles: {
        transform: "skewX(0deg)",
      },
}
```

### Transaction Page Persistance

You can control whether the transaction page state is maintained when the page is reloaded by setting the `persistTxnData` option. This setting determines if users stay on the transaction page after a page refresh.

Copy

```
const configuration = {
  persistTxnData: false, // true (default)
  ...
};
```

**Options:**

* `true` (default): The transaction page state is preserved when the page is reloaded - users will remain on the transaction page
* `false`: The transaction page state is not preserved - users will return to the main widget page after reload

**Use Cases:**

* Set to `false` if you want users to always start fresh on the main widget page after reload
* Set to `true` (default) to maintain the transaction flow continuity even after page refresh


# Widget Studio

Widget Studio is an interactive configuration tool that helps you customize your Blockend Widget visually. Instead of manually writing JSON configuration objects, you can use the intuitive interface to:

* ✨ Customize themes and colors
* 🎨 Style container and gradients
* ⚙️ Set default chains and tokens
* 📝 Generate configuration code
* 🔄 Import/export configurations

#### Access Widget Studio

Visit our Widget Studio

{% embed url="<https://studio.lazy.exchange/>" %}

#### Key Features

**Visual Theme Editor**

* Switch between light/dark themes
* Create custom color schemes
* Customize text, background, and border colors
* Real-time preview of changes

**Styling Controls**

* Container border and shadow customization
* Gradient background configuration
* Typography and font settings
* Heading text and positioning

**Configuration Management**

* **Copy Configuration**: Export your settings as JSON
* **Paste Your Config**: Import existing configurations
* **Reset**: Return to default settings
* **Live Preview**: See changes instantly

**Default Chain & Token Setup**

* Set default source and destination chains
* Configure default token addresses
* Prevent same-chain selection errors

#### How to Use

1. **Open Widget Studio** and start with the default configuration
2. **Customize Settings** using the Design tab controls
3. **Preview Changes** in real-time on the widget
4. **Copy Configuration** from the Code tab
5. **Integrate** the configuration into your app

#### Integration Example

After customizing in Widget Studio, copy the generated configuration:

```javascript
import Blockend from "@blockend/widget";
import "@blockend/widget/dist/style.css";

// Configuration generated from Widget Studio
const configuration = {
  integratorId: "YOUR_INTEGRATOR_ID",
  theme: "dark",
  gradientStyle: {
    background: "linear-gradient(135deg, #2CFFE4, #A45EFF)",
    spinnerColor: "#2CFFE4",
    stopColor: "#A45EFF"
  },
  containerStyle: {
    border: "1px solid #353535",
    borderRadius: "12px"
  },
  defaultChains: {
    from: { chainId: "1" },
    to: { chainId: "10" }
  }
  // ... other customizations
};

export const Home = () => {
  return <Blockend configuration={configuration} />;
};
```

#### Import/Export Configurations

**Exporting Configuration**

1. Customize your widget in the Design tab
2. Navigate to the Code tab
3. Click the copy icon to copy the configuration JSON
4. Save it for future use or sharing

**Importing Configuration**

1. Navigate to the Code tab
2. Scroll to "Paste Your Config" section
3. Paste your JSON configuration
4. Click "Paste Your Config" to apply
5. Widget updates instantly with your settings


# Embed Widget

The iframe integration allows you to embed the Blockend widget using the URL `https://www.blockend.com/embedwidget` with optional URL parameters and postMessage API for dynamic configuration.

**Key Features:**

* URL parameters for initial configuration
* PostMessage API for dynamic updates
* Automatic height adjustment
* Theme customization
* Default chain and token selection

**💡 Need help with configuration?** Use the [Widget Studio](https://studio.lazy.exchange/) to generate your widget configuration.

### Quick Start

#### Basic Implementation

```html
<iframe src="https://www.blockend.com/embedwidget?integratorId=YOUR_INTEGRATOR_ID" width="100%" height="600px" frameborder="0"> </iframe>
```

Note:  integratorId is required

#### React Implementation

Dynamically update height if you want the iframe to match the height of the widget.

```jsx
import React, { useEffect, useState, useRef } from "react";

function BlockendWidget() {
  const [height, setHeight] = useState(0);
  const iframeRef = useRef(null);

  useEffect(() => {
    const handleMessage = (event) => {
      if (event.data.type === "BLOCKEND_HEIGHT_UPDATE") {
        setHeight(event.data.height);
      }
    };

    window.addEventListener("message", handleMessage);
    return () => window.removeEventListener("message", handleMessage);
  }, []);
  
useEffect(() => {
    // Request for the widget height
    window.postMessage(
      {
        type: "BLOCKEND_REQUEST_HEIGHT",
      },
      "*"
    );
  }, []);
  
  return <iframe ref={iframeRef} src="https://www.blockend.com/embedwidget?integratorId=YOUR_INTEGRATOR_ID" width="100%" height={height} style={{ border: "none" }} />;
}
```

### URL Parameters

URL parameters provide initial configuration for the widget. These parameters have higher precedence than postMessage configurations.

#### Available Parameters

| Parameter      | Type   | Description                              | Example                                               |
| -------------- | ------ | ---------------------------------------- | ----------------------------------------------------- |
| `integratorId` | string | **Required** - Your unique integrator ID | `integratorId=`YOUR\_INTEGRATOR\_ID                   |
| `theme`        | string | Widget theme (`light` or `dark`)         | `theme=dark`                                          |
| `headingText`  | string | Custom widget heading                    | `headingText=Lazy%20Exchange`                         |
| `fromChain`    | string | Default source chain ID                  | `fromChain=137`                                       |
| `toChain`      | string | Default destination chain ID             | `toChain=1`                                           |
| `fromCoin`     | string | Default source token address             | `fromCoin=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` |
| `toCoin`       | string | Default destination token address        | `toCoin=0xA0b86a33E6441b8C4C8C8C8C8C8C8C8C8C8C8C8C`   |

#### URL Example

```
https://www.blockend.com/embedwidget?integratorId=YOUR_INTEGRATOR_ID&theme=dark&fromChain=137&headingText=Lazy%20Exchange&fromCoin=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
```

### PostMessage API

The postMessage API enables dynamic configuration and communication between your application and the embedded widget.

#### Message Types

**1. Configuration Message**

Send configuration updates to the widget:

```javascript
// Send configuration to widget
iframe.contentWindow.postMessage(
  {
    type: "BLOCKEND_CONFIG",
    config: {
      theme: "dark",
      defaultChains: {
        from: { chainId: "137" }, // Polygon
        to: { chainId: "1" }, // Ethereum
      },
      defaultTokens: {
        from: { tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" }, // Native token
        to: { tokenAddress: "0xA0b86a33E6441b8C4C8C8C8C8C8C8C8C8C8C8C8C" }, // USDC
      },
      headingText: "Custom Exchange",
      gradientStyle: {
        background: "linear-gradient(#E66465, #9198E5)",
        spinnerColor: "#E66465",
        stopColor: "#9198E5",
      },
      customTheme: {
        text: {
          primary: "#808080",
          secondary: "rgba(128, 128, 128, 0.75)",
          placeholder: "#cccccc",
          success: "#49AD71",
          error: "#FD5868",
        },
        background: {
          container: "#FFFFFF",
          secondary: "#E9E9E9",
          networkCard: "#F6F6F6",
        },
        border: {
          primary: "#E0E0E0",
        },
        fontFamily: '"Arial", sans-serif',
        shadow: {
          boxShadow: "1px 1px 7px 5px rgb(255,255,255,0.1)",
        },
      },
    },
  },
  "*"
);
```

**2. Height Request Message**

Request current widget height:

```javascript
// Request height from widget
iframe.contentWindow.postMessage(
  {
    type: "BLOCKEND_REQUEST_HEIGHT",
  },
  "*"
);
```

#### Received Messages

**1. Configuration Request**

The widget requests configuration on load:

```javascript
window.addEventListener("message", (event) => {
  if (event.data.type === "BLOCKEND_REQUEST_CONFIG") {
    // Send configuration back to widget
    iframe.contentWindow.postMessage(
      {
        type: "BLOCKEND_CONFIG",
        config: {
          // Your configuration here
        },
      },
      "*"
    );
  }
});
```

**2. Configuration Confirmation**

Confirmation that configuration was received:

```javascript
window.addEventListener("message", (event) => {
  if (event.data.type === "BLOCKEND_CONFIG_RECEIVED") {
    console.log("Configuration received by widget:", event.data.success);
  }
});
```

**3. Height Updates**

Automatic height updates from the widget:

```javascript
window.addEventListener("message", (event) => {
  if (event.data.type === "BLOCKEND_HEIGHT_UPDATE") {
    const newHeight = event.data.height;
    // Update iframe height using react state
    setHeight(newHeight);
  }
});
```

### Complete Implementation Example

#### React Component with Full Features

<pre class="language-jsx"><code class="lang-jsx">import React, { useEffect, useState, useRef } from "react";

function BlockendWidget() {
  const [height, setHeight] = useState(600);
  const [isConfigured, setIsConfigured] = useState(false);
  const iframeRef = useRef(null);

  useEffect(() => {
    const handleMessage = (event) => {
      switch (event.data.type) {
        case "BLOCKEND_REQUEST_CONFIG":
          // Send configuration to widget
<strong>          iframeRef.current?.contentWindow?.postMessage(
</strong>            {
              type: "BLOCKEND_CONFIG",
              config: {
                theme: "dark",
                defaultChains: {
                  from: { chainId: "137" },
                  to: { chainId: "1" },
                },
                defaultTokens: {
                  from: { tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" },
                  to: { tokenAddress: "0xA0b86a33E6441b8C4C8C8C8C8C8C8C8C8C8C8C8C" },
                },
                headingText: "My Exchange",
                gradientStyle: {
                  background: "linear-gradient(#E66465, #9198E5)",
                  spinnerColor: "#E66465",
                  stopColor: "#9198E5",
                },
              },
            },
            "*"
          );
          break;

        case "BLOCKEND_CONFIG_RECEIVED":
          setIsConfigured(event.data.success);
          break;

        case "BLOCKEND_HEIGHT_UPDATE":
          // Widget responds with the height
          setHeight(event.data.height);
          break;
      }
    };

    window.addEventListener("message", handleMessage);
    return () => window.removeEventListener("message", handleMessage);
  }, []);

  useEffect(() => {
    // Request for the widget height
    window.postMessage(
      {
        type: "BLOCKEND_REQUEST_HEIGHT",
      },
      "*"
    );
  }, []);

  return (
    &#x3C;div className="widget-container">
      &#x3C;iframe
        ref={iframeRef}
        src="https://blockend.com/embedwidget?integratorId=YOUR_INTEGRATOR_ID&#x26;theme=dark"
        width="100%"
        height={height}
        style={{
          border: "none",
          borderRadius: "12px",
          boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
        }}
        title="Blockend Widget"
      />
    &#x3C;/div>
  );
}

export default BlockendWidget;
</code></pre>

For easy configuration generation, use the [Widget Studio](https://studio.lazy.exchange/) to:

* Customize widget themes and styling
* Set default chains and tokens
* Preview your widget configuration
* Get ready-to-use configuration code

#### Vanilla JavaScript Implementation

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blockend Widget Integration</title>
    <style>
      .widget-container {
        max-width: 500px;
        margin: 20px auto;
        padding: 20px;
      }
      .blockend-widget {
        border: none;
        border-radius: 12px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div class="widget-container">
      <iframe id="blockend-widget" class="widget-iframe" src="https://blockend.com/embedwidget?integratorId=YOUR_INTEGRATOR_ID&theme=dark" height="600"> </iframe>
    </div>

    <script>
      const iframe = document.getElementById("blockend-widget");
      let isConfigured = false;

      window.addEventListener("message", (event) => {
        switch (event.data.type) {
          case "BLOCKEND_REQUEST_CONFIG":
            iframe.contentWindow.postMessage(
              {
                type: "BLOCKEND_CONFIG",
                config: {
                  theme: "dark",
                  defaultChains: {
                    from: { chainId: "137" },
                    to: { chainId: "1" },
                  },
                  headingText: "My Exchange",
                },
              },
              "*"
            );
            break;

          case "BLOCKEND_CONFIG_RECEIVED":
            isConfigured = event.data.success;
            console.log("Widget configured:", isConfigured);
            break;

          case "BLOCKEND_HEIGHT_UPDATE":
            iframe.style.height = `${event.data.height}px`;
            break;
        }
      });

      // Request initial height
      setTimeout(() => {
        window.postMessage(
          {
            type: "BLOCKEND_REQUEST_HEIGHT",
          },
          "*"
        );
      }, 1000);
    </script>
  </body>
</html>
```

For easy configuration generation, use the [Widget Studio](https://studio.lazy.exchange/) to:

* Customize widget themes and styling
* Set default chains and tokens
* Preview your widget configuration
* Get ready-to-use configuration code

### Best Practices

#### 1. Security Considerations

* Always validate message origins in production
* Use specific origins instead of `'*'` when possible
* Sanitize configuration data before sending

```javascript
// Production-ready message handler
window.addEventListener("message", (event) => {
  // Validate origin
  if (event.origin !== "https://www.blockend.com") {
    return;
  }

  // Handle messages
  // ...
});
```

#### 2. Performance Optimization

* Debounce height updates to prevent excessive reflows
* Use `requestAnimationFrame` for smooth height transitions
* Implement proper cleanup in React components

#### 3. Error Handling

```javascript
window.addEventListener("message", (event) => {
  try {
    if (event.data.type === "BLOCKEND_HEIGHT_UPDATE") {
      const height = event.data.height;
      if (typeof height === "number" && height > 0) {
        iframe.style.height = `${height}px`;
      }
    }
  } catch (error) {
    console.error("Error handling widget message:", error);
  }
});
```


# Widget Events

This guide explains how to integrate and use these events in your application.

```javascript
import Blockend, { blockendEventsConstants, useBlockendEvents } from "@blockend/widget";
```

### Event System Overview

The widget uses [mitt](https://github.com/developit/mitt) as the underlying event emitter, providing a lightweight and efficient event system. The `useBlockendEvents` hook returns a mitt instance that you can use to listen to widget events.

### Setting Up Event Listeners

#### Basic Setup

```javascript
import React, { useEffect } from "react";
import { useBlockendEvents, blockendEventsConstants } from "@blockend/widget";

function MyApp() {
  const eventEmitter = useBlockendEvents();

  useEffect(() => {
    // Subscribe to events
    const handleTransactionStarted = (data) => {
      console.log("Transaction started:", data);
    };

    eventEmitter.on(blockendEventsConstants.TransactionStarted, handleTransactionStarted);

    // Cleanup on unmount
    return () => {
      eventEmitter.off(blockendEventsConstants.TransactionStarted, handleTransactionStarted);
    };
  }, [eventEmitter]);

  return (
    <div>
      <Blockend />
    </div>
  );
}
```

#### Complete Event Listener Setup

```javascript
import React, { useEffect } from "react";
import { useBlockendEvents, blockendEventsConstants } from "@blockend/widget";

function MyApp() {
  const eventEmitter = useBlockendEvents();

  useEffect(() => {
    // Transaction Started Event
    const handleTransactionStarted = (data) => {
      console.log("🚀 Transaction Started:", data);
      // Handle transaction initiation
    };

    // Transaction Steps Event
    const handleTransactionSteps = (data) => {
      console.log("📋 Transaction Steps:", data);
      // Handle step information
    };

    // Transaction Data Event
    const handleTransactionData = (data) => {
      console.log("📄 Transaction Data:", data);
      // Handle transaction data updates
    };

    // Transaction Status Event
    const handleTransactionStatus = (data) => {
      console.log("📊 Transaction Status:", data);
      // Handle status updates
    };

    // Submit Signed Transaction Event
    const handleSubmitSignedTxn = (data) => {
      console.log("✍️ Submit Signed Transaction:", data);
      // Handle transaction submission results
    };

    // Register all event listeners
    eventEmitter.on(blockendEventsConstants.TransactionStarted, handleTransactionStarted);
    eventEmitter.on(blockendEventsConstants.TransactionSteps, handleTransactionSteps);
    eventEmitter.on(blockendEventsConstants.TransactionData, handleTransactionData);
    eventEmitter.on(blockendEventsConstants.TransactionStatus, handleTransactionStatus);
    eventEmitter.on(blockendEventsConstants.SubmitSignedTxn, handleSubmitSignedTxn);

    // Cleanup function
    return () => {
      eventEmitter.all.clear();
    };
  }, [eventEmitter]);

  return (
    <div>
      <Blockend consfiguration={...}/>
    </div>
  );
}
```

### Available Events

#### 1. TransactionStarted

**Event Name:** `blockendEventsConstants.TransactionStarted`

**When Triggered:** When a user initiates a transaction through the widget

```javascript
{
  // Contains the complete route data including:
  routeId: "string",
  fee: [
    {
      amountInToken: "number",
      token: {
        address: "string",
        symbol: "string",
        decimals: number,
        chainId: "string",
        blockchain: "string",
        networkType: "string"
      },
      source: "string"
    }
  ],
  // ... other route properties
}
```

**Example Usage:**

```javascript
eventEmitter.on(blockendEventsConstants.TransactionStarted, (data) => {
  // Track transaction initiation
  analytics.track("Transaction Started", {
    routeId: data.routeId,
    fromToken: data.fromToken,
    toToken: data.toToken,
  });

  // Show loading state
  setTransactionInProgress(true);
});
```

#### 2. TransactionSteps

**Event Name:** `blockendEventsConstants.TransactionSteps`

**When Triggered:** When transaction steps are created or when step-related errors occur

**Data Structure:**

```javascript
// Success case
{
  routeId: "string",
  steps: [
    {
      stepId: "string",
      // ... step details
    }
  ],
  numOfSteps: number
}

// Error case
{
  error: "string",
  routeId: "string",
  status: "error"
}
```

**Example Usage:**

```javascript
eventEmitter.on(blockendEventsConstants.TransactionSteps, (data) => {
  if (data.error) {
    // Handle step creation error
    showNotification("Error creating transaction steps: " + data.error, "error");
    return;
  }

  // Update UI with step information
  setTransactionSteps(data.steps);
  setTotalSteps(data.numOfSteps);
});
```

#### 3. TransactionData

**Event Name:** `blockendEventsConstants.TransactionData`

**When Triggered:** When transaction data is fetched for each step or when data-related errors occur

**Data Structure:**

```javascript
// Success case
{
  data: {
    txnData: {
      txnEvm: "object", // EVM transaction data
      txnType: "string",
      gasless: boolean
    },
    // ... other transaction data
  },
  status: "success"
}

// Error case
{
  error: "string",
  routeId: "string",
  stepId: "string"
}
```

**Example Usage:**

```javascript
eventEmitter.on(blockendEventsConstants.TransactionData, (data) => {
  if (data.error) {
    // Handle transaction data error
    showNotification("Error fetching transaction data: " + data.error, "error");
    return;
  }

  // Process transaction data
  if (data.data?.txnData?.gasless) {
    showNotification("Gasless transaction detected!", "info");
  }

  setCurrentTransactionData(data);
});
```

#### 4. TransactionStatus

**Event Name:** `blockendEventsConstants.TransactionStatus`

**When Triggered:** When polling for transaction status updates

**Data Structure:**

```javascript
{
  data: {
    status: "pending" | "success" | "failed" | "partial-success" | "in-progress",
    // ... other status data
  },
  status: "pending" | "success" | "failed" | "partial-success" | "in-progress",
  isLastStep: boolean
}
```

**Example Usage:**

```javascript
eventEmitter.on(blockendEventsConstants.TransactionStatus, (data) => {
  const { status, isLastStep } = data;

  switch (status) {
    case "pending":
      showNotification("Transaction pending...", "info");
      break;
    case "success":
      if (isLastStep) {
        showNotification("Transaction completed successfully!", "success");
        setTransactionInProgress(false);
      } else {
        showNotification("Step completed, proceeding to next step...", "info");
      }
      break;
    case "failed":
      showNotification("Transaction failed", "error");
      setTransactionInProgress(false);
      break;
    case "partial-success":
      showNotification("Transaction partially completed", "warning");
      break;
    case "in-progress":
      showNotification("Transaction in progress...", "info");
      break;
  }

  // Update progress indicator
  updateTransactionProgress(status, isLastStep);
});
```

#### 5. SubmitSignedTxn

**Event Name:** `blockendEventsConstants.SubmitSignedTxn`

**When Triggered:** When a signed transaction is submitted to the blockchain

**Data Structure:**

```javascript
// Success case
{
  data: {
    // Submission response data
    txnHash: "string",
    // ... other response data
  }
}

// Error case
{
  error: "string",
  status: "Transaction submission failed!"
}
```

**Example Usage:**

```javascript
eventEmitter.on(blockendEventsConstants.SubmitSignedTxn, (data) => {
  if (data.error) {
    // Handle submission error
    showNotification(`Submission failed: ${data.error}`, "error");
    analytics.track("Transaction Submission Failed", { error: data.error });
    return;
  }

  // Handle successful submission
  showNotification("Transaction submitted successfully!", "success");
  analytics.track("Transaction Submitted", {
    txnHash: data.data?.txnHash,
  });

  // Store transaction hash for tracking
  setTransactionHash(data.data?.txnHash);
});
```

### Advanced Usage Patterns

#### Transaction Progress Tracking

```javascript
function TransactionTracker() {
  const eventEmitter = useBlockendEvents();
  const [progress, setProgress] = useState({
    status: "idle",
    currentStep: 0,
    totalSteps: 0,
    error: null,
  });

  useEffect(() => {
    const handleTransactionStarted = () => {
      setProgress((prev) => ({ ...prev, status: "started" }));
    };

    const handleTransactionSteps = (data) => {
      if (data.error) {
        setProgress((prev) => ({ ...prev, error: data.error, status: "error" }));
        return;
      }
      setProgress((prev) => ({ ...prev, totalSteps: data.numOfSteps }));
    };

    const handleTransactionStatus = (data) => {
      if (data.status === "success" && data.isLastStep) {
        setProgress((prev) => ({ ...prev, status: "completed" }));
      } else if (data.status === "failed") {
        setProgress((prev) => ({ ...prev, status: "failed" }));
      }
    };

    eventEmitter.on(blockendEventsConstants.TransactionStarted, handleTransactionStarted);
    eventEmitter.on(blockendEventsConstants.TransactionSteps, handleTransactionSteps);
    eventEmitter.on(blockendEventsConstants.TransactionStatus, handleTransactionStatus);

    return () => {
      eventEmitter.off(blockendEventsConstants.TransactionStarted, handleTransactionStarted);
      eventEmitter.off(blockendEventsConstants.TransactionSteps, handleTransactionSteps);
      eventEmitter.off(blockendEventsConstants.TransactionStatus, handleTransactionStatus);
    };
  }, [eventEmitter]);

  return (
    <div>
      <ProgressBar status={progress.status} currentStep={progress.currentStep} totalSteps={progress.totalSteps} />
      {progress.error && <ErrorMessage message={progress.error} />}
    </div>
  );
}
```

### Best Practices

1. **Always Clean Up Event Listeners**: Make sure to remove event listeners in the cleanup function to prevent memory leaks.
2. **Handle Error Cases**: Always check for error properties in event data and handle them appropriately.
3. **Use Event Constants**: Always use `blockendEventsConstants` instead of hardcoded strings to avoid typos.

### Troubleshooting

#### Events Not Firing

* Ensure you're importing the hook correctly: `import { useBlockendEvents } from '@blockend/widget'`
* Verify that the widget is properly mounted before setting up event listeners
* Check that you're using the correct event constants

#### Memory Leaks

* Always clean up event listeners in useEffect cleanup functions
* Avoid creating new handler functions on every render - use useCallback if necessary

#### TypeScript Errors

* Make sure you have the latest version of the widget package
* Import types properly: `import type { ... } from '@blockend/widget'`


# Wallet Management

Overview

The Blockend Widget features intelligent wallet management that seamlessly integrates with your existing dApp's wallet setup. The widget automatically detects and reuses external wallet providers when available, providing a unified user experience without requiring users to connect multiple times.

### Key Features

* **Automatic Provider Detection**: Detects existing Wagmi, Dynamic Labs, and TanStack Query providers
* **Multi-Chain Support**: Handles automatic provider detection(External Providers) for EVM and Solana.
* **Fallback Providers**: Uses internal providers when external ones aren't available for the supported ecosystems.
* **Zero Configuration**: Works out of the box with Wagmi and @dynamic-labs(Solana) based libraries

### Architecture

The widget uses a conditional provider system that checks for external providers before initialising internal ones:

```mermaid
graph TD
    A[Widget Initialization] --> B[Check External Providers]
    B --> C{Wagmi Provider Found?}
    C -->|Yes| D[Use External Wagmi]
    C -->|No| E[Use Internal Wagmi]

    B --> F{Dynamic Provider Found?}
    F -->|Yes| G[Use External Dynamic]
    F -->|No| H[Use Internal Dynamic]

    B --> I{Query Client Found?}
    I -->|Yes| J[Use External Query Client]
    I -->|No| K[Use Internal Query Client]

    D --> L[Widget Ready]
    E --> L
    G --> L
    H --> L
    J --> L
    K --> L
```

### Supported Provider Libraries

#### EVM Wallet Management

The widget supports the following EVM wallet management libraries:

* **Wagmi v2**: Core Web3 React library
* **RainbowKit**: Built on top of Wagmi
* **Reown AppKit** (formerly WalletConnect): Universal wallet connector

#### Solana Wallet Management

* **Dynamic Labs**: Solana support
* **Solana Wallet Adapter**: Standard Solana wallet library

### Integration Examples

#### Basic Integration (Uses Internal Providers)

```jsx
import Blockend from "@blockend/widget";
import "@blockend/widget/dist/style.css";

function App() {
  return (
    <div>
      {/* Widget will use its internal providers */}
      <Blockend
        configuration={{
          integratorId: "your-integrator-id",
        }}
      />
    </div>
  );
}
```

## Integration for EVM wallets

#### Integration with Wagmi

```jsx
import { WagmiProvider, createConfig, http } from "wagmi";
import { mainnet, polygon, arbitrum } from "wagmi/chains";
import { injected, walletConnect } from "wagmi/connectors";
import Blockend from "@blockend/widget";
import "@blockend/widget/dist/style.css";

const config = createConfig({
  chains: [mainnet, polygon, arbitrum],
  connectors: [injected(), walletConnect({ projectId: "your-project-id" })],
  transports: {
    [mainnet.id]: http(),
    [polygon.id]: http(),
    [arbitrum.id]: http(),
  },
});

function App() {
  return (
    <WagmiProvider config={config}>
      {/* Widget automatically detects and uses your Wagmi setup */}
      <Blockend
        configuration={{
          integratorId: "your-integrator-id",
        }}
      />
    </WagmiProvider>
  );
}
```

#### Integration with RainbowKit

```jsx
import "@rainbow-me/rainbowkit/styles.css";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider } from "wagmi";
import { RainbowKitProvider, getDefaultConfig } from "@rainbow-me/rainbowkit";
import { mainnet, polygon, arbitrum } from "wagmi/chains";
import Blockend from "@blockend/widget";
import "@blockend/widget/dist/style.css";

const config = getDefaultConfig({
  appName: "My RainbowKit App",
  projectId: "YOUR_WALLETCONNECT_PROJECT_ID",
  chains: [mainnet, polygon, arbitrum],
});

const queryClient = new QueryClient();

function App() {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <RainbowKitProvider>
          {/* Widget uses your RainbowKit/Wagmi setup */}
          <Blockend
            configuration={{
              integratorId: "your-integrator-id",
            }}
          />
        </RainbowKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  );
}
```

**Important**: For the widget to work on all supported chains, you must add the widget-supported chains to your Wagmi configuration. Here is the list of supported EVM chains:

Ethereum (mainnet)\
Polygon\
Arbitrum\
Optimism\
BSC\
zkSYNC Era\
BASE\
Avalanche\
Gnosis\
Fantom\
Moonriver\
Moonbeam\
Fuse\
OKXchain\
Boba\
Aurora\
Cronos\
Heco\
Harmony\
Linea\
RootStock\
Mode\
Celo\
Mantle\
Scroll\
Blast\
Berachain\
Unichain\
Sonic\
Story\
Polygon zkEVM

Alternatively, you can dynamically fetch the latest supported chains by calling the Blockend API and filtering for EVM chains using `networkType: 'evm'`:

```bash
curl -X GET "https://api2.blockend.com/v1/chains"
```

This approach ensures you always have the most up-to-date list of supported chains.

or use useUpdateWagmiConfig hook

## useUpdateWagmiConfig Hook

### Purpose

The `useUpdateWagmiConfig` hook synchronizes your Wagmi configuration with the Blockend widget's supported chains, ensuring wallet connections work across all widget networks.

### Usage

```javascript
import { useUpdateWagmiConfig } from "@blockend/widget";
import {useState,useEffect} from "react";
function MyApp() {
//fetch chains from blockend api
const [chains,setChains]=useState([])
useEffect(()=>{
fetch('https://api2.blockend.com/v1/chains').then(res=>res.json()).res(res=>{setChains(res.data)})
},[])
  useUpdateWagmiConfig(
    config, // Your Wagmi config
    config.connectors, // Your connectors
    chains || [] // Widget chain data
  );

  return (
    <WagmiProvider config={config}>
      <BlockendWidget />
    </WagmiProvider>
  );
}
```

### Parameters

* `config`: Wagmi configuration object
* `connectors`: Array of Wagmi connectors
* `chains`: Array of chain data from widget (must have `networkType: "evm"`)

The hook automatically converts widget chains to Wagmi format and updates your config.

## Integration for Solana wallets

#### Integration with Dynamic Labs for Solana wallets

<pre class="language-jsx"><code class="lang-jsx">import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";
<strong>import { SolanaWalletConnectors } from "@dynamic-labs/solana";
</strong>import Blockend from "@blockend/widget";
import "@blockend/widget/dist/style.css";

function App() {
  return (
    &#x3C;DynamicContextProvider
      settings={{
        environmentId: "your-environment-id",
        walletConnectors: [SolanaWalletConnectors],
      }}
    >
      {/* Widget uses your Dynamic setup for Solana */}
      &#x3C;Blockend
        configuration={{
          integratorId: "your-integrator-id",
        }}
      />
    &#x3C;/DynamicContextProvider>
  );
}
</code></pre>

#### Full Stack Integration

```jsx
import { WagmiProvider, createConfig, http } from "wagmi";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";
import { SolanaWalletConnectors } from "@dynamic-labs/solana";
import { mainnet, polygon, arbitrum } from "wagmi/chains";
import { injected, walletConnect } from "wagmi/connectors";
import Blockend from "@blockend/widget";
import "@blockend/widget/dist/style.css";

const wagmiConfig = createConfig({
  chains: [mainnet, polygon, arbitrum],
  connectors: [injected(), walletConnect({ projectId: "your-project-id" })],
  transports: {
    [mainnet.id]: http(),
    [polygon.id]: http(),
    [arbitrum.id]: http(),
  },
});

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <WagmiProvider config={wagmiConfig}>
        <DynamicContextProvider
          settings={{
            environmentId: "your-environment-id",
            walletConnectors: [SolanaWalletConnectors],
          }}
        >
          {/* Widget uses all your external providers */}
          <Blockend
            configuration={{
              integratorId: "your-integrator-id",
            }}
          />
        </DynamicContextProvider>
      </WagmiProvider>
    </QueryClientProvider>
  );
}
```

### Troubleshooting

#### Common Issues

**1. Widget Not Detecting External Providers**

**Problem**: Widget uses internal providers even when external ones are available.

**Solution**: Ensure the widget is wrapped inside the provider components:

```jsx
// ❌ Incorrect - Widget outside providers
<div>
  <Blockend />
  <WagmiProvider config={config}>
    <YourApp />
  </WagmiProvider>
</div>

// ✅ Correct - Widget inside providers
<WagmiProvider config={config}>
  <div>
    <YourApp />
    <Blockend />
  </div>
</WagmiProvider>
```

**2. Chain Switching Issues**

**Problem**: Chain switching doesn't work properly.

**Solution**: Ensure your Wagmi config includes all the chains supported by the widget:

```jsx
const config = createConfig({
  chains: [
    mainnet,
    polygon,
    arbitrum, // Add all supported chains
  ],
  // ... rest of config
});
```

**3. Multiple Wallet Connection Prompts**

**Problem**: Users see multiple wallet connection prompts.

**Solution**: This usually happens when providers are not properly detected. Check the browser console for provider detection logs.

**4. Solana Wallet Issues**

**Problem**: Solana wallets not working with Dynamic Labs integration.

**Solution**: Ensure you have the correct Dynamic Labs environment setup:

```jsx
<DynamicContextProvider
  settings={{
    environmentId: 'your-environment-id', // Correct environment ID
    walletConnectors: [SolanaWalletConnectors], // Include Solana connectors
    initialAuthenticationMode: 'connect-only',
  }}
>
```

### Migration Guide

#### From Internal to External Providers

If you're currently using the widget with internal providers and want to migrate to external providers:

**Step 1: Install Required Dependencies**

```bash
npm install wagmi viem @tanstack/react-query
# or for Solana
npm install @dynamic-labs/sdk-react-core @dynamic-labs/solana
```

**Step 2: Wrap Your App**

```jsx
// Before
function App() {
  return <Blockend configuration={configuration} />;
}

// After
function App() {
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        <Blockend configuration={configuration} />
      </QueryClientProvider>
    </WagmiProvider>
  );
}
```

**Step 3: Test Integration**

Verify that:

* Wallet connections work correctly
* Chain switching functions properly
* Transaction signing operates as expected


# Widget Lite

## Compass Widget Lite: A Streamlined Solution for Focused Use Cases

### Enable users to get the desired token seamlessly, directly on your DApp, with no distractions.

Widget Lite is designed to simplify core use cases, such as NFT checkouts or deposits into LP pools, by focusing on a clean, lightweight interface. It removes unnecessary features, providing users with a single recommended route tailored to the DApp’s customization preferences. This allows users to connect their wallet, view their balances, select the token they have, and specify the amount to transfer or deposit, all seamlessly handled with minimal effort.

With its lightweight design and seamless end-to-end execution, WidgetLite is perfect for scenarios requiring simplicity, speed, and precision.

### ***Note: WidgetLite is currently under active development and is expected to launch in a few weeks, bringing this streamlined solution to life.***


# API Reference


# Getting Started

### Base URL:

```
https://api2.blockend.com/v1/
```

All type definitions can be found [here](/compass-api/api-reference/type-definations)

### Core Transaction Flow <a href="#core-transaction-flow" id="core-transaction-flow"></a>

**1. Fetching quotes**

User flow begins with fetching quotes, which returns a list of quotes for the given input and output assets, along with the steps involved in the transaction. Quotes are by default sorted via best output and contains a scores object and tags to determine fastest/cheapest/best output routes.

{% content-ref url="/pages/XPUQxmIgNKUl7XmauUWB" %}
[Fetching Quotes](/compass-api/api-reference/fetching-quotes)
{% endcontent-ref %}

**2. Creating a transaction**

After fetching quotes, you can create a transaction using the selected quote by passing in the `routeId` of the quote.

{% content-ref url="/pages/k8ntX4gOMt4NWP7uHdLF" %}
[Create Transaction](/compass-api/api-reference/create-transaction)
{% endcontent-ref %}

**3. Getting transaction data to execute**

CommentCall this api with `routeId` and `stepId` of individual steps to get the transaction data to execute.

{% content-ref url="/pages/PyMbWnPLKHYMc2lVGRQx" %}
[Get Raw Transaction To Execute](/compass-api/api-reference/get-raw-transaction-to-execute)
{% endcontent-ref %}

**4. Check status of a transaction**

After user signs and submits the transaction on chain, check the status of the transaction by passing in the signature hash of the transaction.

{% content-ref url="/pages/rS87obNAN10ODquxuTI3" %}
[Check Transaction Status](/compass-api/api-reference/check-transaction-status)
{% endcontent-ref %}

**5. Using WebSockets for realtime updates (in active development)**

You can also check the status of a transaction using WebSockets. This can provide faster and almost realtime updates on the status of a transaction.

> Note: this feature is in active development and will be generally available soon. Contact us to get access to this feature.

**6. Single API for simple flow execution (in active development)**\
\
A simple 1 step endpoint is being worked on where a request directly gives you a single quote in response along with array of transaction data to execute to complete the transaction

> Note: this feature is in active development and will be generally available soon. Contact us to get access to this feature.

### Meta Endpoints <a href="#meta-endpoints-1" id="meta-endpoints-1"></a>

#### **​**[**Tokens**](/compass-api/api-reference/get-supported-chains-and-tokens)**​**

Get a list of supported tokens and their details.

```
curl -X GET "https://api2.blockend.com/v1/tokens"
```

#### **​**[**Chains**](/compass-api/supported-chains)**​**

Get a list of supported chains and their details.

```
curl -X GET "https://api2.blockend.com/v1/chains"
```


# Authentication

### Rate Limiting <a href="#rate-limiting" id="rate-limiting"></a>

Currently we only allow authenticated requests to our system, our APIs will be generally available soon.\
Rate limits with authentication: 200 requests per minute

### :handshake:Request for an API Key:

**Drop an email at**

&#x20;:e-mail: <sohail@blockend.com>

\
**Or Reach out on TG at**

&#x20;:mailbox\_with\_mail:  <https://t.me/StrayNomad>

### :shield:Authentication <a href="#authentication" id="authentication"></a>

While Compass API can be accessed without authentication, it is recommended to authenticate to get access to more features and higher rate limits.

To authenticate, you need to pass in the api-key in the request header.

```
const headers = {
    'x-api-key': 'YOUR_API_KEY'
};

fetch('https://api2.blockend.com/v1/tokens', { headers })
    .then(response => response.json())
    .then(data => console.log(data));
```

```
curl -X GET "https://api2.blockend.com/v1/tokens" \
    -H "x-api-key: YOUR_API_KEY"
```


# Fetching Quotes

Flow of a transaction starts with fetching quotes for it.

### Endpoint: `GET /quotes`&#x20;

```url
/quotes
    ?fromChainId=
    &fromAssetAddress=
    &toChainId=
    &toAssetAddress=
    &inputAmountDisplay=
    &userWalletAddress=
    &recipient=
```

### Query params <a href="#example" id="example"></a>

<table><thead><tr><th width="221">Field</th><th width="143">Type</th><th>Description</th></tr></thead><tbody><tr><td>fromChainId*</td><td>string</td><td>Source blockchain identifier</td></tr><tr><td>fromAssetAddress*</td><td>string</td><td>Token address on source chain</td></tr><tr><td>toChainId*</td><td>string</td><td>Destination blockchain identifier</td></tr><tr><td>toAssetAddress*</td><td>string</td><td>Token address on destination chain</td></tr><tr><td>inputAmountDisplay*</td><td>string</td><td>Human-readable input amount (e.g., “1.5”) <br><strong>Note:</strong> Either inputAmountDisplay or inputAmount should be passed</td></tr><tr><td>inputAmount*</td><td>string</td><td>Input amount in decimals units<br><strong>Note:</strong> Either inputAmountDisplay or inputAmount should be passed</td></tr><tr><td>userWalletAddress*</td><td>string</td><td>User’s wallet address</td></tr><tr><td>recipient</td><td>string</td><td>Final recipient of the tokens. If not provided userWalletAddress is used by default </td></tr><tr><td>slippage</td><td>number</td><td>Slippage tolerance in basis points (100 = 1%)</td></tr><tr><td>solanaOptions</td><td>SolanaOptions</td><td>Solana-specific parameters</td></tr><tr><td>evmOptions</td><td>EvmOptions</td><td>EVM-specific parameters</td></tr><tr><td>skipChecks</td><td>boolean</td><td>Skip validation checks</td></tr><tr><td>include</td><td>string</td><td>Comma-separated list of providers to include</td></tr><tr><td>exclude</td><td>string</td><td>Comma-separated list of providers to exclude</td></tr><tr><td>recommendedProvider</td><td>boolean</td><td>Use only recommended providers</td></tr></tbody></table>

**Solana Options**

<table><thead><tr><th width="187">Field</th><th width="198">Type</th><th>Description</th></tr></thead><tbody><tr><td>solanaPriorityFee</td><td>number | PriorityLevel</td><td>Priority fee in micro lamports or priority level</td></tr><tr><td>solanaJitoTip</td><td>number | PriorityLevel</td><td>Jito MEV tip in lamports or priority level</td></tr></tbody></table>

**Evm Options**

<table><thead><tr><th width="185">Field</th><th width="202">Type</th><th>Description</th></tr></thead><tbody><tr><td>evmPriorityFee</td><td>number | PriorityLevel</td><td>Priority fee in wei or priority level</td></tr></tbody></table>

```typescript
PriorityLevel = 'low' | 'medium' | 'high' | 'ultra' | 'degen'
```

### Response <a href="#example" id="example"></a>

A Route represents a complete path for token transfer, including all necessary steps and fee information.

<table><thead><tr><th width="243">Field</th><th width="146">Type</th><th>Description</th></tr></thead><tbody><tr><td>requestId</td><td>string</td><td>Unique identifier for the quote request</td></tr><tr><td>routeId</td><td>string</td><td>Unique identifier for this specific route</td></tr><tr><td>from</td><td>Asset</td><td>Source token details including chain and token information</td></tr><tr><td>to</td><td>Asset</td><td>Destination token details</td></tr><tr><td>steps</td><td>Steps[]</td><td>Array of execution steps (approval, swap, bridge, etc.)</td></tr><tr><td>fee</td><td>Fee[]</td><td>Breakdown of all fees involved</td></tr><tr><td>provider</td><td>Providers</td><td>Liquidity provider identifier</td></tr><tr><td>providerDetails</td><td>ProviderDetails</td><td>Additional provider information</td></tr><tr><td>protocolsUsed</td><td>string[]</td><td>List of protocols used in this route</td></tr><tr><td>inputAmount</td><td>string</td><td>Input amount in wei/native units</td></tr><tr><td>inputAmountDisplay</td><td>string</td><td>Human-readable input amount</td></tr><tr><td>outputAmount</td><td>string</td><td>Expected output in wei/native units</td></tr><tr><td>outputAmountDisplay</td><td>string</td><td>Human-readable output amount</td></tr><tr><td>minOutputAmount</td><td>string</td><td>Minimum output amount after slippage</td></tr><tr><td>minOutputAmountDisplay</td><td>string</td><td>Human-readable minimum output</td></tr><tr><td>slippage</td><td>number</td><td>Applied slippage tolerance in basis points</td></tr><tr><td>userWalletAddress</td><td>string</td><td>User's wallet address</td></tr><tr><td>recipient</td><td>string</td><td>Final recipient address</td></tr><tr><td>createdAt</td><td>number</td><td>Unix timestamp of quote creation</td></tr><tr><td>deadline</td><td>number</td><td>Unix timestamp when quote expires</td></tr><tr><td>estimatedTimeInSeconds</td><td>number</td><td>Estimated execution time</td></tr><tr><td>tags</td><td>string[]</td><td>Route classification tags</td></tr></tbody></table>

### Example <a href="#example" id="example"></a>

The following example shows how to get quotes for a cross-chain swap transaction from Ethereum to Solana. We'll be fetching quotes for ETH on Ethereum to USDC on Solana.

**Request:**

```url
https://api2.blockend.com/v1/quotes
    ?fromChainId=1
    &fromAssetAddress=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
    &toChainId=sol
    &toAssetAddress=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
    &inputAmountDisplay=0.420
    &userWalletAddress=0x17e7c3DD600529F34eFA1310f00996709FfA8d5c
    &recipient=7zSa114U45nJ8b8ALsuhszS2Kxto8grgedh65Q7xJYii
```

**Response:**

```json
{
    "status": "success",
    "data": {
        "quotes": [
            {
                "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
                "from": {
                    "networkType": "evm",
                    "chainId": "1",
                    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                    "decimals": 18,
                    "name": "Ethereum",
                    "symbol": "ETH",
                    "isNative": true,
                    "isPopular": true,
                    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                    "priceId": "ethereum",
                    "blockchain": "Ethereum",
                    "lastPrice": 3480.62
                },
                "to": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Solana",
                    "decimals": 6,
                    "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                    "networkType": "sol",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "sol",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "steps": [
                    {
                        "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
                        "stepType": "bridge",
                        "protocolsUsed": [
                            "Auction"
                        ],
                        "provider": "mayan",
                        "from": {
                            "networkType": "evm",
                            "chainId": "1",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Ethereum",
                            "symbol": "ETH",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                            "priceId": "ethereum",
                            "blockchain": "Ethereum",
                            "lastPrice": 3480.62
                        },
                        "to": {
                            "symbol": "USDC",
                            "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                            "priceId": "usd-coin",
                            "blockchain": "Solana",
                            "decimals": 6,
                            "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                            "networkType": "sol",
                            "isNative": false,
                            "isPopular": false,
                            "chainId": "sol",
                            "name": "USDC",
                            "lastPrice": 1.002
                        },
                        "fee": [
                            {
                                "token": {
                                    "networkType": "evm",
                                    "chainId": "1",
                                    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                                    "decimals": 18,
                                    "name": "Ethereum",
                                    "symbol": "ETH",
                                    "isNative": true,
                                    "isPopular": true,
                                    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                                    "priceId": "ethereum",
                                    "blockchain": "Ethereum",
                                    "lastPrice": 3480.62
                                },
                                "amount": "1380475027400000",
                                "amountInEther": "1380475027400000",
                                "amountInUSD": "4.804908989868988",
                                "type": "network"
                            }
                        ],
                        "inputAmount": "420000000000000000",
                        "outputAmount": "1459244847",
                        "estimatedTimeInSeconds": 900
                    }
                ],
                "fee": [
                    {
                        "token": {
                            "networkType": "evm",
                            "chainId": "1",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Ethereum",
                            "symbol": "ETH",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                            "priceId": "ethereum",
                            "blockchain": "Ethereum",
                            "lastPrice": 3480.62
                        },
                        "amount": "1380475027400000",
                        "amountInEther": "1380475027400000",
                        "amountInUSD": "4.804908989868988",
                        "type": "network"
                    }
                ],
                "provider": "mayan",
                "providerDetails": {
                    "id": "mayan",
                    "name": "Mayan",
                    "logoUrl": "https://blockend-widget.s3.ap-south-1.amazonaws.com/mayan.svg",
                    "websiteUrl": "https://mayan.finance/"
                },
                "protocolsUsed": [
                    "Auction"
                ],
                "inputAmount": "420000000000000000",
                "inputAmountDisplay": "0.420",
                "outputAmount": "1459244847",
                "outputAmountDisplay": "1459.244847",
                "minOutputAmount": "1459.098923",
                "minOutputAmountDisplay": "1459.098923",
                "slippage": 0,
                "recipient": "7zSa114U45nJ8b8ALsuhszS2Kxto8grgedh65Q7xJYii",
                "createdAt": 1721085515718,
                "deadline": 60,
                "estimatedTimeInSeconds": 900,
                "requestId": "01J2WB1K2D769PJRBMPNX1SKJT",
                "score": {
                    "outputScore": 1,
                    "speedScore": 0.0011111111111111111,
                    "feeScore": 1,
                    "slipparageScore": 0,
                    "stepScore": 1,
                    "outputDiffPercent": 0
                },
                "tags": [
                    "BEST_OUTPUT",
                    "CHEAP"
                ]
            },
            {
                "routeId": "01J2WB1MX7ZDHNB71GH3R52189",
                "from": {
                    "networkType": "evm",
                    "chainId": "1",
                    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                    "decimals": 18,
                    "name": "Ethereum",
                    "symbol": "ETH",
                    "isNative": true,
                    "isPopular": true,
                    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                    "priceId": "ethereum",
                    "blockchain": "Ethereum",
                    "lastPrice": 3480.62
                },
                "to": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Solana",
                    "decimals": 6,
                    "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                    "networkType": "sol",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "sol",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "steps": [
                    {
                        "stepId": "01J2WB1MX7BJA7ZSN8K4KXF1VA",
                        "stepType": "bridge",
                        "protocolsUsed": [
                            "deBridge"
                        ],
                        "provider": "dln",
                        "from": {
                            "networkType": "evm",
                            "chainId": "1",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Ethereum",
                            "symbol": "ETH",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                            "priceId": "ethereum",
                            "blockchain": "Ethereum",
                            "lastPrice": 3480.62
                        },
                        "to": {
                            "symbol": "USDC",
                            "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                            "priceId": "usd-coin",
                            "blockchain": "Solana",
                            "decimals": 6,
                            "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                            "networkType": "sol",
                            "isNative": false,
                            "isPopular": false,
                            "chainId": "sol",
                            "name": "USDC",
                            "lastPrice": 1.002
                        },
                        "fee": [
                            {
                                "type": "network",
                                "token": {
                                    "networkType": "evm",
                                    "chainId": "1",
                                    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                                    "decimals": 18,
                                    "name": "Ethereum",
                                    "symbol": "ETH",
                                    "isNative": true,
                                    "isPopular": true,
                                    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                                    "priceId": "ethereum",
                                    "blockchain": "Ethereum",
                                    "lastPrice": 3480.62
                                },
                                "amount": "5141425082200000",
                                "amountInEther": "5141425082200000",
                                "amountInUSD": "17.895346969606965"
                            }
                        ],
                        "inputAmount": "420000000000000000",
                        "outputAmount": "1449243299",
                        "estimatedTimeInSeconds": 1
                    }
                ],
                "fee": [
                    {
                        "type": "network",
                        "token": {
                            "networkType": "evm",
                            "chainId": "1",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Ethereum",
                            "symbol": "ETH",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
                            "priceId": "ethereum",
                            "blockchain": "Ethereum",
                            "lastPrice": 3480.62
                        },
                        "amount": "5141425082200000",
                        "amountInEther": "5141425082200000",
                        "amountInUSD": "17.895346969606965"
                    }
                ],
                "provider": "dln",
                "providerDetails": {
                    "id": "dln",
                    "name": "DLN",
                    "logoUrl": "https://dln.trade/assets/images/favicon/apple-touch-icon.png",
                    "websiteUrl": "https://dln.trade/"
                },
                "protocolsUsed": [
                    "deBridge"
                ],
                "inputAmount": "420000000000000000",
                "inputAmountDisplay": "0.420",
                "outputAmount": "1449243299",
                "outputAmountDisplay": "1449.243299",
                "minOutputAmount": "1449.243299",
                "minOutputAmountDisplay": "1449.243299",
                "slippage": 0.3,
                "recipient": "7zSa114U45nJ8b8ALsuhszS2Kxto8grgedh65Q7xJYii",
                "createdAt": 1721085514664,
                "deadline": 30,
                "estimatedTimeInSeconds": 1,
                "requestId": "01J2WB1K2D769PJRBMPNX1SKJT",
                "score": {
                    "outputScore": 0.9932454038279075,
                    "speedScore": 1,
                    "feeScore": 0.26850046540195793,
                    "slipparageScore": 0,
                    "stepScore": 1,
                    "outputDiffPercent": 0.00677748576178394
                },
                "tags": [
                    "BEST",
                    "FAST"
                ]
            }
        ]
    }
}
```


# Create Transaction

Once user selects a quote fetched from `/quotes` api, start the transaction by sending a request to `/createTx` api with the `routeId` of the selected quote. Response will contain updated steps for the transaction. These updated steps include any additional steps required to complete the transaction such as, but not limited to, ERC20 approvals.

### Endpoint: `GET /createTx`&#x20;

### Query params

```
/createTx?
    routeId=
```

### Response

```typescript
{
    "steps": Steps[];
}
```

### Example <a href="#exmaple" id="exmaple"></a>

Continuing example from `/quotes` api, let's start the transaction by sending a request to `/createTx` api with the `routeId` of the selected quote.

**Request:**

```
https://api2.bloclend.com/v1/createTx
    ?routeId=01J2WB2ZTWAWXN9K48899CSSVN
```

**Response:** The response for the selected quote now contains 2 steps. Additonal step being the approval step for USDC on Polygon chain.

```json
{
    "status": "success",
    "data": {
        "routeId": "01J2WB2ZTWAWXN9K48899CSSVN",
        "steps": [
            {
                "stepId": "01J2WB3JEB34B0A1SXHT1E3B63",
                "protocolsUsed": [
                    "Blockend"
                ],
                "stepType": "approval",
                "from": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Polygon",
                    "decimals": 6,
                    "address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
                    "networkType": "evm",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "137",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "to": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Polygon",
                    "decimals": 6,
                    "address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
                    "networkType": "evm",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "137",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "inputAmount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
                "outputAmount": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
                "fee": [
                    {
                        "type": "network",
                        "token": {
                            "networkType": "evm",
                            "chainId": "137",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Matic",
                            "symbol": "MATIC",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
                            "priceId": "matic-network",
                            "blockchain": "Polygon",
                            "lastPrice": 0.546532
                        },
                        "amount": "1800000001440000",
                        "amountInEther": "1800000001440000",
                        "amountInUSD": "0.0009837576007870061"
                    }
                ]
            },
            {
                "stepId": "01J2WB2ZTWXW6D39KJN7AAB3VV",
                "stepType": "bridge",
                "protocolsUsed": [
                    "deBridge"
                ],
                "provider": "dln",
                "from": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Polygon",
                    "decimals": 6,
                    "address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
                    "networkType": "evm",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "137",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "to": {
                    "symbol": "USDC",
                    "image": "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                    "priceId": "usd-coin",
                    "blockchain": "Solana",
                    "decimals": 6,
                    "address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                    "networkType": "sol",
                    "isNative": false,
                    "isPopular": false,
                    "chainId": "sol",
                    "name": "USDC",
                    "lastPrice": 1.002
                },
                "fee": [
                    {
                        "type": "network",
                        "token": {
                            "networkType": "evm",
                            "chainId": "137",
                            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                            "decimals": 18,
                            "name": "Matic",
                            "symbol": "MATIC",
                            "isNative": true,
                            "isPopular": true,
                            "image": "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
                            "priceId": "matic-network",
                            "blockchain": "Polygon",
                            "lastPrice": 0.546483
                        },
                        "amount": "518000000014400000",
                        "amountInEther": "518000000014400000",
                        "amountInUSD": "0.28307819400786943"
                    }
                ],
                "inputAmount": "3000000",
                "outputAmount": "1523800",
                "estimatedTimeInSeconds": 1
            }
        ]
    }
}
```


# Get Raw Transaction To Execute

The TxnData type combines transaction metadata with network-specific transaction details for different blockchain networks (EVM, Solana, Cosmos, Tron)

Call this api with `routeId` and `stepId` of individual steps to get the transaction data to execute. Once the transaction is executed, check the status of the transaction using `/status` api and proceed to the next step of the transaction.

> Note: you can ignore status check and skip to next step of the txn if `skipTxn` field is set to `true` in the response. Also, when `skipTxn` is set to `true`, `txnData` will be `null`.

### Endpoint: `GET /nextTx`&#x20;

### Query params

```
/nextTx?
    routeId=
    &stepId=
```

### Response

```typescript
{
    routeId: string;
    stepId: string;
    txnData: TxnData | null;
    skipTxn?: boolean;
}
```

<table><thead><tr><th width="184">Field</th><th width="172">Type</th><th>Description</th></tr></thead><tbody><tr><td>requestId</td><td>string</td><td>Associated request identifier</td></tr><tr><td>routeId</td><td>string</td><td>Associated route identifier</td></tr><tr><td>stepId</td><td>string</td><td>Current step identifier</td></tr><tr><td>networkType</td><td>NetworkType</td><td>Blockchain network type</td></tr><tr><td>deadline</td><td>number</td><td>Transaction expiration timestamp</td></tr><tr><td>skipTxn</td><td>boolean</td><td>This step's associated txn can be skipped</td></tr><tr><td>txnEvm</td><td>TxnEvm | null</td><td>Either of one is present depending on network type</td></tr><tr><td>txnSol</td><td>TxnSol | null</td><td></td></tr><tr><td>txnTron</td><td>TxnTron | null</td><td></td></tr><tr><td>txnCosmos</td><td>TxnCosmos | null</td><td></td></tr></tbody></table>

Network-Specific Transaction Data:

EVM Transaction (TxnEvm)

| Field    | Type   | Required | Description                  |
| -------- | ------ | -------- | ---------------------------- |
| from     | string | No       | Sender address               |
| to       | string | Yes      | Recipient contract/address   |
| value    | string | No       | Native token amount (in wei) |
| data     | string | No       | Transaction calldata         |
| gasPrice | string | No       | Gas price in wei             |
| gasLimit | string | No       | Maximum gas limit            |

Solana Transaction (TxnSol)

| Field | Type   | Required | Description              |
| ----- | ------ | -------- | ------------------------ |
| data  | string | Yes      | Encoded transaction data |

Cosmos Transaction (TxnCosmos)

| Field        | Type   | Required | Description              |
| ------------ | ------ | -------- | ------------------------ |
| data         | string | Yes      | Transaction data         |
| value        | string | Yes      | Transaction value        |
| gasLimit     | string | Yes      | Gas limit                |
| gasPrice     | string | Yes      | Gas price                |
| maxFeePerGas | string | Yes      | Maximum fee per gas unit |

Tron Transaction (txnTron)

| Field          | Type    | Required | Description            |
| -------------- | ------- | -------- | ---------------------- |
| raw\_data      | any     | No       | Raw transaction data   |
| raw\_data\_dex | string  | No       | DEX-specific data      |
| txID           | string  | Yes      | Transaction ID         |
| visible        | boolean | Yes      | Transaction visibility |

### Example <a href="#example" id="example"></a>

Lets now fetch the transaction data for the first step of the transaction we created in `/createTx` api.

**Request:**

```
https://api2.blockend.com/v1/nextTx
    ?routeId=01J2WB2ZTWAWXN9K48899CSSVN
    &stepId=01J2WB3JEB34B0A1SXHT1E3B63
```

**Response:** As the

```json
{
    "status": "success",
    "data": {
        "routeId": "01J2WB2ZTWAWXN9K48899CSSVN",
        "stepId": "01J2WB3JEB34B0A1SXHT1E3B63",
        "txnData": {
            "id": "01J2WD2YRTT6AN4450NKX9H1WB",
            "routeId": "01J2WB2ZTWAWXN9K48899CSSVN",
            "stepId": "01J2WB3JEB34B0A1SXHT1E3B63",
            "isCompleted": false,
            "networkType": "evm",
            "txnEvm": {
                "from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
                "to": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359",
                "data": "0x095ea7b3000000000000000000000000ef4fb24ad0916217251f553c0596f8edc630eb66ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
                "gasPrice": "30000000030",
                "gasLimit": 56167
            },
            "createdAt": 1721087654682,
            "status": "not-started",
            "fetchedAt": 1721087654682,
            "requestId": "01J2WB2ZBWNW0M0CJEYV415HPZ"
        }
    }
}
```


# Check Transaction Status

After user signs and submits the transaction on chain, check the status of the transaction by passing in the signature hash of the transaction. You need to keep polling this api to get the `status` of the transaction. Once the status response is `success`, you can proceed to the next step of the transaction (if any).

### Endpoint: `GET /status`&#x20;

### Query params

```
/status?
    routeId=
    &stepId=
    &txnHash=
```

### Response:

```typescript
{
    routeId: string;
    stepId: string;
    status: TxnStatus;
    srcTxnHash?: string;
    srcTxnUrl?: string;
    destTxnHash?: string;
    destTxnUrl?: string;
    points?: number;
}
```

### Example <a href="#example" id="example"></a>

Now, let check the status of the transaction we fetched in the previous step.

**Request:**

```url
https://api2.blockend.com/v1/status
    ?routeId=01J2WB2ZTWAWXN9K48899CSSVN
    &stepId=01J2WB3JEB34B0A1SXHT1E3B63
    &txnHash=0x3d7bdcfac0062b3c9ae1e4045bc43600c2c55c560dde7eebd2a15afb5ba1c390
```

**Response:**

```json
{
    "status": "success",
    "data": {
        "routeId": "01J2WB2ZTWAWXN9K48899CSSVN",
        "stepId": "01J2WB3JEB34B0A1SXHT1E3B63",
        "status": "success",
        "srcTxnHash": "0x3d7bdcfac0062b3c9ae1e4045bc43600c2c55c560dde7eebd2a15afb5ba1c390",
        "srcTxnUrl": "https://polygonscan.com/tx/0x3d7bdcfac0062b3c9ae1e4045bc43600c2c55c560dde7eebd2a15afb5ba1c390"
    }
}
```


# Quick Swap API

The **Quick Swap API** allows you to perform cross-chain or same-chain token swaps in a **single call**, returning both the best route and all the transactions required to complete it. This API is perfect for dApps, wallets, checkouts, or DeFi flows where simplicity and speed are essential.

### Endpoint: `GET /quick-swap`

```url
/quick-swap
    ?fromChainId=
    &fromAssetAddress=
    &toChainId=
    &toAssetAddress=
    &inputAmountDisplay=
    &userWalletAddress=
    &recipient=
```

### Query Parameters

<table><thead><tr><th width="200.18359375">Field</th><th width="199.75390625">Type</th><th>Description</th></tr></thead><tbody><tr><td>fromChainId*</td><td>string</td><td>Source blockchain identifier</td></tr><tr><td>fromAssetAddress*</td><td>string</td><td>Token address on source chain</td></tr><tr><td>toChainId*</td><td>string</td><td>Destination blockchain identifier</td></tr><tr><td>toAssetAddress*</td><td>string</td><td>Token address on destination chain</td></tr><tr><td>inputAmountDisplay*</td><td>string</td><td>Human-readable input amount (e.g., "1.5") <strong>Note:</strong> Either inputAmountDisplay or inputAmount should be passed</td></tr><tr><td>inputAmount*</td><td>string</td><td>Input amount in decimal units <strong>Note:</strong> Either inputAmountDisplay or inputAmount should be passed</td></tr><tr><td>userWalletAddress*</td><td>string</td><td>User's wallet address</td></tr><tr><td>recipient</td><td>string</td><td>Final recipient of the tokens. If not provided userWalletAddress is used by default</td></tr><tr><td>slippage</td><td>number</td><td>Slippage tolerance in basis points (100 = 1%)</td></tr><tr><td>solanaOptions</td><td>SolanaOptions</td><td>Solana-specific parameters</td></tr><tr><td>evmOptions</td><td>EvmOptions</td><td>EVM-specific parameters</td></tr><tr><td>skipChecks</td><td>boolean</td><td>Skip validation checks</td></tr><tr><td>include</td><td>string</td><td>Comma-separated list of providers to include</td></tr><tr><td>exclude</td><td>string</td><td>Comma-separated list of providers to exclude</td></tr></tbody></table>

**Solana Options**

<table><thead><tr><th width="199.953125">Field</th><th width="199.90234375">Type</th><th>Description</th></tr></thead><tbody><tr><td>solanaPriorityFee</td><td>number | PriorityLevel</td><td>Priority fee in micro lamports or priority level</td></tr><tr><td>solanaJitoTip</td><td>number | PriorityLevel</td><td>Jito MEV tip in lamports or priority level</td></tr></tbody></table>

**EVM Options**

<table><thead><tr><th width="200.02734375">Field</th><th width="200.1640625">Type</th><th>Description</th></tr></thead><tbody><tr><td>evmPriorityFee</td><td>number | PriorityLevel</td><td>Priority fee in wei or priority level</td></tr></tbody></table>

```typescript
PriorityLevel = 'low' | 'medium' | 'high' | 'ultra' | 'degen'
```

### Response

The Quick Swap endpoint returns a simplified response containing both the selected route and ready-to-execute transaction data.

<table><thead><tr><th width="200.0546875">Field</th><th width="199.99609375">Type</th><th>Description</th></tr></thead><tbody><tr><td>route</td><td>Route</td><td>The selected route for the swap (null if no suitable route)</td></tr><tr><td>txn</td><td>TxnData[]</td><td>Array of transaction data ready for execution (null if error)</td></tr><tr><td>error</td><td>string</td><td>Error message if the swap cannot be completed</td></tr></tbody></table>

#### Route Object

The route object contains the same structure as returned by the `/quotes` endpoint, including:

* **from/to**: Source and destination token details
* **inputAmount/outputAmount**: Input and output amounts in wei/native units
* **inputAmountDisplay/outputAmountDisplay**: Human-readable amounts
* **provider**: Liquidity provider used
* **estimatedTimeInSeconds**: Estimated execution time
* **steps**: Transaction steps (limited to simple swaps only)
* **fee**: Fee breakdown

#### Transaction Data Array

The `txn` array contains 1-2 transaction objects ready for execution:

1. **Approval Transaction** (if required): ERC20 token approval for non-native tokens
2. **Swap Transaction**: The actual swap transaction

Each transaction object includes:

* **txnEvm**: EVM transaction data (from, to, data, value, gasPrice, gasLimit)
* **txnSol**: Solana transaction data (base64 encoded transaction)
* **networkType**: "evm" or "sol"
* **routeId/stepId**: Identifiers for tracking

### Limitations

The Quick Swap endpoint is designed for simple swaps only and has the following restrictions:

* Only supports single-step swaps (no complex multi-hop routes)
* Automatically uses recommended providers only
* Routes with more than 2 steps (approval + swap) will be rejected
* Cross-chain swaps are supported but must be single-step

### Example

**Request:**

```url
https://api2.blockend.com/v1/quick-swap
?fromChainId=1
&fromAssetAddress=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
&toChainId=1
&toAssetAddress=0xA0b86a33E6417aE4bbBd449c8E87C2E2e20E84DE
&inputAmountDisplay=0.1
&userWalletAddress=0x17e7c3DD600529F34eFA1310f00996709FfA8d5c
&slippage=100
```

**Response:**

```json
{
  "status": "success",
  "data": {
    "route": {
      "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
      "from": {
        "networkType": "evm",
        "chainId": "1",
        "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
        "decimals": 18,
        "name": "Ethereum",
        "symbol": "ETH",
        "isNative": true,
        "lastPrice": 3480.62
      },
      "to": {
        "networkType": "evm",
        "chainId": "1",
        "address": "0xA0b86a33E6417aE4bbBd449c8E87C2E2e20E84DE",
        "decimals": 18,
        "name": "USDC",
        "symbol": "USDC",
        "isNative": false,
        "lastPrice": 1.002
      },
      "inputAmount": "100000000000000000",
      "inputAmountDisplay": "0.1",
      "outputAmount": "348062000000",
      "outputAmountDisplay": "348.062",
      "provider": "1inch",
      "estimatedTimeInSeconds": 30,
      "steps": [{
        "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
        "stepType": "swap",
        "from": { /* token details */ },
        "to": { /* token details */ },
        "inputAmount": "100000000000000000",
        "outputAmount": "348062000000"
      }]
    },
    "txn": [{
      "id": "txn_123",
      "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
      "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
      "networkType": "evm",
      "txnType": "on-chain",
      "txnEvm": {
        "from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
        "to": "0x1111111254eeb25477b68fb85ed929f73a960582",
        "value": "100000000000000000",
        "data": "0x7c025200000000000000000000000000...",
        "gasPrice": "20000000000",
        "gasLimit": "150000"
      }
    }]
  }
}
```

### Error Responses

The endpoint may return the following error scenarios:

* **No routes found**: When no suitable swap routes are available
* **Route too complex**: When the optimal route requires multiple steps
* **Failed to compute transaction data**: When transaction data cannot be generated

```json
{
  "status": "success",
  "data": {
    "route": null,
    "txn": null,
    "error": "No routes found"
  }
}
```

This endpoint is perfect for applications that need simple, one-click swap functionality without the complexity of managing separate quote and transaction creation flows.


# Lite Mode

### Overview

Lite Mode is an advanced feature **exclusively available for Solana** that optimizes transactions by significantly reducing transaction size and providing developers with granular control over transaction construction. When enabled, the API returns raw transaction instructions instead of pre-serialized base64-encoded transaction data, allowing for more flexible transaction building and better success rates.

> **Note**: This feature is currently only supported for Solana blockchain swaps. Other chains will use the standard transaction mode.

### Key Features

* **Reduced Transaction Size**: Minimizes the number of accounts included in transactions
* **Instruction-Based**: Returns raw Solana instructions for custom transaction building
* **Provider Optimization**: Uses only the most efficient providers for Solana swaps
* **Automatic Account Management**: Intelligently manages account limits based on mode
* **Direct Route Optimization**: Forces single-hop swaps for faster execution and lower complexity
* **Enhanced Success Rate**: Reduces transaction failures due to size constraints

### Supported Providers

* **Jupiter (JUPAG)** - Primary DEX aggregator with advanced routing (Solana only)
* **OKX** - Multi-chain DEX aggregator with Solana support (Solana only)

> **Chain Limitation**: These providers are configured for lite mode only when `fromChainId` and `toChainId` are both set to `"sol"`.

### How It Works

#### Quote API Behavior

When `lite=true` is enabled in the quote request **for Solana swaps**:

1. **Provider Selection**: Only Jupiter and OKX providers are utilized for Solana swaps
2. **Endpoint Optimization**:
   * Jupiter switches to `/swap-instructions` endpoint
   * OKX switches to `/swap-instruction` endpoint
3. **Account Management**:
   * `maxAccounts` is automatically set to 20 (vs default 64 in normal mode)
   * This reduces transaction complexity and size
4. **Direct Route Optimization**:
   * Jupiter: `onlyDirectRoutes: true` - Forces single-hop swaps only
   * OKX: `directRoute: true` - Enables direct routing mode
   * Eliminates multi-hop routing for faster execution and lower complexity

> **Important**: Lite mode is automatically disabled for non-Solana chains, and the request will fall back to standard transaction mode.

#### Next Transaction API Response

Instead of returning serialized transaction data, the API provides raw transaction instructions. The response format varies by provider:

**Jupiter Response Format**

```json
{
  "txnData": {
    "txnSol": {
      "data": "{\"addressLookupTableAccount\":[],\"instructionLists\":[...]}"
    }
  }
}
```

**Jupiter Instruction Structure:**

```json
{
  "tokenLedgerInstruction": {
    "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
    "accounts": [
      {
        "pubkey": "UserWalletAddress",
        "isSigner": true,
        "isWritable": true
      }
    ],
    "data": "base64-encoded-instruction-data"
  },
  "computeBudgetInstructions": [
    {
      "programId": "ComputeBudget111111111111111111111111111111",
      "accounts": [],
      "data": "base64-encoded-instruction-data"
    }
  ],
  "setupInstructions": [
    {
      "programId": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
      "accounts": [
        {
          "pubkey": "AssociatedTokenAccount",
          "isSigner": false,
          "isWritable": true
        }
      ],
      "data": "base64-encoded-instruction-data"
    }
  ],
  "swapInstruction": {
    "programId": "JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB",
    "accounts": [
      {
        "pubkey": "UserWalletAddress",
        "isSigner": true,
        "isWritable": true
      },
      {
        "pubkey": "SourceTokenAccount",
        "isSigner": false,
        "isWritable": true
      }
    ],
    "data": "base64-encoded-instruction-data"
  },
  "cleanupInstruction": {
    "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
    "accounts": [
      {
        "pubkey": "WSOLAccount",
        "isSigner": false,
        "isWritable": true
      }
    ],
    "data": "base64-encoded-instruction-data"
  },
  "addressLookupTableAddresses": [
    "AddressLookupTableAccount1",
    "AddressLookupTableAccount2"
  ]
}
```

**OKX Response Format**

```json
{
  "txnData": {
    "txnSol": {
      "data": "{\"addressLookupTableAccount\":[],\"instructionLists\":[...]}"
    }
  }
}
```

**OKX Instruction Structure:**

```json
{
  "addressLookupTableAccount": [
    "AddressLookupTableAccount1"
  ],
  "instructionLists": [
    {
      "programId": "OKXProgramId",
      "accounts": [
        {
          "pubkey": "UserWalletAddress",
          "isSigner": true,
          "isWritable": true
        },
        {
          "pubkey": "SourceTokenAccount",
          "isSigner": false,
          "isWritable": true
        }
      ],
      "data": "base64-encoded-instruction-data"
    }
  ]
}
```

**Response Components:**

**Jupiter Components:**

* `tokenLedgerInstruction`: Token ledger instruction (if using token ledger)
* `computeBudgetInstructions`: Array of compute budget instructions for gas optimization
* `setupInstructions`: Array of setup instructions for creating missing accounts
* `swapInstruction`: The main swap instruction
* `cleanupInstruction`: Cleanup instruction for unwrapping SOL (if needed)
* `addressLookupTableAddresses`: Array of address lookup table addresses

**OKX Components:**

* `addressLookupTableAccount`: Array of address lookup table accounts for transaction optimization
* `instructionLists`: Array of Solana transaction instructions to be executed
* Each instruction contains `programId`, `accounts`, and `data` fields

### API Integration

#### Quote Request Example

```json
{
  "fromChainId": "sol",
  "toChainId": "sol", 
  "fromAssetAddress": "So11111111111111111111111111111111111111112",
  "toAssetAddress": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "inputAmountDisplay": "1.0",
  "userWalletAddress": "7zSa114U45nJ8b8ALsuhszS2Kxto8grgedh65Q7xJYii",
  "lite": true,
  "slippage": 50
}
```

> **Chain Requirement**: Both `fromChainId` and `toChainId` must be set to `"sol"` for lite mode to be activated.

#### Transaction Building Process

1. **Quote Request**: Include `lite: true` parameter
2. **Instruction Retrieval**: Use the returned instructions from Next Transaction API
3. **Transaction Construction**: Build your Solana transaction using the provided instructions
4. **Address Lookup Tables**: Utilize the `addressLookupTableAccount` data for optimization
5. **Transaction Submission**: Send the constructed transaction to Solana network

### Account Management

#### Automatic maxAccounts Setting

* **Lite Mode (`lite: true`)**: `maxAccounts` is automatically set to **20**
* **Normal Mode (`lite: false`)**: `maxAccounts` is automatically set to **64**
* **Manual Override**: You can still specify `maxAccounts` in the request to override the automatic setting

#### Why Account Limits Matter

* **Transaction Size**: Solana transactions have size limits (1232 bytes)
* **Account Limits**: Each account reference consumes space
* **Success Rate**: Fewer accounts = higher transaction success rate
* **Gas Efficiency**: Smaller transactions are more cost-effective

### Benefits

#### Performance Improvements

* **Faster Execution**: Direct routes eliminate multi-hop complexity
* **Higher Success Rate**: Smaller transactions are less likely to fail
* **Reduced Gas Costs**: Optimized transaction size leads to lower fees
* **Simplified Routing**: Single-hop swaps reduce MEV exposure and slippage

#### Developer Experience

* **Flexible Integration**: Raw instructions allow custom transaction building
* **Better Control**: Fine-grained control over transaction construction
* **Simplified Debugging**: Easier to troubleshoot instruction-level issues

#### Network Efficiency

* **Reduced Congestion**: Smaller transactions contribute to network efficiency
* **Better Batching**: Instructions can be batched with other operations
* **Optimized Routing**: Direct paths reduce unnecessary hops

### Use Cases

#### High-Frequency Trading

* Minimal transaction size for rapid execution
* Reduced slippage due to faster processing and direct routes
* Better price discovery through single-hop swaps
* Lower MEV exposure with simplified routing

#### DeFi Applications

* Integration with complex DeFi protocols
* Custom transaction building for specific needs
* Batch operations with other Solana instructions

#### Mobile Applications

* Reduced data usage for mobile users
* Faster transaction confirmation
* Better user experience on slower connections

### Implementation Guide

#### Step 1: Enable Lite Mode

```javascript
const quoteRequest = {
  fromChainId: "sol",
  toChainId: "sol",
  fromAssetAddress: "So11111111111111111111111111111111111111112",
  toAssetAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  inputAmountDisplay: "1.0",
  userWalletAddress: "7zSa114U45nJ8b8ALsuhszS2Kxto8grgedh65Q7xJYii",
  lite: true
};
```

#### Step 2: Process Quote Response

```javascript
const quoteResponse = await fetch('/api/quote', {
  method: 'POST',
  body: JSON.stringify(quoteRequest)
});
```

#### Step 3: Get Transaction Instructions

```javascript
const nextTxnResponse = await fetch('/api/nextTx', {
  method: 'POST',
  body: JSON.stringify({
    routeId: quoteResponse.routeId,
    stepId: quoteResponse.steps[0].stepId
  })
});

const instructions = JSON.parse(nextTxnResponse.txnData.txnSol.data);
```

#### Step 4: Build and Submit Transaction

**For Jupiter Instructions**

```javascript
import { TransactionInstruction, PublicKey } from '@solana/web3.js';

// Parse Jupiter instructions
const { 
  tokenLedgerInstruction,
  computeBudgetInstructions,
  setupInstructions,
  swapInstruction,
  cleanupInstruction,
  addressLookupTableAddresses 
} = instructions;

// Create transaction instructions array
const txInstructions = [];

// Add compute budget instructions first
if (computeBudgetInstructions) {
  txInstructions.push(...computeBudgetInstructions.map(instruction => 
    new TransactionInstruction({
      programId: new PublicKey(instruction.programId),
      keys: instruction.accounts.map(account => ({
        pubkey: new PublicKey(account.pubkey),
        isSigner: account.isSigner,
        isWritable: account.isWritable,
      })),
      data: Buffer.from(instruction.data, 'base64'),
    })
  ));
}

// Add setup instructions
if (setupInstructions) {
  txInstructions.push(...setupInstructions.map(instruction => 
    new TransactionInstruction({
      programId: new PublicKey(instruction.programId),
      keys: instruction.accounts.map(account => ({
        pubkey: new PublicKey(account.pubkey),
        isSigner: account.isSigner,
        isWritable: account.isWritable,
      })),
      data: Buffer.from(instruction.data, 'base64'),
    })
  ));
}

// Add main swap instruction
if (swapInstruction) {
  txInstructions.push(new TransactionInstruction({
    programId: new PublicKey(swapInstruction.programId),
    keys: swapInstruction.accounts.map(account => ({
      pubkey: new PublicKey(account.pubkey),
      isSigner: account.isSigner,
      isWritable: account.isWritable,
    })),
    data: Buffer.from(swapInstruction.data, 'base64'),
  }));
}

// Add cleanup instruction if needed
if (cleanupInstruction) {
  txInstructions.push(new TransactionInstruction({
    programId: new PublicKey(cleanupInstruction.programId),
    keys: cleanupInstruction.accounts.map(account => ({
      pubkey: new PublicKey(account.pubkey),
      isSigner: account.isSigner,
      isWritable: account.isWritable,
    })),
    data: Buffer.from(cleanupInstruction.data, 'base64'),
  }));
}

// Build and send transaction with address lookup tables
// See Jupiter docs for complete implementation
```

**For OKX Instructions**

```javascript
import { TransactionInstruction, PublicKey } from '@solana/web3.js';

// Parse OKX instructions
const { addressLookupTableAccount, instructionLists } = instructions;

// Create transaction instructions
const txInstructions = instructionLists.map(instruction => 
  new TransactionInstruction({
    programId: new PublicKey(instruction.programId),
    keys: instruction.accounts.map(account => ({
      pubkey: new PublicKey(account.pubkey),
      isSigner: account.isSigner,
      isWritable: account.isWritable,
    })),
    data: Buffer.from(instruction.data, 'base64'),
  })
);

// Build and send transaction with address lookup tables
// See OKX docs for complete implementation
```

### Best Practices

1. **Handle Instructions Properly** - Parse and validate instruction data
2. **Utilize Address Lookup Tables** - They significantly reduce transaction size
3. **Monitor Success Rates** - Lite mode should improve transaction success

### Troubleshooting

#### Common Issues

* **Instruction Parsing Errors**: Ensure proper JSON parsing of instruction data
* **Provider Availability**: Only Jupiter and OKX support lite mode
* **Chain Compatibility**: Lite mode only works with Solana (`fromChainId: "sol"` and `toChainId: "sol"`)

#### Debug Tips

* Check instruction structure before building transactions
* Verify address lookup table accounts are properly included
* Monitor transaction size to ensure it stays within limits

### References

#### Provider Documentation

* [Jupiter Swap Instructions API](https://dev.jup.ag/docs/swap-api/build-swap-transaction) - Complete guide for building transactions with Jupiter instructions
* [Jupiter Swap Instructions Example](https://dev.jup.ag/docs/swap-api/build-swap-transaction#build-your-own-transaction-with-instructions) - Code examples for instruction handling
* [OKX Swap Instruction API](https://web3.okx.com/build/dev-docs/dex-api/dex-solana-swap-instruction) - OKX's swap instruction documentation
* [OKX Solana Integration Guide](https://web3.okx.com/build/dev-docs/dex-api/dex-solana-swap-instruction) - Complete implementation examples

#### Solana Documentation

* [Solana Transaction Format](https://docs.solana.com/developing/programming-model/transactions) - Understanding Solana transactions
* [Address Lookup Tables](https://docs.solana.com/developing/lookup-tables) - Optimizing transaction size with ALTs
* [Transaction Instructions](https://docs.solana.com/developing/programming-model/transactions#instruction) - Working with Solana instructions


# Gasless Swaps

### Overview

To enable gasless transactions in your swap process, you can add the `gasless=true` flag to the quotes request. This ensures that only transactions that can be executed without the user paying for gas are returned.

#### Key Flags

1. **`gasless=true`**:  When set to true, this parameter ensures that all returned transactions (including both token approvals and swaps) can be executed without the end-user paying for gas fees. The gas costs will be covered by the protocol, creating a seamless user experience without requiring native tokens for transaction fees
2. **`gaslessSwap=true`**: When set to true, this parameter guarantees that swap transactions will be executed without the end-user paying for gas fees. Unlike the gasless parameter, this option specifically focuses on making the swap operation gasless, while token approval transactions may or may not require gas payment depending on the specific tokens involved in the swap.

#### Workflow

1. **Quote Request**:
   * Include the `gasless=true` flag to get gasless (approval + swap) transaction quotes.
   * Include `gaslessSwap=true`  to  get  gasless transaction for swaps, but approvals may or may not require gas.
2. **/createTx and /nextTx Calls**:
   * Once you've received the quotes, make the `/createTx` and `/nextTx` calls as usual. The process for these calls remains the same.

***

### Handling Gasless Transactions

#### Response from `/nextTx` and `/createTx`

* The response from both endpoints will contain a `gasless` field.
  * **`gasless: false`**: The transaction requires user gas. The user must sign and submit the transaction via RPC.
  * **`gasless: true`**: The transaction is gasless, and you should make a `/submit` call with the signed transaction data.

#### Gasless Transaction Process

For gasless transactions, the process differs slightly:

1. **Transaction Data**:
   * The transaction data for gasless transactions is different from standard transactions. It only needs to be signed by the user, not submitted to the network via RPC.
2. **Signing the Transaction**:
   * The user must sign the transaction using the provided `txnData` (example signing process shared in the code snippet below).
3. **Submit the Transaction**:

   * Once signed, the transaction must be submitted to Blockend via the `/submit` API.

   **Request Body for `/submit`**

   ```json
   {
     "routeId": "string",
     "stepId": "string",
     "signedTxn": "string"
   }
   ```

   **Response Example from `/submit`**

   ```json
   {
     "status": "success",
     "data": {
       "routeId": "01JN23TP2QNH3A8ESJJEQ5A2NM",
       "stepId": "01JN23TP2QQTXZQ93HM30WRWJ5",
       "status": "in-progress"
     }
   }
   ```

   **`status: success`**: The signed transaction has been successfully submitted.\
   **`status: in-progress`**: The transaction is still being processed. Wait for it to complete.

***

### Waiting for Transaction Fulfilment

You can use the **normal status check endpoint** to monitor the status of the transaction. The key difference is that the `txnHash` field is not required, as the actual transaction hash is generated by Blockend.

#### Request Body for `/status`

```json
{
  "routeId": "string",
  "stepId": "string"
}
```

The response will be similar to the one from a regular transaction, but the transaction hash is managed by Blockend.

***

### Example TypeScript Code for Gasless Swap

```typescript
import { ethers } from 'ethers';

const baseRpcUrl = "https://base.drpc.org";
const evmProvider = new ethers.providers.JsonRpcProvider(baseRpcUrl);
const evmSigner = new ethers.Wallet(EVM_PRIVATE_KEY, evmProvider);

const BASE_URL = "https://api2.blockend.com/v1";
const FETCH_OPTIONS = {
  headers: {
    'content-type': 'application/json',
    'x-api-key': '<api-key>',
  }
};

async function main() {
  const baseQuote = {
    fromChainId: "8453",
    fromAssetAddress: "0x4f9fd6be4a90f2620860d680c0d4d5fb53d1a825", // Example asset
    toAssetAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // Example asset
    inputAmountDisplay: "1",
    userWalletAddress: evmSigner.address,
    // gasless: true, // gasless for both swaps and approvals
    gaslessSwap: true,  // gasless for swaps (approvals may or may not be gasless)
  };

  const quoteReq = baseQuote;
  const urlParams = Object.entries(quoteReq).map(([key, value]) => `${key}=${value}`).join('&');
  const fetchQuoteReq = await fetch(`${BASE_URL}/quotes?${urlParams}`, FETCH_OPTIONS);
  const fetchQuoteRes = await fetchQuoteReq.json();
  console.log("quotes fetched");
  const quotes = fetchQuoteRes.data.quotes;

  const providerQuote = quotes[0];
  if (!providerQuote) throw new Error("Quote not found");

  const createdTxnReq = await fetch(`${BASE_URL}/createTx?routeId=${providerQuote.routeId}`, FETCH_OPTIONS);
  const createdTxnRes = await createdTxnReq.json();
  console.log("Transaction created");
  const createdTxn = createdTxnRes.data;

  let stepId = "";
  for (const step of createdTxn.steps) {
    stepId = step.stepId;
    const nextTxnReq = await fetch(`${BASE_URL}/nextTx?routeId=${providerQuote.routeId}&stepId=${step.stepId}`, FETCH_OPTIONS);
    const nextTxnRes = await nextTxnReq.json();
    const nextTxn = nextTxnRes.data;

    const txnData = nextTxn.txnData;
    if (!txnData) throw new Error("txnData not found");
    const txnEvm = txnData.txnEvm;
    if (!txnEvm) throw new Error("txnEvm not found");

    if (txnData.gasless || txnData.txnType === "sign-typed") {
      console.log("Executing gasless transaction...");
      const signedTxn = await evmSigner._signTypedData(txnEvm.domain, txnEvm.types, txnEvm.message);
      const submitReq = await fetch(`${BASE_URL}/submit?routeId=${providerQuote.routeId}&stepId=${step.stepId}`, {
        ...FETCH_OPTIONS,
        method: "POST",
        body: JSON.stringify({
          routeId: providerQuote.routeId,
          stepId: step.stepId,
          signedTxn: signedTxn,
        })
      });

      const submitResText = await submitReq.text();
      console.log("Transaction submitted:", submitResText);
    } else {
      console.log("Executing regular transaction...");
      const txn = await evmSigner.sendTransaction(txnEvm);
      const statusCheckRes = await getStatus(providerQuote.routeId, step.stepId, txn.hash);
      console.log("Transaction status:", statusCheckRes);
    }
  }

  const statusCheckRes = await getStatus(providerQuote.routeId, stepId);
  console.log("Final transaction status:", statusCheckRes);
}

async function getStatus(routeId: string, stepId: string, txnHash?: string) {
  const statusCheckReq = await fetch(`${BASE_URL}/status?routeId=${routeId}&stepId=${stepId}&txnHash=${txnHash}`, FETCH_OPTIONS);
  const statusCheckRes = await statusCheckReq.json();
  const status = statusCheckRes.data;

  if (status.status !== "in-progress") {
    return status;
  }

  await sleep(3 * 1000);
  return getStatus(routeId, stepId, txnHash);
}

main().catch(console.error).finally(() => process.exit(0));
```


# Type Definations

### Basic Types

```typescript
type NetworkType = "evm" | "sol" | "cosmos" | "tron";

type Asset = {
  networkType?: NetworkType;
  chainId: string;
  address: string;
  decimals: number;

  symbol: string;
  name?: string;
  isNative?: boolean;
  isPopular?: boolean;
  image?: string;

  blockchain: string;
  lastPrice: number;
  marketCap?: number;
};

type Chain = {
  chainId: string;
  symbol: string;
  name: string;
  networkType: NetworkType;

  image: string;
  isPopular?: boolean;
  isEnabled: boolean;

  explorer: {
    token: string; // https://polygonscan.com/token/{tokenAddress}
    txn: string; // https://polygonscan.com/tx/{txnHash}
    address?: string; // https://polygonscan.com/address/{address}
  };
  rpcUrls: string[];
  tokenCount: number;
};

enum FeeType {
  NETWORK = "NETWORK", // gas fee
  PROVIDER = "PROVIDER", // fee charged by the provider
  BLOCKEND = "BLOCKEND", // fee charged by blockend
  INTEGRATOR = "INTEGRATOR", // custom fee someone want to charge via blockend integration
};

enum FeeSource {
  FROM_SOURCE_WALLET = "FROM_SOURCE_WALLET",
  FROM_OUTPUT_AMOUNT = "FROM_OUTPUT_AMOUNT",
  FROM_INPUT_AMOUNT = "FROM_INPUT_AMOUNT",
};

type Fee = {
  type: FeeType;
  token: Asset;
  source: FeeSource;
  amountInToken: string;
  amountInUSD: number | string;
};

type ProviderDetails = {
  name: string;
  logoUrl: string;
};

type StepType = "approval" | "swap" | "bridge" | "sign" | "claim";
type TxnStatus = "not-started" | "in-progress" | "success" | "failed" | "cancelled";
```

### Quote Request

```typescript
type QuoteRequest = {
  fromChainId: string; // chainId of the asset to swap from
  fromAssetAddress: string; // address of the asset to swap from

  toChainId: string; // chainId of the asset to swap to
  toAssetAddress: string; // address of the asset to swap to

  // send either inputAmountDisplay or inputAmount
  inputAmountDisplay: string; // 3.2
  inputAmount: string; // 3.2*10^18

  userWalletAddress: string; // address of the user who will perform the swap
  recipient?: string; // address of the recipient (in case recipient is different)
  
  slippage: number; // in bps, 100bps = 1%
  solanaOptions?: SolanaOptions;
  evmOptions?: EvmOptions;
  skipChecks?: boolean;
};

type QuoteResponse = {
  quotes: Routes[];
};

export type Route = {
  requestId?: string;
  routeId: string;

  from: Asset;
  to: Asset;
  steps: Steps[];
  fee: Fee[];

  provider: Providers;
  providerDetails: ProviderDetails;
  protocolsUsed: string[];

  inputAmount: string; // 3.2*10^18
  inputAmountDisplay: string; // 3.2

  outputAmount: string; // 4.56*10^18
  outputAmountDisplay: string; // 4.56
  minOutputAmount: string; // 4.32*10^18
  minOutputAmountDisplay?: string; // 4.32
  slippage: number;

  userWalletAddress: string;
  recipient?: string;

  createdAt: number; // time when quote is created
  deadline: number; // deadline (in seconds) for quote to be used
  estimatedTimeInSeconds: number;
  tags?: string[];
};

type Steps = {
  stepId: string;
  stepType: StepType;
  protocolsUsed: string[];
  provider?: Providers;

  from: Asset;
  to: Asset;
  txnHash?: string;
  status?: TxnStatus;

  inputAmount: string;
  outputAmount: string;
  fee: Fee[];
  estimatedTimeInSeconds?: number;
};
```

### Create a transaction

```typescript
type CreateTxnRequest = {
  routeId: string;
};

type CreateTxnResponse = {
  routeId: string;
  steps: Steps[];
};
```

### Transaction Data

```typescript
type NextTxnRequest = {
  routeId: string;
  stepId: string;
};

type NextTxnResponse = {
  routeId: string;
  stepId: string;
  txnData: TxnData | null;
  skipTxn?: boolean;
};

type TxnData = TxnMetaData & {
  txnEvm?: TxnEvm;
  txnSol?: TxnSol;
  txnTron?: TxnTron;
  txnCosmos?: TxnCosmos;
};

type TxnEvm = {
  from: string | null;
  to: string;
  value?: string | null;
  data?: string | null;

  gasPrice?: string | null;
  gasLimit?: string | null;
};

type TxnSol = {
  data: string;
};

type TxnTron = {
  raw_data?: any | null;
  raw_data_dex?: string | null;
  txID: string;
  visible: boolean;
};

type TxnCosmos = {
  data: string; 
  value: string;
  gasLimit: string;
  gasPrice: string;
  maxFeePerGas: string;
};

type TxnMetaData = {
  requestId: string;
  routeId: string;
  stepId: string;
  networkType: NetworkType;

  deadline?: number;
  skipTxn?: boolean;
};
```

### Check status of a transaction

```typescript
type StatusCheckRequest = {
  routeId: string;
  stepId: string;
  txnHash: string;
};

type StatusCheckResponse = {
  routeId: string;
  stepId: string;
  status: TxnStatus;
  srcTxnHash?: string;
  srcTxnUrl?: string;
  destTxnHash?: string;
  destTxnUrl?: string;
  points?: number;
};
```


# Get Supported Chains & Tokens

### Meta Endpoints <a href="#meta-endpoints" id="meta-endpoints"></a>

#### Tokens <a href="#tokens" id="tokens"></a>

Get a list of supported tokens and their details.

```
curl -X GET "https://api2.blockend.com/v1/tokens"
```

#### Chains <a href="#chains" id="chains"></a>

Get a list of supported chains and their details.

```
curl -X GET "https://api2.blockend.com/v1/chains"
```


# SDK

Compass SDK is a powerful cross-chain transaction SDK that provides a unified liquidity layer by aggregating multiple liquidity sources across blockchain networks. It seamlessly integrates DEXs (Decentralised Exchanges), Cross-chain Bridges, RFQ (Request for Quote) systems, and Intent Protocols into a single, reliable interface. \
\
This enables developers to easily implement cross-chain token swaps, transfers, and complex DeFi operations across EVM chains, Solana, and Cosmos ecosystems.


# Getting Started

### Installation

```bash
npm install @blockend/compass-sdk @solana/web3.js @cosmjs/stargate 
# or
yarn add @blockend/compass-sdk @solana/web3.js @cosmjs/stargate
```

### Quick Start

```typescript
import {
  initializeSDK,
  getQuotes,
  executeTransaction,
  createTransaction,
  getNextTxn,
  checkStatus,
} from "@blockend/compass-sdk";

// Initialize the SDK with your API key
initializeSDK({
  apiKey: "YOUR_API_KEY",
  integratorId: "YOUR_INTEGRATOR_ID",
});

// Get quotes for a token swap
const quotes = await getQuotes({
  fromChainId: "137",
  fromAssetAddress: "0x...",
  toChainId: "sol",
  toAssetAddress: "...",
  inputAmount: "1000000000000000000", // Amount in wei
  inputAmountDisplay: "1.0", // Human readable amount
  userWalletAddress: "0x...",
  recipient: "0x...",
});

// Execute the transaction with the best quote
const result = await executeTransaction({
  quote: quotes.data.quotes[0],
  provider: ethersProvider, // For EVM chains
  walletAdapter: solanaWallet, // For Solana
  cosmosClient: cosmosClient, // For Cosmos
  onStatusUpdate: (status, data) => {
    console.log(`Transaction status: ${status}`, data);
  },
});

// Check transaction status, poll the status until the status is "success" or "failed" or "partial-success". "in-progress" means the transaction is still being processed.
const status = await checkStatus({
  routeId: transaction.routeId,
  stepId: transaction.steps[0].id,
  txnHash: result.hash,
});
```

See checkStatus example implementation using while loop in link below

{% content-ref url="/pages/NT1qwM1LlG7erFwggPoO" %}
[Check Status](/compass-api/sdk/core-methods/check-status)
{% endcontent-ref %}


# Configuration

**`initializeSDK(config)`**

Initialize the SDK with your credentials and configuration.

```typescript
initializeSDK({
  apiKey: string;
  integratorId: string;
  baseURL?: string;
  enableCache?: boolean;
  cacheTimeout:number;
});
```

To get config, use the `getConfig()` method.

```typescript
const config = getConfig();
```

To update config, use the `updateConfig()` method. You can update one or more parameters mentioned in the Configuration Parameters section.

```typescript
updateConfig({
  apiKey: "YOUR_API_KEY",
});
```

#### Configuration Parameters

**`apiKey` (required)**

* Your unique API key for authentication with the Blockend API
* Must be obtained through the Blockend platform
* Used to track API usage and enforce rate limits

**`integratorId` (required)**

* A unique identifier for your integration/application
* Used for analytics, tracking, and support purposes
* Helps identify your specific implementation when interacting with Blockend services

**`errorHandler` (optional)**

* A callback function to handle SDK errors globally
* Receives a `BlockendError` object with properties:
  * `message`: Description of the error
  * `code`: Error code (e.g., "CONFIGURATION\_ERROR", "NETWORK\_ERROR", "VALIDATION\_ERROR")
  * `data`: Additional error context (if available)
* Useful for centralized error handling, logging, and error reporting
* Example usage:

```typescript
initializeSDK({
  apiKey: "YOUR_API_KEY",
  integratorId: "YOUR_INTEGRATOR_ID",
  errorHandler: (error) => {
    console.error(
      `[Compass SDK Error] ${error.code}: ${error.message}`,
      error.data
    );
    // Custom error handling logic (e.g., reporting to monitoring service)
  },
});
```

**`baseURL` (optional)**

* The base URL endpoint for the Blockend API
* Defaults to `https://api2.blockend.com/v1`
* Can be modified for different environments (staging, testing, etc.)
* Should include the version prefix (`/v1`)

**`enableCache` (optional)**

* Boolean flag to enable/disable SDK's built-in caching mechanism
* When enabled, caches API responses to reduce network requests
* Particularly useful for frequently accessed data like token lists and chain information
* Defaults to `false` if not specified

**`cacheTimeout` (optional)**

* Duration in milliseconds for how long cached items should remain valid
* Only applies when `enableCache` is `true`
* Defaults to 1 hour (3600000 milliseconds)
* Can be adjusted based on your application's needs and data freshness requirements


# Core Methods

This section explains about core methods of the SDK.


# getQuotes

Gets quotes for cross-chain token swaps or transfers by aggregating liquidity from multiple sources including DEXs, Bridges, RFQs, and Intent Protocols.

```typescript
interface QuoteParams {
  // Chain ID of the source blockchain (e.g., "ethereum", "solana", "bsc")
  fromChainId: string;

  // Token contract address on source chain (use native token address for chain's native currency)
  fromAssetAddress: string;

  // Chain ID of the destination blockchain
  toChainId: string;

  // Token contract address on destination chain
  toAssetAddress: string;

  // Amount in smallest unit (wei, lamports, etc.)
  inputAmount: string;

  // Human readable amount (e.g., "1.0" ETH)
  inputAmountDisplay: string;

  // Source wallet address that will initiate the transaction
  userWalletAddress: string;

  // Optional: Destination wallet address (defaults to userWalletAddress if not specified)
  recipient?: string;

  // Optional: Solana priority fee in lamports or predefined level ("LOW" | "MEDIUM" | "HIGH")
  solanaPriorityFee?: number | PriorityLevel;

  // Optional: Solana Jito MEV tip in lamports or predefined level
  solanaJitoTip?: number | PriorityLevel;

  // Optional: EVM priority fee in gwei or predefined level
  evmPriorityFee?: number | PriorityLevel;

  // Optional: Maximum allowed slippage in BPS (default: 50)
  slippage?: number;

  // Optional: Skip certain validation checks for faster response
  skipChecks?: boolean;

  // Optional: Comma-separated list of preferred liquidity sources
  include?: string;

  // Optional: Comma-separated list of liquidity sources to exclude
  exclude?: string;

  // Optional: Use recommended liquidity provider
  recommendedProvider?: boolean;

  // Optional: To get gasless (approval + swap) transaction quotes.
  gasless?:boolean;

  // Optional: To  get  gasless transaction for swaps, but approvals may or may not require gas.
  gaslessSwap:boolean;

  // Optional: To set fee in BPS
  feeBps: number | string;
}

//Example implementation
const quotes = await getQuotes({
  fromChainId: "137",
  fromAssetAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
  toChainId: "137",
  toAssetAddress: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f.",
  inputAmountDisplay: "1.0",
  userWalletAddress: "0x...",
  recipient: "0x...",
});

// Example Response (shortened)
{
  "status": "success",
  "data": {
    "quotes": [{
      "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
      "from": {
        "chainId": "1",
        "symbol": "ETH",
        // ... other token details
      },
      "to": {
        "chainId": "sol",
        "symbol": "USDC",
        // ... other token details
      },
      "outputAmountDisplay": "1459.244847",
      "estimatedTimeInSeconds": 900
    }]
  }
}
```

[View full quotes response example](https://docs.blockend.com/compass-api/api-reference/fetching-quotes)


# Create Transaction

Creates a transaction from a selected quote, preparing all necessary steps for the cross-chain transfer.

```typescript
interface CreateTransactionParams {
  // Route ID obtained from getQuotes response
  routeId: string;
}

//Example implementation
const transaction = await createTransaction({
  routeId: quotes.data.quotes[0].routeId,
});

// Example Response (shortened)
{
  "status": "success",
  "data": {
    "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
    "steps": [{
      "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
      "stepType": "bridge",
      "chainId": "1"
    }]
  }
}
```

[View full createTransaction response example](https://docs.blockend.com/compass-api/api-reference/create-transaction)


# getNextTxn

Retrieves the raw transaction data for the next pending step in the transaction sequence. The response format varies based on the blockchain network:

```typescript
interface TransactionDataParams {
  routeId: string; // Route ID from createTransaction
  stepId: string; // Step ID from the transaction steps array
}

//Example implementation
const nextTxn = await getNextTxn({
  routeId: transaction.routeId,
  stepId: transaction.steps[0].id,
});

// Example Response (shortened)
{
  "status": "success",
  "data": {
    "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
    "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
    "networkType": "evm",
    "txnData": {
      "txnType": "on-chain" | "sign-typed" | "sign-untyped"
      "txnEvm": {
        "to": "0x...",
        "value": "420000000000000000",
        // ... other transaction details
      }
    }
  }
}
```

**Transaction Types**

The SDK supports multiple transaction types that are automatically handled based on the protocol and requirements:

1. **On-chain Transactions** (`txnType: "on-chain"`):

   * Regular blockchain transactions that require gas fees
   * Used for standard token transfers and swaps

   ```typescript
   // Example response for on-chain transaction
   {
     "txnType": "on-chain",
     "txnEvm": {
       "from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
       "to": "0x1234567890abcdef1234567890abcdef12345678",
       "value": "420000000000000000",
       "data": "0x095ea7b3...",
       "gasPrice": "30000000000",
       "gasLimit": "250000"
     }
   }

   // Execute using wagmi/viem
   import { getWalletClient } from "wagmi";
   const client = await getWalletClient();
   const hash = await client.sendTransaction({
     to: txnEvm.to as `0x${string}`,
     data: txnEvm.data as `0x${string}`,
     value: BigInt(txnEvm.value),
     gas: BigInt(txnEvm.gasLimit),
     gasPrice: BigInt(txnEvm.gasPrice),
   });

   // Execute using ethers.js
   import { BrowserProvider } from "ethers";
   const provider = new BrowserProvider(window.ethereum);
   const signer = await provider.getSigner();
   const transaction = await signer.sendTransaction({
     from: txnEvm.from,
     to: txnEvm.to,
     data: txnEvm.data,
     gasLimit: txnEvm.gasLimit,
     gasPrice: txnEvm.gasPrice,
     value: txnEvm.value,
   });
   const hash = transaction.hash;
   ```
2. **EIP-712 Typed Data Signing** (`txnType: "sign-typed"`):

   * Implements EIP-712 for structured data signing on EVM chains
   * Used for permit-style approvals and meta-transactions (for gasless)

   ```typescript
   // Example response for typed data signing
   {
     "txnType": "sign-typed",
     "txnEvm": {
       "domain": {
         "name": "Permit2",
         "version": "1",
         "chainId": 1,
         "verifyingContract": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
       },
       "types": {
         "PermitSingle": [
           { "name": "details", "type": "PermitDetails" },
           { "name": "spender", "type": "address" },
           { "name": "sigDeadline", "type": "uint256" }
         ],
         "PermitDetails": [
           { "name": "token", "type": "address" },
           { "name": "amount", "type": "uint160" },
           { "name": "expiration", "type": "uint48" },
           { "name": "nonce", "type": "uint48" }
         ]
       },
       "message": {
         "details": {
           "token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
           "amount": "1461501637330902918203684832716283019655932542975",
           "expiration": "1747836789",
           "nonce": "0"
         },
         "spender": "0x1234567890123456789012345678901234567890",
         "sigDeadline": "1747836789"
       },
       "primaryType": "PermitSingle"
     }
   }

   // Execute using wagmi/viem
   import { getWalletClient } from "wagmi";
   const client = await getWalletClient();
   const signature = await client.signTypedData({
     account, // userWalletAddress
     domain: txnEvm.domain,
     types: txnEvm.types,
     primaryType: txnEvm.primaryType,
     message: txnEvm.message,
   });

   // Execute using ethers.js
   import { BrowserProvider } from "ethers";
   const provider = new BrowserProvider(window.ethereum);
   const signer = await provider.getSigner();
   // Remove EIP712Domain from types before signing
   delete txnEvm.types.EIP712Domain;
   const signature = await signer.signTypedData(
     txnEvm.domain,
     {
       [txnEvm.primaryType]: txnEvm.types[txnEvm.primaryType],
       ...txnEvm.types,
     },
     txnEvm.message
   );
   ```
3. **Untyped Message Signing** (`txnType: "sign-untyped"`):

   * Used for protocols like Meson.fi that require message signing
   * Supports cross-chain message verification

   ```typescript
   // Example response for untyped message signing
   {
     "txnType": "sign-untyped",
     "txnEvm": {
       "message": "0x1901c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f4fc3",
     }
   }

   // Execute using wagmi/viem
   import { getWalletClient } from "wagmi";
   const client = await getWalletClient();
   const signature = await client.request({
     method: "personal_sign",
     params: [txnEvm.message, account],
   });

   // Execute using ethers.js
   import { BrowserProvider } from "ethers";
   const provider = new BrowserProvider(window.ethereum);
   const signer = await provider.getSigner();
   const signature = await provider.send("personal_sign", [
     txnEvm.message,
     account,
   ]);
   ```

The transaction type is automatically determined based on the quote and protocol being used. The SDK handles all the necessary signing logic internally, including:

* Proper formatting of typed and untyped data
* Chain-specific signature requirements
* Protocol-specific message formatting
* Gasless transaction handling

**Transaction Data Response Examples**

Send txnEvm or txnSol or txnCosmos to the appropriate wallet/provider based on the networkType and get the transaction hash to monitor the status of the transaction.

**EVM Chain Response**

```typescript
{
  "status": "success",
  "data": {
    "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
    "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
    "networkType": "evm",
    "txnData": {
      "txnEvm": {
        "from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
        "to": "0x1234567890abcdef1234567890abcdef12345678",
        "value": "420000000000000000",
        "data": "0x095ea7b3...",
        "gasPrice": "30000000000",
        "gasLimit": "250000"
      }
    }
  }
}
```

**Solana Chain Response**

```typescript
{
  "status": "success",
  "data": {
    "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
    "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
    "networkType": "sol",
    "txnData": {
      "txnSol": {
        "data": "base64EncodedTransactionData...",
      }
    }
  }
}
```

**Cosmos Chain Response**

```typescript
{
  "status": "success",
  "data": {
    "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
    "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
    "networkType": "cosmos",
    "txnData": {
      "txnCosmos": {
        "data": "{"typeUrl":"/ibc.applications.trans"}",
        "value": "0",
        "gasLimit": "250000",
        "gasPrice": "0.025",
      }
    }
  }
}
```

[View full getNextTxn response example](https://docs.blockend.com/compass-api/api-reference/get-raw-transaction-to-execute)


# Check Status

Monitors the status of a transaction step, providing detailed information about its progress.

```typescript
interface StatusCheckParams {
  // Route ID of the transaction
  routeId: string;

  // Step ID being checked
  stepId: string;

  // Transaction hash from the blockchain
  txnHash: string;
}

//Example implementation
const status = await checkStatus({
  routeId: transaction.routeId,
  stepId: transaction.steps[0].id,
  txnHash: result.hash,
});

// Example Response (shortened)
{
  "status": "success",
  "data": {
    "status": "success",
    "outputAmount": "1459244847",
    "outputAmountDisplay": "1459.244847"
  }
}
type TransactionStatus = "not-started" | "in-progress" | "success" | "failed";
```

See checkStatus example implementation using while loop below.

[View full checkStatus response example](https://docs.blockend.com/compass-api/api-reference/check-transaction-status)

Here's a simpler example to poll the transaction status:

```typescript
async function pollWithWhileLoop(
  routeId: string,
  stepId: string,
  txnHash: string
) {
  const POLLING_INTERVAL = 3000; // 3 seconds
  const MAX_ATTEMPTS = 200; // Maximum number of attempts (10 minutes with 3s interval)
  let attempts = 0;

  while (attempts < MAX_ATTEMPTS) {
    try {
      const response = await checkStatus({ routeId, stepId, txnHash });
      const status = response.data.status;

      console.log(`Current status: ${status}`);

      if (["success", "failed", "partial-success"].includes(status)) {
        return response.data;
      }

      // Wait for the polling interval
      await new Promise((resolve) => setTimeout(resolve, POLLING_INTERVAL));
      attempts++;
    } catch (error) {
      console.error("Error checking status:", error);
      throw error;
    }
  }

  throw new Error("Polling timeout: Maximum attempts reached");
}

// Usage example:
try {
  const result = await pollWithWhileLoop(
    "your-route-id",
    "your-step-id",
    "your-transaction-hash"
  );
  console.log("Final result:", result);
} catch (error) {
  console.error("Polling failed:", error);
}
```


# pollTransactionStatus

Continuously monitors a transaction's status by polling at regular intervals until a final state is reached or timeout occurs. This method provides a convenient way to track cross-chain transactions through their entire lifecycle.

```typescript
interface PollTransactionStatusParams {
  // Route ID of the transaction
  routeId: string;

  // Step ID being monitored
  stepId: string;

  // Transaction hash from the blockchain
  txnHash: string;

  // Optional: Interval between status checks in milliseconds (default: 2000ms)
  pollingIntervalMs?: number;

  // Optional: Maximum time to poll before timing out in milliseconds (default: 600000ms / 10 minutes)
  timeoutMs?: number;

  // Optional: Callback function for real-time status updates
  onStatusUpdate?: (status: TransactionStatus, data?: ExecuteTransactionResult) => void;
}

// Example usage:
const result = await pollTransactionStatus({
  routeId: "your-route-id",
  stepId: "your-step-id",
  txnHash: "your-transaction-hash",
  pollingIntervalMs: 3000, // Poll every 3 seconds, by default it's 2 seconds
  timeoutMs: 300000, // Timeout after 5 minutes, by default it's 10 minutes
  onStatusUpdate: (status, data) => {
    console.log(`Transaction status updated: ${status}`);
    if (data) {
      console.log("Transaction data:", data);
    }
  },
});

// Example Response
{
  "status": "success",
  "data": {
    "status": "success",
    "outputAmount": "1459244847",
    "outputAmountDisplay": "1459.244847",
    "srcTxnHash": "0x...",
    "dstTxnHash": "0x...",
  "srcTxnUrl": "https://etherscan.io/tx/0x...",
  "dstTxnUrl": "https://etherscan.io/tx/0x...",
  "points": 100,
  "warnings": [],
  }
}
```

The method will continue polling until one of these conditions is met:

* Transaction reaches a final status ("success", "failed", or "partial-success")
* Polling timeout is reached
* An error occurs during status checking

**Status Types:**

* `"not-started"`: Transaction has not been initiated
* `"in-progress"`: Transaction is being processed
* `"success"`: Transaction completed successfully
* `"failed"`: Transaction failed
* `"partial-success"`: Transaction partially succeeded (some steps completed)

**Error Handling:**

* Throws a timeout error if `timeoutMs` is exceeded
* Throws any errors encountered during status checking
* Provides detailed error information through the `BlockendError` class

**Best Practices:**

1. Set appropriate `pollingIntervalMs` based on chain block times
2. Configure reasonable `timeoutMs` for your use case
3. Implement proper error handling
4. Use the `onStatusUpdate` callback for real-time UI updates


# executeQuote

Execute quote with the provided quote and wallet. This method handles the actual execution of the cross-chain transaction using the appropriate wallet/provider based on the chain type.

```typescript
interface ExecuteTransactionParams {
  quote: Quote;
  // For EVM chains (Ethereum, BSC, Polygon, etc.)
  provider?: Provider | WalletClient; // Supports ethers.js BrowserProvider or viem WalletClient (including wagmi's getWalletClient)
  // For Solana chain
  walletAdapter?: WalletAdapter; // Compatible with @solana/web3.js and @solana/wallet-adapter-base wallets
  // For Cosmos-based chains
  cosmosClient?: any; // Compatible with @cosmjs/stargate and @cosmjs/cosmwasm-stargate clients
  // Optional callback for tracking transaction status
  onStatusUpdate?: (status: TransactionStatus, data?: ExecuteTransactionResult) => void;
  onCreateTxComplete?: (tx: CreateTransactionResponse) => void;
  onNextTxComplete?: (tx: TransactionDataResponse) => void;
  onSignComplete?: (txDetail: { stepId: string; txHash: string }) => void;
  solanaRpcUrl?: string;
}
```

**Examples for different chains:**

```typescript
// 1. EVM Chains Examples
// Using ethers.js BrowserProvider
import { BrowserProvider } from "ethers";
const provider = new BrowserProvider(window.ethereum);
const evmResult = await executeTransaction({
  quote: quotes.data.quotes[0],
  provider: provider,
});

// Using viem WalletClient
import { createWalletClient, custom } from "viem";
const walletClient = createWalletClient({
  transport: custom(window.ethereum),
});
const evmViemResult = await executeTransaction({
  quote: quotes.data.quotes[0],
  provider: walletClient,
});

// Using wagmi's getWalletClient
import { getWalletClient } from "@wagmi/core";
const wagmiClient = await getWalletClient();
const evmWagmiResult = await executeTransaction({
  quote: quotes.data.quotes[0],
  provider: wagmiClient,
});

// 2. Solana Examples
// Using Phantom Wallet
import { PhantomWalletAdapter } from "@solana/wallet-adapter-phantom";
const phantomWallet = new PhantomWalletAdapter();
await phantomWallet.connect();
const solanaResult = await executeTransaction({
  quote: quotes.data.quotes[0],
  walletAdapter: phantomWallet,
});

// Using Solana Wallet Adapter
import { useWallet } from "@solana/wallet-adapter-react";
const { wallet } = useWallet();
const solanaAdapterResult = await executeTransaction({
  quote: quotes.data.quotes[0],
  walletAdapter: wallet,
});

// 3. Cosmos Examples
// Using CosmJS with Keplr
import { SigningStargateClient } from "@cosmjs/stargate";
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";

// For standard Cosmos chains
const getStargateClient = async () => {
  if (!window.keplr) throw new Error("Keplr not installed");
  await window.keplr.enable("cosmoshub-4"); // or your chain ID
  const offlineSigner = window.keplr.getOfflineSigner("cosmoshub-4");
  const client = await SigningStargateClient.connectWithSigner(
    "https://rpc.cosmos.network", // your RPC endpoint
    offlineSigner
  );
  return client;
};

const cosmosResult = await executeTransaction({
  quote: quotes.data.quotes[0],
  cosmosClient: await getStargateClient(),
});

// For CosmWasm chains (e.g., Terra, Secret Network)
const getCosmWasmClient = async () => {
  if (!window.keplr) throw new Error("Keplr not installed");
  await window.keplr.enable("phoenix-1"); // or your chain ID
  const offlineSigner = window.keplr.getOfflineSigner("phoenix-1");
  const client = await SigningCosmWasmClient.connectWithSigner(
    "https://terra-rpc.example.com", // your RPC endpoint
    offlineSigner
  );
  return client;
};

const cosmWasmResult = await executeTransaction({
  quote: quotes.data.quotes[0],
  cosmosClient: await getCosmWasmClient(),
});
```

The `provider`, `walletAdapter`, and `cosmosClient` parameters are mutually exclusive - you should provide the appropriate one based on the chain you're interacting with:

* For EVM chains: provide the `provider` parameter
* For Solana: provide the `walletAdapter` parameter
* For Cosmos chains: provide the `cosmosClient` parameter

### onStatusUpdate

The `onStatusUpdate` callback receives real-time updates about the transaction status and optional data payload.<br>

<pre class="language-typescript"><code class="lang-typescript">export interface ExecuteTransactionResult {
  routeId: string;
  status: TransactionStatus;
  srcTxnHash?: string;
  srcTxnUrl?: string;
  destTxnHash?: string;
  destTxnUrl?: string;
  outputAmount: string;
  outputToken: Token;
  warnings?: string[];
  points?: number;
  stepId?: string;
  txHash?: string;
}
export type Status="not-started" | "in-progress" | "success" | "failed" | "partial-success";

<strong>onSuccessUpdate:(status:string,data:ExecuteTransactionResult)=>{
</strong>console.log(status)// current status of the transaction
console.log(data)// data realted to the current transaction like transaction hash, transaction url, output token details etc..,
<strong>}
</strong></code></pre>

### onCreateTxComplete

The `onCreateTxComplete` callback receives the success response of /createTx endpoint

```typescript
onCreateTxComplete?: (tx: CreateTransactionResponse) => void;
onCreateTxComplete:(createTxData:CreateTransactionData)=>{
console.log(createTxData)
}
```

Refer the  page below for more details related to createTxData

{% content-ref url="/pages/k8ntX4gOMt4NWP7uHdLF" %}
[Create Transaction](/compass-api/api-reference/create-transaction)
{% endcontent-ref %}

### onNextTxComplete

The `onNextTxComplete` callback receives the success response of /nextTx endpoint

```typescript
onNextTxComplete?: (tx: TransactionDataResponse) => void;
onCreateTxComplete:(nextTxData:TransactionDataResponse)=>{
console.log(nextTxData)
}
```

Refer the  page below for more details related to nextTxData

{% content-ref url="/pages/PyMbWnPLKHYMc2lVGRQx" %}
[Get Raw Transaction To Execute](/compass-api/api-reference/get-raw-transaction-to-execute)
{% endcontent-ref %}

### onSignComplete

The `onSignComplete` callback receives stepId of the signed transaction and the transaction hash

```typescript
onSignComplete?: (txDetail: { stepId: string; txHash: string }) => void;
onSignComplete:(txDetail:{ stepId: string; txHash: string})=>{
console.log(txDetail)
}
```

\
Errors will be thrown if any of the apis or signing transaction failed so that developers can catch the error and show it to their users.


# executeTransaction

Executes a single transaction step with the provided transaction data. This method is used internally by `executeQuote` but can also be used directly for more granular control over transaction execution.

<pre class="language-typescript"><code class="lang-typescript"><strong>interface ExecuteTransactionParams {
</strong>  txDataResponse: TransactionDataResponse;
  quote: Quote;
  step: TransactionStep;
  provider: BrowserProvider | WalletClient;
  walletAdapter: WalletAdapter;
  cosmosClient: SigningStargateClient | SigningCosmWasmClient;
  solanaRpcUrl?: string;
}

// Example implementation
const txnResponse = await getNextTxn({
  routeId: quote.routeId,
  stepId: step.stepId,
});
// Example implementation
const txHash = await executeTransaction({
  txDataResponse,
  quote,
  step,
  provider: ethersProvider,
  walletAdapter: solanaWallet,
  cosmosClient: cosmosClient,
  solanaRpcUrl: "https://api.mainnet-beta.solana.com",
});
</code></pre>

The method handles different transaction types based on the network:

* For EVM chains: Supports regular transactions for on chain transactions, EIP-712 typed data signing for gasless transactions, and untyped message signing for meson finance transactions.
* For Solana: Handles Solana-specific transaction formats
* For Cosmos: Manages Cosmos SDK transaction types

The `provider`, `walletAdapter`, and `cosmosClient` parameters are mutually exclusive - you should provide the appropriate one based on the chain you're interacting with:

* For EVM chains: provide the `provider` parameter
* For Solana: provide the `walletAdapter` parameter
* For Cosmos chains: provide the `cosmosClient` parameter

The method returns the transaction hash of the executed transaction, which can be used to monitor its status using `checkStatus` or `pollTransactionStatus`.


# Gasless Transactions

The SDK supports gasless transactions through two options in the `QuoteParams`:

```typescript
interface QuoteParams {
  // ... other params ...

  // Optional: Get fully gasless transactions (both approval and swap)
  gasless?: boolean;

  // Optional: Get gasless swap transactions (approvals may still require gas)
  gaslessSwap?: boolean;
}
```

Example of requesting a gasless quote:

```typescript
const gaslessQuote = await getQuotes({
  fromChainId: "137",
  fromAssetAddress: "0x...",
  toChainId: "1",
  toAssetAddress: "0x...",
  inputAmount: "1000000000000000000",
  inputAmountDisplay: "1.0",
  userWalletAddress: "0x...",
  gasless: true, // Enable gasless(approval+swap) transactions
  gaslessSwap: true, // Enable gasless atleast for swaps and approval may or not be gasless based on the tokens selected
});
```

Example response for a gasless quote:

```typescript
{
  "status": "success",
  "data": {
    "quotes": [{
      "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
      "from": {
        "chainId": "137",
        "symbol": "MATIC",
        "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
        "decimals": 18,
        "name": "Polygon",
        "blockchain": "Polygon",
        "isNative": true
      },
      "to": {
        "chainId": "1",
        "symbol": "USDC",
        "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "decimals": 6,
        "name": "USD Coin",
        "blockchain": "Ethereum"
      },
      "steps": [{
        "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
        "stepType": "swap",
        "protocolsUsed": ["uniswap-v3"],
        "provider": "uniswap",
        "gasless": true, // Indicates this step is gasless
        "from": {
          // Token details same as above
        },
        "to": {
          // Token details same as above
        },
        "fee": [{
          "name": "Protocol Fee",
          "value": "0.3",
          "token": "MATIC"
        }],
        "inputAmount": "1000000000000000000",
        "outputAmount": "1459244847",
        "estimatedTimeInSeconds": 300
      }],
      "outputAmountDisplay": "1.459244847",
      "outputAmount": "1459244847",
      "estimatedTimeInSeconds": 300,
      "fee": [{
        "name": "Protocol Fee",
        "value": "0.3",
        "token": "MATIC"
      }],
      "gasless": true // Indicates the entire route is gasless
    }]
  }
}
```

Example response for a gasless create transaction:

```typescript
{
  "status": "success",
  "data": {
    "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
    "steps": [{
      "stepId": "01J2WB1NY64MKVCM8FM994WMZV",
      "stepType": "approval",
      "protocolsUsed": ["permit2"],
      "provider": "permit2",
      "gasless": true,
      "chainId": "137"
    },
    {
      "stepId": "01J2WB1NY64MKVCM8FM994WMZW",
      "stepType": "swap",
      "protocolsUsed": ["uniswap-v3"],
      "provider": "uniswap",
      "gasless": true,
      "chainId": "137"
    }]
  }
}
```

Example response for a gasless transaction step (swap):

```typescript
{
  "status": "success",
  "data": {
    "routeId": "01J2WB1NY6MD3F25CJTTB01D8F",
    "stepId": "01J2WB1NY64MKVCM8FM994WMZW",
    "networkType": "evm",
    "txnData": {
      "txnType": "sign-typed",
      "txnEvm": {
        "domain": {
          "name": "Gasless Swap",
          "version": "1",
          "chainId": 137,
          "verifyingContract": "0x9876543210987654321098765432109876543210"
        },
        "types": {
          "MetaTransaction": [
            { "name": "from", "type": "address" },
            { "name": "to", "type": "address" },
            { "name": "value", "type": "uint256" },
            { "name": "nonce", "type": "uint256" },
            { "name": "deadline", "type": "uint256" }
          ]
        },
        "message": {
          "from": "0x17e7c3DD600529F34eFA1310f00996709FfA8d5c",
          "to": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
          "value": "1000000000000000000",
          "nonce": "1",
          "deadline": "1747836789"
        },
        "primaryType": "MetaTransaction"
      }
    },
    "gasless": true
  }
}
```

Example code to execute a gasless transaction :

```typescript
// wagami / viem
import { getWalletClient } from "wagmi";
import { config } from "./config";

const client = getWalletClient(config);
const signature = await client.signTypedData({
  account, // userWalletAddress
  domain,
  types,
  primaryType,
  message,
});

// Ethers
import { BrowserProvider } from "ethers";
const provider = new BrowserProvider(window.ethereum);
//make sure the wallet is connected before executing this step
delete types.EIP712Domain;
const signer = await provider.getSigner();
const signature = await signer.signTypedData(
  domain,
  {
    [primaryType]: types[primaryType],
    ...types,
  },
  message
);
```


# Tokens and Chains

Get a list of supported tokens, optionally filtered by chain ID.

```typescript
interface TokensParams {
  chainId?: string;
}

//Example implementation
const tokens = await getTokens();// to fetch all tokens from all chains
const tokens = await getTokens("1");// to fetch all tokens from chain 1

//Example response
{
  "status": "success",
  "data":{
    "1":[
      {
    "networkType": "evm",
    "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
    "chainId": "1",
    "blockchain": "Ethereum",
    "decimals": 18,
    "name": "Ethereum",
    "symbol": "ETH",
    "image": "https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1595348880",
    "lastPrice": 2703.62,
    "isEnabled": true,
    "isFlagged": false,
    "isNative": true,
    "isPopular": true
},
//other coins on chain 1
    ]
  }
}
```

**`getChains()`** <br>

Get a list of supported blockchain networks.

```typescript
interface Chain {
  id: string;
  name: string;
  networkType: "evm" | "sol" | "cosmos";
  nativeCurrency: {
    name: string;
    symbol: string;
    decimals: number;
  };
  blockExplorer: string;
  rpcUrls: string[];
}
//Example implementation
const chains = await getChains(); // to fetch all chains

//Example response
{
  "status": "success",
  "data": [
    {
  "chainId": "sol",
  "symbol": "sol",
  "name": "Solana",
  "networkType": "sol",
  "image": "https://assets.coingecko.com/coins/images/4128/large/solana.png?1696504756",
  "explorer": {
    "address": "https://solscan.io/account/{address}",
    "token": "https://solscan.io/token/{tokenAddress}",
    "txn": "https://solscan.io/tx/{txnHash}"
  },
  "isPopular": true,
  "tokenCount": 946,
  "isEnabled": true
},
//other supported chains
  ]
}
```


# Supported Chains

You can get list of supported chains from the following endpoint

```
curl -X GET "https://api2.blockend.com/v1/chains" \
  -H "accept: application/json"
```

### List of chains supported

<table><thead><tr><th width="106">Sr. No</th><th width="196">Chain Name</th><th>Chain ID</th></tr></thead><tbody><tr><td>1</td><td>Ethereum</td><td>1</td></tr><tr><td>2</td><td>Solana</td><td>sol</td></tr><tr><td>3</td><td>BSC</td><td>56</td></tr><tr><td>4</td><td>Base</td><td>8453</td></tr><tr><td>5</td><td>Arbitrum</td><td>42161</td></tr><tr><td>6</td><td>Avalanche</td><td>43114</td></tr><tr><td>7</td><td>Polygon</td><td>137</td></tr><tr><td>8</td><td>Optimism</td><td>10</td></tr><tr><td>9</td><td>Cronos</td><td>25</td></tr><tr><td>10</td><td>Blast</td><td>81457</td></tr><tr><td>11</td><td>Mantle</td><td>5000</td></tr><tr><td>12</td><td>Linea</td><td>59144</td></tr><tr><td>13</td><td>dYdX</td><td>dydx-mainnet-1</td></tr><tr><td>14</td><td>Gnosis</td><td>100</td></tr><tr><td>15</td><td>Scroll</td><td>534352</td></tr><tr><td>16</td><td>Rootstock</td><td>30</td></tr><tr><td>17</td><td>Sei</td><td>pacific-1</td></tr><tr><td>18</td><td>Mode</td><td>34443</td></tr><tr><td>19</td><td>Osmosis</td><td>osmosis-1</td></tr><tr><td>20</td><td>CELO</td><td>42220</td></tr><tr><td>21</td><td>Fantom</td><td>250</td></tr><tr><td>22</td><td>zkSync Era</td><td>324</td></tr><tr><td>23</td><td>Neutron</td><td>neutron-1</td></tr><tr><td>24</td><td>Injective</td><td>injective-1</td></tr><tr><td>25</td><td>Kujira</td><td>kaiyo-1</td></tr><tr><td>26</td><td>Aurora</td><td>1313161554</td></tr><tr><td>27</td><td>Moonbeam</td><td>1284</td></tr><tr><td>28</td><td>Secret</td><td>secret-4</td></tr><tr><td>29</td><td>Polygon zkEVM</td><td>1101</td></tr><tr><td>30</td><td>Moonriver</td><td>1285</td></tr><tr><td>31</td><td>Dymension</td><td>dymension_1100-1</td></tr><tr><td>32</td><td>Carbon</td><td>carbon-1</td></tr><tr><td>33</td><td>Harmony</td><td>1666600000</td></tr><tr><td>34</td><td>Archway</td><td>archway-1</td></tr><tr><td>35</td><td>Boba</td><td>288</td></tr><tr><td>36</td><td>OKXChain</td><td>66</td></tr><tr><td>37</td><td>Cosmos Hub</td><td>cosmoshub-4</td></tr><tr><td>38</td><td>Fuse</td><td>122</td></tr><tr><td>39</td><td>Terra Classic</td><td>columbus-5</td></tr><tr><td>40</td><td>Heco</td><td>128</td></tr><tr><td>41</td><td>Evmos</td><td>9001</td></tr><tr><td>42</td><td>Chihuahua</td><td>chihuahua-1</td></tr><tr><td>43</td><td>Juno</td><td>juno-1</td></tr><tr><td>44</td><td>Migaloo</td><td>migaloo-1</td></tr><tr><td>45</td><td>Nolus</td><td>pirin-1</td></tr><tr><td>46</td><td>Nibiru</td><td>cataclysm-1</td></tr><tr><td>47</td><td>Stargaze</td><td>stargaze-1</td></tr><tr><td>48</td><td>Comdex</td><td>comdex-1</td></tr><tr><td>49</td><td>Crescent</td><td>crescent-1</td></tr><tr><td>50</td><td>Agoric</td><td>agoric-3</td></tr><tr><td>51</td><td>Akash</td><td>akashnet-2</td></tr><tr><td>52</td><td>AssetMantle</td><td>mantle-1</td></tr><tr><td>53</td><td>Axelar</td><td>axelar-dojo-1</td></tr><tr><td>54</td><td>BandChain</td><td>band-laozi-mainnet1</td></tr><tr><td>55</td><td>BitCanna</td><td>bitcanna-1</td></tr><tr><td>56</td><td>BitSong</td><td>bitsong-2b</td></tr><tr><td>57</td><td>Celestia</td><td>celestia</td></tr><tr><td>58</td><td>Chain4Energy</td><td>perun-1</td></tr><tr><td>59</td><td>Cheqd</td><td>cheqd-mainnet-1</td></tr><tr><td>60</td><td>Coreum</td><td>coreum-mainnet-1</td></tr><tr><td>61</td><td>Decentr</td><td>mainnet-3</td></tr><tr><td>62</td><td>Desmos</td><td>desmos-mainnet</td></tr><tr><td>63</td><td>Gravity Bridge</td><td>gravity-bridge-3</td></tr><tr><td>64</td><td>Humans.ai</td><td>humans_1089-1</td></tr><tr><td>65</td><td>IRISnet</td><td>irishub-1</td></tr><tr><td>66</td><td>Impacts Hub</td><td>ixo-5</td></tr><tr><td>67</td><td>Jackal</td><td>jackal-1</td></tr><tr><td>68</td><td>Kava IBC</td><td>kava_2222-10</td></tr><tr><td>69</td><td>Lava</td><td>lava-mainnet-1</td></tr><tr><td>70</td><td>LikeCoin</td><td>likecoin-mainnet-2</td></tr><tr><td>71</td><td>Lum Network</td><td>lum-network-1</td></tr><tr><td>72</td><td>Mars Hub</td><td>mars-1</td></tr><tr><td>73</td><td>Noble</td><td>noble-1</td></tr><tr><td>74</td><td>OmniFlix</td><td>omniflixhub-1</td></tr><tr><td>75</td><td>Persistence</td><td>core-1</td></tr><tr><td>76</td><td>Quasar</td><td>quasar-1</td></tr><tr><td>77</td><td>Quicksilver</td><td>quicksilver-2</td></tr><tr><td>78</td><td>Regen</td><td>regen-1</td></tr><tr><td>79</td><td>Saga</td><td>ssc-1</td></tr><tr><td>80</td><td>Sentinel</td><td>sentinelhub-2</td></tr><tr><td>81</td><td>Sommelier</td><td>sommelier-3</td></tr><tr><td>82</td><td>Stride</td><td>stride-1</td></tr><tr><td>83</td><td>Teritori</td><td>teritori-1</td></tr><tr><td>84</td><td>Umee</td><td>umee-1</td></tr><tr><td>85</td><td>Taiko</td><td>167000</td></tr><tr><td>86</td><td>Metis</td><td>1088</td></tr><tr><td>87</td><td>Fraxtal</td><td>252</td></tr><tr><td>88</td><td>World Chain</td><td>480</td></tr><tr><td>89</td><td>Soneium</td><td>1868</td></tr><tr><td>90</td><td>Zircuit</td><td>48900</td></tr><tr><td>91</td><td>Abstract</td><td>2741</td></tr><tr><td>92</td><td>BeraChain</td><td>80094</td></tr><tr><td>93</td><td>Unichain</td><td>130</td></tr><tr><td>94</td><td>Sonic</td><td>146</td></tr><tr><td>95</td><td>Story</td><td>1514</td></tr><tr><td>96</td><td>Eclipse</td><td>eclipse-svm</td></tr><tr><td>97</td><td>HyperEVM</td><td>999</td></tr><tr><td>98</td><td>Bitcoin</td><td>0</td></tr><tr><td>99</td><td>Manta Pacific</td><td>169</td></tr><tr><td>100</td><td>Mint</td><td>185</td></tr><tr><td>101</td><td>Shape</td><td>360</td></tr><tr><td>102</td><td>AppChain</td><td>466</td></tr><tr><td>103</td><td>Redstone</td><td>690</td></tr><tr><td>104</td><td>Flow EVM</td><td>747</td></tr><tr><td>105</td><td>Lisk</td><td>1135</td></tr><tr><td>106</td><td>Sei (EVM)</td><td>1329</td></tr><tr><td>107</td><td>Perennial</td><td>1424</td></tr><tr><td>108</td><td>Gravity</td><td>1625</td></tr><tr><td>109</td><td>SwellChain</td><td>1923</td></tr><tr><td>110</td><td>Sanko</td><td>1996</td></tr><tr><td>111</td><td>Ronin</td><td>2020</td></tr><tr><td>112</td><td>G7 Network</td><td>2187</td></tr><tr><td>113</td><td>Morph</td><td>2818</td></tr><tr><td>114</td><td>Hychain</td><td>2911</td></tr><tr><td>115</td><td>Ham</td><td>5112</td></tr><tr><td>116</td><td>Superseed</td><td>5330</td></tr><tr><td>117</td><td>Cyber</td><td>7560</td></tr><tr><td>118</td><td>Powerloom V2</td><td>7869</td></tr><tr><td>119</td><td>Arena-Z</td><td>7897</td></tr><tr><td>120</td><td>B3</td><td>8333</td></tr><tr><td>121</td><td>Onchain Points</td><td>17071</td></tr><tr><td>122</td><td>Ape Chain</td><td>33139</td></tr><tr><td>123</td><td>Funkichain</td><td>33979</td></tr><tr><td>124</td><td>Arbitrum Nova</td><td>42170</td></tr><tr><td>125</td><td>Hemi</td><td>43111</td></tr><tr><td>126</td><td>Superposition</td><td>55244</td></tr><tr><td>127</td><td>Ink</td><td>57073</td></tr><tr><td>128</td><td>BOB</td><td>60808</td></tr><tr><td>129</td><td>Animechain</td><td>69000</td></tr><tr><td>130</td><td>Proof of Play Apex</td><td>70700</td></tr><tr><td>131</td><td>Proof of Play Boss</td><td>70701</td></tr><tr><td>132</td><td>Plume</td><td>98866</td></tr><tr><td>133</td><td>ZERO</td><td>543210</td></tr><tr><td>134</td><td>Xai</td><td>660279</td></tr><tr><td>135</td><td>Forma</td><td>984122</td></tr><tr><td>136</td><td>Zora</td><td>7777777</td></tr><tr><td>137</td><td>Corn</td><td>21000000</td></tr><tr><td>138</td><td>Degen</td><td>666666666</td></tr><tr><td>139</td><td>Ancient8</td><td>888888888</td></tr><tr><td>140</td><td>RARI</td><td>1380012617</td></tr><tr><td>141</td><td>TRON</td><td>728126428</td></tr><tr><td>142</td><td>Etherlink</td><td>42793</td></tr></tbody></table>


# Liquidity Sources

At Compass, we prioritize liquidity sources that offer seamless swaps and cross-chain transactions across 80+ chains, ensuring comprehensive coverage for our users.\
These are the current liquidity sources available on Compass, carefully curated to provide the most efficient liquidity with a focus on capital efficiency, broad token support, and wide chain compatibility. <br>

* [Jupiter](https://jup.ag/) - Solana Aggregator
* [0x](https://0x.org/) - EVM DEX Aggregator
* [1Inch](https://1inch.io/) - EVM DEX Aggregator&#x20;
* [Paraswap](https://paraswap.io/) - EVM DEX Aggregator&#x20;
* [ODOS](https://www.odos.xyz/) - EVM DEX Aggregator&#x20;
* [Virtuals](https://www.virtuals.io/) - AI Agents Launchpad
* [Pump.fun](https://pump.fun/) - Solana Launchpad
* [Mayan Finance](https://mayan.finance/) - Cross Chain Swaps
* [DLN (deBridge)](https://dln.trade/) Cross Chain Swaps&#x20;
* [LiFi](https://li.fi/) - Cross Chain Aggregator
* [Socket](https://socket.tech/) - Cross Chain Aggregator
* [Squid Router](https://www.squidrouter.com/) - Cross Chain Swaps
* [LayerSwap](https://layerswap.io/) - Cross Chain Swaps
* [Across](https://across.to/) - Cross Chain Intents
* [Relay](https://relay.link/) - Cross Chain Intents
* [Kyberswap](https://kyberswap.com/) - EVM DEX Aggregator
* [Meson](https://meson.fi/) - Cross Chain Intents
* [Four.Meme](https://four.meme/) - Token Launchpad
* [Magpie](https://magpiefi.xyz) - Cross Chain Aggregator
* [Orca](https://www.orca.so/) - Multi Chain DEX
* [DFlow](https://dflow.net/)- Solana RFQ DEX
* [Pyth Express](https://www.pyth.network/express-relay)- Solana Intent Protocol
* [OKX](https://web3.okx.com/) - DEX Aggregator

In addition to the listed integrations, there are several active partnerships and integrations under testing and analysis. Our comprehensive analytics mechanism evaluates each liquidity source for performance, reliability, and efficiency before making the integration live.

If you’re interested in being added as a liquidity source and get orderflow, feel free to reach out to us at **<buidl@blockend.com>.**


# Technical FAQs


# EVM Swaps

This guide demonstrates how to execute a token swap on EVM-compatible chains using the Compass API. The example covers the complete workflow from connecting a wallet to monitoring transaction status.

### Overview

The implementation follows these key steps:

1. Wallet Connection
2. Quote Retrieval
3. Transaction Creation
4. Step-by-Step Execution
5. Status Monitoring

### Implementation Details

#### Prerequisites

* MetaMask or any EVM-compatible wallet
* Integrator ID from Compass
* ethers.js library

#### API Endpoints

The example uses the following endpoints:

**`/quotes`**

This endpoint fetches quotes from available liquidity sources and responds with quotes that are sorted by best output amount by default. The first item in the quotes array is the recommended quote.

**Request Parameters**

```javascript
let requestParams = {
  fromChainId: "137", // Source blockchain network ID (Polygon), for chain IDs reference: "/chains" api endpoint
  toChainId: "137", // Destination blockchain network ID (Polygon), for chain IDs reference: "/chains" api endpoint
  fromAssetAddress: "0xb7b31a6bc18e48888545ce79e83e06003be70930", // Source token contract address, for token addresses reference: "/tokens" api endpoint
  toAssetAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // Destination token contract address, for token addresses reference: "/tokens" api endpoint
  inputAmountDisplay: "0.449594453", // Amount of source token to swap, this is the amount that will be transferred from the source token to the destination token, typically received as input from the user
  userWalletAddress: "0x..", // User's wallet address
  recipient: "0x..", // Recipient's wallet address
};
```

**Example Request**

```
GET /quotes?fromChainId=137&toChainId=137&fromAssetAddress=0xc2132d05d31c914a87c6611c10748aeb04b58e8f&toAssetAddress=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&inputAmountDisplay=0.449594453&userWalletAddress=0x1...&recipient=0x1...
```

**Example Response**

```javascript
let quoteResponse = {
  status: "success",
  data: {
    quotes: [
      {
        routeId: "a1b2c3d4-e5f6-g7h8-i9j0",
        fromChainId: "137",
        toChainId: "137",
        from: {
          networkType: "evm",
          address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
          chainId: "137",
          blockchain: "Polygon",
          decimals: 6,
          name: "Tether",
          symbol: "USDT",
          image:
            "https://assets.coingecko.com/coins/images/325/small/Tether.png",
          lastPrice: 0.99999,
          isEnabled: true,
          isFlagged: false,
          isNative: false,
          isPopular: false,
        },
        to: {
          networkType: "evm",
          address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
          chainId: "137",
          blockchain: "Polygon",
          decimals: 18,
          name: "Matic",
          symbol: "MATIC",
          image:
            "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
          lastPrice: 0.412969,
          isEnabled: true,
          isFlagged: false,
          isNative: true,
          isPopular: true,
        },
        protocolsUsed: [],
        providerDetails: {
          id: "odos",
          name: "Odos",
          logoUrl:
            "https://raw.githubusercontent.com/blockend-com/docs-v1/refs/heads/main/resources/png/odos.png",
          websiteUrl: "https://www.odos.xyz/",
        },
        inputAmount: "449594453000000000",
        inputAmountDisplay: "0.449594453",
        outputAmount: "2428429590331476992",
        outputAmountDisplay: "2.4284295903314769927",
        estimatedTimeInSeconds: 15,
      },
    ],
  },
};
```

[View full quotes response](/compass-api/api-reference/fetching-quotes)

**`/createTx`**

This endpoint fetches the transaction steps for the selected quote. A transaction can have multiple steps, e.g., token approval, swap/bridge, etc. Since this is an EVM swap example, the transaction steps can include token approval and swap, or only swap if the source token is already approved. The response includes steps that need to be executed sequentially. Each step includes a step ID and step type (approval, swap, bridge, etc.).

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
};
```

**Example Request**

```
GET /createTx?routeId=a1b2c3d4-e5f6-g7h8-i9j0
```

**Example Response**

```javascript
let createTxResponse = {
  status: "success",
  data: {
    steps: [
      {
        stepId: "step_12345",
        stepType: "approval",
      },
      {
        stepId: "step_67890",
        stepType: "swap",
      },
    ],
  },
};
```

[View full createTx API response](/compass-api/api-reference/create-transaction)

**`/nextTx`**

This endpoint fetches the transaction data that needs to be executed for the selected step. The transaction data includes the transaction parameters for the step. Since this is an EVM swap example, the transaction data includes the txnEvm object field in the transaction data.

Note: The transaction data is specific to the step type. For example, if the step type is swap, the transaction data includes the swap parameters. If the step type is token approval, the transaction data includes the token approval parameters. Moreover, the next step data will be available only if the previous step is executed successfully.

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
  stepId: createTxResponse.data.steps[0].stepId, // stepId is available in the createTx steps[] response
};
```

**Example Request**

```
GET /nextTx?routeId=a1b2c3d4-e5f6-g7h8-i9j0&stepId=step_12345
```

**Example Response**

```javascript
let nextTxResponse = {
  status: "success",
  data: {
    txnData: {
      txnEvm: {
        from: "0x1b1E919E51a1592Dce70a4FD74107941109B8235",
        to: "0xcontractAddress",
        data: "0x...",
        value: "0",
        chainId: 137,
        gasLimit: "300000",
      },
    },
  },
};
```

[View full nextTx API response](/compass-api/api-reference/get-raw-transaction-to-execute)

**`/status`**

This endpoint fetches the transaction status for the selected step once the transaction step is submitted to the blockchain. The transaction status includes: the status of the transaction, the source transaction hash, the source transaction URL, the destination transaction hash, the destination transaction URL, the output amount received, and the output token details.

[View full status API documentation](/compass-api/api-reference/check-transaction-status)

#### Transaction Status Codes

* `in-progress`: Transaction is pending
* `success`: Transaction completed successfully
* `partial-success`: If output amount token is different from the destination token, the transaction is partial success.
* `failed`: Transaction failed

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
  stepId: createTxResponse.data.steps[0].stepId, // stepId is available in the createTx steps[] response
  txnHash: nextTxResponse.data.txnData.txnEvm.hash, // pass the txnHash that is received from the wallet provider once the transaction is signed successfully by the user
};
```

**Example Request**

```
GET /status?routeId=a1b2c3d4-e5f6-g7h8-i9j0&stepId=step_12345&txnHash=0x1234...abcd
```

**Example Response**

```javascript
let statusResponse = {
  status: "success",
  data: {
    status: "success",
    srcTxnHash: "0x1234...abcd",
    srcTxnUrl: "https://polygonscan.com/tx/0x1234...abcd",
    destTxnHash: "0x5678...efgh",
    destTxnUrl: "https://polygonscan.com/tx/0x5678...efgh",
    outputAmount: "449144858547000000",
    outputToken: {
      address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
      symbol: "MATIC",
      decimals: 18,
      name: "MATIC",
    },
  },
};
```

### Code Example

In the code example below, we use plain JavaScript for simplicity, but the code is framework-agnostic and can be easily adapted to React, Next.js, Vite, or any other JavaScript framework. Simply modify the syntax and component structure to match your chosen framework's conventions.

```javascript
import { BrowserProvider, JsonRpcProvider } from "ethers";
const headers = {
  "x-integrator-id": "YOUR_INTEGRATOR_ID",
};

// Helper function to establish connection with an EVM wallet
// Returns essential wallet interaction objects: provider, signer, and wallet address
async function connectWallet() {
  if (!window.ethereum) {
    throw new Error("MetaMask or EVM wallet not detected");
  }

  // For browser environment
  const provider = new BrowserProvider(window.ethereum);
  const accounts = await provider.send("eth_requestAccounts", []);
  const signer = await provider.getSigner();
  // For server environment(nodejs)
  // const provider = new JsonRpcProvider(process.env.RPC_URL);
  // const accounts = await provider.send("eth_requestAccounts", []);
  // const signer = await provider.getSigner();
  return { provider, signer, address: accounts[0] };
}

async function evmSwap() {
  let baseUrl = "https://api2.blockend.com/v1/";

  let queryParams = {
    fromChainId: "137",
    toChainId: "137",
    fromAssetAddress: "0xb7b31a6bc18e48888545ce79e83e06003be70930",
    toAssetAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
    inputAmountDisplay: "0.449594453",
    userWalletAddress: "0x1..",
    recipient: "0x1..",
  };

  // For details about each parameter, refer end points section above

  // Construct API query string for quote retrieval
  let quotesQueryString = `quotes?fromChainId=${queryParams.fromChainId}&toChainId=${queryParams.toChainId}&fromAssetAddress=${queryParams.fromAssetAddress}&toAssetAddress=${queryParams.toAssetAddress}&inputAmountDisplay=${queryParams.inputAmountDisplay}&userWalletAddress=${queryParams.userWalletAddress}&recipient=${queryParams.recipient}`;

  try {
    // Step 1: Initialize wallet connection
    // Establishes connection and gets necessary wallet interfaces
    const { provider, signer, address } = await connectWallet();

    // Step 2: Fetch available quotes
    // Retrieves possible swap routes with pricing information
    // Response: { status: string, data: { quotes: [{ routeId: string, ... }] } }
    const quoteRequest = await fetch(`${baseUrl}${quotesQueryString}`, {
      headers,
    });
    const quotes = await quoteRequest.json();

    // Step 3: Initialize transaction sequence
    // Gets all necessary transaction steps using the selected quote
    // Response: { status: string, data: {  steps:[{stepId: string}] } }
    // Note: Production implementations should include quote selection logic
    let routeId = quotes.data.quotes[0].routeId;
    let createTransactionQueryString = `createTx?routeId=${routeId}`;
    const createTxRequest = await fetch(
      `${baseUrl}${createTransactionQueryString}`,
      {
        headers,
      }
    );

    const createTransactionData = await createTxRequest.json();

    // Step 4: Execute transaction sequence
    // Processes each step (e.g., token approval, swap)
    // Each step requires separate blockchain transaction
    // Response: { status: string, data: {  steps:[{stepId: string}] } }
    let stepCount = 1;
    for (let step of createTransactionData.data.steps) {
      let stepId = step.stepId;
      let nextTxQueryString = `nextTx?routeId=${routeId}&stepId=${stepId}`;
      const nextTxRequest = await fetch(`${baseUrl}${nextTxQueryString}`, {
        headers,
      });
      const nextTxData = await nextTxRequest.json();

      // Step 5: Submit transaction
      // Sends the transaction to the blockchain network
      // Response includes transaction hash for status tracking
      const transaction = await signer.sendTransaction(
        nextTxData.data.txnData.txnEvm
      );
      console.log("Transaction Result:", transaction);
      let txnHash = transaction.hash;

      // Step 6: Monitor transaction status
      // Polls status endpoint until the status is not in-progress
      // Response: { status: string, data: {  status: string,srcTxnHash: string,srcTxnUrl: string,destTxnHash: string,destTxnUrl: string,outputAmount: string,outputToken:{...} } }
      // Status codes: in-progress, success, partial-success, failed
      let currentStatus = "in-progress";
      let statusResponse;

      while (currentStatus === "in-progress") {
        let transactionStatusQueryString = `status?routeId=${routeId}&stepId=${stepId}&txnHash=${txnHash}`;
        const transactionStatusRequest = await fetch(
          `${baseUrl}${transactionStatusQueryString}`,
          {
            headers,
          }
        );
        statusResponse = await transactionStatusRequest.json();

        if (statusResponse.status === "error") {
          currentStatus = "in-progress";
          continue;
        } else {
          currentStatus = statusResponse.data.status;
        }

        // Handle different transaction states
        if (currentStatus === "failed") {
          throw new Error("Transaction failed");
        }

        if (currentStatus === "in-progress") {
          // Wait 2 seconds before next status check
          await new Promise((resolve) => setTimeout(resolve, 2000));
        }

        // Update progress for multi-step transactions
        if (currentStatus === "success") {
          stepCount === createTransactionData.data.steps.length
            ? alert("Transaction successful, TxnHash: " + txnHash)
            : stepCount++;
        }
        if (currentStatus === "partial-success") {
          stepCount === createTransactionData.data.steps.length
            ? alert("Transaction partially successful, txnHash: " + txnHash)
            : stepCount++;
        }
      }
    }
  } catch (error) {
    console.error("Error:", error);
    throw new Error(error.message);
  }
}
```


# EVM to SOL Bridge

This guide demonstrates how to execute a token bridge from EVM-compatible chains to Solana using the Compass API. The example covers the complete workflow from connecting a wallet to monitoring transaction status.

### Overview

The implementation follows these key steps:

1. Wallet Connection
2. Quote Retrieval
3. Transaction Creation
4. Step-by-Step Execution
5. Status Monitoring

### Implementation Details

#### Prerequisites

* MetaMask or any EVM-compatible wallet
* Integrator ID from Compass
* ethers.js library

### API Endpoints

The example uses the following endpoints:

**`/quotes`**

This endpoint fetches quotes from available liquidity sources and responds with quotes that are sorted by best output amount by default. The first item in the quotes array is the recommended quote.

**Request Parameters**

```javascript
let requestParams = {
  fromChainId: "137", // Source blockchain network ID (Polygon), for chain IDs reference: "/chains" api endpoint
  toChainId: "sol", // Destination blockchain network ID (Solana), for chain IDs reference: "/chains" api endpoint
  fromAssetAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // Source token contract address, for token addresses reference: "/tokens" api endpoint
  toAssetAddress: "So11111111111111111111111111111111111111112", // Destination token contract address, for token addresses reference: "/tokens" api endpoint
  inputAmountDisplay: "10", // Amount of source token to bridge, this is the amount that will be transferred from the source token chain to the destination token chain, typically received as input from the user
  userWalletAddress: "0x..", // User's wallet address
  recipient: "4s..", // Recipient's wallet address
};
```

**Example Request**

```
GET /quotes?fromChainId=137&toChainId=sol&fromAssetAddress=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&toAssetAddress=So11111111111111111111111111111111111111112&inputAmountDisplay=10&userWalletAddress=0x1...&recipient=4s...
```

**Example Response**

```javascript
let quoteResponse = {
  status: "success",
  data: {
    quotes: [
      {
        routeId: "bae216ad-de5f-4a28-bf49-8b5d80cd722a",
        from: {
          networkType: "evm",
          address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
          chainId: "137",
          blockchain: "Polygon",
          decimals: 18,
          name: "Matic",
          symbol: "MATIC",
          image:
            "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
          lastPrice: 0.412124,
          isEnabled: true,
          isFlagged: false,
          isNative: true,
          isPopular: true,
        },
        to: {
          networkType: "sol",
          address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
          chainId: "sol",
          blockchain: "Solana",
          decimals: 6,
          name: "Tether",
          symbol: "USDT",
          image:
            "https://assets.coingecko.com/coins/images/325/small/Tether.png",
          lastPrice: 0.999919,
          isEnabled: true,
          isFlagged: false,
          isNative: false,
          isPopular: false,
        },
        steps: [
          {
            stepId: "bae216ad-de5f-4a28-bf49-8b5d80cd722a:0",
            stepType: "bridge",
            protocolsUsed: ["Allbridge"],
            from: {
              networkType: "evm",
              address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 18,
              name: "Matic",
              symbol: "MATIC",
              image:
                "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
              lastPrice: 0.412124,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            to: {
              networkType: "sol",
              address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 6,
              name: "Tether",
              symbol: "USDT",
              image:
                "https://assets.coingecko.com/coins/images/325/small/Tether.png",
              lastPrice: 0.999919,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            inputAmount: "10000000000000000000",
            outputAmount: "2208730",
            fee: [
              {
                type: "NETWORK",
                token: {
                  networkType: "evm",
                  address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                  chainId: "137",
                  blockchain: "Polygon",
                  decimals: 18,
                  name: "Matic",
                  symbol: "MATIC",
                  image:
                    "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
                  lastPrice: 0.412124,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: true,
                  isPopular: true,
                },
                source: "FROM_SOURCE_WALLET",
                amountInToken: "13350000089000000",
                amountInUSD: "0.0055",
              },
              {
                type: "PROVIDER",
                token: {
                  networkType: "evm",
                  address: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
                  chainId: "137",
                  blockchain: "Polygon",
                  decimals: 6,
                  name: "USDC",
                  symbol: "USDC.e",
                  image:
                    "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                  lastPrice: 1,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: false,
                  isPopular: false,
                },
                source: "FROM_OUTPUT_AMOUNT",
                amountInToken: "2127239",
                amountInUSD: 2.1271999999999998,
              },
              {
                type: "PROVIDER",
                token: {
                  networkType: "evm",
                  address: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
                  chainId: "137",
                  blockchain: "Polygon",
                  decimals: 6,
                  name: "USDC",
                  symbol: "USDC.e",
                  image:
                    "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
                  lastPrice: 1,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: false,
                  isPopular: false,
                },
                source: "FROM_OUTPUT_AMOUNT",
                amountInToken: "13008",
                amountInUSD: "0.0130",
              },
            ],
            estimatedTimeInSeconds: 765,
          },
        ],
        fee: [
          {
            type: "NETWORK",
            token: {
              networkType: "evm",
              address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 18,
              name: "Matic",
              symbol: "MATIC",
              image:
                "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
              lastPrice: 0.412124,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            source: "FROM_SOURCE_WALLET",
            amountInToken: "13350000089000000",
            amountInUSD: "0.0055",
          },
          {
            type: "PROVIDER",
            token: {
              networkType: "evm",
              address: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 6,
              name: "USDC",
              symbol: "USDC.e",
              image:
                "https://assets.coingecko.com/coins/images/6319/small/usdc.png",
              lastPrice: 1,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            source: "FROM_OUTPUT_AMOUNT",
            amountInToken: "2127239",
            amountInUSD: 2.1271999999999998,
          },
          {
            type: "BLOCKEND",
            source: "FROM_OUTPUT_AMOUNT",
            token: {
              networkType: "sol",
              address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 6,
              name: "Tether",
              symbol: "USDT",
              image:
                "https://assets.coingecko.com/coins/images/325/small/Tether.png",
              lastPrice: 0.999919,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            amountInToken: "0",
            amountInUSD: "0",
          },
        ],
        provider: "lifi",
        providerDetails: {
          id: "lifi",
          name: "LI.FI",
          logoUrl:
            "https://raw.githubusercontent.com/blockend-com/docs-v1/refs/heads/main/resources/png/lifi.png",
          websiteUrl: "https://li.fi/",
        },
        protocolsUsed: ["Allbridge"],
        inputAmount: "10000000000000000000",
        inputAmountDisplay: "10",
        outputAmount: "2224279",
        outputAmountDisplay: "2.224279",
        minOutputAmount: "2.224279",
        slippage: 4603,
        userWalletAddress: "0x1b1E919E51a1592Dce70a4FD74107941109B8235",
        recipient: "4sd55KCv7RFcc14goe3yJtsBTb9XMFjR5GAnemaDdYTd",
        createdAt: 1738063547633,
        deadline: 60,
        estimatedTimeInSeconds: 765,
        requestId: "",
        score: {
          outputScore: 1,
          speedScore: 0.00130718954248366,
          feeScore: 1,
          slipparageScore: 1,
          stepScore: 1,
          outputDiffPercent: 0,
        },
        tags: ["BEST_OUTPUT", "CHEAP", "LOW_SLIPPAGE"],
      },
      {
        routeId: "01JJPAJ2FS477PTT6EW97H52G6",
        from: {
          networkType: "evm",
          address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
          chainId: "137",
          blockchain: "Polygon",
          decimals: 18,
          name: "Matic",
          symbol: "MATIC",
          image:
            "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
          lastPrice: 0.412124,
          isEnabled: true,
          isFlagged: false,
          isNative: true,
          isPopular: true,
        },
        to: {
          networkType: "sol",
          address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
          chainId: "sol",
          blockchain: "Solana",
          decimals: 6,
          name: "Tether",
          symbol: "USDT",
          image:
            "https://assets.coingecko.com/coins/images/325/small/Tether.png",
          lastPrice: 0.999919,
          isEnabled: true,
          isFlagged: false,
          isNative: false,
          isPopular: false,
        },
        steps: [
          {
            stepId: "01JJPAJ2FS5AYXGCPYB817R7JP",
            stepType: "bridge",
            protocolsUsed: ["deBridge"],
            provider: "dln",
            from: {
              networkType: "evm",
              address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 18,
              name: "Matic",
              symbol: "MATIC",
              image:
                "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
              lastPrice: 0.412124,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            to: {
              networkType: "sol",
              address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 6,
              name: "Tether",
              symbol: "USDT",
              image:
                "https://assets.coingecko.com/coins/images/325/small/Tether.png",
              lastPrice: 0.999919,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            fee: [
              {
                type: "NETWORK",
                token: {
                  networkType: "evm",
                  address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                  chainId: "137",
                  blockchain: "Polygon",
                  decimals: 18,
                  name: "Matic",
                  symbol: "MATIC",
                  image:
                    "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
                  lastPrice: 0.412124,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: true,
                  isPopular: true,
                },
                source: "FROM_SOURCE_WALLET",
                amountInToken: "17802000070200000",
                amountInUSD: "0.0073366314769311046",
              },
              {
                type: "PROVIDER",
                token: {
                  networkType: "evm",
                  address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                  chainId: "137",
                  blockchain: "Polygon",
                  decimals: 18,
                  name: "Matic",
                  symbol: "MATIC",
                  image:
                    "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
                  lastPrice: 0.412124,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: true,
                  isPopular: true,
                },
                source: "FROM_SOURCE_WALLET",
                amountInToken: "500000000000000000",
                amountInUSD: "0.206062",
              },
              {
                type: "BLOCKEND",
                source: "FROM_OUTPUT_AMOUNT",
                token: {
                  networkType: "sol",
                  address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
                  chainId: "sol",
                  blockchain: "Solana",
                  decimals: 6,
                  name: "Tether",
                  symbol: "USDT",
                  image:
                    "https://assets.coingecko.com/coins/images/325/small/Tether.png",
                  lastPrice: 0.999919,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: false,
                  isPopular: false,
                },
                amountInToken: "0",
                amountInUSD: "0",
              },
            ],
            inputAmount: "10000000000000000000",
            outputAmount: "1807631",
            estimatedTimeInSeconds: 1,
          },
        ],
        fee: [
          {
            type: "NETWORK",
            token: {
              networkType: "evm",
              address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 18,
              name: "Matic",
              symbol: "MATIC",
              image:
                "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
              lastPrice: 0.412124,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            source: "FROM_SOURCE_WALLET",
            amountInToken: "17802000070200000",
            amountInUSD: "0.0073366314769311046",
          },
          {
            type: "PROVIDER",
            token: {
              networkType: "evm",
              address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 18,
              name: "Matic",
              symbol: "MATIC",
              image:
                "https://assets.coingecko.com/coins/images/4713/standard/polygon.png?1698233745",
              lastPrice: 0.412124,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            source: "FROM_SOURCE_WALLET",
            amountInToken: "500000000000000000",
            amountInUSD: "0.206062",
          },
          {
            type: "BLOCKEND",
            source: "FROM_OUTPUT_AMOUNT",
            token: {
              networkType: "sol",
              address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 6,
              name: "Tether",
              symbol: "USDT",
              image:
                "https://assets.coingecko.com/coins/images/325/small/Tether.png",
              lastPrice: 0.999919,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            amountInToken: "0",
            amountInUSD: "0",
          },
        ],
        provider: "dln",
        providerDetails: {
          id: "dln",
          name: "DLN",
          logoUrl:
            "https://raw.githubusercontent.com/blockend-com/docs-v1/refs/heads/main/resources/png/dln.png",
          websiteUrl: "https://dln.trade/",
        },
        protocolsUsed: ["deBridge"],
        inputAmount: "10000000000000000000",
        inputAmountDisplay: "10",
        outputAmount: "1807631",
        outputAmountDisplay: "1.807631",
        minOutputAmount: "1.807631",
        minOutputAmountDisplay: "1.807631",
        slippage: 5614,
        userWalletAddress: "0x1b1E919E51a1592Dce70a4FD74107941109B8235",
        recipient: "4sd55KCv7RFcc14goe3yJtsBTb9XMFjR5GAnemaDdYTd",
        createdAt: 1738063546873,
        deadline: 30,
        estimatedTimeInSeconds: 1,
        requestId: "",
        score: {
          outputScore: 0.8126817723855685,
          speedScore: 1,
          feeScore: 0.7496628414952957,
          slipparageScore: 0.8199144994656217,
          stepScore: 1,
          outputDiffPercent: 0.20667524820742533,
        },
        tags: ["BEST", "FAST"],
      },
    ],
  },
};
```

[View full quotes response](/compass-api/api-reference/fetching-quotes)

**`/createTx`**

This endpoint fetches the transaction steps for the selected quote. A transaction can have multiple steps, e.g., token approval, swap/bridge, etc. Since this is an EVM to Solana bridge example, the transaction steps can include token approval and bridge, or only bridge if the source token is already approved. The response includes steps that need to be executed sequentially. Each step includes a step ID and step type (approval, swap, bridge, etc.).

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
};
```

**Example Request**

```
GET /createTx?routeId=a1b2c3d4-e5f6-g7h8-i9j0
```

**Example Response**

```javascript
let createTxResponse = {
  status: "success",
  data: {
    steps: [
      {
        stepId: "step_12345",
        stepType: "approval",
      },
      {
        stepId: "step_67890",
        stepType: "bridge",
      },
    ],
  },
};
```

[View full createTx API response](/compass-api/api-reference/create-transaction)

**`/nextTx`**

This endpoint fetches the transaction data that needs to be executed for the selected step. The transaction data includes the transaction parameters for the step. Since this is an EVM to Solana bridge example, the transaction data includes the txnEvm object field in the transaction data.

Note: The transaction data is specific to the step type. For example, if the step type is brige, the transaction data includes the bridge parameters. If the step type is token approval, the transaction data includes the token approval parameters. Moreover, the next step data will be available only if the previous step is executed successfully.

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
  stepId: createTxResponse.data.steps[0].stepId, // stepId is available in the createTx steps[] response
};
```

**Example Request**

```
GET /nextTx?routeId=a1b2c3d4-e5f6-g7h8-i9j0&stepId=step_12345
```

**Example Response**

```javascript
let nextTxResponse = {
  status: "success",
  data: {
    txnData: {
      txnEvm: {
        from: "0x1b1E919E51a1592Dce70a4FD74107941109B8235",
        to: "0xcontractAddress",
        data: "0x...",
        value: "0",
        chainId: 137,
        gasLimit: "300000",
      },
    },
  },
};
```

[View full nextTx API response](/compass-api/api-reference/get-raw-transaction-to-execute)

**`/status`**

This endpoint fetches the transaction status for the selected step once the transaction step is submitted to the blockchain. The transaction status includes: the status of the transaction, the source transaction hash, the source transaction URL, the destination transaction hash, the destination transaction URL, the output amount received, and the output token details.

[View full status API documentation](/compass-api/api-reference/check-transaction-status)

#### Transaction Status Codes

* `in-progress`: Transaction is pending
* `success`: Transaction completed successfully
* `partial-success`: If output amount token is different from the destination token, the transaction is partial success.
* `failed`: Transaction failed

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
  stepId: createTxResponse.data.steps[0].stepId, // stepId is available in the createTx steps[] response
  txnHash: nextTxResponse.data.txnData.txnEvm.hash, // pass the txnHash that is received from the wallet provider once the transaction is signed successfully by the user
};
```

**Example Request**

```
GET /status?routeId=a1b2c3d4-e5f6-g7h8-i9j0&stepId=step_12345&txnHash=0x1234...abcd
```

**Example Response**

```javascript
let statusResponse = {
  status: "success",
  data: {
    status: "success",
    srcTxnHash: "0x1234...abcd",
    srcTxnUrl: "https://polygonscan.com/tx/0x1234...abcd",
    destTxnHash: "0x5678...efgh",
    destTxnUrl: "https://polygonscan.com/tx/0x5678...efgh",
    outputAmount: "449144858547000000",
    outputToken: {
      address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
      symbol: "MATIC",
      decimals: 18,
      name: "MATIC",
    },
  },
};
```

### Code Example

In the code example below, we use plain JavaScript for simplicity, but the code is framework-agnostic and can be easily adapted to React, Next.js, Vite, or any other JavaScript framework. Simply modify the syntax and component structure to match your chosen framework's conventions.

```javascript
import { BrowserProvider, JsonRpcProvider } from "ethers";
const headers = {
  "x-integrator-id": "YOUR_INTEGRATOR_ID",
};

// Helper function to establish connection with an EVM wallet
// Returns essential wallet interaction objects: provider, signer, and wallet address
async function connectWallet() {
  if (!window.ethereum) {
    throw new Error("MetaMask or EVM wallet not detected");
  }

  // For browser environment
  const provider = new BrowserProvider(window.ethereum);
  const accounts = await provider.send("eth_requestAccounts", []);
  const signer = await provider.getSigner();
  // For server environment(nodejs)
  // const provider = new JsonRpcProvider(process.env.RPC_URL);
  // const accounts = await provider.send("eth_requestAccounts", []);
  // const signer = await provider.getSigner();
  return { provider, signer, address: accounts[0] };
}

async function evmToSolBridge() {
  let baseUrl = "https://api2.blockend.com/v1/";

  let queryParams = {
    fromChainId: "137",
    toChainId: "137",
    fromAssetAddress: "0xb7b31a6bc18e48888545ce79e83e06003be70930",
    toAssetAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
    inputAmountDisplay: "0.449594453",
    userWalletAddress: "0x...",
    recipient: "4s...",
  };

  // For details about each parameter, refer end points section above

  // Construct API query string for quote retrieval
  let quotesQueryString = `quotes?fromChainId=${queryParams.fromChainId}&toChainId=${queryParams.toChainId}&fromAssetAddress=${queryParams.fromAssetAddress}&toAssetAddress=${queryParams.toAssetAddress}&inputAmountDisplay=${queryParams.inputAmountDisplay}&userWalletAddress=${queryParams.userWalletAddress}&recipient=${queryParams.recipient}`;

  try {
    // Step 1: Initialize wallet connection
    // Establishes connection and gets necessary wallet interfaces
    const { provider, signer, address } = await connectWallet();

    // Step 2: Fetch available quotes
    // Retrieves possible bridge routes with pricing information
    // Response: { status: string, data: { quotes: [{ routeId: string, ... }] } }
    const quoteRequest = await fetch(`${baseUrl}${quotesQueryString}`, {
      headers,
    });
    const quotes = await quoteRequest.json();

    // Step 3: Initialize transaction sequence
    // Gets all necessary transaction steps using the selected quote
    // Response: { status: string, data: {  steps:[{stepId: string}] } }
    // Note: Production implementations should include quote selection logic
    let routeId = quotes.data.quotes[0].routeId;
    let createTransactionQueryString = `createTx?routeId=${routeId}`;
    const createTxRequest = await fetch(
      `${baseUrl}${createTransactionQueryString}`,
      {
        headers,
      }
    );

    const createTransactionData = await createTxRequest.json();

    // Step 4: Execute transaction sequence
    // Processes each step (e.g., token approval, bridge)
    // Each step requires separate blockchain transaction
    // Response: { status: string, data: {  steps:[{stepId: string}] } }
    let stepCount = 1;
    for (let step of createTransactionData.data.steps) {
      let stepId = step.stepId;
      let nextTxQueryString = `nextTx?routeId=${routeId}&stepId=${stepId}`;
      const nextTxRequest = await fetch(`${baseUrl}${nextTxQueryString}`, {
        headers,
      });
      const nextTxData = await nextTxRequest.json();

      // Step 5: Submit transaction
      // Sends the transaction to the blockchain network
      // Response includes transaction hash for status tracking
      const transaction = await signer.sendTransaction(
        nextTxData.data.txnData.txnEvm
      );
      console.log("Transaction Result:", transaction);
      let txnHash = transaction.hash;

      // Step 6: Monitor transaction status
      // Polls status endpoint until the status is not in-progress
      // Response: { status: string, data: {  status: string,srcTxnHash: string,srcTxnUrl: string,destTxnHash: string,destTxnUrl: string,outputAmount: string,outputToken:{...} } }
      // Status codes: in-progress, success, partial-success, failed
      let currentStatus = "in-progress";
      let statusResponse;

      while (currentStatus === "in-progress") {
        let transactionStatusQueryString = `status?routeId=${routeId}&stepId=${stepId}&txnHash=${txnHash}`;
        const transactionStatusRequest = await fetch(
          `${baseUrl}${transactionStatusQueryString}`,
          {
            headers,
          }
        );
        statusResponse = await transactionStatusRequest.json();

        if (statusResponse.status === "error") {
          currentStatus = "in-progress";
          continue;
        } else {
          currentStatus = statusResponse.data.status;
        }

        // Handle different transaction states
        if (currentStatus === "failed") {
          throw new Error("Transaction failed");
        }

        if (currentStatus === "in-progress") {
          // Wait 2 seconds before next status check
          await new Promise((resolve) => setTimeout(resolve, 2000));
        }

        // Update progress for multi-step transactions
        if (currentStatus === "success") {
          stepCount === createTransactionData.data.steps.length
            ? alert("Transaction successful, TxnHash: " + txnHash)
            : stepCount++;
        }
        if (currentStatus === "partial-success") {
          stepCount === createTransactionData.data.steps.length
            ? alert("Transaction partially successful, txnHash: " + txnHash)
            : stepCount++;
        }
      }
    }
  } catch (error) {
    console.error("Error:", error);
    throw new Error(error.message);
  }
} 
```


# SOLANA Swaps

This guide demonstrates how to execute a token swap on solana network using the Compass API. The example covers the complete workflow from connecting a wallet to monitoring transaction status.

### Overview

The implementation follows these key steps:

1. Wallet Connection
2. Quote Retrieval
3. Transaction Creation
4. Step-by-Step Execution
5. Status Monitoring

### Implementation Details

#### Prerequisites

* Phantom or any solana compatible wallet
* Integrator ID from Compass
* Solana Web3.js library

#### API Endpoints

The example uses the following endpoints:

**`/quotes`**

This endpoint fetches quotes from available liquidity sources and responds with quotes that are sorted by best output amount by default. The first item in the quotes array is the recommended quote.

**Request Parameters**

```javascript
let requestParams = {
  fromChainId: "sol", // Source blockchain network ID (Solana), for chain IDs reference: "/chains" api endpoint
  toChainId: "sol", // Destination blockchain network ID (Solana), for chain IDs reference: "/chains" api endpoint
  fromAssetAddress: "So11111111111111111111111111111111111111112", // Source token contract address, for token addresses reference: "/tokens" api endpoint
  toAssetAddress: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", // Destination token contract address, for token addresses reference: "/tokens" api endpoint
  inputAmountDisplay: "0.01", // Amount of source token to swap, this is the amount that will be transferred from the source token to the destination token, typically received as input from the user
  userWalletAddress: "4sd..", // User's wallet address
  recipient: "4sd..", // Recipient's wallet address
};
```

**Example Request**

```
GET /quotes?fromChainId=sol&toChainId=sol&fromAssetAddress=So11111111111111111111111111111111111111112&toAssetAddress=Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB&inputAmountDisplay=0.01&userWalletAddress=4sd..&recipient=4sd..
```

**Example Response**

```javascript
let quoteResponse = {
  status: "success",

  quotes: [
    {
      routeId: "01JJP65XJXPGSSJ8NNV15WFW41",
      from: {
        networkType: "sol",
        address: "So11111111111111111111111111111111111111112",
        chainId: "sol",
        blockchain: "Solana",
        decimals: 9,
        name: "Solana",
        symbol: "SOL",
        image:
          "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
        lastPrice: 238.21,
        isEnabled: true,
        isFlagged: false,
        isNative: true,
        isPopular: true,
      },
      to: {
        networkType: "sol",
        address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
        chainId: "sol",
        blockchain: "Solana",
        decimals: 6,
        name: "Tether",
        symbol: "USDT",
        image: "https://assets.coingecko.com/coins/images/325/small/Tether.png",
        lastPrice: 0.999916,
        isEnabled: true,
        isFlagged: false,
        isNative: false,
        isPopular: false,
      },
      steps: [
        {
          stepId: "01JJP65XJXFZ4R7RJ1N5V0SY1E",
          stepType: "swap",
          protocolsUsed: ["SolFi", "Stabble Stable Swap"],
          provider: "jupag",
          from: {
            networkType: "sol",
            address: "So11111111111111111111111111111111111111112",
            chainId: "sol",
            blockchain: "Solana",
            decimals: 9,
            name: "Solana",
            symbol: "SOL",
            image:
              "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
            lastPrice: 238.21,
            isEnabled: true,
            isFlagged: false,
            isNative: true,
            isPopular: true,
          },
          to: {
            networkType: "sol",
            address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
            chainId: "sol",
            blockchain: "Solana",
            decimals: 6,
            name: "Tether",
            symbol: "USDT",
            image:
              "https://assets.coingecko.com/coins/images/325/small/Tether.png",
            lastPrice: 0.999916,
            isEnabled: true,
            isFlagged: false,
            isNative: false,
            isPopular: false,
          },
          inputAmount: "10000000",
          outputAmount: "2378645",
          fee: [
            {
              type: "NETWORK",
              token: {
                networkType: "sol",
                address: "So11111111111111111111111111111111111111112",
                chainId: "sol",
                blockchain: "Solana",
                decimals: 9,
                name: "Solana",
                symbol: "SOL",
                image:
                  "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
                lastPrice: 238.21,
                isEnabled: true,
                isFlagged: false,
                isNative: true,
                isPopular: true,
              },
              source: "FROM_SOURCE_WALLET",
              amountInToken: "105000",
              amountInUSD: "0.02501205",
            },
            {
              type: "BLOCKEND",
              source: "FROM_OUTPUT_AMOUNT",
              token: {
                networkType: "sol",
                address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
                chainId: "sol",
                blockchain: "Solana",
                decimals: 6,
                name: "Tether",
                symbol: "USDT",
                image:
                  "https://assets.coingecko.com/coins/images/325/small/Tether.png",
                lastPrice: 0.999916,
                isEnabled: true,
                isFlagged: false,
                isNative: false,
                isPopular: false,
              },
              amountInToken: "0",
              amountInUSD: "0",
            },
          ],
          estimatedTimeInSeconds: 10,
        },
      ],
      fee: [
        {
          type: "NETWORK",
          token: {
            networkType: "sol",
            address: "So11111111111111111111111111111111111111112",
            chainId: "sol",
            blockchain: "Solana",
            decimals: 9,
            name: "Solana",
            symbol: "SOL",
            image:
              "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
            lastPrice: 238.21,
            isEnabled: true,
            isFlagged: false,
            isNative: true,
            isPopular: true,
          },
          source: "FROM_SOURCE_WALLET",
          amountInToken: "105000",
          amountInUSD: "0.02501205",
        },
        {
          type: "BLOCKEND",
          source: "FROM_OUTPUT_AMOUNT",
          token: {
            networkType: "sol",
            address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
            chainId: "sol",
            blockchain: "Solana",
            decimals: 6,
            name: "Tether",
            symbol: "USDT",
            image:
              "https://assets.coingecko.com/coins/images/325/small/Tether.png",
            lastPrice: 0.999916,
            isEnabled: true,
            isFlagged: false,
            isNative: false,
            isPopular: false,
          },
          amountInToken: "0",
          amountInUSD: "0",
        },
      ],
      provider: "jupag",
      providerDetails: {
        id: "jupag",
        name: "Jupiter",
        logoUrl:
          "https://raw.githubusercontent.com/blockend-com/docs-v1/refs/heads/main/resources/png/jupiter.png",
        websiteUrl: "https://jup.ag/",
      },
      protocolsUsed: ["SolFi", "Stabble Stable Swap"],
      inputAmount: "10000000",
      inputAmountDisplay: "0.01",
      outputAmount: "2378645",
      outputAmountDisplay: "2.378645",
      minOutputAmount: "2.366752",
      minOutputAmountDisplay: "2.366752",
      slippage: 15,
      userWalletAddress: "4sd..",
      recipient: "4sd..",
      createdAt: 1738058954333,
      deadline: 60,
      estimatedTimeInSeconds: 10,
      requestId: "",
      score: {
        outputScore: 1,
        speedScore: 1,
        feeScore: 1,
        slipparageScore: 1,
        stepScore: 1,
        outputDiffPercent: 0.005012436261918719,
      },
      tags: ["BEST"],
    },
  ],
};
```

[View full quotes response](/compass-api/api-reference/fetching-quotes)

**`/createTx`**

This endpoint fetches the transaction steps for the selected quote. A solana transaction cn have either swap step or bridge step . Since this is s solana swap example, the transaction step includes swap. The response includes steps that need to be executed.The Step object includes a step ID and step type (swap).

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
};
```

**Example Request**

```
GET /createTx?routeId=a1b2c3d4-e5f6-g7h8-i9j0
```

**Example Response**

```javascript
let createTxResponse = {
  status: "success",
  data: {
    steps: [
      {
        stepId: "step_12345",
        stepType: "approval",
      },
      {
        stepId: "step_67890",
        stepType: "swap",
      },
    ],
  },
};
```

[View full createTx API response](/compass-api/api-reference/create-transaction)

**`/nextTx`**

This endpoint fetches the transaction data that needs to be executed for the selected step. The transaction data includes the transaction parameters for the step. Since this is an Solana swap example, the transaction data includes the txnSol object field in the transaction data.

Note: The transaction data is specific to the step type. For example, if the step type is swap, the transaction data includes the swap parameters. If the step type is token approval, the transaction data includes the token approval parameters. Moreover, the next step data will be available only if the previous step is executed successfully.

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
  stepId: createTxResponse.data.steps[0].stepId, // stepId is available in the createTx steps[] response
};
```

**Example Request**

```
GET /nextTx?routeId=a1b2c3d4-e5f6-g7h8-i9j0&stepId=step_12345
```

**Example Response**

```javascript
let nextTxResponse = {
  status: "success",
  data: {
    txnData: {
      id: "01JJP6MS082138Y3NJB7XYDC1D",
      routeId: "01JJP6MGNXTS99P34JX6PC01GV",
      stepId: "01JJP6MGNXAZ9CV61FNX022ZTZ",
      isCompleted: false,
      networkType: "sol",
      createdAt: 1738059441160,
      txnSol: {
        data: "AQAAAAAAA..", // base64 encoded transaction data
      },
      status: "in-progress",
      fetchedAt: 1738059441160,
      nextTxStart: 1738059440990,
      nextTxEnd: 1738059441160,
    },
  },
};
```

[View full nextTx API response](/compass-api/api-reference/get-raw-transaction-to-execute)

**`/status`**

This endpoint fetches the transaction status for the selected step once the transaction step is submitted to the blockchain. The transaction status includes: the status of the transaction, the source transaction hash, the source transaction URL, the destination transaction hash, the destination transaction URL, the output amount received, and the output token details.

[View full status API documentation](/compass-api/api-reference/check-transaction-status)

#### Transaction Status Codes

* `in-progress`: Transaction is pending
* `success`: Transaction completed successfully
* `partial-success`: If output amount token is different from the destination token, the transaction is partial success.
* `failed`: Transaction failed

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
  stepId: createTxResponse.data.steps[0].stepId, // stepId is available in the createTx steps[] response
  txnHash: nextTxResponse.data.txnData.txnSol.hash, // pass the txnHash that is received from the wallet provider once the transaction is signed successfully by the user
};
```

**Example Request**

```
GET /status?routeId=a1b2c3d4-e5f6-g7h8-i9j0&stepId=step_12345&txnHash=0x1234...abcd
```

**Example Response**

```javascript
let statusResponse = {
  status: "success",
  data: {
    status: "success",
    srcTxnHash: "0x1234...abcd",
    srcTxnUrl: "https://polygonscan.com/tx/0x1234...abcd",
    destTxnHash: "0x5678...efgh",
    destTxnUrl: "https://polygonscan.com/tx/0x5678...efgh",
    outputAmount: "449144858547000000",
    outputToken: {
      address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
      symbol: "MATIC",
      decimals: 18,
      name: "MATIC",
    },
  },
};
```

### Code Example

In the code example below, we use plain JavaScript for simplicity, but the code is framework-agnostic and can be easily adapted to React, Next.js, Vite, or any other JavaScript framework. Simply modify the syntax and component structure to match your chosen framework's conventions.

### NodeJS Implementation

```javascript
import { Connection, Keypair, VersionedTransaction } from "@solana/web3.js";
import bs58 from "bs58";

// Initialize connection and keypair
const keypair = Keypair.fromSecretKey(bs58.decode(SOLANA_PRIVATE_KEY));
console.log({ keypair: keypair.publicKey.toString() });
const connection = new Connection(RPC_URL, "confirmed");
```

### Browser Implementation with Phantom Wallet

```javascript
import { Connection, VersionedTransaction, KeyPair } from "@solana/web3.js";
import Buffer from "buffer";

// Initialize Phantom wallet connection
async function initializeWallet() {
  if (!window.solana || !window.solana.isPhantom) {
    throw new Error("Phantom wallet is not installed!");
  }

  try {
    // Connect to the wallet
    const resp = await window.solana.connect();
    console.log("Connected to wallet:", resp.publicKey.toString());
    return window.solana;
  } catch (err) {
    console.error("Failed to connect to wallet:", err);
    throw err;
  }
}

// Initialize Solana connection
const connection = new Connection(
  "https://api.mainnet-beta.solana.com",
  "confirmed"
);
```

### Common Implementation

```javascript
async function solanaSwap() {
  // Initialize wallet based on environment
  const wallet =
    typeof window !== "undefined" ? await initializeWallet() : null;

  const solQuoteReq = {
    fromChainId: "sol",
    toChainId: "sol",
    fromAssetAddress: "So11111111111111111111111111111111111111112",
    toAssetAddress: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
    inputAmountDisplay: "0.01",
    userWalletAddress: wallet ? wallet.publicKey.toString() : "7z..",
    slippage: 2000,
    fixedSlippage: true,
    recipient: wallet ? wallet.publicKey.toString() : "7z...",
  };

  const headers = {
    "x-integrator-id": "your-integrator-id",
  };

  // Fetch quote
  const urlParams = Object.entries(solQuoteReq)
    .map(([key, value]) => `${key}=${value}`)
    .join("&");
  const fetchQuoteReq = await fetch(
    `https://api2.blockend.com/v1/quotes?${urlParams}`,
    {
      headers,
    }
  );
  const fetchQuoteRes = await fetchQuoteReq.json();
  console.log("quotes fetched");
  const quotes = fetchQuoteRes.data.quotes;

  const provider = "jupag";
  const providerQuote = quotes.find((q) => q.provider === provider);
  if (!providerQuote) throw new Error("quote not found, " + provider);

  // Create transaction
  const createdTxnReq = await fetch(
    `https://api2.blockend.com/v1/createTx?routeId=${providerQuote.routeId}`,
    {
      headers,
    }
  );
  const createdTxnRes = await createdTxnReq.json();
  console.log("txn created");

  // Get next transaction
  const nextTxnReq = await fetch(
    `https://api2.blockend.com/v1/nextTx?routeId=${providerQuote.routeId}&stepId=${createdTxnRes.data.steps[0].stepId}`,
    {
      headers,
    }
  );
  const nextTxnRes = await nextTxnReq.json();
  console.log("got next txn");

  const solTxn = nextTxnRes.data.txnData?.txnSol?.data;
  if (!solTxn) throw new Error("txn data not found");

  // Deserialize the transaction
  const txnBuffer = Buffer.from(solTxn, "base64");
  const transaction = VersionedTransaction.deserialize(txnBuffer);

  let signature;

  if (wallet) {
    // Browser environment - Sign with Phantom
    try {
      // Sign and send transaction
      let txn = await wallet.signAndSendTransaction(transaction);
      signature = txn.signature;
      console.log("Transaction sent:", signature);
    } catch (err) {
      console.error("Error sending transaction:", err);
      throw err;
    }
  } else {
    // NodeJS environment - Sign with keypair
    transaction.sign([keypair]);

    // Simulate the transaction
    const result = await connection.simulateTransaction(transaction, {
      sigVerify: true,
    });

    if (!result.value.err) {
      // Send the transaction
      signature = await connection.sendTransaction(transaction);
      console.log("Transaction sent:", signature);
    } else {
      console.error("Transaction simulation failed:", result.value.err);
      throw new Error("Transaction simulation failed");
    }
  }

  // Check transaction status
  const statusCheckReq = await fetch(
    `https://api2.blockend.com/v1/status?routeId=${providerQuote.routeId}&stepId=${createdTxnRes.data.steps[0].stepId}&txnHash=${signature}`,
    { headers }
  );
  const statusCheckRes = await statusCheckReq.json();
  console.log("Transaction status:", statusCheckRes);

  let currentStatus = "in-progress";
  let statusResponse;
  while (currentStatus === "in-progress") {
    // Check transaction status
    const transactionStatusRequest = await fetch(
      `https://api2.blockend.com/v1/status?routeId=${
        providerQuote.routeId
      }&stepId=${createdTxnRes.data.steps[0].stepId}&txnHash=${
        signature || ""
      }`,
      { headers }
    );
    statusResponse = await transactionStatusRequest.json();

    if (statusResponse.status === "error") {
      currentStatus = "in-progress";
      continue;
    } else {
      currentStatus = statusResponse.data.status;
    }

    // Handle different transaction states
    if (currentStatus === "failed") {
      throw new Error("Transaction failed");
    }

    if (currentStatus === "in-progress") {
      // Wait 2 seconds before next status check
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }
  }
}

solanaSwap()
  .catch(console.error)
  .finally(() => process.exit(0));
```

### Usage Notes

1. For browser implementation:
   * Make sure Phantom wallet extension is installed
   * Handle wallet connection states and user interactions appropriately
2. For NodeJS implementation:
   * Ensure you have the required environment variables (SOLANA\_PRIVATE\_KEY, RPC\_URL)
   * Handle errors and cleanup appropriately
3. Common considerations:
   * Replace 'your-integrator-id' with your actual integrator ID
   * Implement proper error handling and loading states
   * Add appropriate UI feedback for transaction status


# Solana to EVM Bridge

This guide demonstrates how to execute a token bridge from solana network to EVM-compatible chains using the Compass API. The example covers the complete workflow from connecting a wallet to monitoring transaction status.

### Overview

The implementation follows these key steps:

1. Wallet Connection
2. Quote Retrieval
3. Transaction Creation
4. Step-by-Step Execution
5. Status Monitoring

### Implementation Details

#### Prerequisites

* Phantom or any solana compatible wallet
* Integrator ID from Compass
* Solana Web3.js library

#### API Endpoints

The example uses the following endpoints:

**`/quotes`**

This endpoint fetches quotes from available liquidity sources and responds with quotes that are sorted by best output amount by default. The first item in the quotes array is the recommended quote.

**Request Parameters**

```javascript
let requestParams = {
  fromChainId: "sol", // Source blockchain network ID (Solana), for chain IDs reference: "/chains" api endpoint
  toChainId: "137", // Destination blockchain network ID (Solana), for chain IDs reference: "/chains" api endpoint
  fromAssetAddress: "So11111111111111111111111111111111111111112", // Source token contract address, for token addresses reference: "/tokens" api endpoint
  toAssetAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // Destination token contract address, for token addresses reference: "/tokens" api endpoint
  inputAmountDisplay: "0.1", // Amount of source token(Solana) to bridge, this is the amount that will be transferred from the source token chain to the destination token chain, typically received as input from the user
  userWalletAddress: "4sd..", // User's wallet address
  recipient: "0x..", // Recipient's wallet address
};
```

**Example Request**

```
GET /quotes?fromChainId=sol&toChainId=137&fromAssetAddress=So11111111111111111111111111111111111111112&toAssetAddress=0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee&inputAmountDisplay=0.1&userWalletAddress=4sd..&recipient=0x..
```

**Example Response**

```javascript
let quoteResponse = {
  status: "success",
  data: {
    quotes: [
      {
        routeId: "f3c8f492-6531-414e-b16f-49146f28e562",
        from: {
          networkType: "sol",
          address: "So11111111111111111111111111111111111111112",
          chainId: "sol",
          blockchain: "Solana",
          decimals: 9,
          name: "Solana",
          symbol: "SOL",
          image:
            "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
          lastPrice: 237.56,
          isEnabled: true,
          isFlagged: false,
          isNative: true,
          isPopular: true,
        },
        to: {
          networkType: "evm",
          address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
          chainId: "137",
          blockchain: "Polygon",
          decimals: 6,
          name: "Tether",
          symbol: "USDT",
          image:
            "https://assets.coingecko.com/coins/images/325/small/Tether.png",
          lastPrice: 0.99996,
          isEnabled: true,
          isFlagged: false,
          isNative: false,
          isPopular: false,
        },
        steps: [
          {
            stepId: "f3c8f492-6531-414e-b16f-49146f28e562:0",
            stepType: "bridge",
            protocolsUsed: ["Mayan (Swift)"],
            from: {
              networkType: "sol",
              address: "So11111111111111111111111111111111111111112",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 9,
              name: "Solana",
              symbol: "SOL",
              image:
                "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
              lastPrice: 237.56,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            to: {
              networkType: "evm",
              address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 6,
              name: "Tether",
              symbol: "USDT",
              image:
                "https://assets.coingecko.com/coins/images/325/small/Tether.png",
              lastPrice: 0.99996,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            inputAmount: "100000000",
            outputAmount: "23246337",
            fee: [
              {
                type: "NETWORK",
                token: {
                  networkType: "sol",
                  address: "So11111111111111111111111111111111111111112",
                  chainId: "sol",
                  blockchain: "Solana",
                  decimals: 9,
                  name: "Solana",
                  symbol: "SOL",
                  image:
                    "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
                  lastPrice: 237.56,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: true,
                  isPopular: true,
                },
                source: "FROM_SOURCE_WALLET",
                amountInToken: "370000",
                amountInUSD: "0.0883",
              },
            ],
            estimatedTimeInSeconds: 12,
          },
        ],
        fee: [
          {
            type: "NETWORK",
            token: {
              networkType: "sol",
              address: "So11111111111111111111111111111111111111112",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 9,
              name: "Solana",
              symbol: "SOL",
              image:
                "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
              lastPrice: 237.56,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            source: "FROM_SOURCE_WALLET",
            amountInToken: "370000",
            amountInUSD: "0.0883",
          },
          {
            type: "BLOCKEND",
            source: "FROM_OUTPUT_AMOUNT",
            token: {
              networkType: "evm",
              address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 6,
              name: "Tether",
              symbol: "USDT",
              image:
                "https://assets.coingecko.com/coins/images/325/small/Tether.png",
              lastPrice: 0.99996,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            amountInToken: "0",
            amountInUSD: "0",
          },
        ],
        provider: "lifi",
        providerDetails: {
          id: "lifi",
          name: "LI.FI",
          logoUrl:
            "https://raw.githubusercontent.com/blockend-com/docs-v1/refs/heads/main/resources/png/lifi.png",
          websiteUrl: "https://li.fi/",
        },
        protocolsUsed: ["Mayan (Swift)"],
        inputAmount: "100000000",
        inputAmountDisplay: "0.1",
        outputAmount: "23473512",
        outputAmountDisplay: "23.473512",
        minOutputAmount: "23.473512",
        slippage: 119,
        userWalletAddress: "4sd55KCv7RFcc14goe3yJtsBTb9XMFjR5GAnemaDdYTd",
        recipient: "0x1b1E919E51a1592Dce70a4FD74107941109B8235",
        createdAt: 1738064338811,
        deadline: 60,
        estimatedTimeInSeconds: 12,
        requestId: "",
        score: {
          outputScore: 1,
          speedScore: 1,
          feeScore: 1,
          slipparageScore: 1,
          stepScore: 1,
          outputDiffPercent: 0,
        },
        tags: ["BEST", "BEST_OUTPUT", "FAST", "LOW_SLIPPAGE"],
      },
      {
        routeId: "a6baa303-d15b-4dd1-bdf6-0278b36e4275",
        from: {
          networkType: "sol",
          address: "So11111111111111111111111111111111111111112",
          chainId: "sol",
          blockchain: "Solana",
          decimals: 9,
          name: "Solana",
          symbol: "SOL",
          image:
            "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
          lastPrice: 237.56,
          isEnabled: true,
          isFlagged: false,
          isNative: true,
          isPopular: true,
        },
        to: {
          networkType: "evm",
          address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
          chainId: "137",
          blockchain: "Polygon",
          decimals: 6,
          name: "Tether",
          symbol: "USDT",
          image:
            "https://assets.coingecko.com/coins/images/325/small/Tether.png",
          lastPrice: 0.99996,
          isEnabled: true,
          isFlagged: false,
          isNative: false,
          isPopular: false,
        },
        steps: [
          {
            stepId: "a6baa303-d15b-4dd1-bdf6-0278b36e4275:0",
            stepType: "bridge",
            protocolsUsed: ["Mayan (Wormhole)"],
            from: {
              networkType: "sol",
              address: "So11111111111111111111111111111111111111112",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 9,
              name: "Solana",
              symbol: "SOL",
              image:
                "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
              lastPrice: 237.56,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            to: {
              networkType: "evm",
              address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 6,
              name: "Tether",
              symbol: "USDT",
              image:
                "https://assets.coingecko.com/coins/images/325/small/Tether.png",
              lastPrice: 0.99996,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            inputAmount: "100000000",
            outputAmount: "19163918",
            fee: [
              {
                type: "NETWORK",
                token: {
                  networkType: "sol",
                  address: "So11111111111111111111111111111111111111112",
                  chainId: "sol",
                  blockchain: "Solana",
                  decimals: 9,
                  name: "Solana",
                  symbol: "SOL",
                  image:
                    "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
                  lastPrice: 237.56,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: true,
                  isPopular: true,
                },
                source: "FROM_SOURCE_WALLET",
                amountInToken: "370000",
                amountInUSD: "0.0883",
              },
              {
                type: "PROVIDER",
                token: {
                  networkType: "sol",
                  address: "So11111111111111111111111111111111111111112",
                  chainId: "sol",
                  blockchain: "Solana",
                  decimals: 9,
                  name: "Solana",
                  symbol: "SOL",
                  image:
                    "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
                  lastPrice: 237.56,
                  isEnabled: true,
                  isFlagged: false,
                  isNative: true,
                  isPopular: true,
                },
                source: "FROM_OUTPUT_AMOUNT",
                amountInToken: "18750421",
                amountInUSD: "4.4750",
              },
            ],
            estimatedTimeInSeconds: 120,
          },
        ],
        fee: [
          {
            type: "NETWORK",
            token: {
              networkType: "sol",
              address: "So11111111111111111111111111111111111111112",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 9,
              name: "Solana",
              symbol: "SOL",
              image:
                "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
              lastPrice: 237.56,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            source: "FROM_SOURCE_WALLET",
            amountInToken: "370000",
            amountInUSD: "0.0883",
          },
          {
            type: "PROVIDER",
            token: {
              networkType: "sol",
              address: "So11111111111111111111111111111111111111112",
              chainId: "sol",
              blockchain: "Solana",
              decimals: 9,
              name: "Solana",
              symbol: "SOL",
              image:
                "https://assets.coingecko.com/coins/images/4128/standard/solana.png?1696504756",
              lastPrice: 237.56,
              isEnabled: true,
              isFlagged: false,
              isNative: true,
              isPopular: true,
            },
            source: "FROM_OUTPUT_AMOUNT",
            amountInToken: "18750421",
            amountInUSD: "4.4750",
          },
          {
            type: "BLOCKEND",
            source: "FROM_OUTPUT_AMOUNT",
            token: {
              networkType: "evm",
              address: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
              chainId: "137",
              blockchain: "Polygon",
              decimals: 6,
              name: "Tether",
              symbol: "USDT",
              image:
                "https://assets.coingecko.com/coins/images/325/small/Tether.png",
              lastPrice: 0.99996,
              isEnabled: true,
              isFlagged: false,
              isNative: false,
              isPopular: false,
            },
            amountInToken: "0",
            amountInUSD: "0",
          },
        ],
        provider: "lifi",
        providerDetails: {
          id: "lifi",
          name: "LI.FI",
          logoUrl:
            "https://raw.githubusercontent.com/blockend-com/docs-v1/refs/heads/main/resources/png/lifi.png",
          websiteUrl: "https://li.fi/",
        },
        protocolsUsed: ["Mayan (Wormhole)"],
        inputAmount: "100000000",
        inputAmountDisplay: "0.1",
        outputAmount: "19260271",
        outputAmountDisplay: "19.260271",
        minOutputAmount: "19.260271",
        slippage: 1892,
        userWalletAddress: "4sd55KCv7RFcc14goe3yJtsBTb9XMFjR5GAnemaDdYTd",
        recipient: "0x1b1E919E51a1592Dce70a4FD74107941109B8235",
        createdAt: 1738064338816,
        deadline: 60,
        estimatedTimeInSeconds: 120,
        requestId: "",
        score: {
          outputScore: 0.8205108379180754,
          speedScore: 0.1,
          feeScore: 1,
          slipparageScore: 0.06289640591966174,
          stepScore: 1,
          outputDiffPercent: 0.19718549139447822,
        },
        tags: [],
      },
    ],
  },
};
```

[View full quotes response](/compass-api/api-reference/fetching-quotes)

**`/createTx`**

This endpoint fetches the transaction steps for the selected quote . Since this is s solana to EVM bridge example, the transaction step includes bridge step. The response includes steps that need to be executed.The Step object includes a step ID and step type (bridge).

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
};
```

**Example Request**

```
GET /createTx?routeId=a1b2c3d4-e5f6-g7h8-i9j0
```

**Example Response**

```javascript
let createTxResponse = {
  status: "success",
  data: {
    steps: [
      {
        stepId: "step_12345",
        stepType: "approval",
      },
      {
        stepId: "step_67890",
        stepType: "bridge",
      },
    ],
  },
};
```

[View full createTx API response](/compass-api/api-reference/create-transaction)

**`/nextTx`**

This endpoint fetches the transaction data that needs to be executed for the selected step. The transaction data includes the transaction parameters for the step. Since this is an Solana to EVM bridge example, the transaction data includes the txnSol object field in the transaction data.

Note: The transaction data is specific to the step type. For example, if the step type is bridge, the transaction data includes the bridge parameters. Moreover, the next step data will be available only if the previous step is executed successfully.

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
  stepId: createTxResponse.data.steps[0].stepId, // stepId is available in the createTx steps[] response
};
```

**Example Request**

```
GET /nextTx?routeId=a1b2c3d4-e5f6-g7h8-i9j0&stepId=step_12345
```

**Example Response**

```javascript
let nextTxResponse = {
  status: "success",
  data: {
    txnData: {
      id: "01JJP6MS082138Y3NJB7XYDC1D",
      routeId: "01JJP6MGNXTS99P34JX6PC01GV",
      stepId: "01JJP6MGNXAZ9CV61FNX022ZTZ",
      isCompleted: false,
      networkType: "sol",
      createdAt: 1738059441160,
      txnSol: {
        data: "AQAAAAAAA..", // base64 encoded transaction data
      },
      status: "in-progress",
      fetchedAt: 1738059441160,
      nextTxStart: 1738059440990,
      nextTxEnd: 1738059441160,
    },
  },
};
```

[View full nextTx API response](/compass-api/api-reference/get-raw-transaction-to-execute)

**`/status`**

This endpoint fetches the transaction status for the selected step once the transaction step is submitted to the blockchain. The transaction status includes: the status of the transaction, the source transaction hash, the source transaction URL, the destination transaction hash, the destination transaction URL, the output amount received, and the output token details.

[View full status API documentation](/compass-api/api-reference/check-transaction-status)

#### Transaction Status Codes

* `in-progress`: Transaction is pending
* `success`: Transaction completed successfully
* `partial-success`: If output amount token is different from the destination token, the transaction is partial success.
* `failed`: Transaction failed

**Request Parameters**

```javascript
let requestParams = {
  routeId: quoteResponse.data.quotes[0].routeId, // routeId is available in the selected quote response
  stepId: createTxResponse.data.steps[0].stepId, // stepId is available in the createTx steps[] response
  txnHash: nextTxResponse.data.txnData.txnSol.hash, // pass the txnHash that is received from the wallet provider once the transaction is signed successfully by the user
};
```

**Example Request**

```
GET /status?routeId=a1b2c3d4-e5f6-g7h8-i9j0&stepId=step_12345&txnHash=0x1234...abcd
```

**Example Response**

```javascript
let statusResponse = {
  status: "success",
  data: {
    status: "success",
    srcTxnHash: "0x1234...abcd",
    srcTxnUrl: "https://polygonscan.com/tx/0x1234...abcd",
    destTxnHash: "0x5678...efgh",
    destTxnUrl: "https://polygonscan.com/tx/0x5678...efgh",
    outputAmount: "449144858547000000",
    outputToken: {
      address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
      symbol: "MATIC",
      decimals: 18,
      name: "MATIC",
    },
  },
};
```

### Code Example

In the code example below, we use plain JavaScript for simplicity, but the code is framework-agnostic and can be easily adapted to React, Next.js, Vite, or any other JavaScript framework. Simply modify the syntax and component structure to match your chosen framework's conventions.

### NodeJS Implementation

```javascript
import { Connection, Keypair, VersionedTransaction } from "@solana/web3.js";
import bs58 from "bs58";

// Initialize connection and keypair
const keypair = Keypair.fromSecretKey(bs58.decode(SOLANA_PRIVATE_KEY));
console.log({ keypair: keypair.publicKey.toString() });
const connection = new Connection(RPC_URL, "confirmed");
```

### Browser Implementation with Phantom Wallet

```javascript
import { Connection, VersionedTransaction, KeyPair } from "@solana/web3.js";
import Buffer from "buffer";

// Initialize Phantom wallet connection
async function initializeWallet() {
  if (!window.solana || !window.solana.isPhantom) {
    throw new Error("Phantom wallet is not installed!");
  }

  try {
    // Connect to the wallet
    const resp = await window.solana.connect();
    console.log("Connected to wallet:", resp.publicKey.toString());
    return window.solana;
  } catch (err) {
    console.error("Failed to connect to wallet:", err);
    throw err;
  }
}

// Initialize Solana connection
const connection = new Connection(
  "https://api.mainnet-beta.solana.com",
  "confirmed"
);
```

### Common Implementation

```javascript
async function solanaToEvmBridge() {
  // Initialize wallet based on environment
  const wallet =
    typeof window !== "undefined" ? await initializeWallet() : null;

  const solQuoteReq = {
    fromChainId: "sol",
    toChainId: "sol",
    fromAssetAddress: "So11111111111111111111111111111111111111112",
    toAssetAddress: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
    inputAmountDisplay: "0.01",
    userWalletAddress: wallet ? wallet.publicKey.toString() : "7z..",
    slippage: 2000,
    fixedSlippage: true,
    recipient: wallet ? wallet.publicKey.toString() : "7z...",
  };

  const headers = {
    "x-integrator-id": "your-integrator-id",
  };

  // Fetch quote
  const urlParams = Object.entries(solQuoteReq)
    .map(([key, value]) => `${key}=${value}`)
    .join("&");
  const fetchQuoteReq = await fetch(
    `https://api2.blockend.com/v1/quotes?${urlParams}`,
    {
      headers,
    }
  );
  const fetchQuoteRes = await fetchQuoteReq.json();
  console.log("quotes fetched");
  const quotes = fetchQuoteRes.data.quotes;

  const provider = "jupag";
  const providerQuote = quotes.find((q) => q.provider === provider);
  if (!providerQuote) throw new Error("quote not found, " + provider);

  // Create transaction
  const createdTxnReq = await fetch(
    `https://api2.blockend.com/v1/createTx?routeId=${providerQuote.routeId}`,
    {
      headers,
    }
  );
  const createdTxnRes = await createdTxnReq.json();
  console.log("txn created");

  // Get next transaction
  const nextTxnReq = await fetch(
    `https://api2.blockend.com/v1/nextTx?routeId=${providerQuote.routeId}&stepId=${createdTxnRes.data.steps[0].stepId}`,
    {
      headers,
    }
  );
  const nextTxnRes = await nextTxnReq.json();
  console.log("got next txn");

  const solTxn = nextTxnRes.data.txnData?.txnSol?.data;
  if (!solTxn) throw new Error("txn data not found");

  // Deserialize the transaction
  const txnBuffer = Buffer.from(solTxn, "base64");
  const transaction = VersionedTransaction.deserialize(txnBuffer);

  let signature;

  if (wallet) {
    // Browser environment - Sign with Phantom
    try {
      // Sign and send transaction
      let txn = await wallet.signAndSendTransaction(transaction);
      signature = txn.signature;
      console.log("Transaction sent:", signature);
    } catch (err) {
      console.error("Error sending transaction:", err);
      throw err;
    }
  } else {
    // NodeJS environment - Sign with keypair
    transaction.sign([keypair]);

    // Simulate the transaction
    const result = await connection.simulateTransaction(transaction, {
      sigVerify: true,
    });

    if (!result.value.err) {
      // Send the transaction
      signature = await connection.sendTransaction(transaction);
      console.log("Transaction sent:", signature);
    } else {
      console.error("Transaction simulation failed:", result.value.err);
      throw new Error("Transaction simulation failed");
    }
  }

  // Check transaction status
  const statusCheckReq = await fetch(
    `https://api2.blockend.com/v1/status?routeId=${providerQuote.routeId}&stepId=${createdTxnRes.data.steps[0].stepId}&txnHash=${signature}`,
    { headers }
  );
  const statusCheckRes = await statusCheckReq.json();
  console.log("Transaction status:", statusCheckRes);

  let currentStatus = "in-progress";
  let statusResponse;
  while (currentStatus === "in-progress") {
    // Check transaction status
    const transactionStatusRequest = await fetch(
      `https://api2.blockend.com/v1/status?routeId=${
        providerQuote.routeId
      }&stepId=${createdTxnRes.data.steps[0].stepId}&txnHash=${
        signature || ""
      }`,
      { headers }
    );
    statusResponse = await transactionStatusRequest.json();

    if (statusResponse.status === "error") {
      currentStatus = "in-progress";
      continue;
    } else {
      currentStatus = statusResponse.data.status;
    }

    // Handle different transaction states
    if (currentStatus === "failed") {
      throw new Error("Transaction failed");
    }

    if (currentStatus === "in-progress") {
      // Wait 2 seconds before next status check
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }
  }
}

solanaToEvmBridge()
  .catch(console.error)
  .finally(() => process.exit(0));
```

### Usage Notes

1. For browser implementation:
   * Make sure Phantom wallet extension is installed
   * Handle wallet connection states and user interactions appropriately
2. For NodeJS implementation:
   * Ensure you have the required environment variables (SOLANA\_PRIVATE\_KEY, RPC\_URL)
   * Handle errors and cleanup appropriately
3. Common considerations:
   * Replace 'your-integrator-id' with your actual integrator ID
   * Implement proper error handling and loading states
   * Add appropriate UI feedback for transaction status


# Onboards Users from any chain & Token right on your dApp


# Lex Protocol


# Brand Assets

## SVGs

{% file src="/files/VCT1TjD0b4yxxfUZNRUC" %}

{% file src="/files/9loGNLrcMIZoxtixw509" %}

{% file src="/files/J25MjZhd9KVzKXHYNc7D" %}

{% file src="/files/zCmBlfaYHLkxb2wjWhYh" %}

{% file src="/files/l8Hpjf61rmPyLbZi4sOM" %}

{% file src="/files/SBHJGvgMw8R6XICVuLXN" %}

{% file src="/files/WcCnSW441q2iZvtbmf7R" %}

***

## PNGs

{% file src="/files/Bkh1pq7LsZuiKP5Iy9qj" %}

{% file src="/files/vLzIhGm4dlkSltdN4ds4" %}

{% file src="/files/6ZXL2MclM4A71h0KE8E0" %}

{% file src="/files/sYy7pyggOOR1ynwrU3qt" %}

{% file src="/files/HwWAzjIojjdAJ3SbjZtU" %}

{% file src="/files/nmoGug8IBzqVCn2uQIND" %}

{% file src="/files/YAX2w9aijWOFZ2PNxrQM" %}


# Support


# React issues

This page addresses the possible errors while setting up the widget in CRA or Vite applications

## 1. RPC websocket

```
Class extends value /static/media/client.98866d6736d9f36d61b8.cjs is not a constructor or null
TypeError: Class extends value /static/media/client.98866d6736d9f36d61b8.cjs is not a constructor or null
```

If you encounter the above error, add this code to your package.json file

```
"resolutions": {
    "rpc-websockets": "7.10.0",
    "@solana/web3.js": "1.91.6"
}
```

for more details please refer <https://docs.dynamic.xyz/troubleshooting/react/cannot-resolve-rpc-websockets>


# Next js issues

This page addresses the possible errors while setting up the widget in Next js applications

## 1. Self is not defined or HTMLElement not defined

You may encounter Server Error... ReferenceError: self is not defined in your Next JS app, this is because blockend requires web apis to work and the web apis are not available on the server side when next js renders a page, in order to avoid this you can start by importing the Blockend Widget like below

<pre><code><strong>const Blockend = dynamic(() => import("blockend"), {
</strong>  ssr: false,
});
import "blockend/dist/style.css";
</code></pre>


