# `allow_unsafe`: Preventing & Handling Bad Execution
Source: https://skip-go.mintlify-go.com/go/advanced-swapping/allow_unsafe-preventing-handling-bad-execution



## Introduction

**The`allow_unsafe` parameter in the requests to `/route` & `/msgs_direct` endpoints is designed to protect users from bad trade execution.**

This parameter indicates whether you want to allow the API to return and execute a route even when our routing engine forecasts low or unknown execution quality:

* `allow_unsafe=false` (default): The API will throw an error instead of returning a route when the routing engine forecasts bad execution quality (i.e. > 10% `price_impact` or difference between USD value in and out) or when execution quality can't be determined.
* `allow_unsafe=true`: The API will return a route for a trade even when the routing engine forecasts bad execution quality (i.e. > 10% `price_impact` or difference between USD value in and out) or when execution quality can't be determined. In these cases, the API appends a `warning` to the response in a `warning` field

<Info>
  **Make sure you understand execution/quote quality measurements first**

  Before reading this doc, you should read our documentation on quote quality: [ Understanding Quote Quality Metrics](./understanding-quote-quality-metrics). This provides basic background information about the different ways the Skip Go API measures whether a route will likely give a user a bad execution price, namely the difference between the USD value of the input and the output & on-chain price impact.
</Info>

## `allow_unsafe=false` Behavior

When `allow_unsafe=false`, the endpoint throws an error when execution quality is poor (as measured by price impact or estimated USD value lost) or when execution quality can't be determined (i.e. neither of these measurements are available).

In particular, if `allow_unsafe=false`, `/route` and `/msgs_direct` return errors when:

* `price_impact > .10`(the swap will move the on-chain price by more than 10%)
* `(usd_amount_in-usd_amount_out)/usd_amount_in)>.10` (greater than 10% of the value of the input is lost)
* Neither of the above metrics can be computed

Below, we provide examples of the responses in each these cases.

The price impact is greater than 10% (`BAD_PRICE_ERROR`):

*

```{ theme={null}
  "code": 3,
  "message": "swap execution price in route deviates too far from market price. expected price impact: 98.6915%",
  "details": [
    {
      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
      "reason": "BAD_PRICE_ERROR",
      "domain": "skip.build",
      "metadata": {}
    }
  ]
}
```

The user loses more than 10% of their USD value (`BAD_PRICE_ERROR`):

*

```{ theme={null}
  "code": 3,
  "message": "difference in usd value of route input and output is too large. input usd value: 1000 output usd value: 600",
  "details": [
    {
      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
      "reason": "BAD_PRICE_ERROR",
      "domain": "skip.build",
      "metadata": {}
    }
  ]
}
```

The `price_impact` and the estimated USD value difference cannot be calculated (`LOW_INFO_ERROR`)

*

```JSON JSON theme={null}
{
  "code": 3,
  "message": "unable to determine route safety",
  "details": [
    {
      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
      "reason": "LOW_INFO_ERROR",
      "domain": "skip.build",
      "metadata": {}
    }
  ]
}
```

## `allow_unsafe=true` Behavior

When `allow_unsafe=true`, the endpoints will still return routes even when the routing engine forecasts will have unknown or poor execution quality (measured by price\_impact or estimated USD lost), but they will have a `warning` field appended to them.

The `warning` field is populated exactly when the endpoints would return an error if `allow_unsafe` were `false`, namely:

* `price_impact > .10`(the swap will move the on-chain price by more than 10%)
* `(usd_amount_in-usd_amount_out)/usd_amount_in)>.10` (greater than 10% of the value of the input is lost)
* Neither of the above metrics can be computed

Below, we provide examples of the responses in each these cases.

The price impact is greater than 10% (`BAD_PRICE_WARNING`):

*

```JSON JSON theme={null}
"warning": {
    "type": "BAD_PRICE_WARNING",
    "message": "swap execution price in route deviates too far from market price. expected price impact: 98.6826%"
}
```

More than 10% of the USD value of the input is lost in the swap (`BAD_PRICE_WARNING`):

*

```"warning": { theme={null}
    "type": "BAD_PRICE_WARNING",
    "message": "difference in usd value of route input and output is too large. input usd value: 1000 output usd value: 600"
}
```

The `price_impact` and the estimated USD value difference cannot be calculated (`LOW_INFO_ERROR`)

*

```
"warning": {
    "type": "LOW_INFO_WARNING",
    "message": "unable to determine route safety"
}
```

## Best Practices for Protecting Users

**Above all else, we recommend setting `allow_unsafe=false`**

In addition, we recommend reading our documentation around [safe API integrations](./safe-swapping-how-to-protect-users-from-harming-themselves) to learn about UX/UI practices that can further help prevent users from performing trades they'll immediately regret.

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# SAFE Swapping: How to Protect Users from Bad Trades
Source: https://skip-go.mintlify-go.com/go/advanced-swapping/safe-swapping-how-to-protect-users-from-harming-themselves



<Info>
  **Summary**

  **This doc covers several UI/UX principles we recommend Skip Go API integrators implement to protect users from harming themselves by swapping at bad execution prices. Collectively, we refer to these principles as S.A.F.E.**

  The document introduces the S.A.F.E framework and provides detailed guidance for how you can use the information provided in the Skip Go API to implement the framework & give your users a worry-free swapping experience.
</Info>

### Keeping Users Safe on your Application

Many users are unfamiliar with the technology behind cross-chain swaps and transfers. As a result they will take actions that aren't in their best interests:

1. Execute swaps & transfers they don't understand at unfavorable prices using money they cannot afford to lose (e.g. Spending \$1000 on a new, illiquid meme coin within 2 hours of launch)
2. Accuse **you** (& Skip) of responsibility for their losses (even if your software & ours worked as expected), demand a refund, and publicly vilify & troll you if you do not give one.

To protect both you and the user, we've developed a framework called **S.A.F.E** to help you remember and organize the UX principles that can keep your users safe:

1. **S**hare all available information about expected execution price
2. **A**lert when info indicates an action might be harmful
3. **F**ail transactions that trigger your alerts (i.e. transactions that seem likely to harm users)
4. **E**nforce additional approval stages for users who want to create these transactions anyhow

### S.hare Info

You should share as much information about the estimated swap with your users as possible. Fortunately, the `/fungible/route` and `/fungible/msgs_direct` endpoints return a ton of useful information.

In addition to showing estimated amount in and out (the obvious ones), we recommend showing:

* **Estimated USD value of the amount in** (`response.usd_amount_in`)
* **Estimated USD value of the amount out** (`response.usd_amount_out`)
* **Price Impact** (`response.swap_price_impact_percent`) -- This measures how much the user's expected execution price differs from the current on-chain spot price at time of execution. A high price impact means the user's swap size is large relative to the available on chain liquidity that they're swapping against, which makes a bad price very likely.
* **Swapping Venue** (Available in the `swap_venue` field of the `swap` operation in `response.operations`) - This tells the user what DEX they're actually performing the underlying swap on, which helps avoid confusion about prices. This can be useful information in the event the API returns an usual route and routes the user to a DEX they're unfamiliar with / don't want to use or to a DEX where there's not much liquidity of the token they're swapping (e.g. SEI liquidity on Osmosis is sparse at the time of this writing)
* **Bridge Fee Amounts** (Available in the `transfer` and `axelar_transfer` entries in `response.operations` under `fee_asset` and `fee_amount`) -- These represent the fees that bridges take from the user along the route, denominated in the token(s) they're taking. It's important to show because sometimes bridges take fees unexpectedly (e.g. Noble used to take 0.10% fee on IBC transfers), and sometimes they take large fees (e.g. During periods of high gas prices, Axelar fees can be as high as \$200)
* **USD value of bridge fee amounts** (Available in the `transfer` and `axelar_transfer` entries in `response.operations` under `usd_fee_amount`) -- This gives the user a sense of the actual cost of their fee amounts. In cases of more complex swaps and transfers, the user might have a hard time making sense of the underlying fee tokens because the fees are being charged at an intermediate point in the route

The quote shown to the users should **always** match the transaction that they end up signing. Once you have called `/route` and displayed the quote to the user, a call to `/msgs` is the only way to generate the correct message. (DO NOT call `/msgs_direct` after calling `/route` since this will regenerate the quote)

Alternatively you can call `/msgs_direct` to both generate the quote information and the transaction that needs to be signed with 1 request. Remember that these endpoints are not deterministic and calling either again will generate a different output and your user will not execute the transaction they think they are executing.

### A.lert users to bad prices

We recommend alerting users in the following three scenarios at least:

1. **High Price Impact** (`swap_price_impact > PRICE_IMPACT_THRESHOLD`) : This indicates the user's swap is executing at a considerably worse price than the on-chain spot price -- meaning they're probably getting a worse price than they think they should. It also indicates the size of their trade is large relative to the available on chain liquidity. We recommend using`PRICE_IMPACT_THRESHOLD = 2.5 `in your calculations
2. **High difference in relative USD value in and out** (`(usd_amount_in - usd_amount_out)/usd_amount_in)*100 > USD_REL_VALUE_THRESHOLD` ): This estimates the underlying value the user will lose instantly as a result of swapping, represented as a percentage of the value of their input. A high value for this figure indicates the user is instantly losing a large percentage of the value of their starting tokens. For example, a value of 50 indicates the user loses 50% of the estimated value of their input. We recommend using `USD_REL_VALUE_THRESHOLD=2.5`
3. **High fees** ( `usd_fee_amount / usd_amount_in > FEE_THRESHOLD`) : This indicates that the value of fees charged by bridges used in the route amount to a large percentage of the underlying amount being transferred. If this value is high, user might want to wait until bridging more funds to execute (since bridge fees rarely scale with volume). We recommend setting `FEE_THRESHOLD=.25`

Loud visual emphasis of the values that exceed safe tolerances is the most effective form of alerting. This includes:

* Bolding unusually high/low quote numbers -- or otherwise making them larger than surrounding text/numbers
* Automatically opening drop downs / detail panes that are usually closed by default to display the alert field
* Highlighting the offending quote number in red, yellow, or some other loud color indicating danger and/or greying out other numbers

For example, when a swap exceeds our `PRICE_IMPACT_THRESHOLD` on [go.skip.build](https://go.skip.build), we auto-open the drop-down that normally hides price impact and highlight the whole field in red.

<Frame>
  <img alt="" />
</Frame>

### F.ail Transactions when they're likely to cause user harm

We recommend preventing transactions that may significantly harm the user altogether -- even if your user seems to want to complete the transaction.

We recommend failing/preventing user transactions in the following scenarios:

1. **Greater than 10% difference in relative USD value in and out** `(usd_amount_in - usd_amount_out)/usd_amount_in)*100 > 10`
2. **Greater than 10% price impact** (`swap_price_impact > 10`)

You could can decide how you want to signal this failure to user, e.g. no route found, some form of low liquidity message, or something else entirely.

Preventing transactions altogether that violate your safety thresholds is the strongest form of user safety.

### E.nforce explicit, additional approval

If you do not want to fail transactions that exceed safety thresholds outright, one viable alternative is to require additional stages of user approval before letting the user sign the transaction.

Importantly, this is different and more disruptive than simply warning the user about some aspect of the quote looking unfavorable. This means putting additional clicks between the user and the swap they want to perform, and having them explicitly agree to performing a swap your UI indicates will have a bad price.

For example, this is go.skip.build's warning screen:

<Frame>
  <img alt="" />
</Frame>

* It's very clear that our expectation is that the swap will harm the user with the "Bad Trade Warning" across the top
* The page explicitly reminds the user what the problem is -- foregrounding the predicted price impact and forcing them to acknowledge it again
* The "happy path" or "default" path is to go back -- not to finish the swap (Notice that the "Go Back" button is highlighted)

We recommend requiring additional steps of user approval in the following cases:

1. **Greater than 5% difference in relative USD value in and out** `(usd_amount_in - usd_amount_out)/usd_amount_in)*100 > 5`
2. **Greater than 5% price impact** (`swap_price_impact > 5`)
3. **Price impact AND relative-USD-value-difference cannot be calculated** (i.e. `swap_price_impact`, `usd_amount_out`, and/or `usd_amount_in` are missing)

#### Choosing the right level of protection: warnings, additional approvals, and outright failures

It's important to think about this tradeoff because protecting users often directly trades off against making a cleaner, simpler, and more powerful user experiences. For example, excessive warnings might get annoying to users who know they're trading illiquid shitcoins, and additional steps of approval might frustrate pro traders who care deeply about speed

For any safety metric you might track to determine whether a transaction could harm a user, consider 4 tiers of safety you can implement. From least safe and least disruptive to most safe and most disruptive:

1. **None**: Just let it rip. Don't give the user any heads up. Don't do anything to slow them down or prevent them from trading.
2. **Alert**: Use some visual cue to indicate to the user that they should be wary about swap
3. **Enforce additional approval**: Require additional clicks to actually execute the swap and foreground the warning -- so the user needs to approve it explicitly.
4. **Fail**: Just block / fail / prevent transactions that exceed your safety tolerance bounds outright

Here are some suggestions for navigating this design space:

1. **Set lower trigger thresholds for weaker forms of security and more conservative thresholds for stronger forms of security** (e.g. You could alert users about high price impact at 2.5%, require an additional stage of approval at 10%, and fail the transaction outright at 25%) This approach is nice because it gives users who may be very conservative some indication that they may face some danger without getting in their way too much, while still hard-stopping more inexcusable failures that are probably never acceptable to any trader
2. **Use stronger forms of security when safety tolerances are exceeded for higher value transactions** (e.g. You could use warnings when price impact is greater than 10% for transactions where the amount in is $0-100, additional approvals when amount in is $1,000 - 10,000, and block transactions above \$10k outright if price impact is greater than 10%.

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Smart Swap
Source: https://skip-go.mintlify-go.com/go/advanced-swapping/smart-swap-options

This page introduces the Smart Swap functionality provided by the Skip Go API to improve swap speed, price, and customization.

## Introduction

Smart Swap refers to a feature set that improves swap speed, price, and control.

It currently allows for:

* [External routers](#feature-use-external-routers-to-improve-price-execution) (e.g. Hallswap and Osmosis SQS) for better price execution
* [Route splitting](#feature-route-splitting) for better price execution
* [EVM swaps](#feature-evm-swaps)

<Warning>
  If you're using the deprecated `@skip-router` library, you must use version v4.0.0+ to enable Smart Swap.

  We strongly recommend using the `@skip-go/client` [TypeScript package](https://www.npmjs.com/package/@skip-go/client), which is actively maintained.
</Warning>

The rest of this document will show you how to use Smart Swap with the `@skip-go/client` library. The only changes you'll notice between this context and the REST API are naming conventions.

# Smart Swap Features

Set your Smart Swap settings in your `skipClient` function call or REST API request body.

## Feature: Use External Routers to Improve Price Execution

The Skip Go API considers multiple internal and external routers to find the route with the best price execution.

Currently supported external swap routers:

1. Skip Go API's in-house Router
2. Hallswap's Dex Aggregator
3. Osmosis's Sidecar Query Service (SQS) (Used in the Osmosis frontend)

### Usage

Pass an empty `smartSwapOptions` object into your route request.

<CodeGroup>
  ```ts TypeScript (Client) theme={null}
  const route = await skipClient.route({
    smartSwapOptions: {}, // You're not required to activate a particular flag for this feature
    sourceAssetDenom: "uusdc",
    sourceAssetChainID: "noble-1",
    destAssetDenom: "utia",
    destAssetChainID: "celestia",
    amountIn: "1000000", // 1 uusdc
    cumulativeAffiliateFeeBPS: "0"
  }
  ```

  ```JSON JSON (REST API) theme={null}
  // POST /v2/fungible/route
  {
    "amount_in": "1000000",
    "source_asset_denom": "uusdc",
    "source_asset_chain_id": "noble-1",
    "dest_asset_denom": "utia",
    "dest_asset_chain_id": "celestia",
    "cumulative_affiliate_fee_bps": "0",
    "allow_multi_tx": true,
    "smart_swap_options": {}
  }
  ```
</CodeGroup>

That's it! Skip Go API will now consider supported external routers and return the best available option.

## Feature: Route Splitting

Route splitting involves dividing a user's trade into multiple parts and swapping them through different pools. This reduces price impact and can increase the user's output compared to using a single route. It works especially well when one or both tokens being swapped are commonly paired with other assets on a DEX (e.g., OSMO on Osmosis).

### Usage

Pass the `splitRoutes` flag in the `smartSwapOptions` object.

<CodeGroup>
  ```ts TypeScript (Client) theme={null}
  const route = await skipClient.route({
    smartSwapOptions: {
      splitRoutes: true
    }, // smart swap object
    sourceAssetDenom: "uusdc",
    sourceAssetChainID: "noble-1",
    destAssetDenom: "utia",
    destAssetChainID: "celestia",
    amountIn: "1000000", // 1 uusdc
    cumulativeAffiliateFeeBPS: "0"
  }
  ```

  ```JSON JSON (REST API) theme={null}
  // POST /v2/fungible/route
  {
    "amount_in": "1000000",
    "source_asset_denom": "uusdc",
    "source_asset_chain_id": "noble-1",
    "dest_asset_denom": "utia",
    "dest_asset_chain_id": "celestia",
    "cumulative_affiliate_fee_bps": "0",
    "allow_multi_tx": true,
    "smart_swap_options": {
      "split_routes": true
    }
  }
  ```
</CodeGroup>

### Response Changes when using Split Routes

We've added a new `swapType` called `SmartSwapExactCoinIn` that's returned in the `routeResponse` and `msgsDirectResponse` when the provided route is a split route. This new `swapType` has fields that allow for multiple routes, across multiple swap venues.

```ts theme={null}
export type SmartSwapExactCoinIn = {
  swapVenue: SwapVenue;
  swapRoutes: SwapRoute[];
};

export type SwapRoute = {
  swapAmountIn: string;
  denomIn: string;
  swapOperations: SwapOperation[];
};
```

## Feature: EVM Swaps

Smart Swap supports bidirectional EVM swaps: go from any asset on an EVM chain to any asset on a Cosmos chain and back again. With EVM swaps, users can onboard to your IBC connected chain in 1 transaction from a broad range of EVM assets, including the memecoins retail loves to hold!

Currently, the API supports EVM swapping on Velodrome (Optimism) & Aerodrome (Base), and swapping on official Uniswap V3 deployments on the following chains:

| Network      | Chain ID |
| ------------ | -------- |
| Ethereum     | 1        |
| Polygon      | 137      |
| Optimism     | 10       |
| Arbitrum One | 42161    |
| Base         | 8453     |
| BNB Chain    | 56       |
| Avalanche    | 43114    |
| Blast        | 81457    |
| Celo         | 42220    |

### Usage

Set the `evmSwaps` flag to true in the `smartSwapOptions` object. If using the deprecated `@skip-router` library, you must be on v5.1.0+ (we strongly recommend migrating to `@skip-go/client` as soon as possible).

<CodeGroup>
  ```ts TypeScript (Client) theme={null}
  const route = await skipClient.route({
    sourceAssetDenom: "arbitrum-native",
    sourceAssetChainID: "42161",
    destAssetDenom: "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
    destAssetChainID: "dydx-mainnet-1",
    amountIn: "10000000000000000000",
    cumulativeAffiliateFeeBPS: "0",
    smartRelay: true,
    smartSwapOptions: {
      evmSwaps: true
    },
  }
  ```

  ```JSON JSON (REST API) theme={null}
  { // POST /v2/fungible/route
    "amount_in": "10000000000000000000",
    "source_asset_denom": "arbitrum-native",
    "source_asset_chain_id": "42161",
    "dest_asset_denom": "ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",
    "dest_asset_chain_id": "dydx-mainnet-1",
    "cumulative_affiliate_fee_bps": "0",
    "allow_multi_tx": true,
    "smart_relay": true,
    "smart_swap_options": {
    	"evm_swaps": true
    },
  }
  ```
</CodeGroup>

### How do EVM Swaps Change the `route` Response?

When an EVM swap occurs in a route, a new operation of type `evm_swap` is returned in the array of `operations` in the `v2/route` and `v2/msgs_direct` response.

<Warning>
  If your API use follows the `v2/route` then `v2/msgs` call pattern, this new operation type must be passed to the `v2/msgs` endpoint, so make sure you use the latest [Skip Go Client version](https://www.npmjs.com/package/@skip-go/client) and decode the operation properly.
</Warning>

The `evm_swap` operation type is as follows:

<CodeGroup>
  ```ts TypeScript theme={null}
  export type EvmSwap = {
    inputToken: string;
    amountIn: string;
    swapCalldata: string;
    amountOut: string;
    fromChainID: string;
    denomIn: string;
    denomOut: string;
    swapVenues: SwapVenue[];
  }
  ```

  ```JSON JSON theme={null}
  {
    "evm_swap": {
      "input_token": "ox",   // string (token contract address if an ERC20 token, blank if native)
      "amount_in": "100",    // string
      "swap_calldata": "0x", // string
      "amount_out": "123",   // string
      "from_chain_id": "1",  // string
      "denom_in": "0x",      // string
      "denom_out": "0x",     // string
      "swap_venues": [],     // []swap_venue
    }
  }
  ```
</CodeGroup>

### How does this Change the `/msgs` and `/status` Response?

Nothing new in particular! The `msg_type` used for EVM swaps is the same `evm_tx` type used for all of our EVM transactions. Similarly, there is no new `transfer_event` type; the swap is atomic with the bridging action (Axelar or CCTP), so the same types are used (`axelar_transfer_info` and `cctp_transfer_info` respectively).

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Understanding Quote Quality Metrics
Source: https://skip-go.mintlify-go.com/go/advanced-swapping/understanding-quote-quality-metrics

This doc covers the various ways route quote quality is measured -- slippage, USD estimates of the amount in and out, and price impact

<Info>
  **Video Summary**

  [Here's a video](https://www.loom.com/share/5293719872714557b03db41fb5ca590e) that summarizes the content below.
</Info>

### Different ways to measure quote quality

* `slippage`: This is the maximum allowable difference between what Skip estimates the price of the swap will execute at and the worst price it can execute at. If the price of the swap turns out to be worse than the slippage tolerance allows, the swap will revert entirely. Slippage does not account for the impact of the user's swap itself because this is incorporated in the estimate. You can still get a "bad price" with *low* slippage if you make a big swap against a low liquidity pool because your swap itself will move the price. As a result, you should think of slippage as tolerance for difference between actual price and quoted price, not a measure of whether the quoted price is "good".
* `usd_estimate_in` and `usd_estimate_out`: These are estimates of the dollar-value of the amount in and amount out. These use coingecko prices that can be a maximum of 5 minutes stale. These values aren't always available because not all tokens are listed on Coingecko (e.g. some meme coins or new coins won't have feeds). This is really useful for providing a sanity check on whether a price is "good" and flagging to users when the difference between estimated input and output dollar values exceeds some threshold as a percentage of the input amount. (For example, we recommend you flag the user when their input dollar value is $100 and their output is $50. This indicates they're receiving a bad price for some reason.)
* `price_impact`: This measures how much the user's expected execution price differs from the current on-chain spot price at time of execution. This is available whenever the underlying DEX makes it feasible to calculate on-chain spot price. This is especially useful when `usd_estimate_in` or `usd_estimate_out` isn't available. A high price impact means the user's swap size is large relative to the available on chain liquidity that they're swapping against, and they're moving the price significantly a lot. Like with USD estimate, we recommend warning users when this exceeds some threshold (e.g. 10%).

### More on `slippage` vs `price_impact`

Some people have asked why are both slippage and price\_impact necessary. The reason is that they are trying to capture fundamentally different concepts:

* slippage = tolerance to the world / liquidity changing between when the API gives you a quote and when the transaction gets executed (0 slippage = "I want to get exactly the amount out that Skip estimates"). Of course, this could still be a bad price if there's high price\_impact, or if the difference between `usd_amount_in` and `usd_amount_out` is large. **Slippage is better understood as a tolerance to volatility, rather than an estimate of execution quality.**
* price impact = A measure of how much you're going to move the on-chain price with your trade. Some folks use the word "slippage" to describe price impact. This is intended to capture your tolerance to low liquidity and bad pricing.

Fundamentally, you can execute a trade that has low price impact but high slippage if you want to execute a volatile trade against a lot of liquidity

### Protecting users with SAFE interfaces

If you're wondering how you should use these values to help protect your users from poor execution prices, we have a whole guide written about how to build a safe swapping interface: [SAFE Swapping: How to Protect Users from Bad Trades](./safe-swapping-how-to-protect-users-from-harming-themselves)! Check it out!

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# CW20 Tokens & Their Limitations
Source: https://skip-go.mintlify-go.com/go/advanced-transfer/cw20-swaps

Information about performing CW20 swaps

This page covers the basics of CW20s and the limitations around performing cross-chain actions with CW20 tokens -- compared to tokenfactory and "native" Cosmos assets (aka Bank Module assets).

### CW20 Token Denom Formatting In API Requests

To use CW20 tokens in the Skip Go API, specify the denom as "cw20:" + the token contract address.

Example denom for Astro on Terra2: `cw20:terra1nsuqsk6kh58ulczatwev87ttq2z6r3pusulg9r24mfj2fvtzd4uq3exn26`

### Background

#### What is a CW20 token?

[CW20](https://github.com/CosmWasm/cw-plus/blob/main/packages/cw20/README.md) is the fungible token spec for the CosmWasm (i.e. CW) VM. CosmWasm is the most popular smart contract VM among CosmosSDK blockchains today. At a high-level, CW20 is very similar to ERC20 (the popular EVM fungible token standard).

Contracts that comply with the standard implement the following functionalities:

* Transferring tokens from one account to another
* Sending tokens to a contract along with a message (similar to `callContractWithToken`)
* Tracking balances
* Delegating balance spending to other accounts and contracts

ASTRO (Astroport's governance token) is one CW20 token issued on Terra2.

#### How do CW20 tokens interact with IBC?

[CW20-ICS20](https://github.com/CosmWasm/cw-plus/tree/v0.6.0-beta1/contracts/cw20-ics20) converter contracts make a CW20 token compatible with the ICS20 token transfer standard, so they can be sent to other chains over normal ICS20 transfer channels. When they arrive on the destination chain, they're indistinguishable from bank module and tokenfactory tokens.

These converter contracts are the source of much difficulty when attempting to perform cross-chain actions with CW20s:

* Different converter contracts implement different versions of the ICS20 standard (e.g. Some don't support memos, which are required for post-transfer contract calls and multi-hop transfers)
* On transfer failure, converter contracts just return assets to sender. That means if one of our contracts attempts to send tokens on your behalf unsuccessfully, it will receive the tokens. We can't atomically send them to you.

#### How do CW20 tokens compare to "native" (aka bank module) tokens?

"Native" tokens are tokens where minting, burning, balances, and transfer functionality are managed by the [bank module](https://docs.cosmos.network/v0.46/modules/bank/), instead of by contracts. Unlike CW20s, native tokens are directly compatible with ICS20 and IBC modules. One can send a native token to another chain over a transfer channel just using a `MsgTransfer` -- no conversion contracts or anything of the sort required.

The downside of native tokens is that they're permissioned and deeply ingrained into the chain's state machine. As a result, issuing a new native token requires a chain upgrade. Issuing a CW20 on the other hand, only requires deploying a new contract (just a transaction).

#### How do CW20 tokens compare to "tokenfactory" tokens?

Tokenfactory tokens are created with the [tokenfactory](https://docs.osmosis.zone/osmosis-core/modules/tokenfactory/) module. They're designed to have the best of both worlds of CW20 and native tokens:

* Like CW20s, they're permissionless and users can create new ones just by submitting transactions -- no need to modify the chain's state machine
* Like native tokens, they're directly compatible with IBC out-of-the-box, and the bank module manages their balances + transferring functionality.

This combination of traits leads many to see tokenfactory as a strict improvement on CW20 that devs should prefer in the vast majority of cases. We strongly agree with this conclusion.

Unlike `CW20s` , tokenfactory tokens have no limitations in the cross-chain functionality Skip Go API can offer for them.

### What limitations do CW20 tokens have within the Skip Go API?

At a high-level, basically any multi-chain action--in which the token is on the chain where it was issued for one stage of the action--requires multiple transactions.

In particular, this means you cannot perform the following actions in 1 transaction:

* IBC transfer after purchasing a cw20 asset

<Frame>
  <img alt="Chain 1 is the origin chain where the cw20 token can be swapped freely, but it cannot be transferred to another chain in the same transaction." />
</Frame>

* Call a contract on a remote chain after purchasing a cw20 asset (e.g. since this requires an IBC transfer under the hood)

<Frame>
  <img alt="Chain 1 is the origin chain, where the token can be used freely for post-route actions, but it cannot be used in post-route actions on other chains." />
</Frame>

* IBC transfer from a remote chain to the CW20's origin chain then perform a swap or any other post-route action on that chain

<Frame>
  <img alt="Chain 2 is the origin chain. The token can be transferred back there, but it can't be used or swapped for anything in the same transaction." />
</Frame>

In principle, you can use the Skip Go API to construct any of these action sequences across multiple transactions, but it will be more challenging for you and your end users.

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# EVM Transactions
Source: https://skip-go.mintlify-go.com/go/advanced-transfer/evm-transactions

This doc covers how to interact with the EvmTx type returned by the Skip Go API

## Intro

* When a user needs to transfer or swap from an EVM chain (e.g. Ethereum mainnet, Arbitrum, Optimism, etc...), the Skip Go API will return an `EvmTx` type for the developer to pass to the user for signing
* Unlike CosmosSDK transactions, EVM transactions do not have a notion of messages, so this object doesn't correspond 1-to-1 to a "message", which might be a more familiar notion to Cosmos developers
* This doc is intended for CosmosSDK developers who aren't already familiar with the concepts of transaction construction in the EVM and need to use `EvmTx` to help their users move from/to EVM chains.

## `EvmTx` Data Structure

The EvmTx has 4 fields that the developer needs to understand:

* `to`: The address of the smart contract or externally owned account (EOA) with which this transaction interacts, as a hex-string prefixed with 0x (e.g. 0xfc05aD74C6FE2e7046E091D6Ad4F660D2A159762)
* `value`: The amount of `wei` this transaction sends to the contract its interacting with (1 ETH = 1^18 WEI)
* `data`: The calldata this transaction uses to call the smart contract it interacts with, as a hex string. The data bytes will be interpreted according to the application-binary-interface (ABI) of the contract that's being interacted with. If this field is empty, it means the transaction is sending funds to an address, rather than calling a contract.
* `required_erc20_approvals`: The permissions that must be granted to a specific smart contract to spend or transfer a certain amount of their ERC-20 tokens on behalf of the end user. This allows smart contracts to execute expressive flows that may involve moving some amount of the user's ERC-20 tokens
  * Skip Go will always return this field if there are any erc20 approvals needed for the route. It is the client's responsibility to check if the user's approval is already at or above the returned approval needed (for example, if the integrator allows for max approvals). If this field is non-empty and the user does not have the approvals necessary, the approval must be granted, signed, and submitted before the `EvmTx` populated by the other fields in the response can be submitted to the network. Otherwise, it will fail to execute with a permission error.
  * Skip's `ERC20Approval` object has 3 fields that define approval:
    \_ `token_contract`: The address of the ERC-20 token on which the approval is granted
    \_ `spender`: The address of the contract to which the approval will grant spend authority \* `amount`: The amount of `token_contract` tokens the approval will grant the `spender` to spend
  * Check out EIP-2612 for more information on ERC-20 approvals.
* `chain_id`: This is the same as in the Cosmos context (simply an identifier for the chain), but it's an int instead of a string

For more information on transactions, check out the Ethereum foundation's [docs](https://ethereum.org/en/developers/docs/transactions/)

## Example constructing & signing an EVM Transaction

### 1. Install Signing Library and Skip Library

To enable EVM transactions in your application, first install an EVM developer library. The most popular options are:

* [viem](https://viem.sh/)
* [ethers.js](https://docs.ethers.org/v5/)
* [web3.js](https://web3js.readthedocs.io/en/v1.10.0/)

The code snippets below use viem.

```Shell Shell theme={null}
npm i viem
npm i @skip-go/client
```

### 1. Initialize the `SkipClient` client with the EVM `WalletClient` object

All 3 libraries mentioned above allow you to create WalletClient "signer" objects that:

* Use an RPC provider under the hood to query the chain for necessary data to create transactions (e.g. nonce, gas price, etc...)
* Expose an API that allows constructing, signing, and broadcasting transactions

You need to set up the `getEVMSigner` function in the `SkipClient` constructor to initialize this signer object for the a given EVM chain.

For example, with Viem, we do the following:

```TypeScript TypeScript theme={null}
import { createWalletClient, custom} from 'viem';
import * as chains from 'viem/chains';
import { SkipClient } from '@skip-go/client';

const
const skipClient = new SkipClient({
  getEVMSigner: async (chainID) => {
    const chain = extractChain({
  		chains: Object.values(chains),
  		id: parseInt(chainID)
    });
    const evmWalletClient = createWalletClient({
  		chain: chain,
  		transport: custom(window.ethereum!)
  	});
    return evmWalletClient;
  }
});
```

### 2. Request Route using `SkipClient` and get required chain

Next, request your route as normal:

```Typescript TypeScript theme={null}
const route = await skipClient.route({
  amountIn: "1000",
  sourceAssetDenom: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  sourceAssetChainID: "1",
  destAssetDenom: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
  destAssetChainID: "42161",
  smartRelay: true,
  smartSwapOptions: {
    splitRoutes: true
  }
};

```

### 3. Get User Addresses for all Required Chains

Use the route to determine the chains for which you need to supply a user address (the source, destination, and all intermediate chains that require a recovery address for receiving tokens in case of a failure)

```TypeScript TypeScript theme={null}
let userAddresses = []
const requiredAddresses = route.requiredChainAddresses;
// iterate over chain IDs for chains that require addresses
for (const chainID of requiredAddresses) {
  	// Check that the chain is an EVM chain
    if (parseInt(chainID)) {
      // use signer library to get address from wallet
      const chain = extractChain({
        chains: Object.values(chains),
        id: parseInt(chainID)
      });
      const evmWalletClient = createWalletClient({
        chain: chain,
        transport: custom(window.ethereum!)
      });
      const [address] = await client.requestAddresses();
      // add to map
      userAddresses.append({address: address, chainID: chainID})
    } else {
      // handle cosmos and SVM wallets -- not shown
    }

});
return evmWalletClient;
}

```

### 4. Execute the Route using `SkipClient`

Finally, you can use `SkipClient.executeRoute` to prompt the user to sign the approval(s) and transaction, and submit the transaction on chain.

```TypeScript TypeScript theme={null}
await skipClient.executeRoute({
  route:route,
  userAddresses: userAddresses
});
```

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Experimental Features
Source: https://skip-go.mintlify-go.com/go/advanced-transfer/experimental-features

This page provides a living record of the features that can be turned on with the experimental_features flag

### Background

The `experimental_features` parameter on `/route` and `/msgs_direct` gives us a consistent mechanism for rolling out new features to the folks who want to adopt them ASAP in an "opt-in" fashion, without threatening to destabilize power users who might want the new hottness.

*(Of course, we avoid shipping changes that are technically breaking no matter what. But we've found that even additive changes can break some integrators).*

We will probably auto-activate most features that we soft launch in `experimental_features` within a few weeks or months of the initial launch -- especially when the feature makes a strict improvement to end user UX (e.g. adding a new DEX or bridge).

The `experimental_features` parameter accepts an array of strings, where each string identifies a feature. The rest of this doc describes each experimental feature currently in prod, when the feature will become opt-out (rather than opt-in), and gives the feature's identifier.

### Stargate ("stargate")

**Description:** Support for routing over the Stargate V2 bridge on EVM chains incl. Sei EVM

**Opt-out switch**: Stargate routing will auto-activate on March 1 2025

**Identifier:** "stargate"

### Eureka ("eureka")

**Description:** Support for routing over the IBC Eureka bridge, starting with a connection between Cosmos and Ethereum Mainnet.

**Opt-out switch**: Eureka routing will auto-activate on May 1 2025

**Identifier:** "eureka"

### Layerzero (`"layer_zero"`)

**Description:**\
Improves cross-chain capabilities to support more assets such as USDT.

**Opt-out switch:**\
Layerzero routing was auto-activated on **March 1, 2025**.

**Identifier:** `"layer_zero"`

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.gg/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Go Fast
Source: https://skip-go.mintlify-go.com/go/advanced-transfer/go-fast

A brief overview of the Go Fast Transfer system

<Info>
  Read the whitepaper [here](https://skip-protocol.notion.site/EXT-Skip-Go-Fast-b30bc47ecc114871bc856184633b504b).
  Find integration details for Go Fast [here](../client/advanced-features#use-the-go-fast-transfer-system).
</Info>

# Overview

Go Fast is a decentralized bridging protocol, built by Skip, designed to enable rapid and secure cross-chain transactions across major blockchain ecosystems such as Ethereum, Cosmos, and Solana. Go Fast accelerates cross-chain actions by up to 25 times, reducing onboarding times from 10+ minutes to seconds.

# How it Works

The Go Fast Protocol lets you quickly move assets and execute smart contracts between two different blockchains: the source chain and the destination chain. Here's a simple breakdown of how it all happens.

To start, you—the user—initiate a transfer by calling the `submitOrder` function on the protocol contract on your current blockchain (source chain). In this step, you specify the assets, any message you want to send, and the address on the destination chain. This information is then broadcasted as an intent.

Permissionless participants called solvers, who watch for these intents, ingest the event emitted from the Go Fast contracts. When they see the intent submitted, they evaluate whether they can fulfill the intent based on their resources on the destination chain and the potential reward for fulfilling it. If a solver agrees to fulfill the intent, they call the `fillOrder` function on the protocol contract deployed on the destination chain.

This step transfers the specified assets and processes any additional actions, like executing a contract call with the provided message payload. From your perspective, the assets or messages appear on the destination chain almost instantly, marking the transfer as complete.

After fulfilling the transfer, the solver seeks to recover the assets they fronted, plus any earned fees. They do this by calling the `initiateSettlement` function on the destination chain's Go Fast smart contract, listing the intents they fulfilled. The protocol verifies the solver's actions, then sends a secure message back to the source chain through a cross-chain messaging system.

A relayer delivers this message to the source chain, where the settle function on the protocol contract verifies the solver's fulfillment of each intent. Once confirmed, the solver receives back the assets they provided and any earned fees on the source chain.

# Can I become a solver?

Yes! Go Fast is a permissionless protocol, so anybody can run a solver!

**Open-Source Reference Solver Implementation:** To help you get started quickly, we've open-sourced a reference implementation of a solver that handles everything—from monitoring events to filling orders, settling transactions, and rebalancing. All you need to do is set up the config with the chains you want to solve for, provide node endpoints to use, and customize your capital and rebalancing preferences. Check out the repo [here](https://github.com/skip-mev/skip-go-fast-solver).

**Open-Source Protocol Contracts:** Although we recommend starting with the open-source solver, ambitious solvers are already modifying the reference implementation or developing their own solving systems. If you fall under this category, another useful resource will be our open-source Solidity and CosmWasm protocol contracts to integrate directly. You can find them [here](https://github.com/skip-mev/go-fast-contracts).

If you have any questions about setting up a solver, please don't hesitate to reach out to us!

# What chains are supported today?

Currently, Go Fast supports the following source chains:

1. Ethereum Mainnet
2. Arbitrum
3. Avalanche
4. Base
5. Optimism
6. Polygon

And the following destination chains:

1. Any IBC-connected chain supported by Skip Go

# What are the minimum and maximum transfer sizes for Go Fast?

Below is a table summarizing the minimum and maximum transfer sizes for each chain currently supported by Go Fast.

| Source Chain         | Minimum Transfer Size (in USD) | Maximum Transfer Size (in USD) |
| -------------------- | ------------------------------ | ------------------------------ |
| **Ethereum Mainnet** | 20                             | 25,000                         |
| **Arbitrum**         | 10                             | 25,000                         |
| **Avalanche**        | 10                             | 25,000                         |
| **Base**             | 10                             | 25,000                         |
| **Optimism**         | 10                             | 25,000                         |
| **Polygon**          | 10                             | 25,000                         |

Note: If a user is starting from an asset that is not USDC on the source chain, Skip Go will swap the asset to USDC on the source chain and the post-swap amount is used to see if it is within the min/max bounds of Go Fast transfer sizes.

### dYdX Volume Limits

When transferring to dYdX via Go Fast, there is a \$100,000 USD maximum transfer size.

# What is the fee model for Go Fast?

Go Fast works by having solvers use their own capital to fill orders as quickly as possible, where the solvers take on the re-org risk of the source chain. The Go Fast protocol compensates solvers by paying them a fee (denoted by the difference in the input and output amount of the user's order). The fee is composed of three parts, a basis points fee on the transfer size, a source gas fee, and a destination gas fee.

Currently, the basis points fee on transfer size paid to solvers is 10 basis points across all transfer sizes. As the protocol evolves, the basis points fee charged is expected to decrease as transfer size increases.

The source and destination gas fees are determined dynamically based on the source and destination chains and their current gas costs, optimized to minimize costs while covering settlement and rebalancing for solvers.

# How do I integrate Go Fast into my application?

For instructions on integrating Go Fast using the `@skip-go/client`, see the [Advanced Features guide](../client/advanced-features#use-the-go-fast-transfer-system).

If you're using the Widget, refer to the [Widget Configuration](../widget/configuration#routeconfig).

Note that enabling Go Fast prioritizes speed over lower fees. For more cost-efficient routes, it's recommended to leave Go Fast disabled.


# Cross-chain Failure Cases
Source: https://skip-go.mintlify-go.com/go/advanced-transfer/handling-cross-chain-failure-cases

This page covers the different ways our cross-chain swaps + transfers might fail to help identify failures and manage user expectations

## Failures during IBC Transfers and Swaps

There are two types of IBC failures that may occur when a user attempts to traverse a swap / transfer route produced by the Skip Go API.

1. **Pre-Swap / swap failures**
   * **What:**  These are failures in the sequence of ICS-20 transfers leading up to the swap or a failure in the swap itself (usually due to slippage).
   * **Outcome / What to Expect:**  The users' original source tokens are returned their starting address on the source chain
   * **Common causes:**
     * Inactive relayers on a channel allow a packet to timeout
     * Slippage (the amount out for the swap turns out to be less than the user's specified minimum, i.e. their slippage exceeds their tolerance)
     * The user / frontend provides an invalid recovery address
     * An IBC client on the destination chain has expired
   * **Examples:** Consider a route where the source asset is ATOM on Neutron, the destination asset is STRIDE on Stride, and the swap takes place on Osmosis:
     * The user's tokens transfer from Neutron to the Hub to Osmosis. The swap initiates but the price of STRIDE has gotten so high that the swap exceeds slippage tolerance and fails. A sequence of error acks is propagated back to the Hub then Neutron, releasing the user’s ATOM to their address on Neutron where they started
     * The user attempts to transfer tokens from Neutron to the hub, but the packet isn't picked up by a relayer for more than 5 minutes (past the timeout\_timestamp). When a relayer finally comes online, it relays a timeout message to Neutron, releasing the user's ATOM back to their address on Neutron where they first had it.
   * **For transfer-only routes:** This is the only kind of failure that may happen on a route that only contains transfers. Either the user's tokens will reach their destination chain as intended, or they will wind up with the same tokens, on the same chain where they started.

<Frame>
  <img alt="In a pre-swap or swap related error, the user will end up with the same tokens they started with on their initial chain (e.g. ATOM on Neutron in this example)" />
</Frame>

2. **Post-swap failures:**
   * **Description**: These are failures that occur on the sequence of transfers between the swap venue chain and the user's destination chain, after the user's origin tokens have already been successfully swapped for their desired destination asset.
   * **Outcome / What to Expect**: The user's newly purchased destination asset tokens will be transferred to their address on the swap chain. (This is the address passed to `chains_to_addresses` in `/fungible/msgs` for the chain where the swap takes place, which is given by `swap_venue.chain_id` in the response from `/fungible/route`)
   * **Common failure sources:**
     * Inactive relayers on a channel allow a packet to timeout
     * The user / frontend provides an invalid address for the destination chain
     * An IBC client on the destination chain has expired
   * **Examples:** Consider a route where the source asset is ATOM on Neutron, the destination asset is STRIDE on Stride, and the swap takes place on Osmosis:
     * Suppose the swap took place and the transfer to Stride has been initiated, but the Relayer between Osmosis and Stride is down. So the packet’s timeout occurs after 5 minutes. When the Relayer comes back online after 8 minutes, it relays a timeout message to Osmosis, releasing the user’s STRIDE, which gets forwarded to their Osmosis address

<Frame>
  <img alt="In a post-swap error, the user will end up with their destination asset tokens in their address on the chain where the swap took place (e.g. STRIDE on Osmosis in this example)" />
</Frame>

## Axelar Failures

Axelar transfers can be tracked on [Axelarscan](https://axelarscan.io/). Often, Axelar transfers are delayed by Axelar's relayer or execution services. If a transaction is taking longer than expected, users can visit Axelarscan, find their transaction, and manually execute the steps needed to get the transfer through. See the [Axelar docs](https://docs.axelar.dev/dev/general-message-passing/recovery) for details on how to use Axelarscan.

Internally, the Skip Go API may use Axelar's General Message Passing service to move assets between EVM and Cosmos. There are similar failure modes for Axelar as there are for IBC:

1. **Swap failures**
   * **What:**  Axelar GMP takes user assets from an EVM chain to the swap chain. The swap can still fail at this point due to a timeout or slippage.
   * **Outcome / What to Expect:**  The user receives the Axelar-transferred token on the chain where the swap was supposed to take place at their recovery address. (Note this is different from the IBC swap failure case where the user receives the swap token back on the source chain)
   * **Common failure sources:**
     * Slow relaying from Axelar causes a timeout, and the swap is not attempted.
     * Slippage (the amount out for the swap turns out to be less than the user's specified minimum, i.e. their slippage exceeds their tolerance)
2. **Post-swap failures**
   * Once the swap is executed, Axelar is no longer involved, and the same rules that apply to IBC post-swap failures apply here, so the **Post-swap failures** section above applies.

## CCTP Failures

Routes that use CCTP transfers rely on Circle to produce attestations. The Circle attestation service waits for a specified number of on-chain block confirmations before producing an attestation. The number of block confirmations required is specified by Circle in their documentation [here](https://developers.circle.com/stablecoins/docs/required-block-confirmations).

If Circle's attestation service experiences an outage, malfunction, or otherwise becomes unresponsive, CCTP transfers will continue to burn assets on the source chain, but will not be able to mint assets on the destination chain. In this case, funds that have been burned to initiate a CCTP transfer will be inaccessible until the Circle attestation service recovers.

## Hyperlane Failures

Each Hyperlane token transfer route is secured by an Interchain Security Module (ISM) designated by the deployer of the Hyperlane Warp Route Contracts (the interface to send tokens across chains using Hyperlane). The ISM defines the requirements for a message to be successfully processed on the destination chain.

The most common ISM is a Multisig ISM where "Validators" of a specific Hyperlane route sign attestations that a specific message on an origin chain is a valid message to be processed on the destination chain. In the case where the set of Validators have not hit the required signature threshold to successfully process a Hyperlane message on the receiving chain, funds will not be accessible by the user on either chain until the threshold is met (once met, funds will be sent to the user on the destination chain). This generalizes to the different requirements for different ISMs. The Hyperlane documentation explains the different types of ISMs in more detail: [https://docs.hyperlane.xyz/docs/reference/ISM/specify-your-ISM](https://docs.hyperlane.xyz/docs/reference/ISM/specify-your-ISM)

## Go Fast Failures

If a transfer timeout occurs, meaning a user's intent does not receive a response from solvers within a predefined time frame, the solver initiates a refund process to ensure that users do not lose funds.

Here's a breakdown of what happens in the event of a timeout:

1. Intent Expiration: When a user initiates an intent by calling the `submitOrder` function on the source chain, a time limit is specified. Solvers monitor the intent and assess whether they can fulfill it within this period. If no solver fills the intent before the timeout, the refund process begins.

2. Refunds: Once the timeout period is reached without fulfillment, the solver calls a function on the contract to trigger a refund process. This is handled on-chain, and includes any fees initially allocated from the user for solver compensation.

<Warning>
  **Failures might occur for each transaction in a multi-tx sequence**

  In the event of a multi-tx route, each transaction may suffer from the kinds of failures noted above. This means it's technically inaccurate to say that tokens will always end up on the initial chain or the chain where the swap takes place. More accurately, tokens may end up on each chain where a transaction is initiated or the chain where the swap takes place.

  For instance, if a pre-swap failure takes place on the second transaction in a sequence, the tokens will end up on the chain that transaction targeted. In our example above, if the transfer from Cosmos Hub to Osmosis required a separate user transaction and the Neutron to Hub leg of the route succeeded in the first transaction, the ATOM tokens would end up in the user's account on the Hub if the swap exceeds maximum slippage.
</Warning>

<Check>
  **We're working to make these failures even less common**

  * In the short term, we're working to add packet tracking + live relayer + client status to the API to help identify when packets get stuck and prevent folks from using channels where they're likely to get stuck in the first place
  * In the medium term, we are working to add priority multi-hop relaying into the API.
  * In the long term, we're working to build better incentives for relaying, so relayers don't need to run as charities. (Relayers do not receive fees or payment of any kind today and subsidize gas for users cross-chain)
</Check>

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# IBC Token Routing: Problem + Skip Go API Routing Algorithm
Source: https://skip-go.mintlify-go.com/go/advanced-transfer/ibc-routing-algorithm

This page describes the IBC token routing problem and the algorithm Skip Go API uses to select / recommend token denoms and IBC paths

<Info>
  **tl;dr**

  The routing problem:

  1. IBC tags assets based on the sequence of IBC channels they have been transferred over, so the same asset transferred over two different paths will have two different denoms
  2. Usually, there's only 1 "correct" (i.e. highly liquid) version of each asset on each chain (and frequently there are none)

  Skip Go API solves this problem by:

  1. Sending assets to their origin chain
  2. Find the shortest path from the origin chain to the destination chain, and using the most liquid path when there are multiple distinct shortest paths.
  3. Plus, staying flexible to unusual exceptions
</Info>

## Routing Problem

### IBC Tokens Get Their Names & Identities from Their Paths

IBC transfers data over "channels" that connect two chains. Channels are identified by human-readable port names (e.g. "transfer") and channel IDs (e.g. channel-1). For example, consider a transfer channel between Terra2 and Axelar:

<Frame>
  <img alt="" />
</Frame>

*Notice that both chains maintain their own channel IDs for the channel, which might not be the same. As an analogy, you might think of the different chains as cities and the channel as a road connecting them. IBC packets are cars driving across the road*

When transferring a fungible token from one chain to another over a channel, the denomination of the token on the destination chain is uniquely and predictably determined by the source denomination + the channel(s) over which the token was transferred. Specifically the denomination algorithm is:

```text Naming Algorithm  theme={null}
ibc_denom = 'ibc/' + hash('path' + 'base_denom')
```

*`hash` is typically the sha256 hash function*

Continuing the example from above, the denom of this version of WETH.axl on Terra2 is:

```text axlWETH on Terra2 theme={null}
axlweth_on_terra2_denom = 'ibc/' + hash('transfer/channel-6/weth-wei')
axlweth_on_terra2_denom = 'ibc/BC8A77AFBD872FDC32A348D3FB10CC09277C266CFE52081DE341C7EC6752E674'
```

### So Different Paths Produce Different Tokens

Now that you understand that IBC denoms get their names from their paths, you understand the crux of the routing problem: **The same asset transferred to the same destination over two different paths will have different denominations.**

Continuing the example from above, WETH.axl transferred directly from Axelar to Terra2 will have a different denom than WETH.axl transferred through Osmosis:

<Frame>
  <img alt="" />
</Frame>

To make matters worse, multiple channels can exist between the same two chains (IBC is permissionless afterall), and IBC uses channel identifiers--not chain identifiers--to construct denoms. That means two different versions of the same asset will exist on the destination chain even when tokens are transferred from the same source chain, if they're transferred over two different channels:

<Frame>
  <img alt="" />
</Frame>

<Warning>
  **Why don't we just consider them equivalent anyway and move on?**

  Some folks who don’t work with bridges on a regular basis view this path tagging as a bug, or might think we should just consider these different versions of the same asset as fungible anyway. But that's not advisable!

  The route-based denom construction is a critical security feature because the chain where the token has been transferred to is effectively trusting the validator set of the chain from which the token was transferred.

  Applied to the example here, this trust model means using the purple version of WETH.axl implies trusting the Osmosis validator set AND the Axelar validator set, while using the blue version of WETH.axl only requires trusting the Axelar validator set.
</Warning>

### There are many paths between two chains, but usually only 1 useful version of each asset

Right now, there are about 70 IBC-enabled chains. At least one channel exists between almost every pair in this set. This dense graph of channels contains a very large number of different paths between almost any two chains, which creates many opportunities for "token winding" or "mis-pathing", where a user sends an asset through a suboptimal path of channels from one chain to another and ends up with an illiquid / unusable version of their token.

Mis-pathing almost always produces a practically useless + illiquid version of their token on the destination chain because there's usually only 1 useful version of a given asset on a given destination chain (if that). (There are over 50 versions of ATOM on JUNO!)

As a result, we need to be very careful to send the user through the correct sequence of channels. The next section explains our token routing algorithm.

## Routing Algorithm

<Info>
  **Insight about routing: The correct route depends on the chains + the asset in question**

  Notice that the correct route for a particular asset A on a particular chain Chain-1 to another chain Chain-2 depends not only on the channels that exist between chain-1 and chain-2, but also on what asset-A is.

  This is because asset A is defined by its path from its origin. Consider the following two cases:

  * If asset-A is native to Chain-1, perhaps it can be routed directly over a channel to Chain-2. This would yield a simple asset given by path of Chain-1->Chain-2
  * If asset-A originated on another chain (e.g. Chain-3), it's very unlikely that transferring directly over a channel to Chain-2 would give the correct version of asset A on Chain-2. This would yield a more complex denom given by path of Chain-3->Chain-1->Chain-2, which is probably wrong if Chain-3 and Chain-2 are directly connected.
    * Instead, the asset should probably be routed back through the channel that connects Chain-1 to Chain-3 first, then sent over the channel to Chain-2. This yields a path of Chain-1->Chain-3->Chain-2, and a final denom given by the path Chain-3->Chain-2
</Info>

Ultimately, we use a very simple routing algorithm:

1. Route the given asset back to origin chain (i.e. "unwind" it)
2. Check whether any *high-priority* manual overrides exist for the given asset on the given destination chain. If so, recommend the path from the source that produces this *high-priority* version of the asset
3. If no *high priority* manual overrides exist:
   1. If at least 1 single-hop path to the destination chain exists (i.e. if origin chain and destination chain are directly connected over IBC), recommend the most liquid direct path.
   2. If no direct path exists (or if the client on the direct path is expired, or none of the asset has been transferred over the direct path), do not recommend any asset

A few notes about our data collection:

* We run nodes for every supported chain to ensure we always have low-latency access to high quality data
* We index client + channel status of every channel + client on all the chains we support every couple of hours to ensure we never recommend a path that relayers have abandoned or forgotten about.
* We index the liquidity of every token transferred over every channel on every Cosmos chain every few hours to ensure our liquidity data is up to date. And we closely monitor anomalous, short-term liquidity movements to prevent attacks


# Interpreting Transaction & Transfer Status
Source: https://skip-go.mintlify-go.com/go/advanced-transfer/interpreting-transaction-status

Learn how to interpret the status of transactions and individual transfer steps from the Skip Go API's /v2/tx/status endpoint to provide accurate feedback to users.

<Info>
  The fields and logic discussed in this guide pertain to the JSON response object from the `/v2/tx/status` endpoint of the Skip Go API. Refer to the [API Reference](/go/api-reference/prod/transaction/get-v2txstatus) for detailed schema information.
</Info>

Understanding the status of a cross-chain transaction and its individual steps is crucial for building a clear and reliable user experience. This guide explains how to interpret the relevant fields from the `/v2/tx/status` API response to determine if a transaction (and each of its constituent transfers) is pending, successful, has encountered an error, or has been abandoned.

This approach is useful for driving UI elements such as progress indicators, status messages, and error displays in your application.

### Example `/v2/tx/status` Response

Below is an example of a JSON response from the `/v2/tx/status` endpoint, illustrating some of the key fields discussed in this guide:

```json theme={null}
{
  "state": "STATE_COMPLETED_SUCCESS",
  "transfer_sequence": [
    {
      "cctp_transfer": {
        "from_chain_id": "42161",
        "to_chain_id": "8453",
        "state": "CCTP_TRANSFER_RECEIVED",
        "txs": {
          "send_tx": {
            "chain_id": "42161",
            "tx_hash": "0xYOUR_SEND_TRANSACTION_HASH_HERE_...",
            "explorer_link": "https://arbiscan.io/tx/0xYOUR_SEND_TRANSACTION_HASH_HERE_..."
          },
          "receive_tx": {
            "chain_id": "8453",
            "tx_hash": "0xYOUR_RECEIVE_TRANSACTION_HASH_HERE_...",
            "explorer_link": "https://basescan.org/tx/0xYOUR_RECEIVE_TRANSACTION_HASH_HERE_..."
          }
        },
        "src_chain_id": "42161",
        "dst_chain_id": "8453"
      }
    }
  ],
  "next_blocking_transfer": null,
  "transfer_asset_release": {
    "chain_id": "8453",
    "denom": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "amount": "YOUR_EXAMPLE_AMOUNT",
    "released": true
  },
  "error": null
}
```

## Core Concepts for Status Interpretation

The logic relies on a few key pieces of information typically available in the `/v2/tx/status` API response object:

1. **The Overall Transaction Status:** This provides a high-level view of the entire multi-step operation.
   * Look at the top-level `state` field in the response.
   * Possible values include:
     * `'STATE_COMPLETED_SUCCESS'`: The entire transaction finished successfully.
     * `'STATE_COMPLETED_ERROR'`: The transaction finished, but an error occurred.
     * `'STATE_ABANDONED'`: The transaction was abandoned (e.g., due to timeout or user action).
   * If the state is not one of these terminal states, it's generally assumed to be pending or in progress.

2. **The Next Blocking Step (or Failure Point):** This indicates which specific transfer in the sequence is currently active, or which one caused a failure or abandonment.
   * Utilize the `next_blocking_transfer.transfer_sequence_index` field (if `next_blocking_transfer` exists in the response).
   * This will be an index pointing to an operation within the top-level `transfer_sequence` array.

3. **Categorizing Each Operation in the Sequence:** For each operation within the `transfer_sequence` array of the response, you can determine its individual status:

   * **Loading/Pending:**
     * The operation's index matches the `next_blocking_transfer.transfer_sequence_index` (if `next_blocking_transfer` exists).
     * AND the overall transaction is still in progress (i.e., the top-level `state` is not `STATE_COMPLETED_ERROR` or `STATE_ABANDONED`).

   * **Error/Failed/Abandoned:**
     * The operation's index matches the `next_blocking_transfer.transfer_sequence_index` (if `next_blocking_transfer` exists - it is typically `null` if the overall `state` is terminal (e.g., `STATE_COMPLETED_SUCCESS`, `STATE_COMPLETED_ERROR`, or `STATE_ABANDONED`) as the transaction is no longer actively blocked or has finished successfully).
     * AND the overall transaction state (the top-level `state` field) is `STATE_COMPLETED_ERROR` or `STATE_ABANDONED`.
     * Additionally, if the overall transaction state is `STATE_COMPLETED_ERROR` and this is the *last* operation in the sequence, it is also considered to be in an error state.
     * **Note:** If the overall transaction `state` is `STATE_COMPLETED_ERROR`, it's also crucial to inspect the specific `error` object within each individual transfer step in the `transfer_sequence` (e.g., `step.ibc_transfer.packet_txs.error`, `step.cctp_transfer.error`, etc.). This will help pinpoint the exact leg(s) that encountered issues, as the `next_blocking_transfer` might be `null` if the transaction reached a terminal error state rather than getting stuck midway.

   * **Success:**
     * If the overall transaction state (top-level `state` field) is `STATE_COMPLETED_SUCCESS`, then all operations in the sequence are considered successful.
     * If the overall transaction is still in progress, or has failed/been abandoned, any operation *before* the `next_blocking_transfer.transfer_sequence_index` (if `next_blocking_transfer` exists - see note above about it typically being `null` in terminal states) is assumed to have completed successfully.

## Example Implementation Logic (JavaScript)

The following JavaScript snippet demonstrates how these concepts can be translated into code to determine the status of each step.

```javascript theme={null}
// Assume 'transfer' is the main transaction object from our API
// and 'totalSteps' is the length of transfer.transfer_sequence

// 1. Determine overall transaction status from the main transaction object
const isTransactionSuccessful = transfer.state === 'STATE_COMPLETED_SUCCESS';
const isTransactionFailed = transfer.state === 'STATE_COMPLETED_ERROR';
const isTransactionAbandoned = transfer.state === 'STATE_ABANDONED';

// 2. Get the index of the step that is currently blocking progress or has failed
const nextBlockingIndex = transfer.next_blocking_transfer?.transfer_sequence_index;

// Then, when we process each 'step' in the 'transfer.transfer_sequence' at a given 'index':
// (This logic would typically be inside a loop, e.g., transfer.transfer_sequence.forEach((step, index) => { ... }))

// 3. Categorize the current step:

// Is this step currently "pending" (loading)?
const isStepPending = index === nextBlockingIndex && 
                      !isTransactionFailed && 
                      !isTransactionAbandoned;

// Is this step in an "error" state (or part of an abandoned flow)?
// 'totalSteps' would be transfer.transfer_sequence.length
const isStepAbandonedOrFailed = (isTransactionAbandoned || isTransactionFailed) && 
                                (index === nextBlockingIndex || (index === totalSteps - 1 && isTransactionFailed));

// If 'isTransactionSuccessful' is true, this step is part of an overall successful transaction.
// If a step isn't 'isStepPending' and isn't 'isStepAbandonedOrFailed', 
// and its 'index < nextBlockingIndex' (for an ongoing or failed tx), it's also implicitly a success.

// These boolean flags (isStepPending, isStepAbandonedOrFailed, isTransactionSuccessful)
// are then used to drive the UI styling for that specific step (e.g., node color, edge animation, icons).
// For example:
// if (isStepAbandonedOrFailed) { /* show error UI */ }
// else if (isStepPending) { /* show loading UI */ }
// else { /* show success UI (either part of overall success, or completed before a pending/error state) */ }
```

By implementing logic based on these fields and states, you can provide users with accurate and timely feedback on the progress of their cross-chain transactions.

## Understanding Asset Release (`transfer_asset_release`)

The `transfer_asset_release` object in the `/v2/tx/status` response provides crucial information about where the user's assets have ultimately landed or are expected to be claimable, especially in scenarios involving swaps or complex routes.

Key fields include:

* `chain_id`: The chain ID where the assets are located.
* `denom`: The denomination (asset identifier) of the released assets.
* `amount`: The quantity of the released assets.
* `released`: A boolean indicating if the assets have been definitively released to the user (e.g., available in their wallet or claimable). If `false`, it might indicate that assets are still in a contract or awaiting a final step for release.

In the event of a cross-chain swap failure, the `transfer_asset_release` field is particularly important for determining the location and state of the user's funds. For a comprehensive understanding of how assets are handled in different failure scenarios (e.g., pre-swap vs. post-swap failures), please refer to our detailed guide on [Handling Cross-Chain Failure Cases](./handling-cross-chain-failure-cases.mdx).


# SVM Transactions
Source: https://skip-go.mintlify-go.com/go/advanced-transfer/svm-transaction-details

This document explains how to use Skip Go API and Client TypeScript Package to construct SVM transactions.

## Intro

* When a user needs to transfer or swap from an SVM chain (e.g. Solana), the Skip Go API will return an `SvmTx` type for the developer to pass to the user for signing
* This doc is intended for CosmosSDK and EVM developers who aren't already familiar with the concepts of transaction construction in the SVM and need to use `SvmTx` to help their users move from/to Solana and other SVM chains.
* **Due to the difficult nature of including Solana transactions on chain during times of high network congestion, we HIGHLY recommend using the `/submit` endpoint to avoid dealing with complex retry logic and/or multiple RPC providers for submission reliability. Skip Go API's `/submit` endpoint implements best practices for Solana transactions submission for you!**

## Interact with Solana Wallets

We recommend using [@solana/wallet-adapter](https://github.com/anza-xyz/wallet-adapter#readme) to interact with Solana wallets and build transactions. It provides a standardized `Adapter` object that wraps all major Solana wallets (e.g. Phantom, Backpack, etc...), as well as visual React components for wallet selection. See [here](https://github.com/anza-xyz/wallet-adapter/blob/master/PACKAGES.md) for all the supported wallets.

## Set up the `SkipClient` to use a Solana wallet

All you need to do is initialize the `getSVMSigner` method in `SkipClient.options` to extract the `@solana/wallet-adapter-base` from the user's connected wallet of choice:

```TypeScript TypeScript theme={null}
import { useWallet } from "@solana/wallet-adapter-react";
import { PhantomWalletName } from "@solana/wallet-adapter-phantom"
import { SkipClient } from '@skip-go/client';

const { wallets } = useWallet();

const skipClient = new SkipClient({
  getSVMSigner: async (chainID) => {
		const { svm } = trackWallet.get();
		const solanaWallet = wallets.find((w) => w.adapter.name === PhantomWalletName);
    return solanaWallet
  }
});
```

After this point, you can use `route`, `executeRoute`, and the other methods of `SkipClient` as you normally would.

The rest of these docs cover the underlying details of the data structures, in case you need them.

## Understand `SvmTx` Data Structure

The `SvmTx` has 2 fields that the developer needs to understand:

* `chain_id`: The ID of the chain that this transaction should be submitted to
* `tx`: This is the base64 encoded bytes of the transaction you should have the end user sign.

### Info on `SvmTx.tx`

This is a fully constructed transaction. You don't need to change it or add anything to it to prepare it for signing. You just need to sign it and have the user submit it on chain within about 1 minute (or the nonce will expire).

For more detail, the transaction already includes:

* User's nonce (In Solana, this is actually a recent blockhash by default)
* Instructions (Solana's equivalent to messages)
* Base transaction fees (Set to the default of 500 lamports per signature)
* Priority fees (More info on how we set these below)

For more information on transactions, check out the Solana's official [docs](https://solana.com/docs/core/transactions)

#### Signing `tx`

[Skip Go Client](https://www.npmjs.com/package/@skip-go/client) takes care of all of the complexity of signing the transaction that gets returned in `SvmTx.tx`.

You just need to have set the `getSVMSigner` method in the `SkipClientOptions` object in the `SkipClient` constructor then use `executeRoute` or `executeTxs`.

#### How Priority Fees are Set

Solana "priority fees" affect how likely it is a transaction gets included in a block. Unlike for many other major blockchain networks, Solana's priority fees are evaluated "locally". In other words, the size of the fee is compared to other transactions that access the same pieces of state (e.g. the same DEX pool, the same token contract etc...):

* If the fee is low relative to other transactions that access the same state, the transaction is unlikely to get included.
* If its high relative to these other transactions accessing similar state, its likely to be included

As a result, transactions that touch "congested" or "popular" state will be the most expensive.

At this time, we are setting priority fees to match the 90% percentile of priority fees for the "wif" pool state on Jupiter, which we believe is highly congested state. This is a very conservative setting, but it even with these "high amounts", fees are still fractions of a cent.

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# API Error Codes & Status Messages
Source: https://skip-go.mintlify-go.com/go/api-reference/error-codes

Reference for error codes and status messages returned by the Skip Go API, including transaction, bridge, and packet-specific statuses.

This document provides a reference for the various error codes and status messages you may encounter when using Skip Go's APIs. Understanding these codes is essential for handling API responses correctly and providing accurate feedback to users.

## Transaction Status Codes

These codes represent the overall status of a transaction being processed or tracked by the Skip Go API.

| Status                    | Description                                                              | Notes                                                                                                 |
| ------------------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| `STATE_UNKNOWN`           | The status of the transaction is unknown.                                | Should be treated as an **error state**.                                                              |
| `STATE_SUBMITTED`         | The transaction has been submitted to the blockchain network.            |                                                                                                       |
| `STATE_PENDING`           | The transaction is in progress and waiting to be processed.              |                                                                                                       |
| `STATE_RECEIVED`          | The transaction has been received by the blockchain network.             |                                                                                                       |
| `STATE_COMPLETED`         | (Internal transitional state)                                            | This state is resolved to `STATE_COMPLETED_SUCCESS` or `STATE_COMPLETED_ERROR` before API response.   |
| `STATE_ABANDONED`         | The transaction was abandoned, often due to timeout (e.g., IBC relayer). | Tracking timed out. Not necessarily a permanent transaction failure; may be retriable.                |
| `STATE_COMPLETED_SUCCESS` | The transaction has completed successfully.                              | This is the **only** status that definitively indicates successful end-to-end transaction completion. |
| `STATE_COMPLETED_ERROR`   | The transaction has completed but encountered errors.                    |                                                                                                       |
| `STATE_PENDING_ERROR`     | The transaction encountered errors while being processed.                |                                                                                                       |

## General Error Types

These error types provide a broad categorization of issues.

| Error Type                           | Description                                                               |
| ------------------------------------ | ------------------------------------------------------------------------- |
| `STATUS_ERROR_UNKNOWN`               | Unknown error type.                                                       |
| `STATUS_ERROR_TRANSACTION_EXECUTION` | Error occurred during the execution of the transaction on the blockchain. |
| `STATUS_ERROR_INDEXING`              | Error occurred during Skip's internal processing or indexing.             |
| `STATUS_ERROR_TRANSFER`              | Error related to a specific transfer operation within the transaction.    |

## Bridge Protocol Status Codes

Different bridge protocols have their own specific status codes that reflect the state of a transfer leg using that bridge.

### IBC Transfer Status

| Status              | Description                                                  |
| ------------------- | ------------------------------------------------------------ |
| `TRANSFER_UNKNOWN`  | The status of the IBC transfer is unknown.                   |
| `TRANSFER_PENDING`  | The IBC transfer is in progress.                             |
| `TRANSFER_RECEIVED` | The IBC transfer has been received by the destination chain. |
| `TRANSFER_SUCCESS`  | The IBC transfer has completed successfully.                 |
| `TRANSFER_FAILURE`  | The IBC transfer has failed.                                 |

### Axelar Transfer Status

| Status                                 | Description                                      |
| -------------------------------------- | ------------------------------------------------ |
| `AXELAR_TRANSFER_UNKNOWN`              | The status of the Axelar transfer is unknown.    |
| `AXELAR_TRANSFER_PENDING_CONFIRMATION` | The Axelar transfer is waiting for confirmation. |
| `AXELAR_TRANSFER_PENDING_RECEIPT`      | The Axelar transfer is waiting for receipt.      |
| `AXELAR_TRANSFER_SUCCESS`              | The Axelar transfer has completed successfully.  |
| `AXELAR_TRANSFER_FAILURE`              | The Axelar transfer has failed.                  |

### CCTP Transfer Status

| Status                               | Description                                             |
| ------------------------------------ | ------------------------------------------------------- |
| `CCTP_TRANSFER_UNKNOWN`              | The status of the CCTP transfer is unknown.             |
| `CCTP_TRANSFER_SENT`                 | The CCTP transfer has been sent.                        |
| `CCTP_TRANSFER_PENDING_CONFIRMATION` | The CCTP transfer is waiting for confirmation.          |
| `CCTP_TRANSFER_CONFIRMED`            | The CCTP transfer has been confirmed.                   |
| `CCTP_TRANSFER_RECEIVED`             | The CCTP transfer has been received at the destination. |

### GoFast Transfer Status

| Status                       | Description                                                 |
| ---------------------------- | ----------------------------------------------------------- |
| `GO_FAST_TRANSFER_UNKNOWN`   | The status of the GoFast transfer is unknown.               |
| `GO_FAST_TRANSFER_SENT`      | The GoFast transfer has been sent.                          |
| `GO_FAST_POST_ACTION_FAILED` | The post-transfer action on the GoFast transfer has failed. |
| `GO_FAST_TRANSFER_TIMEOUT`   | The GoFast transfer has timed out.                          |
| `GO_FAST_TRANSFER_FILLED`    | The GoFast transfer has been filled.                        |
| `GO_FAST_TRANSFER_REFUNDED`  | The GoFast transfer has been refunded.                      |

### LayerZero Transfer Status

| Status                         | Description                                      |
| ------------------------------ | ------------------------------------------------ |
| `LAYER_ZERO_TRANSFER_UNKNOWN`  | The status of the LayerZero transfer is unknown. |
| `LAYER_ZERO_TRANSFER_SENT`     | The LayerZero transfer has been sent.            |
| `LAYER_ZERO_TRANSFER_RECEIVED` | The LayerZero transfer has been received.        |
| `LAYER_ZERO_TRANSFER_FAILED`   | The LayerZero transfer has failed.               |

### Hyperlane Transfer Status

| Status                        | Description                                      |
| ----------------------------- | ------------------------------------------------ |
| `HYPERLANE_TRANSFER_UNKNOWN`  | The status of the Hyperlane transfer is unknown. |
| `HYPERLANE_TRANSFER_SENT`     | The Hyperlane transfer has been sent.            |
| `HYPERLANE_TRANSFER_FAILED`   | The Hyperlane transfer has failed.               |
| `HYPERLANE_TRANSFER_RECEIVED` | The Hyperlane transfer has been received.        |

### OPInit Transfer Status

| Status                     | Description                                   |
| -------------------------- | --------------------------------------------- |
| `OPINIT_TRANSFER_UNKNOWN`  | The status of the OPInit transfer is unknown. |
| `OPINIT_TRANSFER_SENT`     | The OPInit transfer has been sent.            |
| `OPINIT_TRANSFER_RECEIVED` | The OPInit transfer has been received.        |

### Stargate Transfer Status

| Status                       | Description                                     |
| ---------------------------- | ----------------------------------------------- |
| `STARGATE_TRANSFER_UNKNOWN`  | The status of the Stargate transfer is unknown. |
| `STARGATE_TRANSFER_SENT`     | The Stargate transfer has been sent.            |
| `STARGATE_TRANSFER_RECEIVED` | The Stargate transfer has been received.        |
| `STARGATE_TRANSFER_FAILED`   | The Stargate transfer has failed.               |

### Eureka Transfer Status

The Eureka transfer status codes are identical to the IBC transfer status codes.

| Status              | Description                                                     |
| ------------------- | --------------------------------------------------------------- |
| `TRANSFER_UNKNOWN`  | The status of the Eureka transfer is unknown.                   |
| `TRANSFER_PENDING`  | The Eureka transfer is in progress.                             |
| `TRANSFER_RECEIVED` | The Eureka transfer has been received by the destination chain. |
| `TRANSFER_SUCCESS`  | The Eureka transfer has completed successfully.                 |
| `TRANSFER_FAILURE`  | The Eureka transfer has failed.                                 |

## Additional Error Types

### Packet Error Types

When dealing with IBC packets, you may see these error types:

| Error Type                     | Description                      |
| ------------------------------ | -------------------------------- |
| `PACKET_ERROR_UNKNOWN`         | Unknown packet error.            |
| `PACKET_ERROR_ACKNOWLEDGEMENT` | Error in packet acknowledgement. |
| `PACKET_ERROR_TIMEOUT`         | Packet timed out.                |

### Bridge-Specific Error Types

| Error Type                                 | Description                                             |
| ------------------------------------------ | ------------------------------------------------------- |
| `SEND_TOKEN_EXECUTION_ERROR`               | Error during Axelar send token execution.               |
| `CONTRACT_CALL_WITH_TOKEN_EXECUTION_ERROR` | Error during Axelar contract call with token execution. |


# Get /v2/fungible/assets
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/fungible/get-v2fungibleassets

swagger get /v2/fungible/assets
Get supported assets. Optionally limit to assets on a given chain and/or native assets.



# Get /v2/fungible/venues
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/fungible/get-v2fungiblevenues

swagger get /v2/fungible/venues
Get supported swap venues.



# Post /v2/fungible/assets_between_chains
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/fungible/post-v2fungibleassets_between_chains

swagger post /v2/fungible/assets_between_chains
Given 2 chain IDs, returns a list of equivalent assets that can be transferred



# Post /v2/fungible/assets_from_source
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/fungible/post-v2fungibleassets_from_source

swagger post /v2/fungible/assets_from_source
Get assets that can be reached from a source via transfers under different conditions (e.g. single vs multiple txs)



# Post /v2/fungible/ibc_origin_assets
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/fungible/post-v2fungibleibc_origin_assets

swagger post /v2/fungible/ibc_origin_assets
Get origin assets from a given list of denoms and chain IDs.



# Post /v2/fungible/msgs
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/fungible/post-v2fungiblemsgs

swagger post /v2/fungible/msgs
This supports cross-chain actions among EVM chains, Cosmos chains, and between them. Returns minimal number of messages required to execute a multi-chain swap or transfer. Input consists of the output of route with additional information required for message construction (e.g. destination addresses for each chain)



# Post /v2/fungible/msgs_direct
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/fungible/post-v2fungiblemsgs_direct

swagger post /v2/fungible/msgs_direct
This supports cross-chain actions among EVM chains, Cosmos chains, and between them. Returns minimal number of messages required to execute a multi-chain swap or transfer. This is a convenience endpoint that combines /route and /msgs into a single call.



# Post /v2/fungible/route
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/fungible/post-v2fungibleroute

swagger post /v2/fungible/route
This supports cross-chain actions among EVM chains, Cosmos chains, and between them. Returns the sequence of transfers and/or swaps to reach the given destination asset from the given source asset, along with estimated amount out. Commonly called before /msgs to generate route info and quote.



# Get /v2/info/bridges
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/info/get-v2infobridges

swagger get /v2/info/bridges
Get all supported bridges



# Get /v2/info/chains
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/info/get-v2infochains

swagger get /v2/info/chains
Get all supported chains along with additional data useful for building applications + frontends that interface with them (e.g. logo URI, IBC capabilities, fee assets, bech32 prefix, etc...)



# Post /v2/info/balances
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/info/post-v2infobalances

swagger post /v2/info/balances
Get the balances of a given set of assets on a given chain and wallet address. Compatible with all Skip Go-supported assets, excluding CW20 assets, across SVM, EVM, and Cosmos chains.



# Get /v2/tx/status
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/transaction/get-v2txstatus

swagger get /v2/tx/status
Get the status of the specified transaction and any subsequent IBC or Axelar transfers if routing assets cross chain. The transaction must have previously been submitted to either the /submit or /track endpoints.



# Post /v2/tx/submit
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/transaction/post-v2txsubmit

swagger post /v2/tx/submit
Submit a signed base64 encoded transaction to be broadcast to the specified network. On successful submission, the status of the transaction and any subsequent IBC or Axelar transfers can be queried through the /status endpoint.



# Post /v2/tx/track
Source: https://skip-go.mintlify-go.com/go/api-reference/prod/transaction/post-v2txtrack

swagger post /v2/tx/track
Requests tracking of a transaction that has already landed on-chain but was not broadcast through the Skip Go API. The status of a tracked transaction and subsequent IBC or Axelar transfers if routing assets cross chain can be queried through the /status endpoint.



# Advanced Features
Source: https://skip-go.mintlify-go.com/go/client/advanced-features

This page details advanced features and utilities in the Skip Go client library.

## Adding custom messages before or after route execution

The `executeRoute` method now accepts `beforeMsg` and `afterMsg`  parameter to allow for the execution of custom Cosmos messages before and/or after the route is executed. This is useful for executing custom messages that are not part of the route definition.

```typescript theme={null}
const msg = JSON.stringify({
  fromAddress: 'cosmos1...',  // Replace with sender address
  toAddress: 'cosmos1...',    // Replace with recipient address
  amount: [{
    denom: 'uatom',           // Replace with the actual denom, e.g., 'uatom' for ATOM
    amount: '1000000'         // Replace with the actual amount (in smallest unit, e.g., micro-ATOM)
  }]
});

await executeRoute({
  route,
  userAddresses,
  beforeMsg: { msg, msgTypeUrl: '/cosmos.bank.v1beta1.MsgSend' }
});
```

## Use the Go Fast Transfer system

The `route` function accepts a `goFast` parameter to enable the Go Fast Transfers. Then pass this route to the `executeRoute` method to execute.

```typescript theme={null}
import { executeRoute, route } from '@skip-go/client';

const route = await route({
  goFast: true
  ...otherParams,
});

await executeRoute({
  route,
  ...otherParams,
});
```

## Add a fee payer in solana transaction

The `executeRoute` method accepts a `svmFeePayer` parameter to specify a fee payer for Solana transactions. This is useful when you want to have a different account pay the transaction fees.

```typescript theme={null}
import { Keypair } from "@solana/web3.js";
import nacl from "tweetnacl";
import bs58 from "bs58";
import { executeRoute, route } from '@skip-go/client';


const route = await route({
  // ... other parameters
});

await executeRoute({
  route,
  userAddresses,
  svmFeePayer: {
    address: 'FEE_PAYER_ADDRESS.', // Replace with the fee payer's Solana address
    signTransaction: async (dataToSign: Buffer) => {
      // this is an example the fee payer signer is using a private key
      const privateKey = "FEE_PAYER_PRIVATE_KEY";
      const keypairBytes = bs58.decode(privateKey);
      const keypair = Keypair.fromSecretKey(keypairBytes);
      return nacl.sign.detached(dataToSign, keypair.secretKey);
    },
  }
  ...otherParams,
})
```


# Balances, Gas and Transaction Fee Utilities
Source: https://skip-go.mintlify-go.com/go/client/balance-gas-and-fee-tooling

This page details the utility functions for token balances, gas calculations, and transaction fees in Skip Go.

## Getting token balances

To query token balances, you can use the `balances` function or via the [REST API](https://docs.skip.build/go/api-reference/prod/info/post-v2infobalances). You have the option to specify a set of token denoms to query or leave the array empty to fetch balances for all denoms associated with an address.

* **When no denoms are specified**: The response will include only the denoms for which you have a balance.
* **When denoms are specified**: The response will include balances for all the specified denoms. If you have no balance for a given denom, it will be included with a balance of zero.

If there is an error fetching a given denom (e.g. the chain is down), the response will include an error message for that denom.

<Warning>
  The balance query is currently compatible with all Skip Go-supported assets, excluding cw20 assets, across svm, evm, and Cosmos chains.
</Warning>

<CodeGroup>
  ```ts TypeScript (Client) theme={null}
  const balances = await balances({
    chains: {
    "noble-1": {
      address: noble.address, // noblef8js...
      denoms: ["uusdc"]
    },
    "osmosis-1": {
      address: osmosis.address, // osmois8fo...
      denoms: [] // Fetch all denoms for address
    },
    apiUrl: "https://api.skip.build"
  }
  });
  ```

  ```JSON JSON (REST API) theme={null}
  // POST /v2/info/balances
  {
    "chains": {
      "137": {
        "address": "0x24a9267cE9e0a8F4467B584FDDa12baf1Df772B5",
        "denoms": [
          "polygon-native",
          "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
        ]
      },
      "osmosis-1": {
        "address": "osmo12xufazw43lanl8dkvf3l7y9zzm8n3zswftw2yc",
        "denoms": [] // Fetch all denoms for address
      }
    }
  }
  ```
</CodeGroup>

## Getting info about gas and fees

<Info>
  **Video Overview**

  Here's a [video overview](https://www.loom.com/share/063e96e126d2422bb621b5b0ecf9be2c) of our gas and transaction fee tooling.
</Info>

These functions are useful for getting information about our default gas and fee values or for estimating the fee for a particular transaction (e.g. so you can build a working MAX button).

### `getRecommendedGasPrice`

This returns the gas price (i.e. the price of a single unit of gas) the API recommends you use for transactions on a particular chain.

```ts theme={null}
async getRecommendedGasPrice({chainId, apiUrl, apiKey}: {chainId: string, apiUrl?:string, apiKey?: string}) -> GasPrice
```

`GasPrice` is a [cosmjs](https://cosmos.github.io/cosmjs/latest/stargate/classes/GasPrice.html) type giving the recommended fee denom and recommend price amount (fee/gas):

```ts theme={null}
type GasPrice = {
  denom: string;
  amount: Decimal
}
```

### `getFeeInfoForChain`

This will return high, medium, and low gas prices for a particular chain, given by `chainId`, along with the default fee denom as a `FeeAsset` object:

```ts theme={null}
async getFeeInfoForChain({chainId, apiUrl, apiKey}: {chainId: string, apiUrl?:string, apiKey?: string}) -> FeeAsset
```

```ts theme={null}
type FeeAsset = {
  denom: string;
  gasPrice: GasPriceInfo;
};

type GasPriceInfo = {
  low: string;
  average: string;
  high: string;
};
```

An undefined response indicates that the API cannot find up-to-date gas price information for the chain.

## Settings on `ExecuteRouteOptions` for customizing how gas & fees are set on transactions

### `ExecuteRouteOptions.getGasPrice`

This field in `ExecuteRouteOptions` allows you to override our default gas price on a per chain basis for any transactions created in the router (e.g. in `executeRoute`):

`getGasPrice?: (chainId: string) => Promise<GasPrice | undefined>;`

The argument is a function that takes in a chain ID and returns a gas price for that chain as a `GasPrice` object from CosmJS

```ts theme={null}
type GasPrice = {
  denom: string;
  amount: Decimal
}
```

If you provide a function that only returns a price for a subset of chains, the router will use its default price in cases where yours is missing. If it can't find a default price for a chain, it will error.

### `ExecuteRouteOptions.gasAmountMultiplier`

This field in `ExecuteRouteOptions` allows you to override the default gas multiplier used by default in the SDK. The default value is 1.5. Increasing this value provides higher confidence that transactions will not run out of gas while executing, but increases the fee for the end user.

The gas multiplier increases a transaction's `gasAmount` multiplicatively. To get a final gas amount, the router:

* Simulates a transaction to get an initial gasAmount
* Multiplies the gas consumed in the simulation by `gasAmountMultiplier`


# Executing a route
Source: https://skip-go.mintlify-go.com/go/client/executing-a-route

This page documents the executeRoute function, used to execute a token transfer/swap using a route from /v2/fungible/route API

## Executing a cross-chain route

The executeRoute function is used to execute a route, including optional support for simulating transactions, injecting custom Cosmos messages, and tracking transaction status.
You must provide a list of user addresses (one per chain in route.requiredChainAddresses), along with the route object returned from route (/v2/fungible/route).

<Info> This function handles validation of addresses and gas balances, prepares the route messages, and executes transactions in order across Cosmos, Evm, and Svm chains. </Info>

```ts theme={null}
async executeRoute(options: ExecuteRouteOptions): Promise<void>
```

## Required fields

`route` A RouteResponse containing swap or transfer operations.

`userAddresses` One user address per chain in the same order as route.requiredChainAddresses.

<Warning> All user addresses must match the chain ids expected in the route, and must be valid for the corresponding chain type (Cosmos, Evm, or Svm). An error will be thrown if the addresses are mismatched or malformed. </Warning>

`getCosmosSigner` Function that takes a chainId and returns a `Promise<OfflineSigner>`

`getEvmSigner` Function that takes a chainId and returns a `Promise<WalletClient>`

`getSvmSigner` Function that returns a `Promise<OfflineSigner>`

## Optional fields

`slippageTolerancePercent` Set the maximum slippage tolerance for the route (defaults to "1").

`simulate` Whether to simulate transactions before executing (defaults to true).

`batchSimulate` If true, simulate all transactions in a batch before execution; if false, simulate each transaction individually. (defaults to true).

`batchSignTxs` If true, all transactions in a multi-transaction route will be signed upfront before broadcasting; if false, each transaction will be signed individually just before broadcasting. (defaults to true).

`beforeMsg / afterMsg` Optional Cosmos messages to inject at the beginning or end of the route execution.

`useUnlimitedApproval` If true, sets Evm token allowances to MAX\_UINT256. (defaults to false).

`bypassApprovalCheck` If true, skips token approval checks on Evm. (defaults to false).

`timeoutSeconds` Time in seconds to wait for message preparation before timing out.

`getGasPrice` Override the gas price per chain.

`getFallbackGasAmount` Fallback gas to use if simulation fails.

`gasAmountMultiplier` Overrides the default simulation multiplier (default is 1.5).

`getCosmosPriorityFeeDenom` function that takes a chainId and returns a `Promise<string>` for the priority fee denom to use for Cosmos transactions.

example:

```ts theme={null}
await executeRoute({
  // ...executeRoute params
  getCosmosPriorityFeeDenom: async (chainId) => {
      // this will set the priority fee as ATOM for noble-1 chain
      if (chainId === "noble-1")
        return "ibc/EF48E6B1A1A19F47ECAEA62F5670C37C0580E86A9E88498B7E393EB6F49F33C0";
      return undefined;
    },
});
```

## Callbacks

You can optionally provide the following callbacks:

`onTransactionSignRequested` Called when a transaction is ready to be signed on the wallet.

`onTransactionBroadcast` Called after each transaction is broadcasted.

`onTransactionCompleted` Called after each transaction is confirmed.

`onTransactionTracked` Called during confirmation polling, useful for progress tracking uis.

`onValidateGasBalance` Called while the transaction is calculating the gas and balance validation

`onApproveAllownace` Called when the allowance tx is being executed (only in evm txs).

```ts theme={null}
await executeRoute({
  route,
  userAddresses: [
    { chainId: "osmosis-1", address: osmoAddress },
    { chainId: "ethereum", address: evmAddress },
  ],
  simulate: true,
  batchSignTxs: true,
  slippageTolerancePercent: "0.5",
  beforeMsg: cosmosMsg1,
  afterMsg: cosmosMsg2,
  getCosmosSigner: (chainId) => {},
  getEvmSigner: (chainId) => {},
  getSvmSigner: () => {},
  onTransactionBroadcast: ({ chainId, txHash }) => {
    console.log(`Broadcasted on ${chainId}: ${txHash}`);
  },
  onTransactionCompleted: ({ chainId, txHash, status }) => {
    console.log(`Completed on ${chainId}: ${txHash} (Status: ${status})`);
  },
  onTransactionTracked: ({ chainId, txHash, status }) => {
    console.log(`Tracking ${chainId}: ${txHash} (Status: ${status})`);
  },
  onTransactionSignRequested: ({ chainId, signerAddress }) => {
    console.log(`Sign requested for ${chainId}`, signerAddress);
  },
});
```


# Gas on Receive with Custom Frontends
Source: https://skip-go.mintlify-go.com/go/client/gas-on-receive

Implement Gas on Receive functionality in your custom frontend using the Skip Go Client Library

This guide explains how to implement Gas on Receive functionality when building custom frontends with the Skip Go Client Library. Gas on Receive helps users automatically obtain native gas tokens on destination chains during cross-chain swaps.

## Overview

Gas on Receive prevents users from getting "stuck" with assets they can't use by automatically providing a small amount of native gas tokens on the destination chain.

The client library provides the `getRouteWithGasOnReceive` function that handles all the complexity for you, or you can implement custom logic if you need specific behavior.

## Prerequisites

* Skip Go Client Library v1.5.0 or higher
* Understanding of the basic `route` and `executeRoute` functions
* Access to user wallet signers for multiple chains

### Supported Chains

* **Destination**: Cosmos chains and EVM L2s (Solana not supported)
* **Source**: Most chains except Ethereum mainnet and Sepolia testnet

## Quick Start: Using getRouteWithGasOnReceive

The simplest way to implement Gas on Receive is using the built-in `getRouteWithGasOnReceive` function:

```typescript theme={null}
import { 
  route, 
  getRouteWithGasOnReceive, 
  executeMultipleRoutes,
  executeRoute,
  type RouteRequest,
  type RouteResponse,
  type UserAddress
} from "@skip-go/client";

async function swapWithGasOnReceive() {
  try {
    // Step 1: Define your route request
    const routeRequest = {
      amountIn: "1000000", // 1 OSMO
      sourceAssetChainId: "osmosis-1",
      sourceAssetDenom: "uosmo",
      destAssetChainId: "42161", // Arbitrum
      destAssetDenom: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", // WETH
      smartRelay: true
    };

    // Step 2: Get your initial route
    const originalRoute = await route(routeRequest);

    // Step 3: Automatically split into main and gas routes
    const { mainRoute, gasRoute } = await getRouteWithGasOnReceive({
      routeResponse: originalRoute,
      routeRequest
    });

    // Step 4: Get user addresses based on required chains
    // Note: mainRoute and gasRoute may require different chains
    const mainRouteAddresses = mainRoute.requiredChainAddresses.map(chainId => ({
      chainId,
      address: getUserAddressForChain(chainId) // Your function to get user's address
    }));
    
    const gasRouteAddresses = gasRoute?.requiredChainAddresses.map(chainId => ({
      chainId, 
      address: getUserAddressForChain(chainId)
    }));
    
    // Example helper function:
    // function getUserAddressForChain(chainId: string): string {
    //   const addresses = {
    //     "osmosis-1": "osmo1...",
    //     "42161": "0x..."
    //   };
    //   return addresses[chainId] || throw new Error(`No address for chain ${chainId}`);
    // }

  // Step 5: Execute routes
  if (gasRoute && gasRouteAddresses) {
    // Execute both routes together
    await executeMultipleRoutes({
      route: { mainRoute, feeRoute: gasRoute },
      userAddresses: {
        mainRoute: mainRouteAddresses,
        feeRoute: gasRouteAddresses // May be different chains than mainRoute
      },
      slippageTolerancePercent: {
        mainRoute: "1",
        feeRoute: "10" // Higher tolerance for gas route
      },
      getCosmosSigningClient: async (chainId) => {
        return yourCosmosWallet.getSigningClient(chainId);
      },
      getEVMSigningClient: async (chainId) => {
        return yourEvmWallet.getSigningClient(chainId);
      },
      onRouteStatusUpdated: (status) => {
        console.log("Route status:", status);
        
        // Check if gas route failed
        const gasRouteFailed = status.relatedRoutes?.find(
          r => r.routeKey === "feeRoute" && r.status === "failed"
        );
        
        if (gasRouteFailed) {
          console.warn("Gas route failed, but main swap continues");
        }
      }
    });
  } else {
    // No gas route needed, execute original route
    await executeRoute({
      route: originalRoute,
      userAddresses: mainRouteAddresses,
      slippageTolerancePercent: "1",
      getCosmosSigningClient: async (chainId) => {
        return yourCosmosWallet.getSigningClient(chainId);
      },
      getEVMSigningClient: async (chainId) => {
        return yourEvmWallet.getSigningClient(chainId);
      }
    });
  } catch (error) {
    console.error("Failed to execute swap:", error);
    // Handle error appropriately
  }
}
```

### How getRouteWithGasOnReceive Works

The function automatically:

1. Checks if the destination chain is supported (excludes Solana chains)
2. Checks source chain support (excludes Ethereum mainnet and Sepolia testnet)
3. Verifies the destination asset isn't already a fee asset
4. Calculates appropriate gas amounts:
   * **Cosmos chains**: Average gas price × 3 (or \$0.10 USD fallback if gas price unavailable)
   * **EVM L2 chains**: \$2.00 USD worth of native tokens
5. Creates a gas route to obtain native tokens
6. Adjusts the main route amount accordingly
7. Returns both routes, or the original route as mainRoute if gas route creation fails

**Note**: If gas route creation fails for any reason, the function returns the original route as `mainRoute` with `gasRoute` as undefined, allowing your swap to proceed without gas-on-receive.

## Custom Implementation Guide

If you need to customize the Gas on Receive behavior beyond what `getRouteWithGasOnReceive` provides:

### Step 1: Check Destination Gas Balance

Before initiating a swap, check if the user has sufficient gas on the destination chain:

```typescript theme={null}
import { balances } from "@skip-go/client";

async function checkDestinationGasBalance(
  destinationChainId: string,
  userAddress: string,
  requiredGasAmount?: string
) {
  // Fetch user's balance on destination chain
  const userBalances = await balances({
    chains: {
      [destinationChainId]: { address: userAddress }
    }
  });

  const chainBalances = userBalances.chains?.[destinationChainId]?.denoms;
  
  // For EVM chains, check native token (address 0x0000...)
  const nativeTokenDenom = getNativeTokenDenom(destinationChainId);
  const nativeBalance = chainBalances?.[nativeTokenDenom];

  // Simple check: does user have any native token?
  if (!nativeBalance?.amount || nativeBalance.amount === "0") {
    return false;
  }

  // Optional: Check against a minimum threshold
  if (requiredGasAmount) {
    return Number(nativeBalance.amount) >= Number(requiredGasAmount);
  }

  return true;
}

function getNativeTokenDenom(chainId: string): string {
  // For EVM chains
  if (isEvmChain(chainId)) {
    return "0x0000000000000000000000000000000000000000";
  }
  
  // For Cosmos chains, you'll need to fetch the fee assets
  // This varies by chain (e.g., "uosmo" for Osmosis, "uatom" for Cosmos Hub)
  return getCosmosNativeDenom(chainId);
}
```

### Step 2: Calculate Gas Amount Needed

```typescript theme={null}
const GAS_AMOUNTS_USD = {
  cosmos: 0.10,    // $0.10 for Cosmos chains
  evm_l2: 2.00,    // $2.00 for EVM L2 chains
  evm_mainnet: 0   // Disabled for Ethereum mainnet
};

async function calculateGasAmount(
  sourceAsset: { chainId: string; denom: string },
  destinationChainId: string,
  sourceAssetPriceUsd: number
): Promise<string> {
  const chainType = await getChainType(destinationChainId);
  
  // Determine USD amount based on chain type
  let usdAmount = 0;
  if (chainType === 'cosmos') {
    usdAmount = GAS_AMOUNTS_USD.cosmos;
  } else if (chainType === 'evm' && destinationChainId !== "1") {
    usdAmount = GAS_AMOUNTS_USD.evm_l2;
  }
  
  if (usdAmount === 0) {
    throw new Error("Gas on Receive not supported for this chain");
  }
  
  // Convert USD amount to source asset amount
  const sourceAmount = usdAmount / sourceAssetPriceUsd;
  
  // Convert to crypto amount (considering decimals)
  const sourceAssetDecimals = await getAssetDecimals(sourceAsset);
  return convertToCryptoAmount(sourceAmount, sourceAssetDecimals);
}
```

### Step 3: Create Routes with Custom Logic

```typescript theme={null}
import { route } from "@skip-go/client";

async function createRoutesManually(
  amountIn: string,
  sourceAsset: { chainId: string; denom: string },
  destAsset: { chainId: string; denom: string },
  gasAmount: string,
  enableGasOnReceive: boolean
) {
  // Calculate adjusted amounts
  const gasRouteAmount = enableGasOnReceive ? gasAmount : "0";
  const mainRouteAmount = (Number(amountIn) - Number(gasRouteAmount)).toString();
  
  // Create main route with reduced amount
  const mainRoute = await route({
    amountIn: mainRouteAmount,
    sourceAssetChainId: sourceAsset.chainId,
    sourceAssetDenom: sourceAsset.denom,
    destAssetChainId: destAsset.chainId,
    destAssetDenom: destAsset.denom,
    smartRelay: true
  });
  
  // Create gas route only if enabled
  let gasRoute = null;
  if (enableGasOnReceive) {
    const nativeTokenDenom = getNativeTokenDenom(destAsset.chainId);
    
    gasRoute = await route({
      amountIn: gasRouteAmount,
      sourceAssetChainId: sourceAsset.chainId,
      sourceAssetDenom: sourceAsset.denom,
      destAssetChainId: destAsset.chainId,
      destAssetDenom: nativeTokenDenom,
      smartRelay: true
    });
  }
  
  return { mainRoute, gasRoute };
}
```

### Step 4: Execute Routes

```typescript theme={null}
import { executeMultipleRoutes, type RouteResponse, type UserAddress } from "@skip-go/client";

async function executeSwapWithGasOnReceive(
  mainRoute: RouteResponse,
  gasRoute: RouteResponse | null,
  userAddresses: UserAddress[],
  signers: {
    getCosmosSigningClient: (chainId: string) => Promise<any>;
    getEVMSigningClient: (chainId: string) => Promise<any>;
  }
) {
  // Build routes object with consistent naming
  const routes = gasRoute 
    ? { mainRoute, feeRoute: gasRoute }
    : { mainRoute };
  
  // Build user addresses object
  const addresses = gasRoute
    ? { mainRoute: userAddresses, feeRoute: userAddresses }
    : { mainRoute: userAddresses };
  
  // Build slippage settings
  const slippage = gasRoute
    ? { mainRoute: "1", feeRoute: "10" } // Higher tolerance for gas route
    : { mainRoute: "1" };
  
  // Execute both routes
  await executeMultipleRoutes({
    route: routes,
    userAddresses: addresses,
    slippageTolerancePercent: slippage,
    getCosmosSigningClient: signers.getCosmosSigningClient,
    getEVMSigningClient: signers.getEVMSigningClient,
    onRouteStatusUpdated: (status) => {
      // Handle route status updates
      console.log("Route status:", status);
      
      // Check if gas route failed
      const gasRouteFailed = status.relatedRoutes?.find(
        r => r.routeKey === "feeRoute" && r.status === "failed"
      );
      
      if (gasRouteFailed) {
        console.warn("Gas route failed, but main swap continues");
      }
    }
  });
}
```

## Complete Implementation Example

Here's a full example combining all the concepts:

```typescript theme={null}
import { 
  route, 
  executeMultipleRoutes, 
  balances,
  assets,
  getRouteWithGasOnReceive
} from "@skip-go/client";

class GasOnReceiveManager {
  private readonly GAS_AMOUNTS_USD = {
    cosmos: 0.10,
    evm_l2: 2.00
  };

  async shouldEnableGasOnReceive(
    destinationChainId: string,
    destinationAddress: string,
    destinationAssetDenom: string
  ): Promise<boolean> {
    // Check if chain is supported
    if (!this.isChainSupported(destinationChainId)) {
      return false;
    }
    
    // Don't enable if destination asset is already a gas token
    if (await this.isGasToken(destinationChainId, destinationAssetDenom)) {
      return false;
    }
    
    // Check user's gas balance
    const hasGas = await this.checkGasBalance(destinationChainId, destinationAddress);
    return !hasGas;
  }
  
  private isChainSupported(chainId: string): boolean {
    // Solana chains not supported for destination
    const unsupportedDestChains = ["solana", "solana-devnet"];
    // Ethereum mainnet and Sepolia not supported as source
    const unsupportedSourceChains = ["1", "11155111"];
    // For this example, checking destination support
    return !unsupportedDestChains.includes(chainId);
  }
  
  private async isGasToken(chainId: string, denom: string): boolean {
    const chainAssets = await assets({ chainId });
    const gasTokens = chainAssets.chain?.feeAssets || [];
    return gasTokens.some(token => token.denom === denom);
  }
  
  private async checkGasBalance(
    chainId: string, 
    address: string
  ): Promise<boolean> {
    const balanceResponse = await balances({
      chains: { [chainId]: { address } }
    });
    
    const nativeDenom = await this.getNativeDenom(chainId);
    const balance = balanceResponse?.chains?.[chainId]?.denoms?.[nativeDenom];
    
    // Check if user has any balance
    return balance?.amount && balance.amount !== "0";
  }
  
  async executeSwapWithGasOnReceive(
    params: {
      amountIn: string;
      sourceAsset: { chainId: string; denom: string };
      destAsset: { chainId: string; denom: string };
      userAddresses: Array<{ chainId: string; address: string }>;
      enableGasOnReceive: boolean;
      signers: any;
    }
  ) {
    const { 
      amountIn, 
      sourceAsset, 
      destAsset, 
      userAddresses, 
      enableGasOnReceive,
      signers 
    } = params;
    
    // Get initial route
    const originalRoute = await route({
      amountIn,
      sourceAssetChainId: sourceAsset.chainId,
      sourceAssetDenom: sourceAsset.denom,
      destAssetChainId: destAsset.chainId,
      destAssetDenom: destAsset.denom
    });
    
    if (enableGasOnReceive) {
      // Use automatic splitting
      const { mainRoute, gasRoute } = await getRouteWithGasOnReceive({
        routeResponse: originalRoute,
        routeRequest: {
          amountIn,
          sourceAssetChainId: sourceAsset.chainId,
          sourceAssetDenom: sourceAsset.denom,
          destAssetChainId: destAsset.chainId,
          destAssetDenom: destAsset.denom
        }
      });
      
      if (gasRoute) {
        // Execute both routes
        await executeMultipleRoutes({
          route: { mainRoute, feeRoute: gasRoute },
          userAddresses: { 
            mainRoute: userAddresses,
            feeRoute: userAddresses 
          },
          slippageTolerancePercent: {
            mainRoute: "1",
            feeRoute: "10"  // Higher tolerance for gas route
          },
          ...signers,
          onRouteStatusUpdated: this.handleRouteStatus
        });
      } else {
        // Execute just the main route
        await executeRoute({
          route: mainRoute,
          userAddresses,
          slippageTolerancePercent: "1",
          ...signers
        });
      }
    } else {
      // Execute original route without gas
      await executeRoute({
        route: originalRoute,
        userAddresses,
        slippageTolerancePercent: "1",
        ...signers
      });
    }
  }
  
  private handleRouteStatus(status: RouteStatus) {
    if (status.status === "completed") {
      console.log("Swap completed successfully");
    }
    
    // Check gas route status
    const gasRoute = status.relatedRoutes?.find(r => r.routeKey === "feeRoute");
    if (gasRoute?.status === "failed") {
      console.warn("Gas provision failed, but main swap continues");
    } else if (gasRoute?.status === "completed") {
      console.log("Gas tokens received successfully");
    }
  }
}
```

## UI Considerations

When implementing Gas on Receive in your UI:

### Display Gas Information

```typescript theme={null}
function GasOnReceiveToggle({ 
  enabled, 
  gasAmount, 
  gasAssetSymbol,
  onToggle 
}: GasOnReceiveProps) {
  return (
    <div className="gas-on-receive">
      <div className="gas-info">
        <GasIcon />
        <span>Enable gas top up - You'll get {gasAmount} in {gasAssetSymbol}</span>
        <Tooltip content="Receive native tokens for gas fees on destination chain" />
      </div>
      <Switch checked={enabled} onChange={onToggle} />
    </div>
  );
}
```

### Show Status During Execution

```typescript theme={null}
function GasStatus({ status, amount, symbol }: GasStatusProps) {
  switch (status) {
    case 'pending':
      return <span>Receiving {amount} in {symbol}...</span>;
    case 'completed':
      return <span>✓ Received {amount} in {symbol} as gas top-up</span>;
    case 'failed':
      return <span>⚠ Failed to receive gas tokens</span>;
    default:
      return null;
  }
}
```

## Error Handling

Handle various failure scenarios gracefully:

```typescript theme={null}
async function handleGasRouteErrors(error: Error, mainRouteStatus: string) {
  // Gas route failures don't affect main swap
  if (mainRouteStatus === 'completed') {
    console.log("Main swap succeeded despite gas route failure");
    // Show warning to user about missing gas
    showWarning("Swap completed but gas tokens were not received");
  }
  
  // Log for debugging
  console.error("Gas route error:", error);
  
  // Track in analytics
  trackEvent("gas_route_failed", {
    error: error.message,
    mainRouteStatus
  });
}
```

## Best Practices

1. **Use getRouteWithGasOnReceive**: The automatic function handles edge cases and optimizations
2. **Auto-detection**: Check gas balances and suggest Gas on Receive when needed
3. **User Control**: Always allow users to toggle the feature on/off
4. **Clear Communication**: Show exact amounts and costs transparently
5. **Graceful Degradation**: Main swap should continue even if gas route fails
6. **Higher Slippage**: Use 10% slippage for gas routes (vs 1% for main routes)
7. **Chain Support**: Disable for Ethereum mainnet and Solana
8. **Amount Limits**: Use recommended amounts ($0.10 for Cosmos, $2.00 for EVM L2s)

## Advanced Configuration

### Custom Gas Amounts

```typescript theme={null}
// Override default gas amounts
const customGasAmounts = {
  "osmosis-1": "100000", // 0.1 OSMO
  "42161": "0.001",      // 0.001 ETH on Arbitrum
  "137": "2"             // 2 MATIC on Polygon
};

async function getCustomGasAmount(chainId: string): Promise<string> {
  return customGasAmounts[chainId] || getDefaultGasAmount(chainId);
}
```

### Dynamic Pricing

```typescript theme={null}
// Adjust gas amount based on current gas prices
async function calculateDynamicGasAmount(chainId: string) {
  const gasPrice = await getGasPrice(chainId);
  const estimatedTxCount = 5; // Assume user needs gas for 5 transactions
  const gasPerTx = 21000; // Basic transfer gas limit
  
  const totalGasNeeded = gasPrice * gasPerTx * estimatedTxCount;
  return totalGasNeeded.toString();
}
```

## Comparison with Widget Implementation

| Feature               | Widget (Automatic) | Client Library (Manual)                  |
| --------------------- | ------------------ | ---------------------------------------- |
| Gas balance detection | Automatic          | Manual or use `getRouteWithGasOnReceive` |
| Route creation        | Automatic          | Use `getRouteWithGasOnReceive` or manual |
| Amount calculation    | Built-in defaults  | Built-in with `getRouteWithGasOnReceive` |
| UI components         | Provided           | Build your own                           |
| Error handling        | Automatic          | Manual implementation                    |
| Status tracking       | Built-in           | Via callbacks                            |

## Summary

The Skip Go Client Library provides flexible options for implementing Gas on Receive:

1. **Quick implementation** with `getRouteWithGasOnReceive` for automatic route splitting
2. **Full control** with manual balance checking and route creation
3. **Status tracking** via callbacks in `executeMultipleRoutes`
4. **Graceful error handling** where gas route failures don't affect main swaps

Choose the approach that best fits your application's needs. For most use cases, `getRouteWithGasOnReceive` provides the ideal balance of simplicity and functionality.


# Getting Started
Source: https://skip-go.mintlify-go.com/go/client/getting-started

@skip-go/client is a TypeScript library that streamlines interaction with the Skip Go API, enabling cross-chain swaps and transfers across multiple ecosystems.

<Steps>
  <Step title="Install Library">
    Install the library using npm or yarn:

    <CodeGroup>
      ```Shell npm theme={null}
      npm install @skip-go/client
      ```

      ```Shell yarn theme={null}
      yarn add @skip-go/client
      ```
    </CodeGroup>

    <Info>
      If you're using `yarn` (or another package manager that doesn't install peer dependencies by default)
      you may need to install these peer dependencies as well:

      ```bash theme={null}
        yarn add viem @solana/web3.js
      ```
    </Info>
  </Step>

  <Step title="Initialize Library">
    To start integrating with the Skip Go API, you no longer initialize a `SkipClient` instance. Instead, you configure the library once and then import and use individual functions directly.

    ### Initialization Options

    The library can be initialized using `setClientOptions` or `setApiOptions`. Both functions accept `apiUrl` and `apiKey`.

    * **`setClientOptions(options)`:** Use this if you plan to use `executeRoute`. It configures your API credentials and lets you provide chain-specific settings like endpoints, Amino types, and registry types.
    * **`setApiOptions(options)`:** Use this if you primarily need to configure API interaction (`apiUrl`, `apiKey`) or set up affiliate fees (`chainIdsToAffiliates`). This option does not configure `endpointOptions`, `aminoTypes`, or `registryTypes`.

    You typically call one of these functions once at application startup.

    ```ts Import and Initialize theme={null}
    import {
      setClientOptions,
      setApiOptions,
      chains,
      assets,
      route,
      executeRoute,
      // ... other functions you need
    } from "@skip-go/client";

    // Example: Initialize for executeRoute usage
    setClientOptions({
      apiUrl: "YOUR_API_URL", // Optional: defaults to Skip API
      apiKey: "YOUR_API_KEY",   // Optional: required for certain features
      endpointOptions: { /* ... */ },
      // ... other options like aminoTypes, registryTypes, cacheDurationMs
    });

    // Example: Initialize for direct API calls (simpler, if not using executeRoute)
    setApiOptions({
      apiUrl: "YOUR_API_URL", // Optional: defaults to Skip API
      apiKey: "YOUR_API_KEY",   // Optional: required for certain features
    });

    // Now you can call functions directly, e.g.:
    // const supportedChains = await chains();
    ```

    ### Configuration Parameters

    Below are the common configuration parameters. Refer to the specific `options` type for `setClientOptions` or `setApiOptions` for full details.

    * `apiUrl?: string`: Override the default API URL. Can be passed to `setClientOptions` or `setApiOptions`, or directly to individual API functions if neither initialization function is called.
    * `apiKey?: string`: Your Skip API key. Can be passed to `setClientOptions` or `setApiOptions`, or directly to individual API functions if neither initialization function is called. Required for certain features.
    * `endpointOptions?: EndpointOptions`: Provide RPC and REST endpoints for specific chains (used by `setClientOptions`).
    * `aminoTypes?: AminoConverters`: Additional amino types for message encoding (used by `setClientOptions`).
    * `registryTypes?: Iterable<[string, GeneratedType]>`: Additional registry types (used by `setClientOptions`).
    * `cacheDurationMs?: number`: Duration in milliseconds to cache responses for functions like `chains` and `assets` (used by `setClientOptions`).
  </Step>

  <Step title="Setup Signers">
    To execute transactions, you need to set up signers for the ecosystems you plan to interact with. Below are examples for Cosmos SDK, EVM, and Solana (SVM). Note that for EVM and SVM, you'll need to install additional libraries.

    ### Signer Setup

    <CodeGroup>
      ```ts Cosmos Signer theme={null}
      // For Cosmos transactions, we'll use Keplr wallet from the window object
      const getCosmosSigner = async (chainId: string) => {
        const key = await window.keplr?.getKey(chainId);
        if (!key) throw new Error("Keplr not installed or chain not added");

        return key.isNanoLedger
              ? window.keplr?.getOfflineSignerOnlyAmino(chainId)
              : window.keplr?.getOfflineSigner(chainId);
      };

      ```

      ```ts EVM Signer theme={null}
      // For EVM transactions, we'll use MetaMask and viem
      // npm install viem
      import { createWalletClient, custom, Account } from "viem";
      import { mainnet } from 'viem/chains';

      const getEvmSigner = async (chainId: string) => {
        const ethereum = window.ethereum;
        if (!ethereum) throw new Error("MetaMask not installed");
        const accounts = await ethereum.request({ method: 'eth_requestAccounts' }) as Account[];
        const account = accounts?.[0]
        if (!account) throw new Error('No accounts found');
        const client = createWalletClient({
          account,
          chain: mainnet,
          transport: custom(window.ethereum),
        });
        return client;
      }
      ```

      ```ts Svm Signer theme={null}
      // For Solana transactions, we'll use the Phantom wallet adapter
      // npm install @solana/wallet-adapter-phantom
      import { PhantomWalletAdapter } from '@solana/wallet-adapter-phantom';

      const getSvmSigner = async () => {
        const phantom = new PhantomWalletAdapter();
        await phantom.connect();
        return phantom;
      };
      ```
    </CodeGroup>
  </Step>

  <Step title="Query Basic Info">
    With the library initialized, you can query balances, supported chains and assets using the imported functions.

    ### Query Examples

    <CodeGroup>
      ```ts Supported Chains theme={null}
      import { chains } from "@skip-go/client";

      // returns a Chain[] of all supported Cosmos mainnet chains
      const cosmosChains = await chains();

      // include EVM and SVM chains
      const allChains = await chains({
        includeEvm: true,
        includeSvm: true,
      });

      // only show testnet chains
      const testnetChains = await chains({
        onlyTestnets: true
      });
      ```

      ```ts Supported Assets theme={null}
      import { assets } from "@skip-go/client";

      // returns `Record<string, Asset[]>`
      const allAssets = await assets({ includeEvmAssets: true, includeSvmAssets: true, });

      // get assets filtered by chain ID
      const cosmosHubAssets = await assets({
        chainId: 'cosmoshub-4',
        includeCw20Assets: true,
      });

      // only get assets for specific chains
      const specificAssets = await assets({
        chainIds: ['osmosis-1', '1'], // Ethereum and Osmosis
      });
      ```

      ```ts Token Balances theme={null}
      import { balances } from "@skip-go/client";

      // Define the request structure (already defined earlier in doc, ensure consistency or repeat here for clarity)
      interface BalancesRequest {
        chainId: string;
        address: string;
        denoms?: string[]; // Optional: specify denoms, otherwise fetches all
      }

      const balanceRequests: BalancesRequest[] = [
        {
          chainId: "137", // Polygon
          address: "0x24a9267cE9e0a8F4467B584FDDa12baf1Df772B5",
          denoms: [
            "polygon-native", // Matic
            "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359" // USDC
          ]
        },
        {
          chainId: "osmosis-1",
          address: "osmo12xufazw43lanl8dkvf3l7y9zzm8n3zswftw2yc",
          denoms: ["uosmo"]
        }
      ];

      // returns a map of assets by chain ID (or the structure defined by BalanceResponse)
      const userBalances = await balances({ requests: balanceRequests });
      ```
    </CodeGroup>
  </Step>

  <Step title="Get a Route">
    Once you've selected your source and destination chains and tokens, you can generate a route and get a quote using the `route` function. See it in context [here](https://github.com/skip-mev/skip-go-example/blob/d68ec668ebaa230325ad31658b547bd27c42ac49/pages/index.tsx#L46).

    ### Route Examples

    <CodeGroup>
      ```ts Swap ATOM for OSMO Example theme={null}
      import { route } from "@skip-go/client";

      const routeResult = await route({
        amountIn: "1000000", // Desired amount in smallest denomination (e.g., uatom)
        sourceAssetDenom: "uatom",
        sourceAssetChainId: "cosmoshub-4",
        destAssetDenom: "uosmo",
        destAssetChainId: "osmosis-1",
        cumulativeAffiliateFeeBps: '0',
      });
      ```

      ```ts Swap ETH for TIA Example theme={null}
      import { route } from "@skip-go/client";

      const routeResult = await route({
        amountOut: "1000000", // Desired amount out
        sourceAssetDenom: "ethereum-native",
        sourceAssetChainId: "1", // Ethereum mainnet chain ID
        destAssetDenom: "utia",
        destAssetChainId: "celestia",
        smartRelay: true,
        smartSwapOptions: {
          splitRoutes: true,
          evmSwaps: true
        },
      });
      ```

      ```ts Transfer USDC from Solana to Noble Example theme={null}
      import { route } from "@skip-go/client";

      const routeResult = await route({
        sourceAssetDenom: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
        sourceAssetChainId: "solana",
        destAssetDenom: "uusdc",
        destAssetChainId: "noble-1",
        amountIn: "1000000",
        smartRelay: true
      });
      ```
    </CodeGroup>

    <Info>
      Read more about [affiliate fees](../general/affiliate-fees), [Smart Relay](../general/smart-relay) and [EVM Swaps](../advanced-swapping/smart-swap-options#feature-evm-swaps).
    </Info>
  </Step>

  <Step title="Get Required Addresses">
    After generating a route, you need to provide user addresses for the required chains. The `route.requiredChainAddresses` array lists the chain IDs for which addresses are needed.

    <Warning>
      **Only use addresses your user can sign for.**
      Funds could get stuck in any address you provide, including intermediate chains in certain failure conditions. Ensure your user can sign for each address you provide.
      See [Cross-chain Failure Cases](../advanced-transfer/handling-cross-chain-failure-cases) for more details.
    </Warning>

    We recommend storing the user's addresses and creating a function like [`getAddress`](https://github.com/skip-mev/skip-go-example/blob/c55d9208bb46fbf1a4934000e7ec4196d8ccdca4/pages/index.tsx#L99) that retrieves the address based on the chain ID.

    ```ts theme={null}
    // Assuming 'routeResult' holds the object from the route() call in Step 5
    // get user addresses for each requiredChainAddress to execute the route
      const userAddresses = await Promise.all(
      routeResult.requiredChainAddresses.map(async (chainId) => ({
        chainId,
        address: await getAddress(chainId),
      }))
    );
    ```
  </Step>

  <Step title="Execute the Route">
    Once you have a route, you can execute it in a single function call by passing in the route, the user addresses for at least the chains the route includes, and optional callback functions. This also registers the transaction for tracking.

    ```ts theme={null}
    await executeRoute({
      route: routeResult,
      userAddresses,
      getCosmosSigner,
      getEvmSigner,
      getSvmSigner,
      onTransactionCompleted: async ({ txHash, chainId, status}) => {
        console.log(
          `Route completed on chain ${chainId} with tx hash: ${txHash} & status: ${status?.state}`
        );
      },
      onTransactionBroadcast: async ({ txHash, chainId }) => {
        console.log(`Transaction broadcasted on ${chainId} with tx hash: ${txHash}`);
      },
      onTransactionTracked: async ({ txHash, chainId, explorerLink }) => {
        console.log(`Transaction tracked for ${chainId} with tx hash: ${txHash}, explorer: ${explorerLink}`);
      },
      onTransactionSigned: async ({ chainId }) => {
        console.log(`Transaction signed for ${chainId}`);
      },
      onValidateGasBalance: async (validation) => {
        if (validation.status === "error") {
          console.warn(`Insufficient gas balance or gas validation error on chain ${validation.chainId} (Tx Index: ${validation.txIndex}).`);
        }
      },
      onApproveAllowance: async (approvalInfo) => {
        console.log(`ERC20 allowance ${approvalInfo.status} for token ${approvalInfo.allowance?.tokenContract} on chain ${approvalInfo.allowance?.chainId}`);
      }
    });
    ```

    For routes that consist of multiple transactions, `executeRoute` will monitor each transaction until it completes, then generate the transaction for the next step and prompt the user to sign it using the appropriate signer.

    <Info>
      Alternatively, you can handle message generation, signing, and submission manually using the individual functions:

      * `messages`: Generate transaction messages.
      * `messagesDirect`: A convenience function that combines the functionality of `/route` and `/msgs` into a single call. It returns the minimal number of messages required to execute a multi-chain swap or transfer.
      * `broadcastTx`: Broadcast transactions to the network.
      * `submitTransaction`: Submit and track transactions.
        Refer to the API documentation for details on these lower-level functions.
    </Info>
  </Step>

  <Step title="Transaction Tracking">
    After a transaction is registered for tracking (either via `executeRoute`, `submitTransaction`, or `trackTransaction`), you can poll for its status:

    * **Check Status:** `transactionStatus` - Takes a `txHash` and `chainId` and returns the current cross-chain status.
      ```ts theme={null}
      // Example of checking transaction status:
      // Assuming you have txHash and chainId from a previous step:
      // const statusResult = await transactionStatus({ txHash: "your_tx_hash", chainId: "your_chain_id" });
      // console.log("Transaction State:", statusResult.state);
      // console.log("Full Status Response:", statusResult);
      // Possible states include: STATE_COMPLETED_SUCCESS, STATE_COMPLETED_ERROR, STATE_ABANDONED, STATE_PENDING_CONFIRMATION, STATE_PENDING_EXECUTION, etc.
      // Refer to the TxStatusResponse type or API documentation for a complete list of states.
      ```

    Remember, if you use `executeRoute` (Step 7), it automatically handles the transaction lifecycle, including waiting for completion. The manual tracking functions (`submitTransaction`, `trackTransaction`, `transactionStatus`) are primarily for scenarios where you are not using `executeRoute` for full execution (e.g., if you use `submitTransaction` directly) or if you need more granular control over the tracking and status polling process.
  </Step>
</Steps>

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Migration Guide
Source: https://skip-go.mintlify-go.com/go/client/migration-guide



<Warning>
  Both the Skip Router SDK ([`@skip-router/core`](https://www.npmjs.com/package/@skip-router/core)) and Skip Go Core ([`@skip-go/core`](https://www.npmjs.com/package/@skip-go/core))
  are deprecated. Please migrate to Skip Go Client ([`@skip-go/client`](https://www.npmjs.com/package/@skip-go/client)), our actively maintained client package.
</Warning>

<Update label="@skip-go/client v1.0.0">
  ## Breaking changes

  This section details the migration from previous versions to the latest [`@skip-go/client`](https://www.npmjs.com/package/@skip-go/client).

  ### No More SkipClient Class

  The `SkipClient` class has been removed. Instead, import and use individual functions directly:

  ```TypeScript Example import theme={null}
  import {
    assets,
    assetsBetweenChains,
    assetsFromSource,
    recommendAssets,
    bridges,
    balances,
    chains,
    venues,
    ibcOriginAssets,
    route,
    messages,
    messagesDirect,
    submitTransaction,
    trackTransaction,
    transactionStatus,
    executeRoute,
    setClientOptions,
    setApiOptions,
  } from '@skip-go/client';
  ```

  ### Initialization Changes

  **If not using `executeRoute`:**

  * Call `setApiOptions({ apiUrl, apiKey })` once at initialization.
  * Alternatively, pass `apiUrl` and `apiKey` as arguments to each individual API function call.

  **If using `executeRoute`:**

  * Call `setClientOptions()` with the same options object previously passed to the `SkipClient` constructor.
  * **Exception:** `getCosmosSigner`, `getEVMSigner`, and `getSVMSigner` have been removed from `setClientOptions`. These signer functions are now passed directly to `executeRoute` when needed.
  * **Renamed:** `getEVMSigner` is now `getEvmSigner`, and `getSVMSigner` is now `getSvmSigner`.

  ```Diff Example migration theme={null}
  - const client = new SkipClient(options);
  + setClientOptions(options); // Only if using executeRoute

  - client.chains();
  + chains(); // Assuming apiUrl/apiKey were set via setApiOptions or passed in
  ```

  ### Build Format Change

  The library build format has changed from CommonJS (CJS) to `ES Modules (ESM)`.

  This change enables better tree-shaking, leading to significantly smaller bundle sizes for applications that don't use all the library's features.

  <Info>
    If you're **not** using `executeRoute`, your final bundle size should decrease dramatically (e.g., from \~5MB to potentially \~7KB for a single API function usage), assuming tree-shaking is enabled in your bundler.
  </Info>

  ### Axios Removed

  `axios` is no longer a dependency. All API calls now utilize the standard `window.fetch` API internally.

  ### CamelCase Update

  All property names in API responses and configuration objects now strictly adhere to `camelCase`.

  **Examples:**

  | Before         | After          |
  | -------------- | -------------- |
  | `chainID`      | `chainId`      |
  | `apiURL`       | `apiUrl`       |
  | `logoURI`      | `logoUri`      |
  | `asset.isCW20` | `asset.isCw20` |

  ### Named parameter enforcement for API functions

  Some methods now require named parameters or an options object instead of positional arguments:

  #### recommendAssets

  Old:

  ```ts theme={null}
  await client.recommendAssets(request);
  // OR
  await client.recommendAssets([request1, request2]);
  ```

  New:

  ```ts theme={null}
  await recommendAssets({ requests: [request1, request2] });
  ```

  Wrap the array in a `{ requests: [...] }` object.

  #### ibcOriginAssets

  Old:

  ```ts theme={null}
  await client.ibcOriginAssets(assets);
  ```

  New:

  ```ts theme={null}
  await ibcOriginAssets({ assets: [asset1, asset2] });
  ```

  Wrap the assets array in a `{ assets: [...] }` object.

  #### `getFeeInfoForChain`

  Parameters for `getFeeInfoForChain` should now be passed as an object.

  Old:

  ```ts theme={null}
  await client.getFeeInfoForChain(chainID);
  ```

  New:

  ```ts theme={null}
  import { getFeeInfoForChain } from '@skip-go/client'; // Assuming setApiOptions was called

  await getFeeInfoForChain({ chainId: chainID });
  // Or, if not using setApiOptions globally for apiUrl/apiKey:
  // await getFeeInfoForChain({ chainId: chainID, apiUrl: YOUR_API_URL, apiKey: YOUR_API_KEY });
  ```

  #### `getRecommendedGasPrice`

  Parameters for `getRecommendedGasPrice` should now be passed as an object.

  Old:

  ```ts theme={null}
  await client.getRecommendedGasPrice(chainID);
  ```

  New:

  ```ts theme={null}
  import { getRecommendedGasPrice } from '@skip-go/client'; // Assuming setApiOptions was called

  await getRecommendedGasPrice({ chainId: chainID });
  // Or, if not using setApiOptions globally for apiUrl/apiKey:
  // await getRecommendedGasPrice({ chainId: chainID, apiUrl: YOUR_API_URL, apiKey: YOUR_API_KEY });
  ```

  ### Removed Internal Functions

  The following functions that were previously exported are no longer available in v1.0.0. These were internal functions that were not intended for direct use by integrators, as they are used internally by `executeRoute`:

  * `executeTxs`
  * `executeEvmMsg` (merged with `executeEvmTransaction`)
  * `executeCosmosMessage` (merged with `executeCosmosTransaction`)
  * `executeEVMTransaction`
  * `executeSVMTransaction`
  * `signCosmosMessageDirect`
  * `signCosmosMessageAmino`
  * `getRpcEndpointForChain`
  * `getRestEndpointForChain`
  * `validateGasBalances`
  * `validateEvmGasBalance`
  * `validateEvmTokenApproval`
  * `validateSvmGasBalance`
  * `validateUserAddresses`
  * `getMainnetAndTestnetChains`
  * `getMainnetAndTestnetAssets`
  * `getAccountNumberAndSequence`

  If your application was using any of these functions directly, consider using `executeRoute` instead, which handles all transaction execution internally. If you have a specific use case that requires access to any of these functions, please open a ticket on our [Discord](https://discord.gg/skip).
</Update>

<Update label="@skip-router/core v4.0.0">
  ### Breaking changes

  * Removed `clientID` param in `SkipClient`
  * Added `apiKey` param in `SkipClient`
  * Added `requiredChainAddresses` in `SkipClient.route` response
  * Added `smartSwapOptions` in `SkipClient.route`request

  ```JavaScript Type signature theme={null}
  smartSwapOptions: {
  	splitRoutes: boolean
  }
  ```
</Update>

<Update label="@skip-router/core v3.0.0">
  ## Breaking changes

  * Changed parameter type of `userAddresses` from a map of chainIDs to addresses to an array of `UserAddress` types

  ```TypeScript Type signature theme={null}
  export interface UserAddress {
    chainID: string;
    address: string;
  }
  ```
</Update>

<Update label="@skip-router/core v2.0.0">
  ### Breaking changes

  * Removed `SkipClient.executeMultiChainMessage` method
  * Renamed `SkipClient.getGasAmountForMessage` method to `SkipClient.getCosmosGasAmountForMessage`
  * Renamed `SkipClient.getFeeForMessage` to `SkipClient.getCosmosFeeForMe`
  * Renamed `MultiChainMsg` type to `CosmosMsg`
  * Renamed and changed parameters of `SkipClient.executeMultiChainMsgs` to `SkipClient.executeTxs`

  ```Diff Diff theme={null}
  const client = new SkipClient({
    apiURL: SKIP_API_URL,
  // ... rest of your configs
  });
  - client.executeMultiChainMsgs({
  + client.executeTxs({
  	...options
  -	msgs: types.Msg[]
  +	txs: types.Tx[]
  })
  ```

  * Param of `SkipClient.executeCosmosMessage` changed from `message:MultiChainMsg` to `messages: CosmosMsg[]`

  ```Diff Diff theme={null}
  const client = new SkipClient({
    apiURL: SKIP_API_URL,
  // ... rest of your configs
  });
  client.executeCosmosMessage({
  	...options
  -	message: MultiChainMsg
  +	messages: CosmosMsg[]
  })
  ```
</Update>


# Skip Go Contract Addresses
Source: https://skip-go.mintlify-go.com/go/contracts/skip-go-contracts

Deployed contract addresses for Skip Go's cross-chain infrastructure across various blockchain networks.

## Skip Go Fast Contracts

### Mainnet Contracts

* **Ethereum (Chain ID: 1)**: `0xa11CC0eFb1B3AcD95a2B8cd316E8c132E16048b5`
* **Arbitrum (Chain ID: 42161)**: `0x4c58aE019E54D10594F1Aa26ABF385B6fb17A52d`
* **Avalanche (Chain ID: 43114)**: `0xb7B287F15e5edDFEfF2b05ef1BE7F7cc73197AaA`
* **Base (Chain ID: 8453)**: `0x9335C0c0CBc0317291fd48c00b2f71C8b39DA6F8`
* **Optimism (Chain ID: 10)**: `0x9c540EdC86613b22968Da784b2d42AC79965af91`
* **Polygon (Chain ID: 137)**: `0x2260f6120b634B94A23eF11fa0D615ecf62db3cD`

#### Cosmos

* **Osmosis**: `osmo1vy34lpt5zlj797w7zqdta3qfq834kapx88qtgudy7jgljztj567s73ny82`

## Skip Go Contracts (Axelar Integration)

### Mainnet Contracts

* **Ethereum (Chain ID: 1)**: `0xB773bCc5B325ad9AC6B36e1A046AD4466833A16E`
* **Arbitrum (Chain ID: 42161)**: `0xEF1cE4489962E6d6D6BE8066E160B2799610cB85`
* **Avalanche (Chain ID: 43114)**: `0xBeB12d8861765c850E8426Cc5c6a5207222f2477`
* **Base (Chain ID: 8453)**: `0x569594F181ac9AbdE3eBf89954F3D3Af40d63600`
* **Binance Smart Chain (Chain ID: 56)**: `0x43d090025aAA6C8693B71952B910AC55CcB56bBb`
* **Blast (Chain ID: 81457)**: `0x73529dcA22c23B41325cC50d440D61663c15dD94`
* **Celo (Chain ID: 42220)**: `0x0103ba3D329ebF104a15aA89C6072Ae2773C183e`
* **Fantom (Chain ID: 250)**: `0x39c3D2A07633dc59CaCa9B77250d35C9cd02fB2F`
* **Filecoin (Chain ID: 314)**: `0x66097B6418c8E8bF482b5bEE736c7A22eaA445E9`
* **Linea (Chain ID: 59144)**: `0x32Fb43172c0afB63770372fDe4A84E9b827Ec903`
* **Moonbeam (Chain ID: 1284)**: `0x49a9a8c7bAe5764A6D2b0e9ff5Bf0d233E062087`
* **Optimism (Chain ID: 10)**: `0x8e4404c32c13C2C42910508992aE498FC9984D06`
* **Polygon (Chain ID: 137)**: `0xD87E98798b1441c4b7fB7ABd918F90e42ae3D735`

### Testnet Contracts

* **Ethereum Goerli (Chain ID: 5)**: `0x960f5bb766f56fb30c594f252210c6f512a534a0`
* **Polygon Sepolia (Chain ID: 80002)**: `0xcC0890c02838A2ED61096C0bc272dEf49f1eB982`

## Skip CCTP Payment Contracts

### Mainnet

* **Ethereum (Chain ID: 1, Domain: 0)**: `0xf33e750336e9C0D4E2f4c0D450d753030693CC71`
* **Arbitrum (Chain ID: 42161, Domain: 3)**: `0x6d4d4A979D766e8b87C985a61B262cfCDf8d6446`
* **Avalanche (Chain ID: 43114, Domain: 1)**: `0xB19Ff56BD455C2515207BDbdEDC68B57fBA9A78D`
* **Base (Chain ID: 8453, Domain: 6)**: `0xddAFc591Dda57dCF7b3E9Cf83e72c8591fC9cC24`
* **Optimism (Chain ID: 10, Domain: 2)**: `0x55e4Cf6a73ED8B3307bE610f516fB41BA000f1E5`
* **Polygon (Chain ID: 137, Domain: 7)**: `0x1fe8e504D2Fbd2dfdEB271C6B92016bF0454177f`

### Testnet

* **Ethereum Sepolia (Chain ID: 11155111, Domain: 0)**: `0x585F053d554B8d4c3983A7BBaDbe13B15BA66F37`
* **Arbitrum Sepolia (Chain ID: 421614, Domain: 3)**: `0x3cb7630cAdd5bC6Cba3Aa331feb9b3D018A74f83`
* **Avalanche Fuji (Chain ID: 43113, Domain: 1)**: `0xF1c231F59b6b7Ffa68A7Aad43BbD238BF0bFB9C9`
* **Base Sepolia (Chain ID: 84532, Domain: 6)**: `0x960f5Bb766F56Fb30C594f252210C6F512a534a0`
* **Optimism Sepolia (Chain ID: 11155420, Domain: 2)**: `0x3cb7630cAdd5bC6Cba3Aa331feb9b3D018A74f83`
* **Polygon Amoy (Chain ID: 80002, Domain: 7)**: `0xE6cAE382d08bD61700ff260648A1EfCA5B982E26`

### Cosmos CCTP Addresses

* **Noble (Chain ID: noble-1, Domain: 4)**:
  * Fee Address: `noble1dyw0geqa2cy0ppdjcxfpzusjpwmq85r5a35hqe`
* **Noble Testnet (Chain ID: grand-1, Domain: 4)**:
  * Fee Address: `noble1dyw0geqa2cy0ppdjcxfpzusjpwmq85r5a35hqe`

### Solana CCTP Addresses

* **Solana Mainnet (Domain: 5)**:
  * Fee Address: `6MxMEeH2MQTjk7Cd4JDbJSnTvtpoKJuv374KpQYKJ3Rv`
* **Solana Devnet (Domain: 5)**:
  * Fee Address: `6MxMEeH2MQTjk7Cd4JDbJSnTvtpoKJuv374KpQYKJ3Rv`

## Circle CCTP Core Contracts

### Token Messenger Contracts

* **Ethereum**: `0xbd3fa81b58ba92a82136038b25adec7066af3155`
* **Arbitrum**: `0x19330d10D9Cc8751218eaf51E8885D058642E08A`
* **Avalanche**: `0x6b25532e1060ce10cc3b0a99e5683b91bfde6982`
* **Base**: `0x1682Ae6375C4E4A97e4B583BC394c861A46D8962`
* **Optimism**: `0x2b4069517957735be00cee0fadae88a26365528f`
* **Polygon**: `0x9daF8c91AEFAE50b9c0E69629D3F6Ca40cA3B3FE`

### Message Transmitter Contracts

* **Ethereum**: `0x0a992d191deec32afe36203ad87d7d289a738f81`
* **Arbitrum**: `0xC30362313FBBA5cf9163F0bb16a0e01f01A896ca`
* **Avalanche**: `0x8186359af5f57fbb40c6b14a588d2a59c0c29880`
* **Base**: `0xAD09780d193884d503182aD4588450C416D6F9D4`
* **Optimism**: `0x4d41f22c5a0e5c74090899e5a8fb597a8842b3e8`
* **Polygon**: `0xF3be9355363857F3e001be68856A2f96b4C39Ba9`

## Eureka (IBC) Integration Contracts

### Mainnet Contracts

* **Ethereum (Chain ID: 1)**: `0x47a4b9F949E98a49Be500753c19a8f9c9d6b7689`

### Testnet Contracts

* **Ethereum Sepolia (Chain ID: 11155111)**: `0x46914a36365EC16600D81880903f3e95dcea3e5D`

## Cosmos Entry Point Contracts

### Mainnet Contracts

* **Archway**: `archway1e8pld8ft5rc3qm78hcldy2p05rjrfzaeea50mp0zv5c294pl2pyqje9435`
* **Babylon**: `bbn1g0uuysdqydrmfum8ctn7whlevuwydeqvuw0kumqj8773ru5aglwq6vww30`
* **Chihuahua**: `chihuahua1e8pld8ft5rc3qm78hcldy2p05rjrfzaeea50mp0zv5c294pl2pyqqrn49v`
* **Elys**: `elys1p2fhrn9zfra9lv5062nvzkmp9hduhm9hkk6kz6a3ucwktjvuzv9smry5sk`
* **Initia**: `0xd921c61c7e7d2eead33bdff4c5c2941e66d488f0a15fe7fbc432565dc04b3710/modules/entry_point`
* **Injective**: `inj15fag9p2389wun8z33yr3427vp5fvhyg952vsxe`
* **Migaloo**: `migaloo1e8pld8ft5rc3qm78hcldy2p05rjrfzaeea50mp0zv5c294pl2pyqzeanu2`
* **Neutron**: `neutron1zvesudsdfxusz06jztpph4d3h5x6veglqsspxns2v2jqml9nhywskcc923`
* **Osmosis**: `osmo10a3k4hvk37cc4hnxctw4p95fhscd2z6h2rmx0aukc6rm8u9qqx9smfsh7u`
* **Persistence**: `persistence18x2ae7yhd3ggvw4ryp5fjtxz5e0z3ml6srnv3ssqxedvlaqvecyq9pwq2s`
* **Pryzm**: `pryzm1k6f4crmvu9l4t0x07mj7dm3gvpa38ty8qdvpq2q9vxutqy25esaqcv7adz`
* **Sei**: `sei1wrqzkg3at3eqhqazsm5sndkq8nt8n0azalvxrtpat72aq5sr7suqm7qfzd`
* **Terra**: `terra13jfx06k2zpajtxymdgq2r6mrezzx3ngrhzfe24gdh9mqs8x67lmspee8lp`

### Testnet Contracts

* **Babylon**: `bbn1g0uuysdqydrmfum8ctn7whlevuwydeqvuw0kumqj8773ru5aglwq6vww30`
* **Elys**: `elys1jeqlq99ustyug8rxgsrtmf3awzl83x535v3svykfwkkkr7049wxqgdt6ss`
* **Initia**: `0x777105889E6E42F2BED14DD4D7286C9E982A3E31/modules/entry_point`
* **Neutron**: `neutron1wc26zz2fqcz2fsppj3l8884lckzh20avn520fpdqgcnqtsedkf8svtg7ms`
* **Osmosis**: `osmo1vkdakqqg5htq5c3wy2kj2geq536q665xdexrtjuwqckpads2c2nsvhhcyv`
* **Pryzm**: `pryzm1k6f4crmvu9l4t0x07mj7dm3gvpa38ty8qdvpq2q9vxutqy25esaqcv7adz`


# Contract Addresses
Source: https://skip-go.mintlify-go.com/go/eureka/contract-addresses

Key contract addresses for the IBC Eureka deployment.

<Note>
  The contract addresses listed on this page are for the Ethereum mainnet deployment. Please note that these addresses may change. The most up-to-date deployment information can always be found in the [cosmos/eureka-ops GitHub repository](https://github.com/cosmos/eureka-ops/blob/main/deployments/mainnet/1.json).
</Note>

## Security councils

* **Eureka Ops Council** (Gnosis Safe): `eth:0x4b46ea82D80825CA5640301f47C035942e6D9A46`
* **Eureka Security Council** (Gnosis Safe): `eth:0x7B96CD54aA750EF83ca90eA487e0bA321707559a`

## ICS26 Router

* **clientIdCustomizer**: `0x4b46ea82D80825CA5640301f47C035942e6D9A46`
* **implementation**: `0x4e9083eC6ed91d6ab6b59EaEcfCd4459F76dCdE1`
* **portCustomizer**: `0x4b46ea82D80825CA5640301f47C035942e6D9A46`
* **proxy**: `0x3aF134307D5Ee90faa2ba9Cdba14ba66414CF1A7`
* **relayers**:
  * `0xC4C09A23dDBd1fF0f313885265113F83622284C2`
  * `0xACf94C35456413F9F1FCe1aE8A0412Dd6D6B40D7`
  * `0x4bc16fEC05B2D9Fa72AdE54BB25A464a20D0D49b`
  * `0xeB128b9893aDCf2F6C6305160e57b7Beab9A09AF`
* **timeLockAdmin**: `0xb3999B2D30dD8c9faEcE5A8a503fAe42b8b1b614`

## ICS20 Transfer

* **escrowImplementation**: `0xf24A818d2E276936a7ABDDfaAd9c369a5B9Dcde8`
* **ibcERC20Implementation**: `0x337842047368607f458e3D7bb47E676aec1509d9`
* **ics26Router**: `0x3aF134307D5Ee90faa2ba9Cdba14ba66414CF1A7`
* **implementation**: `0x4658C167824C000eA93D62f15B5c9bb53ee329fE`
* **pausers**:
  * `0x9D91034CF296a02ED54C18A1a2AB9520e5fC135d`
  * `0xCb5d44d2324D36FfFef0e594d8893c4Fee908d4d`
  * `0x64ACC525DC35ebca8345fDF6e2A70D012a17740A`
  * `0x00A8b36491dCc59f1998fa368842709aBdD24eD7`
  * `0x2FeD70e1Ea7bE86a5C99F3456C0fb70db2801AD2`
* **permit2**: `0x000000000022D473030F116dDEE9F6B43aC78BA3`
* **proxy**: `0xa348CfE719B63151F228e3C30EB424BA5a983012`
* **tokenOperator**: `0x4b46ea82D80825CA5640301f47C035942e6D9A46`
* **unpausers**:
  * `0x7B96CD54aA750EF83ca90eA487e0bA321707559a`

## Light Clients

### Client: cosmoshub-0

* **clientId**: `cosmoshub-0`
* **Contract Address**: `0xeA6F72650da80093A1012606Cc7328f5474ed378`

### Client: ledger-mainnet-1

* **clientId**: `ledger-mainnet-1`
* **Contract Address**: `0xc9e814bB90B7e43c138F86D5C93Df21817D976Ca`

### Client: client-4

* **clientId**: `client-4`
* **Contract Address**: `0x1Ba9912Ab92d8c58e1DEF3f783e4EbE0A516d76E`


# Custom ERC20 Integration
Source: https://skip-go.mintlify-go.com/go/eureka/custom-erc20-integration

A guide for asset issuers to deploy and register custom ERC20 contracts for their tokens on Ethereum

# Custom ERC20 Integration

## Overview

In the initial release of [`solidity-ibc-eureka`](https://github.com/cosmos/solidity-ibc-eureka), receiving a non-native token (e.g., ATOM from Cosmos Hub) deploys a default [`IBCERC20`](https://github.com/cosmos/solidity-ibc-eureka/blob/main/contracts/utils/IBCERC20.sol) contract to represent that token on Ethereum.

Many teams bridging through the Cosmos Hub, however, want ownership and control over their ERC20 contracts on Ethereum. Since `IBCERC20` is managed by the `ICS20Transfer` contract and isn't customizable, direct ownership isn't possible.

To address this, we allow teams to deploy custom ERC20 contracts—provided they implement a simple interface that lets the `ICS20Transfer` contract mint and burn tokens.

## Benefits

The benefits of this approach include:

<CardGroup>
  <Card title="Custom Metadata" icon="tag">
    Customize metadata and token naming on deployment. Tokens will not initially be named `ibc/transfer/channel-0...` and can be represented with the name they are recognized by.
  </Card>

  <Card title="Contract Verification" icon="shield-check">
    Easier contract verification on Etherscan. Each project can easily verify the ERC20 contract deployed for their project to increase trust by associating the token with the official project domain.
  </Card>

  <Card title="Improved CEX Listing" icon="dollar-sign">
    This is likely to result in easier CEX listing and generally increased trust in the bridged asset.
  </Card>

  <Card title="Full Control" icon="gear">
    Complete ownership and control over the ERC20 contract representing your token on Ethereum.
  </Card>
</CardGroup>

## Requirements

To replace the default `IBCERC20`, your custom ERC20 contract must implement the [`IMintableAndBurnable`](https://github.com/cosmos/solidity-ibc-eureka/blob/main/contracts/interfaces/IMintableAndBurnable.sol) interface:

```solidity theme={null}
interface IMintableAndBurnable {
    /// @notice Mint new tokens to the Escrow contract
    /// @dev This function can only be called by an authorized contract (e.g., ICS20)
    /// @dev This function needs to allow minting tokens to the Escrow contract
    /// @param mintAddress Address to mint tokens to
    /// @param amount Amount of tokens to mint
    function mint(address mintAddress, uint256 amount) external;

    /// @notice Burn tokens from the Escrow contract
    /// @dev This function can only be called by an authorized contract (e.g., ICS20)
    /// @dev This function needs to allow burning of tokens from the Escrow contract
    /// @param mintAddress Address to burn tokens from
    /// @param amount Amount of tokens to burn
    function burn(address mintAddress, uint256 amount) external;
}
```

For an example implementation of this interface, you can refer to the [`RefImplIBCERC20.sol`](https://github.com/cosmos/solidity-ibc-eureka/blob/main/test/solidity-ibc/utils/RefImplIBCERC20.sol) contract in the `solidity-ibc-eureka` repository.

### Access Control Requirements

These functions must be callable by the proxy of the `ICS20Transfer` contract:

* **Mainnet**: `0xa348CfE719B63151F228e3C30EB424BA5a983012`

> **Security Note:**
> Access to the `mint` and `burn` functions must be strictly limited to the `ICS20Transfer` proxy. Allowing any other address or contract to call these functions could lead to unauthorized token manipulation and compromise the integrity of your token. While token teams may implement additional access controls or rate limits as needed, the `ICS20Transfer` proxy must always retain its ability to perform mint and burn operations.
>
> **Upgradability & Extensibility:**
> We may update our interface over time, but we're committed to ensuring backwards compatibility. While making your contract upgradable is not required, doing so allows you to adopt new features or improvements we introduce in the future.

### Upgradability

You are not required to deploy an upgradable contract for your custom ERC20. We commit to maintaining the stability of the `IMintableAndBurnable` interface. However, please note that if we extend the interface with new functionality in the future, a non-upgradable contract would not be able to utilize these new features.

## Registering a Custom ERC20

The `ICS20Transfer` contract includes a permissioned method for registering a custom ERC20 via the [`setCustomERC20`](https://github.com/cosmos/solidity-ibc-eureka/blob/bce3a4a0de85697607815e2f7c9d9e2a8a508cd3/contracts/ICS20Transfer.sol#L264C14-L264C28) function.

### Prerequisites

Only addresses assigned the `ERC20_CUSTOMIZER_ROLE` can call this function. This role is established by the protocol's security council and administered by the Eureka Ops multi-sig. To request registration of your custom ERC20 contract, [join our Discord](https://discord.com/invite/interchain) and open a support ticket.

Additionally, the token's denomination on the Cosmos Hub must be established. The token must either be live on the Hub, or its original denomination and complete IBC path must be known if it originates elsewhere. We require the token to be active on the Cosmos Hub before registration can proceed.

### Critical Timing Requirement

<Warning>
  `setCustomERC20` must be called **before** the first IBC transfer of the token to the chain where the custom ERC20 is deployed. Once the initial transfer is made, the ERC20 mapping becomes immutable.
</Warning>

## Getting Started

If you're an asset issuer looking to deploy a custom ERC20 contract for your token on Ethereum:

<Steps>
  <Step title="Implement the Interface">
    Deploy your custom ERC20 contract that implements the `IMintableAndBurnable` interface with proper access controls for the `ICS20Transfer` proxy. For an example, see the [reference implementation](https://github.com/cosmos/solidity-ibc-eureka/blob/main/test/solidity-ibc/utils/RefImplIBCERC20.sol) in the `solidity-ibc-eureka` repository.
  </Step>

  <Step title="Request Registration">
    [Join our Discord](https://discord.com/invite/interchain) and open a support ticket to request registration of your custom ERC20 contract.
  </Step>

  <Step title="Verify and Launch">
    Verify your contract on Etherscan for greater transparency. For assistance, see the [Etherscan Contract Verification page](https://etherscan.io/verifyContract). Once verified, start bridging your token with complete control over its ERC20 representation.
  </Step>
</Steps>

## Support and Resources

Need help with your custom ERC20 integration? Our team is ready to assist:

* [Join our Discord](https://discord.com/invite/interchain) and open a support ticket

Additional resources:

* For technical specifications, visit the [solidity-ibc-eureka repository](https://github.com/cosmos/solidity-ibc-eureka)
* View the [reference implementation](https://github.com/cosmos/solidity-ibc-eureka/blob/main/test/solidity-ibc/utils/RefImplIBCERC20.sol) for a sample ERC20 contract
* Learn about [Etherscan contract verification](https://etherscan.io/verifyContract) to enhance trust in your token


# Overview
Source: https://skip-go.mintlify-go.com/go/eureka/eureka-overview

An overview of IBC Eureka for developers

# IBC Eureka: Fast, Cheap, and Seamless Interoperability between Cosmos and Ethereum

## What is IBC Eureka?

IBC Eureka is the canonical implementation of IBC v2 that enables seamless interoperability between Cosmos and Ethereum ecosystem. As a subset of the proven Inter-Blockchain Communication (IBC) protocol, Eureka extends the reach of 115+ Cosmos chains to Ethereum (Q1 2025) with support for Layer 2 networks such as Base and Arbitrum or Solana to be added soon.

<CardGroup>
  <Card title="Connect Your Chain" icon="ethereum">
    Connect your Cosmos chain to Ethereum and other EVM chains with minimal cost and battle-tested security.
  </Card>

  <Card title="Instant Compatibility" icon="puzzle">
    If your chain already uses IBC, is connected to the Cosmos Hub and has been onboarded to the Skip API, you can immediately connect to Ethereum through Eureka with no new dependencies.
  </Card>
</CardGroup>

## Getting Started

To start using Eureka, you have several options:

<Steps>
  <Step title="Understand the Tech">
    Read the [Technical Overview](/go/eureka/eureka-tech-overview) to see how Eureka works.
  </Step>

  <Step title="Asset Issuers: Integrate with Eureka via Custom ERC20">
    If you're an asset issuer, the path to integrating your token with Eureka and maintaining control over its representation on Ethereum is by deploying a [Custom ERC20](/go/eureka/custom-erc20-integration). Follow our guide to learn how.
  </Step>

  <Step title="Connect with Us">
    If you're interested in integrating Eureka, contact [Jeremy](https://t.me/NotJeremyLiu) or [Susannah](https://t.me/bigsuse) to walk through the details.
  </Step>

  <Step title="Integrate Eureka">
    Follow the steps outlined in the [Integration Guide](/go/eureka/integration-guide) to get set up!
  </Step>
</Steps>

## Support and Resources

Need help with your Eureka integration? Our team is ready to assist:

* [Join our Discord](https://discord.com/invite/interchain) and open a support ticket

For technical specifications, visit the [IBC v2 Specification](https://github.com/cosmos/ibc/tree/main/spec/IBC_V2).


# Technical Overview
Source: https://skip-go.mintlify-go.com/go/eureka/eureka-tech-overview

Technical details of how IBC Eureka works

## Native IBC Security Model

Eureka implements the full IBC light client security model, providing trust-minimized verification of cross-chain transactions:

* **Light Client Verification**: Each chain runs a light client of the other chain, enabling cryptographic verification of state transitions. On the Ethereum side we use Succinct's SP1 zero-knowledge proofs for efficient verification
* **No Multisig Dependencies**: Unlike many bridge solutions, Eureka doesn't rely on trusted validator sets or multisigs for security
* **Permissionless Access**: Anyone can connect to the IBC network and Ethereum, as long as your chain has an IBC implementation, classic or v2
* **Minimal Infrastructure Overhead, no ongoing costs**: Relaying, proving and routing between the Cosmos Hub and Ethereum onto your chain is handled by the smart relayer, paid for by end users. Simply maintain an IBC classic connection to the Cosmos Hub

## Performance and Cost Efficiency

```mermaid theme={null}
graph LR
    A[Ethereum] --> |~$5 Fast, ~$1 Standard| B[Cosmos Hub]
    B --> |IBC Eureka| C[Your Cosmos Chain]
```

* **Optimized Gas Consumption**: Transfer from Ethereum to your chain, via Cosmos Hub for approximately \$5 using fast mode and less than \$1 for standard transfers
* **Fast Finality**: Assets arrive on destination chains in seconds, regardless of source chain finality times

## Native Asset Representation

* **Bank Module Integration**: Received assets live directly in the bank module as native tokens
* **No Wrapped Tokens**: Assets are not wrapped or suffixed with bridge-specific identifiers (e.g., no ETH.axl)
* **ERC20 Compatibility**: Assets can be easily represented as ERC20s in the future without conversion complexity

## How Eureka Works

Eureka connects blockchains through a combination of:

1. **IBC Protocol v2**: The standardized communication layer that defines packet formats and verification logic
2. **Solidity Implementation**: Smart contracts deployed on Ethereum and EVM chains that implement the IBC protocol (Other smart contract chains to come)
3. **Light Clients**: Each chain runs a light client of the other chain to verify state transitions. On Ethereum, this uses SP1 zero-knowledge proofs for gas-efficient verification
4. **Relayers**: IBC v2 uses relayers to send messages between chains. We facilitate and operate the relaying infrastructure for Eureka for you.

<Note>
  The IBC protocol guarantees that a packet delivered on the destination chain
  was definitely sent from the source chain, using cryptographic verification
  rather than trusted third parties.
</Note>

## Permissioned Relay

The initial rollout of IBC Eureka will use permissioned relayers for additional safety and security guarantees.
The IBC light clients will be used in the same way as when IBC is permissionless, the permissioning only means that liveness is
dependent on the permissioned relay set. Permissioning will be removed in the near future.

## Architecture Overview

```mermaid theme={null}
flowchart TD
    subgraph "Ethereum Network"
        E[Ethereum]
        ICS26[ICS26 Contract]
        ICS20[ICS20 Transfer Contract]
        LC1[Tendermint Light Client]
    end
    
    subgraph "Cosmos Hub"
        CH[Cosmos Hub]
        LC2[Ethereum Light Client]
        IBCHandler[IBC Handler]
        Transfer[Transfer Module]
    end
    
    subgraph "Your Cosmos Chain"
        YC[Your Chain]
        IBCHandler2[IBC Handler]
        Transfer2[Transfer Module]
    end
    
    E <--> ICS26
    ICS26 <--> ICS20
    ICS26 <--> LC1
    
    CH <--> IBCHandler
    IBCHandler <--> LC2
    IBCHandler <--> Transfer
    
    YC <--> IBCHandler2
    IBCHandler2 <--> Transfer2
    
    Transfer <--> |IBC Connection| Transfer2
    LC1 <--> |Relayer| LC2
```


# Integration Guide
Source: https://skip-go.mintlify-go.com/go/eureka/integration-guide

A guide on how to integrate IBC Eureka for chain developers, asset issuers, and application developers

# Types of Integrators

**There are three types of integrators of Eureka:**

1. **Chain Developers** - ensuring that your chain is compatible with Eureka and can facilitate the bridging of assets to and from other chains in the Eureka ecosystem.
2. **Asset Issuers** - ensuring the assets you care about being bridged over Eureka are properly set up in the protocol and in the Skip Go API for application developers to support easily.
3. **Application Developers** - ensuring your end users have access to Eureka assets and bridging capabilities via the Skip Go API.

## Chain Developers

**If you're developing a Cosmos-based blockchain, the easiest way to unlock Eureka assets and bridging capabilities is by opening up an IBC connection to the Cosmos Hub:**

* Requires an IBC (classic) connection to the Cosmos Hub
* No chain upgrade is needed if you're already using IBC
* Users benefit from reduced cost of asset transfers between Eureka-enabled domains through batching
* Chains only need to maintain a single relayer to the Cosmos Hub to reach the entire Eureka and IBC network

If you are interested in a direct Eureka connection to Ethereum or L2s/Solana coming later this year, please reach out to [Jeremy](https://t.me/NotJeremyLiu) or [Susannah](https://t.me/bigsuse) directly as additional integration work is required.

## Asset Issuers: Bringing Your Token to Ethereum

To bridge assets to Ethereum through Eureka while maintaining full control over your token's representation, you must deploy a custom ERC20 contract. This approach ensures you retain ownership of the token's metadata and on-chain behavior.

**Requirements:**

1. **Custom ERC20 Implementation**
   Deploy an ERC20 contract that implements our required interface standards
2. **CoinGecko Listing**
   Maintain a CoinGecko listing to ensure accurate pricing and metadata in our interfaces

**Why deploy a custom ERC20?**

* **Full Metadata Control** - Set your token's name, symbol, and other details during deployment
* **Verified Ownership** - Register the contract under your project's domain on Etherscan
* **Permanent Governance** - Maintain irrevocable control over the token's core logic

**Ready to get started?**
Follow our step-by-step [Custom ERC20 Integration Guide](/go/eureka/custom-erc20-integration) to deploy your contract.

## Application Developers

**If you're an application developer looking to give your users access to Eureka assets in your UI or to leverage them within your protocol, integrating into the Eureka ecosystem via Skip Go is super simple!**

### Requesting New Assets

If you want to enable bridging of a new asset (e.g., an Ethereum asset) to Cosmos or Eureka-connected chains, you can submit a request by [joining our Discord](https://discord.com/invite/interchain) and opening a support ticket. Our team will review your request and provide guidance on the next steps.

### New Skip Go Integrator

If you're brand new to Skip Go, read about our cross-chain developer platform on the [Getting Started](/go/general/getting-started) page will be the best resource for you to get up to speed on the capabilities of Skip Go and the various integration options.

* For the quickest and easiest integration, you can integrate the [Widget](/go/widget/getting-started) in minutes! For more control over the UI you provide your users, the [Client Library](/go/client/getting-started) is the way to go.
* The integration provides a one-click experience for users to transfer assets across the Eureka ecosystem and beyond in a single integration (via Skip Go's aggregation and composability engine).

### Current Skip Go Integrator

Ensuring Eureka works with your Skip Go integration is the same easy process as any other bridge!

<Note>
  To get routes involving Eureka assets, you must add `"eureka"` to the `experimental_features` array in your `/route` and `/msgs_direct` payload. For example: `"experimental_features": ["eureka"]` if you have no other experimental features enabled, or `"experimental_features": ["cctp", "eureka"]` if you already have other features enabled. This requirement applies to all routes involving Eureka assets, including same-chain swaps. Without this flag, Eureka assets will not be included in routing responses.
</Note>

Changes are as follows:

1. `eureka_transfer` Operation type to be expected to be returned from the `/route` and `/msgs_direct` endpoints
2. `eureka_transfer` Transfer type to be expected to be returned from the `/status` endpoint in the transfer sequence
3. `eureka` bridge type returned from the `/bridges` endpoint
4. To keep Eureka opt-in, integrators must pass `eureka` into the `experimental_features` array in the `/route` and `/msgs_direct` calls to enable Eureka routing

**What this looks like for each type of Skip Go integration:**

1. If you're using the Widget, make sure you're updated to version `3.5.0` or above and pass in `eureka` to the experimentalFeatures prop.
2. If you're using the Client Library, make sure you're updated to version `0.16.22` or above and pass in `eureka` to the experimentalFeatures param.
3. If you're integrated directly with the REST endpoints, you can find the relevant types in the API reference for the [Route Operation](/go/api-reference/prod/fungible/post-v2fungibleroute#response-operations) and for the [Lifecycle Tracking Transfer](/go/api-reference/prod/transaction/get-v2txstatus#response-transfers).


# Security Properties
Source: https://skip-go.mintlify-go.com/go/eureka/security-properties



Depending on where it is deployed, IBC Eureka might have different security properties compared to the ones in IBC Classic. This is mainly because
EVM chains do not have any form of governance, whereas Cosmos chains do.

To improve protocol and fund safety at launch, IBC Eureka is going to launch in stages, delineated by improved security properties at each stage.

## Launch stage (0)

At launch, IBC Eureka is going to be deployed on two blockchains: Ethereum and Cosmos Hub mainnet. On the Cosmos Hub side, the security properties remain
the same as in IBC Classic - governance has ultimate control over the chain, light client and channels.

On the Ethereum mainnet side, it is different - a security council will have control over contract upgradeability, pausing and light client upgrades.

### Security council

The Eureka Security Council is designated as a 5-of-7 council that can take actions such as:

* upgrading the `ICS20Transfer`, `ICS26Router`, `IBCERC20` and `Escrow` contracts
* migrating light clients in case of freezing due to misbehaviour, expiration or security vulnerabilities/incidents
* designating specific canonical names for IBC applications and light clients on Ethereum mainnet

The security council cannot take these actions instantly - the actions are timelocked using a standard OpenZeppelin `TimelockController` contract with a minimum
delay of three days. The delay gives an opportunity for the Cosmos Hub to halt inbound / outbound transfers in case of a malicious action taken by the Security Council.

The security council is composed of individuals associated with well-respected and trusted entities in the Ethereum and Cosmos communities:

* Wildcat Finance
* Informal
* Hypha
* ZK Validator
* Chorus One
* Keplr
* Interchain Labs

### Pausing council

The pausing council is designated for rapid-response to a security incident. The only actions that the pausing council can take are pausing and unpausing transfers out of the Ethereum-side contracts.

The council is composed of a subset of people in the Security Council who are going to be rapidly responding to security incidents related to canonical IBC Eureka deployments. The actions of the pausing council are not time-locked
to allow for a quick response time.

## Governance stage (1)

After the protocol has successfully launched, the next step in the IBC Eureka roadmap is to allow general contract message passing between chains.

This will enable canonical EVM Eureka deployments to be controlled by Cosmos Hub governance. As such, the security council will increase the minimum delay of the `TimelockController`
to be longer than the time it takes to pass a governance proposal on the Cosmos Hub.

This means that the security council will be much closer to becoming obsolete, while allowing the Cosmos Hub to override actions taken by the security council.

## Pausing stage (2)

After a trial period of allowing the Cosmos Hub to govern the canonical Eureka deployments, the security council will revoke its' rights and controls over canonical deployments,
fully allowing the Cosmos Hub to take over its' responsibilities.


# Setting Affiliate Fees
Source: https://skip-go.mintlify-go.com/go/general/affiliate-fees

This page covers how integrators can earn affiliate fees on swaps.

### Overview

Many teams use Skip Go as a source of a revenue for their project by charging fees on swaps. (Charging fees on transfers will be possible in the future!). We refer to these fees throughout the product and documentation as "affiliate fees"

Skip Go's affiliate fee functionality is simple but flexible -- supporting a large variety of bespoke fee collection scenarios:

* Set your desired fee level on each swap (so you can offer lower fees to your most loyal users)
* Set the account that receives the fee on each swap (so you can account for funds easily & separate revenue into different tranches)
* Divide the fee up in customizable proportions among different accounts (so you can create referral/affiliate revenue sharing programs with partners and KOLs)

### Affiliate Fees Work

1. **At this time, affiliate fees can only be collected on swaps**. We do not support collecting affiliate fees on routes that only consist of transfers (e.g. CCTP transfers, IBC transfers, etc...) even when there are multi-hop transfers. Please contact us if charging fees on transfers is important to you
2. **Affiliate fees are collected on the chain where the last swap takes place**: Skip Go aggregates over swap venues (DEXes, orderbooks, liquid staking protocols, etc...) on many different chains. Some routes even contain multiple swaps. For each individual cross-chain or single chain swap where you collect a fee, the fee is applied on the last swap and sent to an address you specify on the chain where the last swap takes place
3. **Affiliate fees are collected/denominated in the output token of each swap**: For example, if a user swaps OSMO to ATOM, your fee collection address will earn a fee in ATOM
4. **Affiliate fees are calculated using the minimum output amount, which is set based on our estimated execution price after accounting for the user's slippage tolerance** : For example, consider an ATOM to OSMO swap where min amount out is 10 uosmo and the cumulative fees are 1000 bps or 10%. If the swap successfully executes, the affiliate fee will be 1 uosmo. It will be 1 uosmo regardless of whether the user actually gets 10, 11, or 12 uosmo out of the swap

### How to Use Affiliate Fees

There are two simple steps involved in using affiliate fees:

1. **Incorporate the fee into the quote** : You need to request the route & quote with the total fee amount (in basis points) you will collect, so Skip Go can deduct this automatically from the estimated `amount_out` it returns to the user. This ensures the quote you show the user already accounts for the fee, and they won't receive any unexpectedly low amount.
2. **Set the address(es) to receive the fee**: You also need to tell Skip Go the exact address(es) to send the fee revenue to. You need to pass a list of addresses and specify a fee amount (in basis points) for each to collect.

### Incorporating Fees with `/route` and `/msgs`

When executing swaps using the `/route` and `/msgs` endpoints, you can incorporate affiliate fees by specifying the total fee during the `/route` request and detailing the fee recipients during the `/msgs` request. Below is a comprehensive guide on how to correctly implement this.

1. **Set Total Fee in `/route` Request**

In your `/route` request, include the `cumulative_affiliate_fee_bps` parameter to specify the total fee you wish to collect, expressed in basis points (bps).

* **Definition**: 1% fee = 100 basis points.
* **Example**: To collect a **0.75%** fee, set `cumulative_affiliate_fee_bps` to `"75"`.

```json theme={null}
{
  "cumulative_affiliate_fee_bps": "75",
  // ...other parameters
}
```

<Info>
  If you're using `@skip-go/client`, use camelCase: `cumulativeAffiliateFeeBps`.
</Info>

2. **Identify Swap Chain**

After the `/route` request, use the `swap_venue.chain_id` field in the response to determine which chain the swap will occur on. You'll need this information to provide valid recipient addresses in the next step.

3. **Specify Fee Recipients in `/msgs` Request**

In your `/msgs` request, define the `chainIdsToAffiliates` object to allocate fees to specific addresses on the relevant chains.

##### Structure:

```json theme={null}
{
  "chainIdsToAffiliates": {
    "<chain_id>": {
      "affiliates": [
        {
          "basisPointsFee": "<fee_in_bps>",
          "address": "<recipient_address>"
        },
        // ...additional affiliates
      ]
    },
    // ...additional chains
  }
}
```

##### Example:

```json theme={null}
{
  "chainIdsToAffiliates": {
    "noble-1": {
      "affiliates": [
        {
          "basisPointsFee": "100", // 1% fee
          "address": "noble1..."
        },
        {
          "basisPointsFee": "100", // 1% fee
          "address": "noble2..."
        }
      ]
    },
    "osmosis-1": {
      "affiliates": [
        {
          "basisPointsFee": "200", // 2% fee
          "address": "osmo1..."
        }
      ]
    }
  }
}
```

**Notes:**

* The **sum** of `basisPointsFee` values across all affiliates **on the swap chain** must equal the `cumulative_affiliate_fee_bps` set in the `/route` request.
* All addresses must be **valid on the chain where the swap will take place**. Invalid addresses will result in a `400` error.
* If using `@skip-go/client`, remember to use camelCase (e.g., `basisPointsFee`) in the config.

### Incorporating Fees with `/msgs_direct`

<Warning>
  We recommend using `/route` and `/msgs` over `/msgs_direct` due to the added complexity when handling fees with `/msgs_direct`.
</Warning>

When using the `/msgs_direct` endpoint, you need to specify affiliate fees for **every possible chain** the swap might occur on since the swap chain is determined during the request.

### Steps:

1. **Define `chainIdsToAffiliates` for All Potential Swap Chains**
   * Use the `chainIdsToAffiliates` object to map each potential `chain_id` to its corresponding affiliates.
   * For each `chain_id`, provide a list of `affiliates`, each with:
     * `basisPointsFee`: The fee amount in basis points (bps).
     * `address`: The recipient's address on that chain.

2. **Include Entries for Every Possible Chain**

   * Retrieve all potential swap chains by querying the `/v2/fungible/swap_venues` endpoint.
   * Include an entry in `chainIdsToAffiliates` for each `chain_id` from the list.

3. **Ensure Fee Consistency Across Chains**

   * The **sum** of `basisPointsFee` values for affiliates on each chain must be **equal** across all chains.
   * This consistency is necessary because the fee amount used in the swap must be the same, regardless of which chain the swap occurs on.
   * If the fee sums differ between chains, the request will return an error.

***

### Example Request:

```json theme={null}
{
  "chainIdsToAffiliates": {
    "noble-1": {
      "affiliates": [
        {
          "basisPointsFee": "100", // 1% fee
          "address": "noble1..."
        },
        {
          "basisPointsFee": "100", // 1% fee
          "address": "noble2..."
        }
      ]
    },
    "osmosis-1": {
      "affiliates": [
        {
          "basisPointsFee": "200", // 2% fee
          "address": "osmo1..."
        }
      ]
    },
    // Include entries for all other potential chains
  },
  // ...other parameters
}
```

**Notes:**

* In the example above, the total fee for each chain is **200 bps (2%)**.
* Ensure that all addresses are **valid** on their respective chains.

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Requesting & Using API Keys
Source: https://skip-go.mintlify-go.com/go/general/api-keys



## Summary

Authentication and authorization for the Skip Go API are managed via API keys.

This document covers:

1. Why you should use an API key
2. How to get your key set up
3. How to use the key in your requests

<Note>
  **API Keys have replaced `client_id`**

  Historically, we used the `client_id` passed as a request parameter to identify and authenticate integrators. This system has been fully deprecated. If you're currently using `client_id`, you should transition to using an API key.

  (We're making this transition because `client_id` didn't abide by best practices for security, and we could only attach limited functionality to it, since it was passed in the request body instead of a header.)
</Note>

## Benefits of using an API key

Technically, you can access most of the basic functionality of the Skip Go API without an API key. But there are numerous benefits to authenticating yourself with a key:

* **No rate limit**: Integrators that do not pass a valid API key in their requests will be subject to a restrictive global rate limit, shared with all other unauthenticated users.
* **Improved fee revenue share pricing**: Unauthenticated integrators will be subject to a 25% revenue share on their fee revenue by default. Authenticated integrators who use API keys will be subject to a cheaper 20% revenue share by default.
* **Access to privileged features:** Integrators who authenticate with an API key will receive access to premium features that we cannot offer to the general public (e.g. Gas estimation APIs, universal balance query APIs, etc...)
* **Metrics on your volume and revenue:** Authenticated integrators will receive access to monthly statistics regarding their total swap and transfer volume and the amount of fee revenue they've earned. They will also receive annual transaction data for taxes.

## How to get an API Key

### 1. Request an API Key

Open a support ticket on our [Discord](https://discord.com/invite/interchain) and tell our customer support that you'd like an API key.

Please provide the following information in your request to help us get to know your project:

1. Your name (or pseudo-anon name) and contact info (ideally Telegram, but possibly Email, Signal, etc...)
2. Your project name
3. A brief, 1-2 sentence description of your project

The customer support team member at Skip will establish an official channel of communication between Skip and your project (e.g. an email thread or a telegram group etc...).

### 2. Store the API Key Securely

**You should store the API key immediately when you create it. We do not store your raw API key in our server for security reasons, so we will not be able to access it for you if you lose it.**

It is important to keep your API key private. Anyone with your API key can make requests to the Skip Go API as you, getting access to your rate limit, privileged features, and affecting your revenue and volume statistics.

## How to use an API key

### Via REST API

You should pass your API key in every call to the Skip Go API using the `authorization` HTTP header.

For example:

```
curl -X 'POST' \
  'https://api.skip.build/v2/fungible/route' \
  -H 'accept: application/json' \
  -H 'authorization: <YOUR API KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
  "amount_in": "1000000",
  "source_asset_denom": "uusdc",
  "source_asset_chain_id": "axelar-dojo-1",
  "dest_asset_denom": "uatom",
  "dest_asset_chain_id": "cosmoshub-4",
  "cumulative_affiliate_fee_bps": "0",
  "allow_multi_tx": true
}'

```

### Via `@skip-go/client`

For users of the `@skip-go/client` TypeScript package (v1.0.0+), you can configure your API key using either `setApiOptions` or `setClientOptions` at initialization. The library will automatically include it in the `authorization` header of all requests.

For example:

```typescript theme={null}
import { setApiOptions, setClientOptions } from "@skip-go/client";

// Option 1: For basic API calls
setApiOptions({
	apiKey: <YOUR API KEY>,
});

// Option 2: For executeRoute functionality
setClientOptions({
	apiKey: <YOUR API KEY>,
	// ... other options like endpointOptions, aminoTypes, etc.
});
```

Note: The `SkipClient` class has been removed in v1.0.0. Instead, you import and use individual functions directly after setting the API options. Also note that `apiURL` has been renamed to `apiUrl` to follow camelCase conventions.

### Setup a Proxy to Receive Skip Go API Requests and Add the API Key

To keep your API key secure and private, we recommend that you proxy the API requests from the frontend to your own backend--where you can add your API key in the header before forwarding the request to the Skip Go API.

The snippets below show you how to use Next.js/Vercel for this kind of proxying. It only takes a moment to set up.

```typescript theme={null}
// This handler runs server-side in Vercel and receive requests from the frontend
// sent to APP_URL/api/skip

import type { NextApiRequest } from 'next';
import { PageConfig } from 'next';

import { API_URL } from '@/constants/api';

export const config: PageConfig = {
  api: {
    externalResolver: true,
    bodyParser: false,
  },
  runtime: 'edge',
};

export default async function handler(req: NextApiRequest) {
  try {
    const splitter = '/api/skip/';

    const [...args] = req.url!.split(splitter).pop()!.split('/');
    const uri = [API_URL, ...args].join('/');
    const headers = new Headers();
    if (process.env.SKIP_API_KEY) {
      headers.set('authorization', process.env.SKIP_API_KEY);
    }
    return fetch(uri, {
      body: req.body,
      method: req.method,
      headers,
    });
  } catch (error) {
    const data = JSON.stringify({ error });
    return new Response(data, { status: 500 });
  }
}
```

```typescript theme={null}
// This config maps the requests to APP_URL/api/skip to the handler we just defined
	rewrites: async () => [
    {
      source: "/api/skip/(.*)",
      destination: "/api/skip/handler",
    },
  ],
// other config...
```

```typescript theme={null}
// This configures your client to make requests to your proxy service instead of
// the standard Skip Go API backend directly
import { setApiOptions, setClientOptions } from '@skip-go/client';

const appUrl =
  process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview' ||
  process.env.NEXT_PUBLIC_VERCEL_ENV === 'staging'
    ? typeof window !== 'undefined'
      ? `https://${window.location.hostname}`
      : process.env.NEXT_PUBLIC_VERCEL_URL
    : 'https://<YOUR APP URL>';

// Option 1: For basic API calls
setApiOptions({
  // you don't need to pass apiKey since you already have it in your proxy handler
  apiUrl: `${appUrl}/api/skip`,
});

// Option 2: For executeRoute functionality
setClientOptions({
  // you don't need to pass apiKey since you already have it in your proxy handler
  apiUrl: `${appUrl}/api/skip`,
  // ... other options if needed
});
```

```
// These are environment variables you set in Vercel
// to store your API key securely in the backend
SKIP_API_KEY=<YOUR API KEY>
```

## How to Request Volume & Revenue Statistics

Just return to your official communication channel with Skip (probably a Telegram channel) and request the data. We can share monthly reports. Eventually, we will create a customer portal with dashboards, so you'll have access to all the data you need in a self-service manner.

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Skip Explorer Integration
Source: https://skip-go.mintlify-go.com/go/general/explorer-integration

Guide to integrating Skip Explorer v2 for transaction visualization and tracking in your applications.

## Overview

Skip Explorer v2 provides a user-friendly interface for visualizing cross-chain transactions and tracking their progress. This guide covers basic explorer usage and how integrators can leverage it to enhance their user experience.

## Basic Explorer Usage

Users can view transaction details by navigating to [explorer.skip.build](https://explorer.skip.build) and entering:

* **Transaction Hash**: Any transaction hash from a supported chain
* **Chain ID**: The chain where the transaction occurred

The explorer will automatically detect and display:

* Transaction status and progress
* Cross-chain hops and bridges used
* Asset transfers and swaps
* Real-time updates as transactions progress

## Integration for Custom Frontends

If you're building a custom frontend and want to provide users with rich transaction visualization, you can generate explorer links that include comprehensive route data.

### Basic Explorer Links

For simple transaction tracking, redirect users to the explorer with URL parameters:

* `tx_hash`: Comma-separated list of transaction hashes
* `chain_id`: The initial source chain ID
* `is_testnet`: Optional boolean parameter for testnet transactions

**Example:**

```
https://explorer.skip.build/?tx_hash=ABC123,DEF456&chain_id=osmosis-1&is_testnet=true
```

This approach works well when you have transaction hashes but limited route context.

### Advanced Rich Data Integration

For a superior user experience with complete transaction context, encode your route data as base64 and pass it via the `data` parameter. This enables the explorer to display detailed multi-hop transaction flows, user addresses, and complete route information.

**Example:**

```
https://explorer.skip.build/?data=eyJyb3V0ZSI6ey4uLn0sInVzZXJBZGRyZXNzZXMiOnsuLi59fQ==
```

#### Required Data Structure

The base64-encoded data must contain a JSON object with this structure:

```typescript theme={null}
{
  route: SimpleRoute,                    // Route from /v2/fungible/route API response
  userAddresses: UserAddress[],          // User wallet addresses for each chain
  transactionDetails: TransactionDetails[] // Transaction details from /v2/tx/status
}
```

#### Implementation

```typescript theme={null}
import { SimpleRoute, UserAddress, TransactionDetails } from '@skip-go/client';

// Collect your data from Skip Go APIs
const routeData = {
  route: simpleRoute,              // From your /v2/fungible/route call
  userAddresses: userAddresses,    // Your user's addresses per chain  
  transactionDetails: txDetails    // From your /v2/tx/status polling
};

// Encode for the explorer
const jsonString = JSON.stringify(routeData);
const base64Encoded = btoa(jsonString); // Browser-compatible base64 encoding

// Generate the rich explorer URL  
const explorerUrl = `https://explorer.skip.build/?data=${base64Encoded}`;

// Redirect user or open in new tab
window.open(explorerUrl, '_blank');
```

## Benefits for Your Users

### Basic Integration Benefits

* **Quick Access**: Users can easily view transaction details without leaving your app
* **Multi-Chain Support**: Works across all supported chains and bridges
* **Real-time Updates**: Live transaction status and progress tracking

### Advanced Integration Benefits

* **Complete Transaction Context**: Users see the full route, not just individual transactions
* **Multi-Hop Visualization**: Clear view of complex transfers across chains and bridges
* **Address Mapping**: Explorer knows which addresses belong to the user
* **Real-time Status**: Current transaction state integrated with visual progress
* **Shareable Links**: Users can bookmark or share complete transaction context

## Best Practices

### When to Use Basic vs Advanced Integration

**Use Basic Integration when:**

* You only have transaction hashes available
* Users initiated transactions outside your application
* You want minimal integration effort

**Use Advanced Integration when:**

* You have complete route information from Skip Go APIs
* Users initiated transactions through your application
* You want to provide the richest user experience

## Common Use Cases

### Transaction Confirmation Pages

After users submit a transaction, redirect them to the explorer with full context:

```typescript theme={null}
// After transaction submission
const explorerUrl = generateExplorerLink(routeData);
window.location.href = explorerUrl;
```

### Transaction History

Provide explorer links for each historical transaction:

```typescript theme={null}
// In transaction history component
{transactions.map(tx => (
  <div key={tx.id}>
    <span>{tx.amount} {tx.asset}</span>
    <a href={generateExplorerLink(tx)} target="_blank">
      View Details
    </a>
  </div>
))}
```

### Support and Debugging

Help users troubleshoot failed transactions by providing detailed explorer views:

```typescript theme={null}
// For failed transactions
const supportUrl = generateExplorerLink(failedTransaction);
// Share this URL with support team or user
```

<Info>
  **Best Practice**: Always use the advanced base64 approach when you have access to complete route information from your Skip Go integration. This provides the richest user experience in the explorer.
</Info>


# FAQ
Source: https://skip-go.mintlify-go.com/go/general/faq



### General / Background

#### How can I get help using Skip Go?

You can reach us easily at [our discord](https://discord.gg/interchain) or in [our developer support channel on Telegram](https://t.me/+3y5biSyZRPIwZWIx)

#### Who uses Skip Go?

Many teams use Skip Go to make it easier for them to build multi-chain flows, including:

* Every major interchain wallet (Keplr, Leap, IBC wallet, Terra Station, all the metamask snap teams)
* Osmosis asset deposit page
* Many major interchain dapps (e.g. Stargaze, Stride, Astroport, Cosmos Millions)
* Many interchain defi frontends (e.g. Coinhall, fortytwo.money)
* TrustWallet
* Our own frontend ([https://go.skip.build](https://go.skip.build))
* ...and many more

#### How many chains does Skip Go API support?

More than 70+. We support:

* Almost every IBC-enabled chain
* Every EVM chain Axelar supports
* Every EVM chain and rollup Hyperlane supports
* Every chain CCTP supports

...with more coming soon!

#### Which bridges and message passing protocols does Skip Go support?

* IBC
* Hyperlane
* Axelar
* CCTP
* Neutron's native bridge
* Stargate
* Layerzero
* Eureka
* GoFast

...with more coming soon!

#### What DEXes does the Skip Go support?

* Osmosis
* Astroport across Terra, Neutron, Sei, and Injective
* White Whale across Terra, Migaloo, and Chihuahua
* Uniswap v2/v3
* Aerodrome
* Velodrome
* Tower
* Elys
* Dojoswap

...with many more coming soon

#### What is the maximum transfer limit for CCTP?

CCTP transfers have a maximum limit of 1,000,000 USDC per transfer.

#### How do I get Skip Go API to support my chain?

Please see the [Chain Support Requirements](/go/support-requirements/chain-support-requirements) document to ensure your chain meets the necessary requirements and submit the chain support request form linked in that doc.

#### How do I get the Skip Go API to support my token?

Please complete the necessary steps detailed in the [Token & Route Support Requirements](/go/support-requirements/token-support-requirements) doc.

#### How do I get the Skip Go API to support a route for a particular token to a remote chain?

Please complete the necessary steps detailed in the [Token & Route Support Requirements](/go/support-requirements/token-support-requirements) doc for the destination chain and token in question.

#### How do I get the Skip Go API to route swaps to my swap venue or DEX?

Please see the [Swap Venue Requirements](/go/support-requirements/swap-venue-requirements) page to ensure your DEX meets the necessary requirements then submit the swap venue request form linked in that doc.

#### How long does it take to build an application with Skip Go?

5-30 minutes

#### Why do I keep getting rate limited?

You need to request an API key from the core team to use Skip Go without limitations.

Pass your API key into all requests with the `client_id` parameter.

#### Does the Skip Go API cost anything?

No, not at this time. We offer unlimited usage at zero cost.

In the future we will introduce two pricing plans:

1. **Fee revenue sharing, unlimited usage**: For customers who use Skip Go API's fee functionality to charge their end-users fees on swaps, we will collect a portion of the fee revenue that you earn. Higher volume users will unlock lower fee tiers.
2. **API Usage Pricing**: For customers who do not charge fees, we will offer monthly and annual plans that allow usage of the API up to some number of requests per month. We will offer several pricing tiers, where higher tiers support higher rate limits and more monthly requests (similar to coingecko, infura, etc..)

#### I have questions, comments, or concerns about Skip Go. How can I get in touch with you?

Join [our Discord](https://discord.gg/interchain) and select the "Skip Go Developer" role to share your questions and feedback.

### Refunds and other financial policies

#### Does Skip ever refund users for swaps or transfers with "bad prices"?

**No.**

Users are responsible for the transactions they sign in all cases:

1. **If our smart contracts behave as expected (i.e. amount\_out exceeds min\_amount\_out signed by the user or amount\_in is less than max\_amount\_in signed), Skip will not offer users refunds, slippage rebates, or any other form of compensation for any reason**. Skip does not accept or bare any financial, legal, or practical responsibility for lost funds in the event a user or integrator believes a particular route is inadequate, bad, supoptimal, low liquidity, or otherwise not performant enough.
2. **If the smart contracts Skip Go depends on do not behave as expected, users who encounter and suffer bugs may report them in exchange for a bug bounty payment**. See the section on our bug bounty policy below.

Integrators are solely and completely responsible for building UIs that maximally protect users from harming themselves by swapping or transferring at unfavorable prices. To help facilitate this goal, we provide:

* Detailed information about quote quality, on-chain liquidity, fees, and price estimates in our API response objects (e.g. estimates of the USD value of amount in and amount out, on-chain price impact, etc...)
* Extensive guidance about how to build S.A.F.E. interfaces in our docs: [SAFE Swapping: How to protect users from harming themselves](/go/advanced-swapping/safe-swapping-how-to-protect-users-from-harming-themselves)
* Hands-on interface design feedback based on years of working with dozens of top interfaces

#### Does Skip provide refunds to users if an interface created an transaction that called a Skip contract incorrectly?

**No**

1. If an integrator or end user misuses one of our contracts intentionally or by accident (e.g. calls the contract with incorrect call data, sends tokens to a contract not designed to receive tokens), Skip bares no financial, legal, or operational responsibility for funds that may be lost as a result.
2. Skip and its affiliates do not have the ability to upgrade contracts to receive or "unstick" lost funds even if we wanted to. We do not own or control the contracts in Skip Go any more than you do.

#### Are there any circumstances under which Skip would offer a refund to an end user for any reason?

**No**

Skip accepts no legal, financial, or operational responsibility for the applications the integrators of the Skip Go API create using its data and services. Skip also accepts no legal, financial, or operational responsibility for the positive or negative financial outcomes of the swaps, transfers, and other transactions that end users may create in these interfaces.

Even in the event a user lost funds as a result of a bug, Skip does not claim any legal, financial, or practical liability for lost funds. In these cases, users may report the bug to Skip's bug bounty program.

### Bug Bounty Policy

#### Does Skip Go offer bug bounties?

Skip may provide a financial bug bounty of up to \$25,000 as compensation to users who report a reproducible catastrophic failure of a smart contract or other piece of software that the Skip team developed. Examples of catastrophic failures include:

* Receiving fewer tokens in the output of a swap than specified and signed over in the min\_amount\_out field of the transaction calldata
* Total loss of funds resulting from a transaction where the call data is correctly formed -- in other words, where the contract call data matches the specification provided by the Skip team and generated by the Skip Go API product

The size of the bug payment is determined at Skip's sole discretion. It may depend on a variety of factors, including: quality, accuracy, and timeliness of the report & severity/exploitability of the bug. Skip is not legally obligated to provide any payment amount.

In the event a user lost funds as a result of a bug, Skip does not claim any legal, financial, or practical liability for lost funds. The size of the bug bounty will not depend directly or indirectly on the amount of funds the user lost. The bug bounty does not constitute a refund under any definition. It is a reward for identifying and characterizing gross failures in intended behavior of the Skip software.

#### How do I report a bug to the bug bounty program?

Please get in touch with our team on [Discord](https://discord.gg/interchain) if you believe you have a bug to report.

### Technical Support

#### Is go.skip.build open source? Where can I find the code?

* Yes! The code for go.skip.build -- our multi-chain DEX aggregator + swapping/transferring interface is open source
* You can find the code at [https://github.com/skip-mev/skip-go-app](https://github.com/skip-mev/skip-go-app) -- Feel free to use it to guide your own integration

#### What's the default IBC-Transfer timeout on the messages returned by `/fungible/msgs` and `/fungible/msgs_direct`?

* 5 minutes

#### What technologies does Skip Go use under the hood?

* IBC and...
  * `ibc hooks` and `ibc callbacks`: Enables the Skip Go swap contracts to be executed as callbacks of IBC transfers, which enables constructing transactions that can transfer tokens to a chain with a swap venue, perform a swap, and transfer them out -- without multiple signing events / transactions.
    * Skip Go will likely not support DEXes on any chains that do not have `ibc-hooks` or equivalent functionality
  * `Packet-forward-middleware`(PFM): Enables incoming IBC transfers from one chain to atomically initiate outgoing transfers to other chains. This allows the chain with PFM to function as the intermediate chain on a multi-hop route. This is especially valuable for chains that issue assets for use throughout the interchain (e.g. Stride + stATOM, Noble + USDC, Axelar + axlUSDC)
  * (This [article we wrote](https://ideas.skip.build/t/how-to-give-ibc-superpowers/81) goes into more detail about both technologies and how to adopt them on your chain)
* [Axelar](https://axelar.network/): A cross-chain messaging protocol that supports a wide variety of EVM chains and connects to Cosmos
* [CCTP](https://www.circle.com/en/cross-chain-transfer-protocol): A cross-chain messaging protocol built by Circle (the issuer of USDC) to move USDC between chains without trusting any parties other than Circle (which USDC users already trust implicitly)
* [Hyperlane](https://www.hyperlane.xyz/): A cross-chain messaging protocol that allows developers to deploy permissionlessly and choose their own security module
* [Go Fast](https://skip-protocol.notion.site/EXT-Skip-Go-Fast-b30bc47ecc114871bc856184633b504b): A decentralized bridging protocol that enables faster-than-finality cross-chain actions across EVM and Cosmos
* [Eureka](https://docs.skip.build/go/eureka/eureka-overview): IBC v2 that enables seamless interoperability between Cosmos and Ethereum ecosystem. Eureka uses Succinct's SP1 zero-knowledge proofs for gas-efficient verification of Cosmos state on Ethereum
* [Stargate](https://docs.skip.build/go/advanced-transfer/experimental-features#stargate-%E2%80%9Cstargate%E2%80%9D): Support for routing over the Stargate V2 bridge on EVM chains incl. Sei EVM
* [Layerzero](https://docs.skip.build/go/advanced-transfer/experimental-features): A omnichain messaging protocol that sends data and instructions between different blockchains

#### How do affiliate fees work?

* Affiliate fees are fees developers using Skip Go charge their end-users on swaps. We support multiple parties taking and sharing fees. For example, if a defi frontend uses the widget a wallet team builds and distributes, the makers of the widget and the users of the widget can separately charge affiliate fees.
* Fees are calculated in basis points or "bps". One basis point equals one one-hundredth of a percent. So 100 bps = 1% fee
* **Affiliate fees are calculated based off the minimum amount out and are taken/denominated in the output token.** For example, consider an ATOM to OSMO swap where min amount out is 10 uosmo and the cumulative fees are 1000 bps or 10%. If the swap successfully executes, the affiliate fee will be 1 uosmo. It will be 1 uosmo regardless of whether the user actually gets 10, 11, or 12 uosmo out of the swap.
* **When performing a swap with an exact amount in, affiliate fees are accounted for in the `amount_out` returned by `/route`**. More plainly, the Skip Go API subtracts off expected affiliate fees prior to the `amount_out` calculation, so that it represents an accurate estimate of what the user will receive at the end of the swap, net of fees. To be exact, the user will probably receive more than the amount out because the actual fee is not known at the time of this calculation / estimate. It's not known until later when slippage is set. So the user will end up paying `slippage_percent`\*`amount_out` less than the API predicts. This is good for the user because the estimated amount out will likely be lower than the actual amount they receive, offering a buffer that protects the user from the effects of slippage.

#### Why does `/assets_from_source` only return assets that are reachable via transfers but not swaps?

We're considering adding support for swappable destinations to `/assets_from_source`, but we're not prioritizing it because almost every asset is reachable via swapping from every other asset. So for 99.99% of use cases, this endpoint would just return a massive amount of fairly uninformative data, if we added destinations reachable via swaps.

#### Why does the Skip Go API sometimes say a route doesn't exist when it should (e.g. transferring ATOM to Stargaze)?

There are two common reasons Skip Go API is missing a route that a user thinks might exist:

1. **No one has ever used it:** By default, the Skip Go API does not recommend channels that have never been used or denoms that it has not seen. For example, if no one has transferred Neutron to Stargaze, the Skip Go API will not recommend a route to do so -- even if a direct connection exists between the two chains.
2. **Expired clients:** Frequently, existing connections between chains expire when they're not used for a period of time that exceeds the "light client trusting period. The Skip Go API indexes all chains every couple of hours to identify these cases and prevent users from accidentally attempting transfers.

*A common gotcha:* `/assets_from_source` only returns assets reachable in a single transaction by default. If you'd like to have access to routes that require multiple transactions, set the `allow_multi_tx` flag to `true` in the input.

#### How long does relaying an IBC packet take?

It depends on many factors, including how many relayers are covering a particular channel, block times, the time-to-finality of the source chain, whether relayers are live, how many packets relayers are waiting to batch together, and much more...

**In short, it can range from several seconds to minutes (or never) in the worst case.** After a timeout window, a packet won't be valid on the destination chain when it gets relayed. This timeout is set to 5 minutes for all packets created via the Skip Go API. It's important to understand what happens to user tokens in the event of timeouts. You can read about that in [Cross-chain Failure Cases](../advanced-transfer/handling-cross-chain-failure-cases)

For now, we recommend making a small warning or disclaimer to users on your application, similar to the following:

> This swap contains at least one IBC transfer.
>
> IBC transfers usually take 10-30 seconds, depending on block times + how quickly relayers ferry packets. But relayers frequently crash or fail to relay packets for hours or days on some chains (especially chains with low IBC volume).
>
> At this time, \[OUR APPLICATION]does not relay packets itself, so your swap/transfer may hang in an incomplete state. If this happens, your funds are stuck, not lost. They will be returned to you once a relayer comes back online and informs the source chain that the packet has timed out. Timeouts are set to 5 minutes but relayers may take longer to come online and process the timeout.

#### Why is the time to relay a packet so variable? And why can IBC relaying be unreliable today?

IBC relayers do not receive payments for relaying user packets or for relaying light client updates. In fact, they have to pay gas for the every packet they relay. That means relaying is strictly a charitable, money-losing operation with fixed infrastructure costs from running nodes + the relayer process, as well as variable costs from user gas.

#### How long does it take to transfer between Cosmos and EVM ecosystem?

In general, transfers take as long as it takes for the source chain to "finalize". That means:

* Transfers originating on EVM chains will take 30 minutes or more. The reason is that most EVM chains take a long time (30+ minutes) to finalize, which means the bridges we rely on do not register the tokens on the source chain as "locked" in the bridge for at least that long.
* Transfers originating on Cosmos chains will finish in less than 30 seconds usually (barring IBC relayer failures) because Cosmos chains have "fast" or "single slot finality". Almost as soon as the block that contains your transfer gets created, its included irreversibly in the chain

#### If Skip doesn't charge fees, how come some simple transfers seem to have a fee taken out of them?

This happens because many of the bridges (which Skip rely on) take fees to pay for gas and the cost of operating their protocol.

<CodeGroup>
  ```ts entrypointsignAmino theme={null}
  import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";

  const txRaw = await signAmino(
  	client,
    signer as OfflineAminoSigner,
    msgJSON.sender,
    [
    	{
    		typeUrl: multiHopMsg.msg_type_url,
    		value: msg.value,
    	},
    ],
      {
        amount: [coin(0, feeInfo.denom)],
        gas: `${simulatedGas * 1.2}`,
      },
        "",
          {
          accountNumber: acc?.accountNumber ?? 0,
          sequence: acc?.sequence ?? 0,
          chainId: multiHopMsg.chain_id,
        }
  );

  const txBytes = TxRaw.encode(txRaw).finish();

  tx = await client.broadcastTx(txBytes, undefined, undefined);
  ```

  ```ts theme={null}
  async function signAmino(
    client: SigningStargateClient,
    signer: OfflineAminoSigner,
    signerAddress: string,
    messages: readonly EncodeObject[],
    fee: StdFee,
    memo: string,
    { accountNumber, sequence, chainId }: SignerData
  ) {
    const aminoTypes = new AminoTypes(createDefaultAminoConverters());

    const accountFromSigner = (await signer.getAccounts()).find(
      (account) => account.address === signerAddress
    );
    if (!accountFromSigner) {
      throw new Error("Failed to retrieve account from signer");
    }

    const pubkey = encodePubkey(encodeSecp256k1Pubkey(accountFromSigner.pubkey));

    const signMode = SignMode.SIGN_MODE_LEGACY_AMINO_JSON;

    const msgs = messages.map((msg) => aminoTypes.toAmino(msg));

    msgs[0].value.memo = messages[0].value.memo;

    const signDoc = makeSignDoc(
      msgs,
      fee,
      chainId,
      memo,
      accountNumber,
      sequence
    );

    const { signature, signed } = await signer.signAmino(signerAddress, signDoc);

    const signedTxBody = {
      messages: signed.msgs.map((msg) => aminoTypes.fromAmino(msg)),
      memo: signed.memo,
    };

    signedTxBody.messages[0].value.memo = messages[0].value.memo;

    const signedTxBodyEncodeObject: TxBodyEncodeObject = {
      typeUrl: "/cosmos.tx.v1beta1.TxBody",
      value: signedTxBody,
    };

    const signedTxBodyBytes = client.registry.encode(signedTxBodyEncodeObject);

    const signedGasLimit = Int53.fromString(signed.fee.gas).toNumber();
    const signedSequence = Int53.fromString(signed.sequence).toNumber();

    const signedAuthInfoBytes = makeAuthInfoBytes(
      [{ pubkey, sequence: signedSequence }],
      signed.fee.amount,
      signedGasLimit,
      signed.fee.granter,
      signed.fee.payer,
      signMode
    );

    return TxRaw.fromPartial({
      bodyBytes: signedTxBodyBytes,
      authInfoBytes: signedAuthInfoBytes,
      signatures: [fromBase64(signature.signature)],
    });
  }
  ```
</CodeGroup>

#### How should I set gas prices for Cosmos transactions?

We recommend setting Cosmos chain gas prices using the chainapsis keplr-chain-registry: [https://github.com/chainapsis/keplr-chain-registry](https://github.com/chainapsis/keplr-chain-registry). In our experience, this registry overestimates gas prices somewhat -- but this leads to a very good UX in Cosmos because:

* Transactions almost always make it on chain
* Gas prices are very cheap -- so overestimation is not costly

Soon, the Skip Go API will surface recommended gas price too, and we will release a client-side library that will abstract away this area of concern.

#### How should I set gas amount for Cosmos transactions?

We recommend using the [Gas and Fee Tooling](/go/client/balance-gas-and-fee-tooling) available in the [Skip Go Client TypeScript Package](https://www.npmjs.com/package/@skip-go/client).

#### What does it mean when the docs say an endpoint is in "ALPHA" or "BETA"?

This means we may make breaking changes to them at any time.

### What are the Skip Go app environments?

The Skip Go app is available in three environments: mainnet, testnet, and dev.

The mainnet/production user facing app runs at [https://go.skip.build](https://go.skip.build). It connects to mainnet chains and uses the production API. This is the version that most users interact with.

The testnet app runs at [https://testnet.go.skip.build](https://testnet.go.skip.build). It connects to testnet chains but still uses the production API. This setup is useful when you want to test on testnet without changing API behavior.

The dev app runs at [https://dev.go.skip.build](https://dev.go.skip.build). It connects to mainnet chains but uses a development version of the API that hasn’t been released to production yet.

#### What does `cumulative_fee_bps` in `/route` mean?

This is where you specify the fee amount in bps aka "bips". (1 bp = 1 / 100th of a percent; 100 bps = 1%)

By specifying it in route, the Skip Go API can adjust the quote that it gives back to you, so that it shows output token estimate net of fees. This ensures the amount the end user gets out of the swap always aligns with their expectations.

The parameter uses the word "cumulative" (i.e. summing over a set) because the API supports multiple partners charging affiliate fees. This parameter should be set to the sum of all of those component fees. (For example, if a widget provider charges a 5 bp fee, and the frontend developer integrating that widget charges a 10 bp fee, `cumulative_fee_bps=15`)

### Misc

#### Is Skip doing anything to make IBC relaying more reliable?

* In the short term, we are adding real time data about relayer + channel health to Skip Go API, so we can accurately predict how long it will take to relay a packet over a channel + the packet tracking + relaying into the API.
* In the medium term, we're going to enable multi-chain relaying through Skip Go API. This will be a paid service.
* In the long term, we're working to build better incentives for relaying, so relayers don't need to run as charities. (Relayers do not receive fees or payment of any kind today and subsidize gas for users cross-chain)


# Getting Fee Info
Source: https://skip-go.mintlify-go.com/go/general/fee-info

Understand how Skip Go handles user-facing fees

## Background

This doc describes functionality in Skip Go for accessing standardized information about the various fees that a user can incur while swapping or transferring. Common fees include:

* Affiliate fees (e.g. fees you charge the user for swapping on your frontend)
* Bridge and relayer fees
* Smart Relayer fees
* Gas fees

### How Bridging Fees Are Applied

The method for applying bridging fees depends on the source chain of the transfer:

* **EVM-Source Transfers**: When a bridge transfer originates from an EVM-based chain (e.g., Ethereum), and the fee is paid in the native token of that chain (like ETH), the fee is typically an *additional charge* on top of the amount being transferred. This approach is common among underlying bridge providers, and we maintain this behavior for consistency across all EVM-source transfers, whether for ERC20 tokens or native assets.

* **Cosmos-Source Transfers**: For transfers originating from Cosmos-based chains, bridging fees are *deducted directly* from the transferred asset amount. Consequently, the amount received on the destination chain will reflect this deduction.

## Understanding incurred fees from all sources: `estimated_fees`

`estimated_fees` in the response of `/route` and `/msgs_direct` provides a `Fee` array where each entry gives information about a particular fee.

Each `Fee` object in the array will have the following attributes:

* `fee_type`: Enum giving the kind of fee — `SMART_RELAY` , `SWAP` , `BRIDGE`, `RELAY` , `GAS`
* `bridge_id` : If the fee is a relayer fee (`RELAY`) or a bridge fee (`BRIDGE`), this gives the ID of the bridge charging the fee (or the bridge where the relayer is providing a service)
* `amount` : The amount of the fee (expressed in the token the fee will be charged in)
* `usd_amount`: Estimated USD value of the fee
* `origin_asset` : An `Asset` object containing useful metadata for displaying and identifying the token in which the fee is denominated
* `chain_id` : Chain ID where the fee will be collected
* `denom` : Denom of the token in which the fee is denominated
* `tx_index`: The zero-indexed identifier of the transaction where the user will incur this fee (For multi-transaction routes, fees may be incurred after the first transaction)
* `operation_index`: The zero-indexed entry in the operations array where the user will incur this fee

<Warning>
  **Included Fees & Current Limitations**

  The `estimated_fees` array consolidates certain fees for easier display. Currently, it includes:

  * `FeeType: SMART_RELAY` for CCTP bridge transfers.
  * `FeeType: BRIDGE` fees for the following specific bridges: `AXELAR`, `HYPERLANE`, and `GO_FAST`.

  Please note that fees for other bridges (`IBC`, `Stargate`, `LayerZero`, etc.) and other fee types like `Swap` or `Gas` are not yet included here and the steps where these fees occur are detailed in the `operations` array. We plan to expand the coverage of `estimated_fees` in the future.
</Warning>

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Introduction
Source: https://skip-go.mintlify-go.com/go/general/getting-started

This pages explains what the Skip Go API is, gives examples of applications built with it, and provides guidance on standard ways to use it.

<Frame>
  <img alt="" />
</Frame>

## 👋 Introduction

Welcome to the Skip Go API docs!

**Skip Go API is an end-to-end interoperability platform that enables developers to create seamless cross-chain experiences for their end users with a variety of underlying DEXes and cross-chain messaging protocols, including IBC, CCTP, Hyperlane, Eureka, Stargate, Gofast and Axelar. We're on a mission to make all interop dead easy for developers and their users!**

Unlike most aggregators, Skip Go API is based around the idea of composing many underlying bridging and swapping operations to create multi-hop routes that can connect any two chains and tokens in a single transaction. The goal is to help developers build interfaces where users can teleport any token to any chain from wherever they might be.

We've designed it so that even developers who are completely new to interoperability and have never worked with any of the bridges or DEXes we use can build applications and frontends that feel magical and offer:

* Any-to-any cross-chain swaps with built-in cross-chain DEX aggregation under the hood (e.g. Swap OSMO on Neutron for ARCH on Archway in a single transaction)
* Onboarding to a sovereign chain from an origin chain or token in any ecosystem (e.g. Onboard to Sei from ETH on Blast)
* Unified bridge-and-act flows (e.g. Transfer and buy an NFT in a single transaction)
* Multi-hop cross-chain transfers with automatic denom & path recommendations for any asset and chain (e.g. Get the most liquid version of ATOM on Terra2)
* Composite bridging paths that use multiple underlying bridges for different stages of the path (e.g. Transfer USDC from Base to Injective over CCTP and IBC behind the scenes)
* Real-time cross-chain workflow tracking, along with gas + completion timing estimates
* Protection from common cross-chain UX failures (e.g. bridging to a chain where the end user doesn't have gas)
  ... and much more

Skip Go API includes several different endpoint types which allow developers to choose their level of abstraction and build a wide variety of cross-chain applications. These include:

* **High-level endpoints** that return fully-formed messages and transactions
* **Low-level endpoints** that return detailed pathing data about all the "operations" that make up a route
* **Utility endpoints** for multi-chain transaction + packet submission, relaying, tracking, and simulation

<Info>
  **What does it cost?**

  The Skip Go API is free to use and integrate with. For integrators who charge fees on swaps using our affiliate fee functionality, we collect a share of those fees. You can learn more about [pricing and fees in our FAQ](/go/general/faq#does-the-skip-go-api-cost-anything%3F).

  You will have very limited access if you do not have an API key from us. Please join [our Discord](https://discord.com/invite/interchain) and request one.
</Info>

## 3 Basic Ways to Use the Skip Go API

There are 3 ways to leverage Skip Go API to build cross-chain swapping & transferring experiences, depending on whether you're optimizing for control or for integration speed.

<CardGroup>
  <Card title="Rest Endpoint — Most control, slowest integration" icon="sliders" href="/general/overview-and-typical-usage">
    Use REST endpoints for low-level control over your interactions.
  </Card>

  <Card title="Client Library — High control, fast integration" icon="code" href="/client/getting-started">
    Use the TypeScript library to abstract the complexity of making HTTP calls and access related helper functionality.
  </Card>

  <Card title="Widget — Medium control, fastest integration" icon="bolt-lightning" href="/widget/getting-started">
    Embed the Skip Go Widget in your frontend in a single line of code to launch with no developer effort.
  </Card>
</CardGroup>

## Learn More

* [DeepWiki for skip-go](https://deepwiki.com/skip-mev/skip-go): Explore the codebase and ask questions using AI.


# Transaction Tracking
Source: https://skip-go.mintlify-go.com/go/general/multi-chain-realtime-transaction-and-packet-tracking

This document covers the tooling provided in Skip Go for tracking transaction status across multiple chains and bridge hops.

## Background

The `/v2/tx` endpoints include unified APIs that broadcast transactions and provide insight into the status of transactions and their subsequent cross-chain actions.

You can use the `/v2/tx` endpoints to track the progress of a cross-chain transfer or swap in realtime -- no matter how many chains or bridges the transfer touches. (For more advanced use cases, the endpoints support tracking multiple distinct transfers initiated in a single transaction).

You can also use it to identify failure cases (e.g. a swap that fails due to slippage, an IBC transfer that fails due to inactive relayers) and determine where the user's tokens will become available.

For example, if one of your end users initiates a swap that begins with ATOM on Neutron and concludes with ATOM on Osmosis, you can use the lifecycle tracking to report when the ATOM moves from Neutron to Osmosis.

<Frame>
  <img alt="" />
</Frame>

## Basics

At a high-level, the transaction tracking works in two stages:

1. Inform our tracking engine that you want to track a particular transaction by submitting it to the chain via `/v2/tx/submit` or submitting it to your own Node RPC then calling `/v2/tx/track`
2. Query the transaction status at some regular interval to get updates on it's progress

<Info>
  **Tracking Multiple Independent Routes**

  You can use the endpoint to track multiple transfers initiated in a single transaction, where the status of transfer `i` is given by entry `i` in the `transfers` array. For example, I could transfer ATOM to the Cosmos Hub and OSMO to Osmosis in a single transaction and track them with `transfers[0]` and `transfers[1]` respectively.

  For a single transfer that has multiple hops (e.g. transferring ATOM to the Cosmos Hub then to Osmosis), you can track the status of each hop using the entries of `transfers[i].transfer_sequence`
</Info>

The status endpoint provides a mixture of high-level fields to keep track of the basic progress of your route and low-level fields to provide high visbility into the individual transactions that make up a single transfer.

### Important high-level `/v2/tx/status` fields

Each entry in the `transfers` array corresponds to a single route that may contain many steps, and each entry in `transfer_sequence` will contain very detailed information about each step in that route.

But there a few high-level fields in each `transfers` entry that you'll find useful no matter what your route does or what bridges it involves:

* `state`: The basic status of your route. **This lets you report the basic state of the route to the user (e.g. in progress, failed, etc...)**
  * `STATE_SUBMITTED`: Indicates the transaction has been accepted for tracking but no on chain evidence has been found yet.
  * `STATE_ABANDONED`: Tracking has stopped after 30 minutes without progress. There is likely a relayer outage, an undetected out of gas error, or some other problem.
  * `STATE_PENDING`: The route is in progress and no errors have occurred yet
  * `STATE_PENDING_ERROR`: The route is in progress and an error has occurred somewhere, but the error is currently propagating, so the user doesn't have their tokens returned yet. (This state will only occur for protocols that require an *acknowledgement* on the source chain to process an error. IBC only at this time)
  * `STATE_COMPLETED_SUCCESS`: The route has completed successfully and the user has their tokens on the destination (indicated by `transfer_asset_release`)
  * `STATE_COMPLETED_ERROR`: The route errored somewhere and the user has their tokens unlocked in one of their wallets. Their tokens are either on the source chain, an intermediate chain, or the destination chain but in the wrong asset. ( `transfer_asset_release` indicates where the tokens are)
* `next_blocking_transfer`: Gives the index of the entry in `transfer_sequence` that corresponds to the currently propagating transfer that is immediately blocking the release of the user's tokens -- `next_blocking_transfer.transfer_sequence_index` (it could be propagating forward or it could be propagating an error ack backward). **This lets you tell the user exactly which operation is pending at a given time**
* `transfer_asset_release`: Info about where the users tokens will be released when the route completes. This populates on `STATE_PENDING_ERROR`, `STATE_COMPLETED_SUCCESS`, or `STATE_COMPLETED_ERROR`. **This lets you tell the user where to recover their funds in the event of a success or failure** *(If you want to better understand how to predict this or where funds might end up, see [Cross-chain Failure Cases](../advanced-transfer/handling-cross-chain-failure-cases))*
  * `transfer_asset_release.released`: Boolean given whether the funds are currently available (if the state is`STATE_PENDING_ERROR` , this will be `false`)
  * `transfer_asset_release.chain_id`: Chain where the assets are released or will be released
  * `transfer_asset_release.denom`: Denom of the tokens the user will have

### Detailed Info: Using`transfer_sequence`

The `transfer_sequence` array consists of `TransferEvent` objects, which give detailed information about an individual transfer operation. The object acts as a wrapper around one details object for each bridge we support:

* `CCTPTransferInfo`
* `IBCTransferInfo`
* `AxelarTransferInfo`
* `HyperlaneTransferInfo`
* `GoFastTransferInfo`
* `StargateTransferInfo`

Each one contains slightly different data and statuses corresponding to the details of their bridge, but they all contain some standard info:

* `from_chain_id`
* `to_chain_id`
* Transactions and block explorer links for all of the significant events in the transfer (send tx, receive tx, and sometimes acknowledge tx)
* A status field giving the status of the transfer, which can vary based on bridge

#### IBC Transfer Data

The `state` field in the `IBCTransferInfo` entries in the `transfer_sequence` array have the following meanings:

* `TRANSFER_UNKNOWN`: The transfer state is unknown
* `TRANSFER_PENDING` - The send packet for the transfer has been committed and the transfer is pending
* `TRANSFER_PENDING_ERROR` - There has been a problem with the transfer (e.g. the packet has timed out) but the user doesn't have their funds unlocked yet because the error is still propagating
* `TRANSFER_RECEIVED`- The transfer packet has been received by the destination chain. It can still fail and revert if it is part of a multi-hop PFM transfer
* `TRANSFER_SUCCESS` - The transfer has been successfully completed and will not revert
* `TRANSFER_FAILURE` - The transfer

`packet_txs` contain transaction hashes, chain IDs, and block explorer links for up to 4 transactions:

* `send_tx`: The packet being sent from the source chain
* `receive_tx`: The packet being received on the destination chain
* `timeout_tx`: The packet being timed out on the destination chain
* `acknowledge_tx`: The successful or failed acknowledgement of the packet on the source chain

#### Axelar Transfer Data

When one of the transfers is an Axelar transfer, the `transfer_sequence` array will give an `axelar_transfer` (`AxelarTransferInfo`), instead of an `ibc_transfer`, which contains different data because:

* The Skip Go API may utilize send\_token or contract\_call\_with\_token (two underlying Axelar protocols) depending on which is cheaper and which is required to execute the user's intent
* Axelar does not have a notion of packets or acks, like IBC does
* Axelar provides a nice high level UI (Axelarscan) to track the status of their transfers

More precise details about all the fields are below:

* `type` : an enum of `AXELAR_TRANSFER_SEND_TOKEN` and `AXELAR_TRANSFER_CONTRACT_CALL_WITH_TOKEN` which indicate whether the Axelar transfer is a [Send Token](https://docs.axelar.dev/dev/send-tokens/overview) or a [Contract Call With Token](https://docs.axelar.dev/dev/general-message-passing/gmp-tokens-with-messages) transfer respectively.
* `axelar_scan_link`: Gives the link to Axelar's bridge explorer (which can help track down and unstick transactions)
* `state` field indicates the current state of the Axelar transfer using the following values:
  * `AXELAR_TRANSFER_UNKNOWN` - The transfer state is unknown
  * `AXELAR_TRANSFER_PENDING_CONFIRMATION` - The transfer has been initiated but is pending confirmation by the Axelar network
  * `AXELAR_TRANSFER_PENDING_RECEIPT` - The transfer has been confirmed by the Axelar network and is pending receipt at the destination
  * `AXELAR_TRANSFER_SUCCESS` - The transfer has been completed successfully and assets have been received at the destination
  * `AXELAR_TRANSFER_FAILURE` - The transfer has failed
* `txs` field schema depends on the `type` of the transfer
  * If `type` is `AXELAR_TRANSFER_SEND_TOKEN`, there are 3 txs:
    * `send_tx` (initiating the transfer)
    * `confirm_tx`(confirming the transfer on axelar)
    * `execute_tx` (executing the transfer on the destination)
  * If `type` is `AXELAR_TRANSFER_CONTRACT_CALL_WITH_TOKEN`:
    * `send_tx` (initiating the transfer)
    * `gas_paid_tx` (paying for the relayer gas on the source chain)
    * `approve_tx` (approving the transaction on Axelar - only exists when the destination chain is an EVM chain)
    * `confirm_tx`(confirming the transfer on Axelar - only exists when destination chain is a Cosmos chain)
    * `execute_tx` (executing the transfer on the destination)

#### CCTP Transfer Data

When one of the transfers is a CCTP transfer, the `transfer_sequence` array will give a `cctp_transfer` (`CCTPTransferInfo`), instead of an `ibc_transfer`, which contains different data because:

* CCTP works by Circle attesting to & signing off on transfers
* There's no notion of an acknowledgement in CCTP

More precise details about the different/new fields are below:

* `state` gives the status of the CCTP transfer:
  * `CCTP_TRANSFER_UNKNOWN` - Unknown error
  * `CCTP_TRANSFER_SENT` - The burn transaction on the source chain has executed
  * `CCTP_TRANSFER_PENDING_CONFIRMATION` - CCTP transfer is pending confirmation by the cctp attestation api
  * `CCTP_TRANSFER_CONFIRMED` - CCTP transfer has been confirmed by the cctp attestation api but not yet received on the destination chain
  * `CCTP_TRANSFER_RECEIVED` - CCTP transfer has been received at the destination chain
* `txs` contains the chain IDs, block explorer links, and hashes for two transactions:
  * `send_tx`: The transaction submitted the CCTP burn action on the source chain to initiate the transfer
  * `receive_tx`: The transaction on the destination chain where the user receives their funds

**Note:** CCTP transfers have a maximum limit of 1,000,000 USDC per transaction.

#### Hyperlane Transfer Data

When one of the transfers is a Hyperlane transfer, the `transfer_sequence` array will give a `hyperlane_transfer` (`HyperlaneTransferInfo`), instead of an `ibc_transfer`, which contains different data because:

* Hyperlane is a very flexible protocol where the notion of "approving/verifying" the transfer is undefined / up to the bridge developer to implement
* There's no notion of an acknowledgement in Hyperlane

More precise details about the different/new fields are below:

* `state` gives the status of the Hyperlane transfer:
  * `HYPERLANE_TRANSFER_UNKNOWN` - Unknown error
  * `HYPERLANE_TRANSFER_SENT` - The Hyperlane transfer transaction on the source chain has executed
  * `HYPERLANE_TRANSFER_FAILED` - The Hyperlane transfer failed
  * `HYPERLANE_TRANSFER_RECEIVED` - The Hyperlane transfer has been received at the destination chain
* `txs` contains the chain IDs, block explorer links, and hashes for two transactions:
  * `send_tx`: The transaction submitted the CCTP burn action on the source chain to initiate the transfer
  * `receive_tx`: The transaction on the destination chain where the user receives their funds

### OPInit Transfer Data

When one of the transfers is a OPInit transfer, the `transfer_sequence` array will give a `op_init_transfer` (`OPInitTransferInfo`), instead of an `ibc_transfer`, which contains different data because:

* The OPInit bridge is the Initia ecosystem's native bridging solution facilitating transfers between Initia and the Minitias.
* There's no notion of an acknowledgement in the OPInit bridge

More precise details about the different/new fields are below:

* `state` gives the status of the OPInit transfer:
  * `OPINIT_TRANSFER_UNKNOWN` - Unknown error
  * `OPINIT_TRANSFER_SENT` - The deposit transaction on the source chain has executed
  * `OPINIT_TRANSFER_RECEIVED` - OPInit transfer has been received at the destination chain
* `txs` contains the chain IDs, block explorer links, and hashes for two transactions:
  * `send_tx`: The transaction that submitted the OPInit deposit action on the source chain to initiate the transfer
  * `receive_tx`: The transaction on the destination chain where the user receives their funds

### Go Fast Transfer Data

When one of the transfers is a `GoFastTransfer`, the `transfer_sequence` array will include a `go_fast_transfer` (`GoFastTransferInfo`). This field includes specific information about user-initiated intents and solver fulfillments, which require specific data fields to track the transfer process.

Below are detailed explanations of the different fields and their purposes:

* `from_chain_id`: The chain ID where the transfer originates (source chain).
* `to_chain_id`: The chain ID where the assets are being sent (destination chain).
* `state`: Indicates the current status of the transfer. Possible values are:
  * `GO_FAST_TRANSFER_UNKNOWN`: An unknown error has occurred.
  * `GO_FAST_TRANSFER_SENT`: The user's intent has been successfully submitted on the source chain.
  * `GO_FAST_POST_ACTION_FAILED`: The transfer's post-intent action failed. For example a swap on the destination chain failed due to slippage.
  * `GO_FAST_TRANSFER_TIMEOUT`: The transfer did not complete within the expected time frame.
  * `GO_FAST_TRANSFER_FILLED`: The transfer was successfully fulfilled on the destination chain.
  * `GO_FAST_TRANSFER_REFUNDED`: The user's assets have been refunded on the source chain.
* `txs`: Contains transaction details related to the GoFast transfer:
  * `order_submitted_tx`: The transaction where the user called initiateIntent on the source chain.
  * `order_filled_tx`: The transaction where the solver called fulfill on the destination chain.
  * `order_refunded_tx`: The transaction where the user received a refund on the source chain, if applicable.
  * `order_timeout_tx`: The transaction indicating a timeout occurred in the transfer process.
* `error_message`: A message describing the error that occurred during the transfer, if applicable.

When tracking a Go Fast transfer, you can use the `GoFastTransferInfo` to monitor the progress and status of your asset transfer between chains. For instance, if the state is `GO_FAST_TRANSFER_FILLED`, you know that the transfer was successful and your assets should be available on the destination chain. If the state is `GO_FAST_TRANSFER_TIMEOUT`, you can check the `orderTimeoutTx` for details on the timeout event.

### Stargate Transfer Data

When one of the transfers is a `StargateTransfer`, the `transfer_sequence` array will include a `stargate_transfer` (`StargateTransferInfo`). This provides detailed information about a cross-chain asset transfer powered by Stargate, a popular cross-chain bridging protocol.

Below are detailed explanations of the fields and their purposes:

* `from_chain_id`: The chain ID where the transfer originates (source chain).

* `to_chain_id`: The chain ID where the assets are being sent (destination chain).

* `state`: Indicates the current status of the Stargate transfer. Possible values are:
  * `STARGATE_TRANSFER_UNKNOWN`: An unknown error has occurred or the state cannot be determined.
  * `STARGATE_TRANSFER_SENT`: The transfer has been successfully initiated on the source chain (i.e., the assets have left the source chain and are in transit).
  * `STARGATE_TRANSFER_RECEIVED`: The transfer has been successfully completed on the destination chain (i.e., the assets are now available at the recipient address on the destination chain).
  * `STARGATE_TRANSFER_FAILED`: The transfer encountered an error during bridging and did not complete as intended.

* `txs`: Contains transaction details related to the Stargate transfer.
  * `send_tx`: The transaction on the source chain that initiated the Stargate transfer.
  * `receive_tx`: The transaction on the destination chain where the assets were received.
  * `error_tx`: A transaction (if any) related to the failure of the transfer.

When monitoring a Stargate transfer, you can use `StargateTransferInfo` to confirm that your assets have safely bridged between chains or identify if and where a problem has occurred.

<Info>
  The Go Fast Protocol involves interactions with solvers who fulfill transfer intents. The additional transaction fields help provide transparency and traceability throughout the transfer process, ensuring users can track each step and identify any issues that may arise.
</Info>

## Detailed Example of Typical Usage

This will walk through an example of how a developer would use the api to track the progress of a route that may include multiple

In this particular example, we'll cover a simple 2-hop IBC transfer from axelar to the cosmoshub through osmosis.

*Usage is similar for tracking Axelar transfers or transfers that include multiple hops over distinct bridges but the data structures change slightly depending on what underlying bridge is being used*

### 1. Call `/tx/submit` to broadcast a transaction

Post a signed user transaction (that you can form using `/fungible` endpoints) to the `/submit` endpoint. The Skip Go API will handle the broadcasting of this transaction and asynchronously begin tracking the status of this transaction and any subsequent transfers.

A successful response looks like the following:

```JSON theme={null}
{
  "tx_hash": "AAEA76709215A808AF6D7FC2B8FBB8746BC1F196E46FFAE84B79C6F6CD0A79C9"
}
```

It indicates that the transaction was accepted by the Skip Go API and its status can be tracked using the returned `tx_hash`.

The transaction is broadcast using `BROADCAST_MODE_SYNC` and in the event that a transaction is rejected by the node, the `/submit` endpoint will return a 400 response along with the failure reason as shown below:

```JSON theme={null}
{
    "code": 3,
    "message": "insufficient fees; got: 0uosmo which converts to 0uosmo. required: 2000uosmo: insufficient fee",
    "details": []
}
```

<Info>
  **Tracking a transaction that was not broadcast using `/submit`**

  If a transaction was not broadcast through the `/submit` endpoint and has already landed on chain, the `/track` endpoint can be used to initiate tracking of the transaction's progress.
</Info>

### 2. Call `/status` to query the status of the transaction and IBC transfer progress

Skip Go API continually indexes chain state to determine the state of the transaction and the subsequent IBC transfer progress. This information can be queried using the `/status` endpoint.

It will initially yield a response that looks like the following:

* There's a top-level `transfers` field, which gives an array where each entry corresponds to a **single sequence of transfers**. This does not mean there's one entry in the `transfers` field for every bridging operation. In general, one `transfer` could consist of an arbitrarily long sequence of swaps and transfers over potentially multiple bridges. `transfers` is an array because one transaction can initiate potentially several distinct and independent transfers (e.g. transferring OSMO to Osmosis and ATOM to the Hub) in the same tx.
* The `state` field will give `STATE_SUBMITTED` indicating the transaction has been accepted for tracking by the Skip Go API but no events have been indexed yet:

```JSON theme={null}
{
  "transfers": [
    {
      "state": "STATE_SUBMITTED",
      "transfer_sequence": [],
      "next_blocking_transfer": null,
      "transfer_asset_release": null,
      "error": null
    }
  ]
}
```

Once indexing for the transaction has begun, the `state` will change to `STATE_PENDING`.

* The status of any transfers along the transfer sequence will be returned in the `transfer_sequence` field as shown in the example response below.
* The entries in the `transfer_sequence` correspond to transfers and will be represented by different objects depending on which bridge is being used (e.g. Axelar or IBC).
* The `next_blocking_transfer` field gives some information about the next blocking transfer in the`transfer_sequence` field.
  * The `transfer_sequence_index` indicates which transfer in the `transfer_sequence` field is blocking progress.
* The `transfer_asset_release` field will be populated with information about the asset release as it is becomes known.
  * The `chain_id` and `denom` fields indicate the location and asset being released.
  * The `released` field indicates whether the assets are accessible. The `transfer_asset_release` field may become populated in advance of asset release if it can be determined with certainty where the eventual release will be. This will happen for example in a transfer sequence that is a PFM-enabled sequence of IBC transfers when one hop fails due to packet timeout or an acknowledgement failure. The transfer sequence will revert and the `transfer_asset_release` field will indicate that the assets will be released on the initial chain.

```JSON theme={null}
{
  "transfers": [
    {
      "state": "STATE_PENDING",
      "transfer_sequence": [
        {
         "ibc_transfer": {
            "from_chain_id": "axelar_dojo-1",
            "to_chain_id": "osmosis-1",
            "state": "TRANSFER_PENDING",
            "packet": {
              "send_tx": {
                "chain_id": "axelar-dojo-1",
                "tx_hash": "AAEA76709215A808AF6D7FC2B8FBB8746BC1F196E46FFAE84B79C6F6CD0A79C9",
                "explorer_link": "https://www.mintscan.io/axelar/transactions/AAEA76709215A808AF6D7FC2B8FBB8746BC1F196E46FFAE84B79C6F6CD0A79C9"
              },
              "receive_tx": null,
              "acknowledge_tx": null,
              "timeout_tx": null,
              "error": null
            }
         }
       }
      ],
      "next_blocking_transfer": {
        "transfer_sequence_index": 0
      },
      "transfer_asset_release": null,
      "error": null
    }
  ]
}
```

The transfer assets will be released before all expected acknowledgements have been indexed. When the transfer sequence has reached this state, the `status` will be updated to `STATE_RECEIVED` as shown in the example response below. Note that `transfer_asset_release` now indicates the chain ID of the chain where the assets are released and the denomination of the released assets.

```JSON theme={null}
{
  "transfers": [
    {
      "state": "STATE_COMPLETED_SUCCESS",
      "transfer_sequence": [
        {
          "ibc_transfer": {
            "from_chain_id": "axelar_dojo-1",
            "to_chain_id": "osmosis-1",
            "state": "TRANSFER_PENDING",
            "packet": {
              "send_tx": {
                "chain_id": "axelar-dojo-1",
                "tx_hash": "AAEA76709215A808AF6D7FC2B8FBB8746BC1F196E46FFAE84B79C6F6CD0A79C9",
                "explorer_link": "https://www.mintscan.io/axelar/transactions/AAEA76709215A808AF6D7FC2B8FBB8746BC1F196E46FFAE84B79C6F6CD0A79C9"

              },
              "receive_tx": {
                "chain_id": "osmosis-1",
                "tx_hash": "082A6C8024998EC277C2B90BFDDB323CCA506C24A6730C658B9B6DC653198E3D",
                "explorer_link": "https://www.mintscan.io/osmosis/transactions/082A6C8024998EC277C2B90BFDDB323CCA506C24A6730C658B9B6DC653198E3D"
              },
              "acknowledge_tx": null,
              "timeout_tx": null,
              "error": null
            }
          }
        },
        {
          "ibc_transfer": {
            "from_chain_id": "osmosis-1",
            "to_chain_id": "cosmoshub-4",
            "state": "TRANSFER_SUCCESS",
            "packet": {
              "send_tx": {
                "chain_id": "osmosis-1",
                "tx_hash": "082A6C8024998EC277C2B90BFDDB323CCA506C24A6730C658B9B6DC653198E3D",
                "explorer_link": "https://www.mintscan.io/osmosis/transactions/082A6C8024998EC277C2B90BFDDB323CCA506C24A6730C658B9B6DC653198E3D"
              },
              "receive_tx": {
                "chain_id": "cosmoshub-4",
                "tx_hash": "913E2542EBFEF2E885C19DD9C4F8ECB6ADAFFE59D60BB108FAD94FBABF9C5671",
                "explorer_link": "https://www.mintscan.io/cosmos/transactions/913E2542EBFEF2E885C19DD9C4F8ECB6ADAFFE59D60BB108FAD94FBABF9C5671"

              },
              "acknowledge_tx": null,
              "timeout_tx": null,
              "error": null
            }
          }
        }
      ],
      "next_blocking_transfer": null,
      "transfer_asset_release": {
        "chain_id": "cosmoshub-4",
        "denom": "uatom",
        "released": true
      },
      "error": null
    }
  ]
}
```

Once it has been determined that all packets along the transfer sequence have either been acknowledged or timed out, `state` will be updated to `STATE_COMPLETED_SUCCESS` as shown in the example response below. Note that `next_blocking_transfer` is now null since the transfer is complete.

```JSON theme={null}
{
  "transfers": [ 
    {
      "state": "STATE_COMPLETED_SUCCESS",
      "transfer_sequence": [
        {
          "ibc_transfer": {
            "from_chain_id": "axelar_dojo-1",
            "to_chain_id": "osmosis-1",
            "state": "TRANSFER_SUCCESS",
            "packet": {
              "send_tx": {
                "chain_id": "axelar-dojo-1",
                "tx_hash": "AAEA76709215A808AF6D7FC2B8FBB8746BC1F196E46FFAE84B79C6F6CD0A79C9",
                "explorer_link": "https://www.mintscan.io/axelar/transactions/AAEA76709215A808AF6D7FC2B8FBB8746BC1F196E46FFAE84B79C6F6CD0A79C9"
              },
              "receive_tx": {
                "chain_id": "osmosis-1",
                "tx_hash": "082A6C8024998EC277C2B90BFDDB323CCA506C24A6730C658B9B6DC653198E3D",
                "explorer_link": "https://www.mintscan.io/osmosis/transactions/082A6C8024998EC277C2B90BFDDB323CCA506C24A6730C658B9B6DC653198E3D"
              },
              "acknowledge_tx": {
                "chain_id": "axelar-dojo-1",
                "tx_hash": "C9A36F94A5B2CA9C7ABF20402561E46FD8B80EBAC4F0D5B7C01F978E34285CCA",
                "explorer_link": "https://www.mintscan.io/axelar/transactions/C9A36F94A5B2CA9C7ABF20402561E46FD8B80EBAC4F0D5B7C01F978E34285CCA"
              },
              "timeout_tx": null,
              "error": null
            }
          }
        },
        {
        	"ibc_transfer": {
            "from_chain_id": "osmosis-1",
            "to_chain_id": "cosmoshub-4",
            "state": "TRANSFER_SUCCESS",
            "packet": {
              "send_tx": {
                "chain_id": "osmosis-1",
                "tx_hash": "082A6C8024998EC277C2B90BFDDB323CCA506C24A6730C658B9B6DC653198E3D",
                "explorer_link": "https://www.mintscan.io/osmosis/transactions/082A6C8024998EC277C2B90BFDDB323CCA506C24A6730C658B9B6DC653198E3D"
              },
              "receive_tx": {
                "chain_id": "cosmoshub-4",
                "tx_hash": "913E2542EBFEF2E885C19DD9C4F8ECB6ADAFFE59D60BB108FAD94FBABF9C5671",
                "explorer_link": "https://www.mintscan.io/cosmos/transactions/913E2542EBFEF2E885C19DD9C4F8ECB6ADAFFE59D60BB108FAD94FBABF9C5671"
              },
              "acknowledge_tx": {
                "chain_id": "osmosis-1",
                "tx_hash": "1EDB2886E6FD59D6B9C096FBADB1A52585745694F4DFEE3A3CD3FF0153307EBC",
                "explorer_link": "https://www.mintscan.io/osmosis/transactions/1EDB2886E6FD59D6B9C096FBADB1A52585745694F4DFEE3A3CD3FF0153307EBC"
              },
              "timeout_tx": null,
              "error": null
            }
        	}
        }
      ],
      "next_blocking_transfer": null,
      "transfer_asset_release": {
        "chain_id": "cosmoshub-4",
        "denom": "uatom",
        "released": true
      },
      "error": null
    }
  ]
}
```

Any packet acknowledgement errors will be surfaced in the error field for the relevant packet as follows:

```JSON theme={null}
{
  "transfers": [
  	{
      "state": "STATE_COMPLETED_ERROR",
      "transfer_sequence": [
        {
          "ibc_transfer": {
            "from_chain_id": "osmosis-1",
            "to_chain_id": "cosmoshub-4",
            "state": "TRANSFER_FAILED",
            "packet": {
              "send_tx": {
                "chain_id": "osmosis-1",
                "tx_hash": "112714A8144019161CAAA8317016505A9A1DDF5DA7B146320A640814DDFA41C0",
                "explorer_link": "https://www.mintscan.io/osmosis/transactions/112714A8144019161CAAA8317016505A9A1DDF5DA7B146320A640814DDFA41C0"
              },
              "receive_tx": {
                "chain_id": "cosmoshub-4",
                "tx_hash": "E7FB2152D8EA58D7F377D6E8DC4172C99791346214387B65676A723FCFC7C980",
                "explorer_link": "https://www.mintscan.io/osmosis/cosmos/E7FB2152D8EA58D7F377D6E8DC4172C99791346214387B65676A723FCFC7C98"

              },
              "acknowledge_tx": {
                "chain_id": "osmosis-1",
                "tx_hash": "8C9C1FA55E73CD03F04813B51C697C1D98E326E1C71AB568A2D23BF8AEAFFEC7",
                "explorer_link": "https://www.mintscan.io/osmosis/transactions/8C9C1FA55E73CD03F04813B51C697C1D98E326E1C71AB568A2D23BF8AEAFFEC7"

              },
              "timeout_tx": null,
              "error": {
                "code": 1,
                "message": "ABCI code: 1: error handling packet: see events for details"
              }
            }
          }
        }
      ],
      "next_blocking_transfer": null,
      "transfer_asset_release": {
        "chain_id": "osmosis-1",
        "denom": "uosmo",
        "released": true
      },
      "error": null
		}
	]
}
```

Any execution errors for the initial transaction will be surfaced in the error field at the top level of the response as follows:

```JSON theme={null}
 {
  "transfers": [
    {
      "state": "STATE_COMPLETED_ERROR",
      "transfer_sequence": [],
      "next_blocking_transfer": null,
      "transfer_asset_release": null,
      "error": {
        "code": 11,
        "message": "out of gas in location: Loading CosmWasm module: sudo; gasWanted: 200000, gasUsed: 259553: out of gas"
      }
    }
  ]
}
```


# Overview & Common Usage Patterns
Source: https://skip-go.mintlify-go.com/go/general/overview-and-typical-usage



## Summary

This doc provides a high-level overview of the different kinds of methods available in the Skip Go API & describes how integrators typically use them in combination to create a cross-chain swapping frontend like [go.skip.build](https://go.skip.build).

See the [API reference](/go/api-reference/prod) for more information on each endpoint.

## Overview of Methods

### `/info` methods: Functionality for Retrieving General Purpose Info

The `/info` endpoints & their corresponding functions in `@skip-go/client` provide general purpose metadata about the chains and bridges that the Skip Go API supports.

The most important `info` methods include:

* `/v2/info/chains` (`chains()`): Get info about all supported chains, including capabilities, address type, logo, etc...
* `/v2/info/bridges` (`bridges()`): Get basic info about all supported bridges, including logo and name

### `/fungible` methods: Functionality for fungible token swaps and transfers

The `/v2/fungible` endpoints & their corresponding functions in `@skip-go/client` provide APIs for cross-chain swaps and transfers of fungible tokens.

In the background, the API provides automatic DEX aggregation, bridge routing, denom recommendation, and relaying for all actions.

The most important `fungible` methods include :

* `/v2/fungible/route` (`route()`): Get a swap/transfer route and quote between a pair of tokens & chains. You can customize this request significantly to only consider particular DEXes, bridges; to add route splitting for better prices; and much more.
* `/v2/fungible/msgs` (`messages()`): Generates the transaction data for the transaction(s) the user must sign to execute a given route
* `/v2/fungible/msgs_direct` (`messagesDirect()`): Generates a route, quote, and associated transaction data at the same time
* `/v2/fungible/venues` (`venues()`): Get metadata for all supported swapping venues (DEXes, liquid staking protocols, etc...), including name and logo.

(There are many other providing more specific functionality for power users. See API docs for more details.)

### `/tx` methods: Functionality for Tracking Inflight transactions

The `/v2/tx` endpoints & their corresponding functions in `@skip-go/client` provide functionality for submitting transactions and tracking the status of cross-chain transactions with a unified interface across all underlying hops & bridge types.

The most important `tx` methods include:

* `/v2/tx/submit` (`submitTransaction()`): Submits a transaction on chain through Skip's nodes and registers the transaction for tracking with Skip Go API *(Recommended especially for Solana and other high congestion networks where successfully submitting a transaction can be tricky)*
* `/v2/tx/track` (`trackTransaction()`): Registers a transaction for tracking with Skip Go API (Often used instead of `/submit` when an integrator has their own chain nodes for submitting)
* `/v2/tx/status` (`transactionStatus()`): Get the current status of a multi-hop transaction

[`/tx` API reference](https://docs.skip.build/go/api-reference/prod/transaction/post-v2txsubmit)

## Typical Usage in Cross-chain Swapping Frontend

On a cross-chain swapping and transferring frontend, integrators typically:

1. Use the `info` methods to populate the list of potential starting & ending chains & assets

   <Frame>
     <img alt="" />
   </Frame>

2. Use `/fungible/route` (`route()`) to get a quote when the user selects all their chains & tokens and inputs one of their amounts

   <Frame>
     <img alt="" />
   </Frame>

3. Use `/fungible/msgs` (`messages()`) to get a transaction for the user to sign after they've locked in the route & begun the transaction creation process

   <Frame>
     <img alt="" />
   </Frame>

4. Use `/tx/track` (`trackTransaction()`) to register the transaction for tracking (or `/tx/submit` to register and submit it on-chain)

5. Use `/tx/status` (`transactionStatus()`) to get the real-time status of the transaction as it progresses across bridges and/or chains.
   <Frame>
     <img alt="" />
   </Frame>


# Post-Route Actions
Source: https://skip-go.mintlify-go.com/go/general/post-route-actions

How to specify actions to perform after a route of transfers/swaps is completed

Use the `post_route_handler` parameter of `/v2/fungible/msgs` endpoint to define actions that will be executed on the destination chain after a route transfer or swap is completed. These actions are executed within the same transaction as the original swap or transfer.

This handler allows developers to build omni-chain and omni-token workflows where users can swap, liquid stake, deposit, buy an NFT, or take any other action starting from any chain or any token in Cosmos -- all in a single transaction.

This parameter currently supports:

1. CosmWasm contract calls on the destination chain
2. `autopilot` support for liquid staking interactions on Stride

### Background Info

All `post_route` actions must have the following characteristics:

* **Permissionless:** Skip Go can only support permissionless actions because the underlying protocols (e.g. IBC hooks, IBC callbacks, packet-forward-middleware) derive the addresses they use to call contracts based on the origin of the transfer. Skip Go supports both `ibc-hooks` and `ibc-callbacks` depending on which module the destination chain has implemented (they are incompatible approaches), automatically generating the appropriate message payloads for each. This means one user originating on two different chains or starting with two different tokens will eventually call the final contract / module with different addresses. You can only reliably permission actions that you know will 1) always originate on the same chain and 2) always take the same path to the destination chain. In general, we recommend not making this assumption unless you are an interoperability expert
* **Single-token input:** The underlying IBC transfer protocol (ICS-20) doesn't support transfers of more than 1 token denom in a single transfer message, so we can only send 1 token denom to the final contract or module at a time. This means the contract or module in the `post_route_handler` must not require multiple token denoms sent to it simultaneously. For example, a classic LP action where the user must provide tokens in both sides of the pool simultaneously would not work.

<Warning>
  **Use authority-delegation with local address for permissionless actions that enable permissioned follow-ups**

  Commonly, the first interaction with a contract is permissionless, but it awards the end-user some kind of permissioned authority to perform follow-on actions (e.g. staking enables unstaking + collecting rewards; depositing enables withdrawing and earning yield) or receipt tokens (e.g. LPing produces LP receipt tokens).

  As a cross-chain caller, you should generally avoid contracts that implicitly delegate these authorities or give receipt tokens to the caller because the caller will depend on the path the user has taken over IBC. You should look for contracts to imply authority delegation -- i.e. contracts that explicitly assign permissions to an address in the calldata that may be different than the caller and address sending the tokens. Examples of this pattern are:

  * Astroport’s `receiver` parameter in the `provide_liquidity` message
  * Mars’ `on_behalf_of` parameter in the `deposit` message
  * Astroport’s `to` parameter in the `swap` message

  We recommend setting these authority delegation parameters to the user's local address on the destination chain, so they can perform future actions locally.
</Warning>

### CosmWasm

To call a CosmWasm contract on the destination chain, the following requirements must be satisfied:

1. The destination chain supports CosmWasm & either `ibc-hooks` or `ibc-callbacks`.
2. The chain in the route immediately before the destination chain supports IBC memos as well as `packet-forward-middleware`.

To specify a CosmWasm contract call on the destination chain, pass a `wasm_msg` as the `post_route_handler` in the `/v2/fungible/msgs` call with:

* `contract_address`: The target contract address
* `msg`: JSON string of the message to pass to the contract

In addition, set the destination address in the `address_list` to the address of the contract.

For example, this is a request for a transfer of USDC from Axelar to Neutron, with a post-route handler that swaps the USDC to Neutron using an Astroport pool on Neutron:

```json theme={null}
{
  "source_asset_denom": "uusdc",
  "source_asset_chain_id": "axelar-dojo-1",
  "dest_asset_denom": "ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349",
  "dest_asset_chain_id": "neutron-1",
  "amount_in": "1000000",
  "amount_out": "1000000",
  "address_list": [
    "axelar1x8ad0zyw52mvndh7hlnafrg0gt284ga7u3rez0",
    "neutron1l3gtxnwjuy65rzk63k352d52ad0f2sh89kgrqwczgt56jc8nmc3qh5kag3"
  ],
  "operations": [
    {
      "transfer": {
        "port": "transfer",
        "channel": "channel-78",
        "chain_id": "axelar-dojo-1",
        "pfm_enabled": false,
        "dest_denom": "ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349",
        "supports_memo": true
      }
    }
  ],
  "post_route_handler": {
    "wasm_msg": {
      "contract_address": "neutron1l3gtxnwjuy65rzk63k352d52ad0f2sh89kgrqwczgt56jc8nmc3qh5kag3",
        "msg": "{\"swap\":{\"offer_asset\":{\"info\":{\"native_token\":{\"denom\":\"ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349\"}},\"amount\":\"10000\"},\"to\":\"neutron1x8ad0zyw52mvndh7hlnafrg0gt284ga7uqunnf\"}}"
    }
  }
}

```

Note that the last address provided in the `address_list` is the address of the pool contract on Neutron, rather than a user address.

The message returned from this request uses `ibc-hooks` on Neutron to perform the CosmWasm contract call atomically with the IBC transfer.

### Autopilot

To use Autopilot after route actions, the following requirements must be satisfied:

1. The destination chain supports the `autopilot` module. Currently, this means the destination chain must be `stride-1`.
2. The chain in the route immediately before the destination chain supports IBC memos as well as `packet-forward-middleware`.

To specify an Autopilot action on the destination chain, pass a `autopilot_msg` as the `post_route_handler` in the `/v2/fungible/msgs` call with:

* `receiver`: Set to the address on behalf of which you're performing the action
* `action`: An enum giving the action that you wish to execute
  * This may be one of `LIQUID_STAKE` (for liquid staking an asset) or `CLAIM` for updating airdrop claim addresses.

For example, this is a request for a transfer of ATOM from Cosmos Hub to Stride, with a post-route handler that atomically liquid stakes the transferred ATOM on Stride, sending stATOM to the specific receiver on Stride:

```json theme={null}
{
  "source_asset_denom": "uatom",
  "source_asset_chain_id": "cosmoshub-4",
  "dest_asset_denom": "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2",
  "dest_asset_chain_id": "stride-1",
  "amount_in": "1000000",
  "amount_out": "1000000",
  "address_list": [
    "cosmos1x8ad0zyw52mvndh7hlnafrg0gt284ga7cl43fw",
    "stride1x8ad0zyw52mvndh7hlnafrg0gt284ga7m54daz"
  ],
  "operations": [
    {
      "transfer": {
        "port": "transfer",
        "channel": "channel-391",
        "chain_id": "cosmoshub-4",
        "pfm_enabled": true,
        "dest_denom": "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2",
        "supports_memo": true
      }
    }
  ],
  "post_route_handler": {
    "autopilot_msg": {
      "receiver": "stride1x8ad0zyw52mvndh7hlnafrg0gt284ga7m54daz",
      "action": "LIQUID_STAKE"
    }
  }
}
```

<Check>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.com/invite/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Check>


# Quickstart Guide
Source: https://skip-go.mintlify-go.com/go/general/quickstart-guide

This guide walks you through the process of setting up and using the Skip Go Client to perform a cross-chain from USDC on Noble to TIA on Celestia.

<Info>
  For a more in-depth guide, check out our [detailed walkthrough](../client/getting-started), which covers both Solana and EVM transactions. You can also explore more about [EVM Transactions](/go/advanced-transfer/evm-transactions) or dive into the specifics of [SVM Transactions](/go/advanced-transfer/svm-transaction-details).
</Info>

## Prerequisites

* Browser environment setup with **Keplr** installed (`create-next-app` is recommended)
* **Node.js** and **npm**

<Steps>
  <Step title="Install Library">
    Install the library using npm or yarn:

    <CodeGroup>
      ```Shell npm theme={null}
      npm install @skip-go/client
      ```

      ```Shell yarn theme={null}
      yarn add @skip-go/client
      ```
    </CodeGroup>
  </Step>

  <Step title="Initialize Client">
    To start integrating with the Skip Go API, configure the library once using `setClientOptions` or `setApiOptions`. After configuration, you import and call functions like `route` and `executeRoute` directly.

    ```ts theme={null}
    import {
      setClientOptions,
      setApiOptions,
      route,
      executeRoute,
      // ...other helpers you might use
    } from "@skip-go/client";

    // Example initialization for executeRoute usage
    setClientOptions({
      apiUrl: "YOUR_API_URL", // optional: defaults to Skip API
      apiKey: "YOUR_API_KEY", // optional: required for some features
      // endpointOptions, aminoTypes, registryTypes, etc.
    });

    // If only calling API functions directly, you can instead use:
    setApiOptions({ apiUrl: "YOUR_API_URL", apiKey: "YOUR_API_KEY" });
    ```
  </Step>

  <Step title="Get a Route">
    Now, we can use the `route` function to request a quote and route to swap USDC on Noble to TIA on Celestia.

    ```ts theme={null}
    const routeResult = await route({
      sourceAssetDenom: 'uusdc',
      sourceAssetChainID: 'noble-1',
      destAssetDenom: 'utia',
      destAssetChainID: 'celestia',
      amountIn: '1000000', // 1 uusdc
      smartRelay: true
    });
    ```

    <Info>
      **Understanding the Route Response**

      The route response contains important information about the swap process:

      * **`amountOut`**: The estimated amount the user will receive after the swap, net of all fees and price impact
      * **`requiredChainAddresses`**: Chain IDs where you need to provide user addresses when generating the transaction
      * **`operations`**: Steps involved in moving from the source to the destination token

      For more details, see the [/route](/go/api-reference/prod/fungible/post-v2fungibleroute) endpoint reference.
    </Info>
  </Step>

  <Step title="Get Required Addresses">
    After generating a route, you need to provide user addresses for the required chains. The `routeResult.requiredChainAddresses` array lists the chain IDs for which addresses are needed.

    <Warning>
      **Only use addresses your user can sign for.**
      Funds could get stuck in any address you provide, including intermediate chains in certain failure conditions. Ensure your user can sign for each address you provide.
      See [Cross-chain Failure Cases](../advanced-transfer/handling-cross-chain-failure-cases) for more details.
    </Warning>

    We recommend storing the user's addresses and creating a function like `getAddress` that retrieves the address based on the chain ID (see an example [here](https://github.com/skip-mev/skip-go-example/blob/c55d9208bb46fbf1a4934000e7ec4196d8ccdca4/pages/index.tsx#L99)).

    ```ts theme={null}
    // get user addresses for each requiredChainAddress to execute the route
    const userAddresses = await Promise.all(
      routeResult.requiredChainAddresses.map(async (chainID) => ({
        chainID,
        address: await getAddress(chainID),
      }))
    );
    ```

    <Warning>
      **Never attempt to derive an address on one chain from an address on another chain**

      Whenever you need a user address, please request it from the corresponding wallet or signer. Do not attempt to use bech32 cross-chain derivation.

      If you attempt to derive an address on one chain from an address on another chain, you may derive an address that the user cannot actually sign for if the two chains have different address-derivation processes. For example, if you derive a Cosmos address from an Ethereum address, you will get an address that the user cannot sign for and thus risk lost tokens.
    </Warning>
  </Step>

  <Step title="Execute the Route">
    Once you have a route, you can execute it in a single function call by passing in the route, the user addresses for at least the chains the route includes, and optional callback functions. This also registers the transaction for tracking.

    ```ts theme={null}
    await executeRoute({
      route: routeResult,
      userAddresses,
      getCosmosSigner: (chainId) => {},
      getEvmSigner: (chainId) => {},
      getSvmSigner: () => {},
      // Executes after all of the operations triggered by a user's signature complete.
      onTransactionCompleted: async (chainID, txHash, status) => {
        console.log(
          `Route completed with tx hash: ${txHash} & status: ${status.state}`
        );
      },
      onTransactionBroadcast: async ({ txHash, chainID }) => {
        console.log(`Transaction broadcasted with tx hash: ${txHash}`);
      },
      onTransactionTracked: async ({ txHash, chainID }) => {
        console.log(`Transaction tracked with tx hash: ${txHash}`);
      },
    });
    ```

    Once the transaction is complete, you'll have new TIA in your Celestia address!
  </Step>
</Steps>


# Smart Relay
Source: https://skip-go.mintlify-go.com/go/general/smart-relay

This page covers Smart Relay -- Skip Go API's universal cross-chain data & token delivery service

This document introduces Skip Go API’s Smart Relay functionality — the fastest & most reliable way to get your users where they’re going over any bridge supported by Skip Go. Smart Relay is an alternative to public bridge relayers. It's designed to enable users to access more swap and transfer routes in fewer transactions with greater speed and reliability.

<Warning>
  **We strongly advise all integrators who want to offer top-notch user experiences to activate Smart Relay.**

  **If you do not use Smart Relay, your performance will suffer:**

  * Many routes will not be available (e.g. Bridging Solana to Base, Solana to any Cosmos chain)
  * Many routes will require more transactions (e.g. Bridging USDC from Ethereum to Osmosis will require 2 transactions, instead of 1)
  * Transfers will get stuck more frequently

  You turn it on simply by setting `smart_relay=true` in `/msgs_direct` or `/route`.
</Warning>

This document covers:

* What Smart Relay is
* The bridges Smart Relay supports today (& whats next)
* How to use Smart Relay
* The factors that affect the price of Smart Relay

<Info>
  **What is relaying?**

  In general, relaying refers to the act of executing a cross-chain message/action by constructing the cross-chain proofs and submitting the burn/mint/wrap/ack proof transactions to the destination & source chains that are required to deliver the message.

  All bridges and general message passing protocols (IBC, Axelar, Wormhole, CCTP, etc…) have some notion of relaying but sometimes it goes by different names.
</Info>

## Background

Smart Relay is a **intent-aware**, **user-centric**, **universal** relayer with better performance guarantees than public relayers for all bridges and routes we support. We offer it at a small cost to the end-user and no cost to the developer/integrator. In short, Smart Relay helps users get to more destinations, in fewer transactions, and at faster speeds than via public relayers — no matter how many bridges or chains stand between them and their destination.

Smart Relay is huge improvement over existing relaying systems, made possible by intelligent integration with Skip Go's routing capabilities.:

* **Intent-aware**: Traditional relayers are unaware of what the user is trying to accomplish beyond the first hop of a transfer, but usually transfers are a part of a broader sequence of swaps, transfers, and actions. Smart Relayer has the context of the user's end-to-end cross-chain intent, and it can use this information to optimize its execution plan.
  * For example, Smart Relay can reduce the number of transactions a user must sign in a route by automatically triggering the second bridge in a route when delivering the packet for the first bridge (e.g. Triggering IBC from CCTP).
  * It can also use this information to prepare the user's destination address to receive the transfer (e.g. Dust it with gas even if there's no way to perform an atomic swap, or initialize a token account on Solana, etc...).
* **User-centric**: Traditional relayers are focused on specific "channels" or "bridges," simply transferring all packets for a single bridge route from one chain to another. Once that task is complete, they consider their job done. In contrast, Smart Relayers prioritize the user, not the bridge. Instead of clearing packets on one bridge at a time, they transfer all packets associated with a specific user across multiple bridges or hops, ensuring the user reaches their destination efficiently.
  * It also offers a deeply simplified payment experience for users that's designed for multi-hop: pay once in the source chain, in the token you're transferring, and receive high quality relaying at every leg of the route thereafter.
* **Universal**: Traditional relayers only support 1 or 2 chains or ecosystems at a time for a single bridge, making cross-ecosystem transfers fraught. Many routes have no relayers or just spotty coverage. Smart Relay was designed to support all ecosystems and all bridges from the start. It already supports EVM, Solana/SVM, Cosmos, and modular -- with more chains, bridges, and routes routinely added.

The cost of Smart Relay is determined dynamically based on the factors covered below. The gas prices and bridge fees involved in a route are the principal determinants of that cost.

## State of Smart Relay

Today, Smart Relay supports:

* CCTP

We are currently building out support for:

* IBC
* Hyperlane
* Axelar

For the bridges that Smart Relay does not support today, Skip Go uses public or enshrined relayers — at whatever cost they’re typically made available to users. (These are free for IBC and have some fee associated with them for others). All costs users will incur will always be made transparent in the relevant endpoint responses.

## How to Use Smart Relay

### How to activate Smart Relay

1. On `/route` or `/msgs_direct`, pass `smart_relay=true`
2. If using `/msgs`, ensure that you are passing the `smart_relay_fee_quote` object provided in the `cctp_transfer` operation from the `/route` response into your `/msgs` request.
   * If you're using the @skip-go/client library, version 0.8.0 and above supports this automatically. If you're integrating the API directly and decoding the `/route` response operations before passing them back into `msgs`, simply ensure you're decoding this new field properly and passing it back through!
3. Sign the transaction as usual, and submit the signed transaction to the Skip Go API via `/track` or `/submit` as normal
   * **NOTE: We HIGHLY recommend using `/submit` to submit Smart Relay transactions on chain to avoid issues incurred by submitting a transaction on chain but not sending it to the `/track` endpoint.**

That’s it! Smart Relay will take care of executing your cross-chain actions across all bridges it currently supports.

### How to determine what Smart Relay will cost the user

In the response to `/route` , `/msgs_direct` and `/msgs`, the cost of Smart Relay will appear in the `estimated_fees` array with `fee_type` set to `SMART_RELAY`. See [Getting Fee Info](./fee-info) for more info about `estimated_fees`

For multi-tx routes, the user may pay up to 1 Smart Relay fee per transaction.

The fee for each transaction pays for all Smart Relay operations in that particular transaction. This prevents Smart Relay from accepting payment prematurely to perform operations for the latter transactions, since the latter transactions may not get signed or executed.

You can use the `tx_index` attribute on the `estimated_fees` entries to identify which Smart Relay fee corresponds to which transaction in the route. (e.g. `tx_index=0` indicates this is the fee for the first transaction in the route)

### What Determines the Cost of Smart Relaying

Smart Relay incurs a user cost because Smart Relay involves actually submitting transactions to various chains and incurring transaction fees as a result.

* **Operations**: The cost of relaying a route depends on the operations in the route, since these affect the amount of gas Smart Relay consumes (e.g. routes that include swaps will require higher gas amounts & involve more expensive relaying)
* **The cost of gas:** Most networks have dynamic fee markets, where the price of gas increases during periods of high network load. Smart Relay takes this into account when generating a quote
* **Token Exchange Rates:** The token the user pays their fee in and the token Smart Relaying pays gas fees in may differ, so exchange rates affect the price the end user experiences. (e.g. If the user pays in OSMO for a route that terminates on Ethereum mainnet, Smart Relay will need to pay fees in ETH, so the amount of OSMO the user pays will depend on the OSMO/ETH spot price.)

### How to properly use the Smart Relay Fee Quote

Skip Go dynamically calculates the Smart Relay fee to be paid based on the underlying costs in real-time.

Although you should use the information in the `estimated_fees` array for display purposes, `cctp_transfer` includes a `smart_relay_fee_quote`, providing necessary information for proper use of the dynamic relaying fee system. Specifically, the `smart_relay_fee_quote` object contains information about the smart relay fee to be paid and when the quote expires (after which the quoted amount may no longer be valid and the transaction may not be succesfully relayed).

If you're using the `/msgs` endpoint, ensure that you are passing the `smart_relay_fee_quote` object provided in the `cctp_transfer` operation from the `/route` response into your `/msgs` request. This is necessary to ensure the transaction generated by the API matches the fee quoted in the `/route` request. If the quote is not passed back into the `/msgs` request, a new quote will be generated in the `/msgs` call that may be different than what was quoted previously in the `/route` request. Version `0.8.0` and above of the `@skip-go/client` library supports this automatically. If you're integrating the API directly and decoding the `/route` response operations before passing them back into `/msgs`, simply ensure you're decoding this new field properly and passing it back through!  See the `SmartRelayFeeQuote` below:

<CodeGroup>
  ```text TypeScript theme={null}
  export type SmartRelayFeeQuote = {
    feeAmount: string;
    feeDenom: string;
    feePaymentAddress: string;
    relayerAddress: string;
    expiration: Date;
  }
  ```

  ```JSON JSON theme={null}
  {
    "smart_relay_fee_quote": {
      "fee_amount": "100000",               // string
      "fee_denom": "uusdc",                 // string
      "fee_payment_address": "0x123",       // string
      "relayer_address": "0x123",           // string
      "expiration": "2024-08-30T05:28:05Z"  // string
    }
  }
  ```
</CodeGroup>


# Supported Ecosystems
Source: https://skip-go.mintlify-go.com/go/general/supported-ecosystems-and-bridges



<Info>
  **Activate Smart Relay (`smart_relay=true`) for global coverage of all chains, bridges, and routes**

  There are many routes that will return a RouteNotFound error if `smart_relay=false` because there are not public relayers that support them. This includes all routes to and from Solana, as well as CCTP routes to and from Polygon, Base, and several other L2s.

  As a result, if you want your users to be able to transfer their tokens over all routes, we recommend using [Smart Relay](/go/general/smart-relay).
</Info>

Skip Go API is a universal interoperability platform. It can be used to swap and transfer tokens within and between all major ecosystems in crypto over many major bridges. We're constantly adding new bridges, new chains, new routes on already-supported bridges, and new multi-hop routes by composing multiple bridges together.

This document gives a high level overview of the different ecosystems and bridges Skip Go API supports, including how to onboard assets into each ecosystem, when different bridges are used, and what DEXes are supported.

For each major ecosystem, this document identifies:

* The bridges over which Skip Go API can route users into and out of the ecosystem
* The bridges over which Skip Go API can route users within the ecosystem
* The DEXes where Skip Go API can swap within the ecosystem

The very short summary is that our Cosmos ecosystem support is most mature, followed by Ethereum, followed by Solana.

## Cosmos Support Details

**Onboard and offboard via**:

* Axelar (Move major tokens to Ethereum, Polygon, Avalanche, and ETH L2s)
* CCTP (Move USDC to all major Ethereum L2s, Polygon, Avalanche, and Solana)
  * Maximum transfer limit: 1,000,000 USDC per transaction
* Go Fast (Move assets at faster-than-finality speeds from EVM to Cosmos)
  * Currently, Go Fast supports the following source chains: Ethereum Mainnet, Arbitrum, Avalanche, Base, Optimism, Polygon.
* Eureka (IBC v2 that enables seamless interoperability between Cosmos and Ethereum ecosystem)

**Move within the ecosystem via:**

* IBC

**Swap within the ecosystem on:**

* Osmosis
* Astroport (on 3+ chains)
* InitiaDEX
* Astrovault (on Archway)
* Dojoswap (on Injective)
* Helix (on Injective)

## Ethereum Support Details

<Warning>
  **Never attempt to derive Cosmos Addresses from Ethereum Addresses (or vice versa)**

  Whenever you need an address on a chain for a user, please request it from the corresponding wallet.

  If you attempt to derive an address on one chain from an address on another chain, you may derive an address that the user cannot actually sign for if the two chains have different address-derivation processes. For example, if you derive a Cosmos address from an Ethereum address, you will get an address that the user cannot sign for or use.

  So don't ever try to derive one address from another -- even for intermediate addresses. (Intermediate addresses may be used for fund recovery if there is some kind of failure on an intermediate chain. Failures could include a timeout, a swap exceeding slippage tolerance, or any other unexpected execution path. We assume users can sign for intermediate addresses, even if they shouldn't have to.)
</Warning>

**Onboard and offboard via:**

* CCTP (Move USDC to/from Cosmos and Solana)
  * Maximum transfer limit: 1,000,000 USDC per transaction
* Axelar (Move ETH, MATIC, ARB, and other major tokens to/from Cosmos)
* Go Fast (Move assets at faster-than-finality speeds)
* Eureka (Seamless interoperability between Cosmos and Ethereum ecosystem)

**Move within ecosystem via:**

* Axelar (Move major assets among all major ETH L2s, Polygon, and Avalanche)

**Skip Go API supports swapping on DEXes within the Ethereum ecosystem**

* Uniswap V2/v3 (on Optimism, Binance, Blast, Base, Avax, Eth, Polygon, Celo )
* Velodrome (Optimism)
* Aerodrome (Base)

## Solana Support Details

**Onboard and offboard via:**

* CCTP (Move USDC to/from Cosmos, Ethereum/L2s and Solana)
  * Maximum transfer limit: 1,000,000 USDC per transfer

**Move within ecosystem via:**

* NA -- Solana is just 1 chain

**Skip Go API does not support swapping on any DEXes within the Solana ecosystem at this time**


# Transaction Support
Source: https://skip-go.mintlify-go.com/go/general/transaction-support



## **Overview**

* This guide outlines how to troubleshoot and escalate issues related to Skip Go transactions.
* The Skip Go Explorer should be used when troubleshooting
* Types of transactions supported (CCTP, Eureka, Layerzero, Stargate, Opinit, Axelar, IBC, Go Fast)
* Tools: [Explorer](https://explorer.skip.build/), Skip API

***

## **Step 1: Check Status in our Explorer**

* Use our [Explorer](https://explorer.skip.build/)
* If you click on your link transaction in your history on [go.skip.build](https://go.skip.build/) it will open with the transaction details preloaded.

<p>
  <img alt="Explorer from history link" />
</p>

* If you do not have the transaction in your history, please locate the source transaction hash and enter it into our [Explorer](https://explorer.skip.build/)
* Required inputs:
  * Initial Transaction hash
  * Chain Name

<p>
  <img alt="Explorer input screen" />
</p>

***

## **Step 2: Transaction status**

`state_completed_success`, `state_pending`, `state_abandoned`, etc. The explorer will tell you where your funds have been released if the transaction has failed, the swap failed and what asset has been released.

<p>
  <img alt="Explorer successful transaction" />
</p>

* If there is no state given, the explorer will ask to reindex/track your transaction:

<p>
  <img alt="Explorer asking to index" />
</p>

* After indexing, the status of your transaction will be updated. Example of successful, failed and pending states:

<p>
  <img alt="Explorer after indexing result" />
</p>

* The explorer will show where your funds have been released on chain:

<p>
  <img alt="Funds released info" />
</p>

* If your IBC transaction is pending, it may take upto 24 hours to clear.

<p>
  <img alt="Funds released info" />
</p>

* If you cannot find where your funds are released, refunded, received, please go to step 3.

***

## **Expanded Transfer Data & Statuses**

Skip Go supports multiple transfer mechanisms. Use the following references to understand and debug each type of transaction.

***

### **IBC Transfers**

Learn more: [IBC Transfer Details](/go/general/multi-chain-realtime-transaction-and-packet-tracking#ibc-transfer-data)

* **States:**
  * `TRANSFER_PENDING`: Sent, waiting to be received. May take upto 24 hours to be received on chain.
  * `TRANSFER_RECEIVED`: Received, may still revert if multi-hop.
  * `TRANSFER_SUCCESS`: Completed successfully.
  * `TRANSFER_FAILURE`: Transfer failed.
  * `TRANSFER_PENDING_ERROR`: Error occurred, refund pending.
* **Transactions:**
  * `send_tx`, `receive_tx`, `timeout_tx`, `acknowledge_tx`

***

### **Axelar Transfers**

Learn more: [Axelar Transfer Details](/go/general/multi-chain-realtime-transaction-and-packet-tracking#axelar-transfer-data)

* **States:**
  * `AXELAR_TRANSFER_PENDING_CONFIRMATION`: Waiting for Axelar confirmation.
  * `AXELAR_TRANSFER_PENDING_RECEIPT`: Confirmed, awaiting receipt.
  * `AXELAR_TRANSFER_SUCCESS`: Assets received.
  * `AXELAR_TRANSFER_FAILURE`: Transfer failed.
* **Transactions:**
  * `send_tx`, `confirm_tx`, `execute_tx`
  * May also include: `gas_paid_tx`, `approve_tx`

***

### **CCTP Transfers**

Learn more: [CCTP Transfer Details](/go/general/multi-chain-realtime-transaction-and-packet-tracking#cctp-transfer-data)

* **States:**
  * `CCTP_TRANSFER_SENT`: Burn submitted.
  * 'CCTP\_TRANSFER\_PENDING\_CONFIRMATION' - CCTP transfer is pending confirmation by the cctp attestation api
  * `CCTP_TRANSFER_CONFIRMED`: Confirmed by Circle.
  * `CCTP_TRANSFER_RECEIVED`: Received on destination chain.
* **Transactions:**
  * `send_tx`, `receive_tx`

***

### **Hyperlane Transfers**

Learn more: [Hyperlane Transfer Details](/go/general/multi-chain-realtime-transaction-and-packet-tracking#hyperlane-transfer-data)

* **States:**
  * `HYPERLANE_TRANSFER_SENT`: The transfer transaction on the source chain has executed.
  * `HYPERLANE_TRANSFER_RECEIVED`: The transfer has been received on the destination chain.
  * `HYPERLANE_TRANSFER_FAILED`: The transfer failed to complete.
  * `PACKET_ERROR_TIMEOUT`: The packet timed out.
  * `PACKET_ERROR_ACKNOWLEDGEMENT`: Error in packet acknowledgement.

* **Transactions:**
  * `send_tx`, `receive_tx`

***

### **OPInit Transfers**

Learn more: [OPInit Transfer Details](/go/general/multi-chain-realtime-transaction-and-packet-tracking#opinit-transfer-data)

* **States:**
  * `OPINIT_TRANSFER_SENT`: The deposit transaction on the source chain has executed.
  * `OPINIT_TRANSFER_RECEIVED`: Received at the destination chain.
  * `OPINIT_TRANSFER_FAILURE`: The transfer has failed.
  * `PACKET_ERROR_TIMEOUT`: The packet timed out.
  * `PACKET_ERROR_ACKNOWLEDGEMENT`: Error in packet acknowledgement.
* **Transactions:**
  * `send_tx`, `receive_tx`

***

### **Go Fast Transfers**

Learn more: [Go Fast Transfer Details](/go/general/multi-chain-realtime-transaction-and-packet-tracking#go-fast-transfer-data)

* **States:**
  * `GO_FAST_TRANSFER_SENT`: Intent submitted.
  * `GO_FAST_TRANSFER_FILLED`: Success.
  * `GO_FAST_TRANSFER_TIMEOUT`, `REFUNDED`, `POST_ACTION_FAILED`
* **Transactions:**
  * `order_submitted_tx`, `order_filled_tx`, `order_timeout_tx`, `order_refunded_tx`

***

### **Stargate Transfers**

Learn more: [Stargate Transfer Details](/go/general/multi-chain-realtime-transaction-and-packet-tracking#stargate-transfer-data)

* **States:**
  * `STARGATE_TRANSFER_SENT`, `RECEIVED`, `FAILED`, `UNKNOWN`
* **Transactions:**
  * `send_tx`, `receive_tx`, `error_tx`

***

### **Eureka Transfers**

Learn more: [Eureka Transfer Details](/go/general/multi-chain-realtime-transaction-and-packet-tracking#ibc-transfer-data)

* **States:**
  * `TRANSFER_SUCCESS`: The Eureka transfer has completed successfully.
  * `TRANSFER_RECEIVED`: The Eureka transfer has been received by the destination chain.
  * `TRANSFER_PENDING`: The Eureka transfer is in progress.
  * `TRANSFER_FAILURE`: The Eureka transfer has failed.
  * `PACKET_ERROR_ACKNOWLEDGEMENT`: Error in packet acknowledgement
  * `PACKET_ERROR_TIMEOUT`: The packet timed out before reaching the destination

* **Transactions:** Typically includes `send_tx`, `receive_tx`

***

### **LayerZero Transfers**

* **States:**
  * `LAYER_ZERO_TRANSFER_SENT`: Transfer initiated on the source chain
  * `LAYER_ZERO_TRANSFER_RECEIVED`: Assets received on the destination chain
  * `LAYER_ZERO_TRANSFER_FAILED`: Transfer failed
  * `LAYER_ZERO_TRANSFER_UNKNOWN`: Transfer state could not be determined

* **Transactions:** Usually `send_tx`, `receive_tx`, and `ack_tx`

***

## **Step 3: Escalate if needed**

* If you are unable to locate your funds please open a ticket in the [Interchain Discord](https://discord.com/invite/interchain)

<p>
  <img alt="Explorer input screen" />
</p>

***


# Privacy Policy
Source: https://skip-go.mintlify-go.com/go/legal-and-privacy/privacy-policy



**Effective date:** August 18, 2025

We take your privacy seriously. Please read this Privacy Policy to learn how we treat your personal data. By using or accessing our Services in any manner, you acknowledge that you accept the practices and policies outlined below, and you hereby consent to our collection, use and disclosure of your Personal Data as described in this Privacy Policy.

Remember that your use of our website(s) and related services ("Services") is at all times subject to any terms of use or other related terms made available to you ("Terms"), which incorporates this Privacy Policy. Any terms we use in this Privacy Policy without defining them have the definitions given to them in the Terms.

You may print a copy of this Privacy Policy by clicking here.

As we continually work to improve our Services, we may need to change this Privacy Policy from time to time. We will alert you of material changes by placing a notice on our website, by sending you an email and/or by some other means. Please note that if you've opted not to receive legal notice emails from us (or you haven't provided us with your email address), those legal notices will still govern your use of the Services, and you are still responsible for reading and understanding them. If you use the Services after any changes to the Privacy Policy have been posted, that means you agree to all of the changes.

## What This Privacy Policy Covers

This Privacy Policy covers how Skip Protocol collects and processes data that identifies or relates to you ("Personal Data") This Privacy Policy does not cover the practices of companies we don't own or control or people we don't manage and that in some instances. Additionally, if you are accessing our Services in connection with one of our Customers, that Customer's privacy policy will govern their collection and processing of your Personal Data.

## Personal Data We May Collect

**Device or Web Data.** If you interact with us online (e.g., by visiting our website or using our web-based Services, or participating in a survey through our Services), we may collect information about your device and/or browser such as your IP address-based location data, and type of device or browser used to interact with our properties.

**Contact Data.** If you sign up for an event, subscribe to our newsletters or other communications, or otherwise contact us, we may collect your contact information such as your name, email, job title, and your third-party handle (e.g., X) or username (e.g., Github, Telegram).

**Other Personal Data.** We may collect other Personal Data that you make available through Services or to us, such as in emails or other communications you send us.

## Sources of Personal Data

**From You.** We collect Personal Data when you provide it directly to us (e.g., you or contact us) and certain Personal Data (such as Device or Web Data) automatically when you use our Services (e.g., through Cookies – as defined in the "Cookies" section below).

**Public Sources.** We may collect Personal Data from widely available media or other public sources.

**Other Parties:** Such as:

* Vendors that provide analytics on how you interact or engage with our Services or that help provide you with customer support.
* Advertising Partners who may provide us with business leads, assist us with marketing or promotional services related to how you interact with our websites, applications, products, Services, advertisements, or communications.
* Other third parties that you access or authorize in connection with our Services

## Purpose for Collection and Processing Personal Data

**To Provide, Customize, and Improve our Services.**

* Providing you with the products, services, or information you request.
* Meeting or fulfilling the reason you provided the information to us, including to provide Services to our Customers.
* Providing support and assistance for the Services.
* Improving the Services, including testing, research, internal analytics, and product development.
* Personalizing the Services, website content, and communications based on your preferences.
* Doing fraud protection, security, and debugging.

**Marketing our Services**

* Marketing and selling the Services.
* Showing you advertisements, including targeted advertising.

**Corresponding with You**

* Responding to correspondence that we receive from you, contacting you when necessary or requested, and sending you information about the Company or the Services.
* Sending emails and other communications according to your preferences.

**Legal or Security**

* Meeting legal requirements and enforcing legal terms.
* Preventing, detecting and investigating security incidents and potentially illegal or prohibited activities.
* Protecting the rights, property or safety of you, Skip Protocol or another party.
* Enforcing any agreements with you;
* Responding to claims that any posting or other content violates third-party rights; and
* Resolving disputes.

## How We Disclose Personal Data

**Service Providers.** These parties help us provide the Services or perform business functions on our behalf. They may include: hosting, technology and communication providers; security and fraud prevention consultants; support and customer service vendors; analytics providers that analyze the use of our Services.

**Advertising Partners.** These parties help us market our services and provide you with other offers that may be of interest to you. They may include: ad networks, data brokers, marketing providers, and analytics providers.

**Customers.** If you access our Services in connection with a Customer, we may share your Personal Data, such as your responses to product-related questions with that Customer.

**Business Partners.** These parties partner with us in offering various services. They may include organizations that we may partner with to offer joint Services or opportunities.

**Parties You Authorize, Access or Authenticate.** This includes third parties you access or interact with through the Services or otherwise direct us to share Personal Data with.

**Others.** We may also disclose Personal Data that we collect with third parties in conjunction with any of the activities set forth under the "Legal or Security" subsection above. Additionally, all of your Personal Data that we collect may be transferred to a third party if we undergo a merger, acquisition, bankruptcy, or other transaction in which that third party assumes control of our business (in whole or in part).

## Cookies

The Services use cookies and similar technologies such as pixel tags, web beacons, clear GIFs and JavaScript (collectively, "Cookies") that may collect or facilitate the collection of your Personal Data for various purposes. We may also supplement the information we collect via Cookies with information received from third parties, including third parties that have placed their own Cookies on your device(s).

We may use the following types of Cookies:

* **Essential Cookies.** Essential Cookies are required for providing you with features or services that you have requested. For example, certain Cookies enable you to log into secure areas of our Services. Disabling these Cookies may make certain features and services unavailable.
* **Functional Cookies.** Functional Cookies are used to record your choices and settings regarding our Services, maintain your preferences over time and recognize you when you return to our Services.
* **Performance/Analytical Cookies.** Performance/Analytical Cookies allow us to understand how visitors use our Services. They do this by collecting information such as the number of visitors to the Services, what pages visitors view on our Services and how long visitors are viewing pages on the Services. These Cookies help us better understand users of our Services and can also help us measure our targeted advertising efforts.
* **Retargeting/Advertising Cookies.** Retargeting/Advertising Cookies collect data about your online activity and identify your interests so that we can provide advertising that we believe is relevant to you.

Many internet browsers have an option for turning off the Cookie feature, which will prevent your browser from accepting new Cookies, as well as (depending on your browser software) allow you to decide on acceptance of each new Cookie in a variety of ways. You can also delete all Cookies that are already on your device. If you do this, however, you may have to manually adjust some preferences every time you visit our website and some of the Services and functionalities may not work.

To find out more information about Cookies generally, including information about how to manage and delete Cookies, please visit [http://www.allaboutcookies.org/](http://www.allaboutcookies.org/) or [https://ico.org.uk/for-the-public/online/cookies/](https://ico.org.uk/for-the-public/online/cookies/) if you are located in the European Union.

## Session Replay Technology

We may use session replay technology in order to identify and resolve customer issues, to monitor and analyze how you use our Services, to better understand user behavior, and to improve our Services. By continuing to use the Services, you consent to the use of session replay technology. If you would like to change your settings with respect to session replay technology, you can access your Cookie management settings on the homepage.

## Data Security and Retention

Although we work to protect the security of your account and Personal Data that we hold in our records, please be aware that no method of transmitting data over the internet or storing data is completely secure.

We retain Personal Data about you for as long as necessary to provide you with our Services or to perform our business or commercial purposes for collecting your Personal Data. When establishing a retention period for certain categories of Personal Data, we consider who we collected the data from, our need for the Personal Data, why we collected the Personal Data, and the sensitivity of the Personal Data. In some cases, we retain Personal Data for longer, if doing so is necessary to comply with our legal obligations, resolve disputes or collect fees owed, or is otherwise permitted or required by applicable law, rule, or regulation. We may further retain information in an anonymous or aggregated form where that information would not identify you personally.

## Personal Data of Children

As noted in the Terms of Use, we do not knowingly collect or solicit Personal Data from children under 18 years of age; if you are a child under the age of 18, please do not attempt to use the Services or send us any Personal Data. If we learn we have collected Personal Data from a child under 18 years of age, we will delete that information as quickly as possible. If you believe that a child under 18 years of age may have provided Personal Data to us, please contact us at [Legal@interchainlabs.io](mailto:Legal@interchainlabs.io).

## State Law Privacy Rights

### California Resident Rights

Under California Civil Code Sections 1798.83-1798.84, California residents are entitled to contact us to prevent disclosure of Personal Data to third parties for such third parties' direct marketing purposes; however, we do not make such disclosures.

### Nevada Resident Rights

If you are a resident of Nevada, you have the right to opt-out of the sale of certain Personal Data to third parties. Please note that we do not currently sell your Personal Data as sales are defined in Nevada Revised Statutes Chapter 603A.

## European Data Subject Rights

If you are a resident of the European Union ("EU"), United Kingdom ("UK"), Lichtenstein, Norway or Iceland, you may have additional rights under the EU or UK General Data Protection Regulation (the "GDPR") with respect to your Personal Data, as outlined below. If you engage with us in connection with a particular Project, we may be processing your Personal Data as a processor to a Customer (the controller). For any other Personal Data, Skip Protocol will be the controller. Depending on your relationship with us, you may need to submit requests related to your Personal Data to our customer. If you have any questions about this section or whether any of the following applies to you, please contact us at [Legal@interchainlabs.io](mailto:Legal@interchainlabs.io).

### Personal Data Use and Processing Grounds

The "Purposes for Collecting and Processing Personal Data" section above explains how we use your Personal Data.

We will only process your Personal Data if we have a lawful basis for doing so. Lawful bases for processing include consent, contractual necessity and our "legitimate interests" or the legitimate interest of others, as further described below.

* **Contractual Necessity:** We process the following categories of Personal Data as a matter of "contractual necessity", meaning that we need to process the data to perform under our Terms with you, which enables us to provide you with the Services. When we process data due to contractual necessity, failure to provide such Personal Data will result in your inability to use some or all portions of the Services that require such data.
  ○ Device or Web Data
  ○ Contact Data

* **Legitimate Interest:** We process the following categories of Personal Data when we believe it furthers the legitimate interest of us or third parties:
  ○ Device or Web Data
  ○ Contact Data
  ○ Project Data
  ○ Other Personal Data
  ○ We may also de-identify or anonymize Personal Data to further our legitimate interests.

Examples of these legitimate interests include (as described in more detail above):
○ Providing, customizing and improving the Services.
○ Marketing the Services.
○ Corresponding with you.
○ Meeting legal requirements and enforcing legal terms.
○ Completing corporate transactions.

* **Consent:** In some cases, we process Personal Data based on the consent you expressly grant to us at the time we collect such data. When we process Personal Data based on your consent, it will be expressly indicated to you at the point and time of collection.
* **Other Processing Grounds:** From time to time we may also need to process Personal Data to comply with a legal obligation, if it is necessary to protect the vital interests of you or other data subjects, or if it is necessary for a task carried out in the public interest.

### Disclosing Personal Data

The "How We Disclose Your Personal Data" section above details how we disclose your Personal Data with third parties.

### EU, UK and Swiss Data Subject Rights

You have certain rights with respect to your Personal Data, including those set forth below. For more information about these rights, or to submit a request, please email us at [Legal@interchain.io](mailto:Legal@interchain.io). Please note that in some circumstances, we may not be able to fully comply with your request, such as if it is frivolous or extremely impractical, if it jeopardizes the rights of others, or if it is not required by law, but in those circumstances, we will still respond to notify you of such a decision. In some cases, we may also need you to provide us with additional information, which may include Personal Data, if necessary to verify your identity and the nature of your request.

* **Access:** You can request more information about the Personal Data we hold about you and request a copy of such Personal Data.
* **Rectification:** If you believe that any Personal Data we are holding about you is incorrect or incomplete, you can request that we correct or supplement such data.
* **Erasure:** You can request that we erase some or all of your Personal Data from our systems.
* **Withdrawal of Consent:** If we are processing your Personal Data based on your consent (as indicated at the time of collection of such data), you have the right to withdraw your consent at any time. Please note, however, that if you exercise this right, you may have to then provide express consent on a case-by-case basis for the use or disclosure of certain of your Personal Data, if such use or disclosure is necessary to enable you to utilize some or all of our Services.
* **Portability:** You can ask for a copy of your Personal Data in a machine-readable format. You can also request that we transmit the data to another controller where technically feasible.
* **Objection:** You can contact us to let us know that you object to the further use or disclosure of your Personal Data for certain purposes, such as for direct marketing purposes.
* **Restriction of Processing:** You can ask us to restrict further processing of your Personal Data.
* **Right to File Complaint:** You have the right to lodge a complaint about our practices with respect to your Personal Data with the supervisory authority of your country or EU Member State. A list of Supervisory Authorities is available here: [https://edpb.europa.eu/about-edpb/board/members\_en](https://edpb.europa.eu/about-edpb/board/members_en).

### Transfers of Personal Data

Depending on your relationship with us, the Services may be hosted and operated in the United States ("U.S.") through Skip Protocol, its affiliates, and its service providers, and laws in the U.S. may differ from the laws where you reside. By using the Services, you acknowledge that any Personal Data about you, regardless of whether provided by you or obtained from a third party, may be provided to Skip Protocol in the U.S. and may be hosted on U.S. servers, and you authorize Skip Protocol to transfer, store and process your information to and in the U.S., and possibly other countries. In some circumstances, your Personal Data may be transferred to the U.S. pursuant to a data processing agreement incorporating standard data protection clauses.

## Contact Information

If you have any questions or comments about this Privacy Policy or the ways in which we collect and use your Personal Data, please do not hesitate to contact us at:

Skip Protocol Inc.
740 Broadway, STE 1002 New York, New York, 10003 United States
[legal@interchainlabs.io](mailto:legal@interchainlabs.io)

## GDPR Job Applicant and Worker Privacy Notice

**Effective Date:** August 18, 2025

Skip Protocol Inc. and its operating groups, subsidiaries and affiliates (collectively, "Company," "us" or "we") are committed to protecting the privacy and security of the personal data of provided by individuals applying for a job or other role at ("Job Applicants"), as well as the personal data of our current and former employees and contractors (collectively, "Workers") and their emergency contacts and beneficiaries. Please read this Job Applicant and Worker Privacy Notice (the "Privacy Notice") to learn how we treat your personal data when you are one of our Job Applicants or Workers. If you are located in in the European Economic Area ("EEA"), Switzerland, or the United Kingdom ("UK"), you have certain rights under General Data Protection Regulation ("EU GDPR") and as the EU GDPR forms part of the law of England and Wales by virtue of section 3 of the European Union (Withdrawal) Act 2018 (together, the "GDPR") with respect to your personal data, as outlined below. In this Privacy Notice, we use the term "personal data" as it is defined under the GDPR. This Privacy Notice only applies to Job Applicants and Workers located in the EEA, Switzerland, and the UK.

As we continually work to improve our operations and business, we may need to change this Privacy Notice from time to time. Upon material changes, we will alert you to any such changes by placing a notice on 's intranet, by sending you an email and/or by some other means.

### What Categories of Personal Data Do We Collect?

Below details the categories of personal data we may collect and may have collected over the past twelve (12) months. Note that the collection, use, and disclosure of your personal data may vary depending on the nature of your relationship with us, including whether you're a Job Applicant, a Worker, or a Worker's emergency contacts and beneficiaries.

**FOR JOB APPLICANTS:**
Depending on where you are in the application stage (e.g., screening, assessment tests, interviews, background and reference checks, or decision stage), the collection, use, and disclosure of your personal data may vary. We may collect:

* Personal Contact Data such as name, alias, mailing address, email address, phone number.
* Internet or Other Electronic Network Activity Data such as information regarding your interaction with our career website, application, or advertisement, including chats and instant messaging.
* Geolocation Data such as IP-address-based location information.
* Sensory Data such as photos, videos, and recordings of you and your environment.
* Professional or Employment-Related Data such as resume, job title, job history, performance evaluations, membership in professional organizations and unions, and job interview notes, responses to screening questions and assessment results.
* Education Data such as grades or transcripts, student financial information, and student disciplinary records.
* Special Categories of Personal Data - in countries where it is legal to do so - such as genetic, biometric and health data, as well as personal data revealing racial and ethnic origin, political opinions, religious or ideological convictions or trade union membership.

**FOR WORKERS:**
Similar categories of data we collect in your role as a Job Applicant as described above may be collected and retained if you are employed by the Company. For additional categories of personal data that may be collected solely from Workers, please see below.

* Geolocation Data such as IP-address-based location information.
* Professional or Employment-Related Data such as performance management information (e.g., employment status, work schedule, job assignments, hours worked, accomplishments, awards), training and development information, discipline and counseling information, and employment termination information.
* Other Personal data such as dependent information, emergency contact information, and beneficiary information.

### Legal Basis for Processing your Personal Data

Depending on the nature of your relationship with us, including whether you're a Job Applicant, a Worker, or a Worker's emergency contacts and beneficiaries, we only process your personal data where applicable law permits or requires it, including where the processing is necessary to assess your potential employment with us, to comply with our legal obligations, for our legitimate interests or the legitimate interests of third parties, or with your consent. We may process your personal data for legitimate business purposes and for the following purposes:

* Process and manage your application: We use your personal data to process your job application, establish a job applicant profile for the recruitment process, assess your qualifications for a specific role with us, schedule and conduct interviews, communicate with you, and carry out background and reference checks (see the following bullet point for additional information). We may collect audio and visual information of job applicants through photographs used for identification purposes. With your consent, we may record video of you in connection with the application process, for example through a third party screening service.
* Process and manage your employment: If you are offered a position with us, we will use your personal data in the employment on-boarding process and managing your personnel records including enrolling and administering employee benefits, paying wages, managing workflows, carrying out job promotion processes, evaluating performance, and other related employment purposes (as authorized by you and permitted by applicable law).
* Conduct reference and background checks (as permitted by applicable law): We use personal data we collect to conduct reference checks and to evaluate your qualifications and experience. We may also conduct background checks (as authorized by you and permitted by applicable law).
* Provide immigration support: If applicable and as permitted by applicable law, we may collect your personal data to assist with immigration support, such as applying for visas or work permits.
* Analyze and improve our recruitment process and tools: For example, we analyze trends in our applicant pool, and use personal data to understand and improve our recruitment process and tools, including improving diversity and inclusion.
* Record-keeping: We keep records of your personal data as required by law and in accordance with our record retention policies.
* Meeting legal requirements and enforcing legal terms: We collect and process your personal data for purposes of: fulfilling our legal obligations under applicable law, regulation, court order or other legal process, such as preventing, detecting and investigating security incidents and potentially illegal or prohibited activities; protecting the rights, property or safety of you, us or another party; enforcing any agreements with you; responding to claims; and resolving disputes. Additionally, we may use information about protected characteristics to analyze and monitor the diversity of our job applicants and Workers in accordance with applicable laws.

We will only process your personal data for the purposes we collected it for or for compatible purposes. If we need to process your personal data for an incompatible purpose, we will provide notice to you and, if required by law, seek your consent. We may process your personal data without your knowledge or consent where required by applicable law or regulation.

We may also process your personal data for our own legitimate interests, including for the following purposes:

* To prevent fraud.
* To ensure network and information security, including preventing unauthorized access to our computer and electronic communications systems and preventing malicious software distribution.
* To support internal administration with our affiliated entities.
* To conduct data analytics analyses to review and better understand our recruitment process.

You will not be subject to automated decision-making or profiling (as such terms are described in the GDPR) without your prior consent.

### Collection and Use of Special Categories of Personal Data

We may collect and process certain special categories personal data about you, in countries where it is legal to do so, such as genetic, biometric and health data, as well as personal data revealing racial and ethnic origin, political opinions, religious or ideological convictions or trade union membership, to the extent such processing is necessary for us to carry out our obligations with respect to your application or employment. Where we have a legitimate need to process special categories of personal data about you for purposes not identified above, we will only do so only after providing you with notice and, if required by law, obtaining your prior, express consent.

### How We Disclose Personal Data

Unless specifically noted, we disclose personal data to the categories of service providers and other parties listed in this section.

* Affiliates. Our affiliates help us to perform business functions on our behalf.
* Service Providers. These parties help us to perform business functions on our behalf, such as:
  ○ Hosting, technology and communication providers.
  ○ Security and fraud prevention consultants.
  ○ Background and reference check screening services.
  ○ Hiring process and benefits management and administration tools.
  ○ Health and safety technology providers.

### Data Security

We seek to protect your personal data from unauthorized access, use and disclosure using appropriate physical, technical, organizational and administrative security measures based on the type of personal data and how we are processing that information. You should also help protect your data by appropriately selecting and protecting your password and/or other sign-on mechanism, limiting access to your computer or device and browser, and signing out after you have finished accessing your account. Although we work to protect the security of your account and other data that we hold in our records, please be aware that no method of transmitting data over the internet or storing data is completely secure.

### Data Retention

We retain personal data about you for as long as necessary to perform our business or commercial purposes, including employment-related purposes, for collecting your personal data. When establishing a retention period for specific categories of personal data, we consider who we collected the personal data from, our need for the personal data, why we collected the personal data, and the sensitivity of the personal data. In some cases we retain personal data for longer, if doing so is necessary to comply with our legal obligations, resolve disputes or collect fees owed, or is otherwise permitted or required by applicable law, rule or regulation. We may further retain information in an anonymous or aggregated form where that information would not identify you personally.

Note that if you are a Job Applicant that applied through a third-party such as a recruiting company or submitted your application through a recruiting software (e.g., Greenhouse, Linkedin, etc.), you may be subject to their separate terms of service and privacy policy.

### Your Rights under the GDPR

If you are a Job Applicant or Worker located in the EEA, Switzerland, or the UK, we are required to provide you with additional information about our processing of your personal data. Please note that, except as otherwise provided by applicable law, the information in this section as well as the other sections of this Privacy Notice apply to you.

If you are a Job Applicant or Worker located in the UK, Switzerland or EEA, is the controller of your personal data. As a data controller, is responsible for ensuring that 's processing of your personal data complies with the GDPR.

### Rights of Access, Correction, Erasure, and Objection

It is important that the personal data we hold about you is accurate and current. Please keep us informed if your personal data changes during the recruitment process. By law, you may have the right to request access to, correct, and erase the personal data that we hold about you, or object to the processing of your personal data under certain circumstances. You may also have the right to request that we transfer your personal data to another party.

### Right to Withdraw Consent

Where you have provided your consent to the collection, processing, or transfer of your personal data, you may have the legal right to withdraw your consent under certain circumstances.

We may request specific information from you to help us confirm your identity and your right to access, and to provide you with the personal data that we hold about you or make your requested changes. Applicable law may allow or require us to refuse to provide you with access to some or all of the personal data that we hold about you, or we may have destroyed, erased, or anonymized your personal data in accordance with our record retention obligations and practices. If we cannot provide you with access to your personal data, we will inform you of the reasons why, subject to any legal or regulatory restrictions.

### Cross-Border Data Transfers

Where permitted by applicable law, we may transfer the personal data we collect about you to the United States and other jurisdictions that may not be deemed to provide the same level of data protection as your home country for the purposes set out in this Privacy Notice. Where necessary, we have implemented standard contractual clauses to help secure the transfer.

### Contact for Questions

If you have any questions or comments regarding this Privacy Notice, the ways in which we collect and use your personal data or your choices and rights regarding such collection and use, please contact:

* [compliance@interchainlabs.io](mailto:compliance@interchainlabs.io)
* 740 Broadway, STE 1002, New York City, 10003, NY, USA

Individuals with disabilities may access this Privacy Notice in an alternative format by contacting [legal@interchainlabs.io](mailto:legal@interchainlabs.io).


# Terms of Service
Source: https://skip-go.mintlify-go.com/go/legal-and-privacy/terms-of-service



**TERMS OF SERVICE**

Last Revised: August 9, 2024

These Terms of Service (the “**Terms**”) constitute a legally binding agreement made between you (“**you**”), and Skip Protocol, Inc. (“**Skip**,” “**we**,” or “**us**”), concerning your access to and use of the skip.build website, together with all sub-domains, and any other websites that may be offered by Skip from time to time (the “**Website**”), the “Skip:Go” front-end user interface hosted by Skip at go.skip.build (the “**Interface**”), and any other web applications or software that may be offered by Skip from time to time (collectively, the “**Services**”). By accessing or using the Services, you agree that you have read, understand and accept all of the terms and conditions contained in the Terms. If you do not agree to all of the Terms, you may not access or use the Services.

**Amendment of the Terms**. We may amend or modify the Terms at any time by posting the revised version on the Website and/or providing a copy to you (“**Revised Terms**”). Such Revised Terms shall be effective as of the time the Revised Terms are posted on the Website. Your continued use of the Services after the posting of Revised Terms constitutes your acceptance of such Revised Terms. If you do not agree with any such revisions, your sole and exclusive remedy is to terminate your use of the Services.

**Technical Services Only**. THE SERVICES INCLUDE, AMONG OTHER THINGS, A WEB-BASED USER INTERFACE THAT ALLOWS USERS TO ENGAGE IN A VARIETY OF BLOCKCHAIN-BASED CRYPTO ASSET TRANSACTIONS VIA PERMISSIONLESS, PUBLIC BLOCKCHAINS AND BLOCKCHAIN-NATIVE DEVELOPER TOOLS. THE INTERFACE ENABLES USERS TO INTERACT DIRECTLY WITH ONCHAIN SMART CONTRACTS THAT FUNCTION DETERMINISTICALLY AND ARE NOT OPERATED OR CONTROLLED (WHETHER VIA ADMINISTRATIVE KEYS OR OTHERWISE) BY SKIP. SKIP IS NOT A BROKER, DEALER, EXCHANGE, INVESTMENT ADVISER, CUSTODIAN OR FINANCIAL SERVICE PROVIDER OF ANY KIND. WE DO NOT HAVE A FIDUCIARY RELATIONSHIP OR OBLIGATION TO YOU IN CONNECTION WITH THE SERVICES.

**Binding Arbitration; Class Action and Jury Trial Waiver**. PLEASE BE AWARE THAT SECTION 9 (DISPUTE RESOLUTION; AGREEMENT TO ARBITRATE) GOVERNS THE RESOLUTION OF DISPUTES BETWEEN YOU AND SKIP. SECTION 9 INCLUDES AN AGREEMENT TO ARBITRATE WHICH REQUIRES, WITH LIMITED EXCEPTIONS, THAT ALL DISPUTES BETWEEN YOU AND US SHALL BE RESOLVED BY BINDING AND FINAL ARBITRATION. SECTION 9 ALSO CONTAINS A CLASS ACTION AND JURY TRIAL WAIVER. PLEASE READ SECTION 9 CAREFULLY.

**Privacy Policy**. Your personal information and privacy are important to us. The collection, use and sharing of your personal information through the Services and while you use the Services are subject to our [Privacy Policy](../legal-and-privacy/privacy-policy) which is hereby incorporated into the Terms.

1. **Eligibility**. To be eligible to access or use the Services, you must satisfy each of the following eligibility requirements:
   1. You are at least eighteen (18) years of age, or are the legal age for entering into legally binding agreements under applicable law;
   2. You are not, nor are you an entity that is, or an entity owned or controlled by any person or entity that is, or conducting any activities itself or on behalf of any person or entity that is: the subject of any sanctions administered or enforced by the U.S. Department of the Treasury’s Office of Foreign Assets Control, the U.S. Department of State or any other governmental authority with jurisdiction over the party; identified on the Denied Persons, Entity or Unverified Lists of the U.S. Department of Commerce’s Bureau of Industry and Security; or located, organized or resident in a country or territory that is, or whose government is, the subject of economic sanctions, including, without limitation, Russia, Crimea, Cuba, Iran, North Korea or Syria (each, a “**Restricted Person**”); and
   3. You are not accessing or using the Services on behalf of a Restricted Person.
2. **Use of the Protocol**.
   1. The Protocol and the Interface. The Services include the Interface, which allows users to access and interact with onchain smart contracts designed to facilitate cross-chain transactions (the “**Protocol**”). Skip contributed to the development of certain of the onchain smart contracts comprising the Protocol, but does not control or operate these smart contracts. The Interface is not the exclusive or sole means to access the Protocol, which is comprised of smart contracts that operate on various permissionless, public blockchains. Please review the Protocol software code and related documentation before using the Services to access or interact with the Protocol to learn more about the code, rules and requirements of the Protocol. For the avoidance of doubt, the Protocol is **not** a part or component of the Services and Skip does not control, maintain administrative rights over or operate the Protocol.
   2. Prior Versions of the Protocol. New versions and upgrades to the Protocol may be released from time to time. The Services may not be compatible with prior, abandoned or outdated versions of the Protocol. Skip undertakes no responsibility or obligation to update or maintain support for legacy versions of the Protocol.
   3. Protocol Fees. You acknowledge and agree that the Protocol may from time to time assess service fees (“**Protocol Fees**”) directly from you in accordance with the Protocol’s rules or as a result of third-part applications that the Protocol utilizes.
3. **Accessing the Services; Informational Resources**.
   1. Connecting a Wallet. To access and use certain aspects of the Services, you will be required to connect a compatible blockchain digital wallet (“**Wallet**”). By connecting a Wallet to the Services, you agree to abide by the terms and conditions of the applicable software provider or developer that developed and/or maintains the applicable Wallet software available to you. You are solely responsible for reviewing the terms of use, technology and security protocols associated with your Wallet software. Skip does not offer Wallet software or take custody, possession or control of your crypto assets at any time as Skip does not maintain any administrative control over the smart contracts that comprise the Protocol. You are solely responsible for maintaining the security of your Wallet, including your credentials, private key and/or seed phrase. Skip shall not be liable for any acts or omissions by you in connection with your Wallet or any security incident related to your Wallet.
   2. Cross-Chain Transactions. You may use the Services to interact with Protocol smart contracts on various blockchain networks to facilitate the exchange of crypto assets on a source blockchain network for crypto assets on a destination blockchain network. When you exchange crypto assets on a source network for crypto assets on a destination network, you will receive the crypto assets on the destination network within a separate blockchain address on the destination network. The purchased crypto assets will appear in your Wallet on the destination network, but will not appear in your Wallet on the source network. You own, control, and are responsible for all crypto assets held in and exchanged via your Wallet and Skip is not liable or responsible for any crypto assets that are destroyed or irretrievably lost by users through the cross-chain transaction process.
   3. Representations and Warranties. By accessing the Services, you represent and warrant to each of the following: (i) any crypto assets you interact with via the Services have been legally obtained by, and belong to, you; (ii) you will not provide any false, inaccurate or misleading information while using the Services, or engage in any activity that operates to defraud or would be viewed as reasonably having a material adverse effect on Skip, other users of the Services or any other person or entity; (iii) you will not use the Services to transmit or exchange crypto assets that are the direct or indirect proceeds of any criminal or fraudulent activity, including, without limitation, terrorism, money laundering or tax evasion; and you will pay all fees (including Protocol Fees, if any) necessary for interacting with the blockchain networks supported by the Services, including all transaction fees or “gas”, as well as all fees charged by us or any third party for your use of the Services, any blockchain network.
   4. Informational Resources. We may make certain informational resources relating to the Services and the Protocol, including, without limitation, technical documentation, blog posts, data, articles, tutorials, social media posts and other informational content published by us, our employees or marketing partners (“**Informational Resources**”), available to you as part of the Services. You acknowledge and agree that all such Informational Resources are intended for informational and educational purposes only and may not be the exclusive or sole source of information regarding the Services and/or the Protocol. Skip shall not be responsible or liable for any damage or loss caused or alleged to be caused by or in connection with the use or reliance on any Informational Resources.
4. **Prohibited Activities**.
   1. You shall not engage in any activities that negatively affect the technical performance of the Services, bypass or circumvent security features of the Services or otherwise disrupt or interfere with the functioning of the Services. You shall not violate or attempt to violate the security of the Services or otherwise misuse the foregoing, including by: (i) using any part of the Services or accessing data not intended for you or logging onto a server or an account that you are not authorized to access (including by using a virtual private network or “VPN” to access such data); (ii) disabling, removing, defeating or avoiding any security device or system; (iii) attempting to probe, scan or test the vulnerability of the Services or to breach security or authentication measures without proper authorization; (iv) attempting to interfere with the Services functionality, including but not limited to via means of submitting any malware or computer programming routines that may damage, disrupt or interfere with, intercept or expropriate any system or data, overloading, “flooding,” “spamming,” “mailbombing” or “crashing” the Services or the Protocol when using the Services; (v) forging any transmission control protocol/internet protocol packet header or any part of the header information in any email or posting; (vi) using the Services or the Protocol in a manner that exceeds reasonable request volume or constitutes excessive or abusive usage; or (vii) providing false, misleading or inaccurate information to the Services, such as information related to your location whether by use of a VPN or otherwise.
   2. You shall not, directly or indirectly: (i) disassemble, decompile, reverse engineer or use any other means to attempt to discover any source code of the Services, or the underlying ideas, file formats, algorithms or trade secrets therein (unless such source code is open sourced); (ii) encumber, sublicense, transfer, rent, lease, time-share or use the Services in any service bureau arrangement or otherwise for the benefit of any third party; (iii) copy, distribute, manufacture, adapt, create derivative works of, translate, localize, port or otherwise modify any software code or documentation for the Services; (iv) knowingly introduce into the Services or the Protocol any malicious code, computer virus, spyware, scareware, Trojan horses, worms, malware or any other similar harmful, malicious or hidden programs or data; (v) use the Services to infringe upon, violate or misappropriate any third party’s intellectual property rights, violating any law or regulation or being defamatory, trade libelous, threatening or harassing; or (vi) authorize or permit any third party to engage in any of the foregoing proscribed acts. For the avoidance of doubt, the restrictions set forth in this Section are in addition to, and in no way limit, any other restrictions or obligations applicable to you set forth in the Terms.
   3. You shall not use the Services to engage in illegal activity of any kind, including, without limitation, any activity that would violate, or assist in violation of, any law, statute, ordinance, regulation or sanctions programs administered under any applicable law, including but not limited to the U.S. Department of Treasury’s Office of Foreign Assets Control or which would involve proceeds of any unlawful activity.
5. **Intellectual Property**.
   1. License. The Services and all of its contents as a whole and in part are protected by copyrights, trademarks, service marks, trade names, international treaties and/or other proprietary rights and applicable laws, and are owned or controlled by Skip, its affiliates and licensors. You agree to protect the proprietary rights of us and all others having rights in the Services. Subject to the Terms, we grant you a limited, revocable, non-exclusive, non-sublicensable, non-transferable license to use the Services for your own personal or legitimate business purposes. You acquire absolutely no rights or licenses in or to the Services or materials contained within the Services and the limited right for you to access and use the Services in accordance with the Terms. Except for the limited license granted in these Terms, Skip and its licensors retain all right, title, interest and all proprietary rights in and to the Services, including, without limitation, copyrights, patents, trademarks, service marks and trade names. Skip may change, suspend or discontinue any aspect of the Services at any time, without any liability or obligation to you. Skip, its licensors and service providers reserve all other rights afforded to them but not granted in these Terms.
   2. Third-Party Licenses. Notwithstanding anything to the contrary in the Terms, the Services may contain software components released under separate open-source or business-source license terms, in which case those license terms will govern such software components.
   3. Feedback. With respect to any feedback you provide to Skip (whether orally or in writing) concerning the Services, including any features or functionalities thereof, and including identifying potential errors and improvements (“**Feedback**”), you hereby grant to Skip an exclusive, worldwide, perpetual, fully paid-up, royalty free, fully-sublicensable (through multiple tiers of sublicensees) and freely assignable and transferable license to use any Feedback for any purpose without payment or restriction. It is further understood that Skip’s use of Feedback, if any, may be used by Skip in its sole discretion, and that Skip shall in no way be obliged to make any payment to you for or make use of any kind of the Feedback or part thereof.
   4. Use of Trademarks and Other Marks or Rights. You may not use any of our trademarks, trade names, service marks, copyrights or logos, or our partners’, affiliated entities’, licensors’, or their licensors’ trademarks, trade names, service marks, copyrights or logos, including but not limited to the Skip name, in any manner that creates the impression that such items: (i) belong to or are associated with you or indicate the sponsorship or approval of us, our licensors, any partners, affiliates or their licensors; or (ii) except as otherwise provided herein, are used with our licensors’, partners’, affiliates’, or their licensors’ consent, and you acknowledge that you have no ownership rights in or to any such items.
6. **Term; Termination**.
   1. The Terms are effective beginning when you accept the Terms or first access or use the Services and ending when terminated as set forth in Section 6.2.
   2. Your right to use and access the Services will automatically terminate in the event you fail to comply with any of the terms and conditions of the Terms. Termination will be effective without notice.
   3. Upon termination of the Terms, your license rights will immediately terminate and you must immediately cease all use of the Services. Sections 4-11 of the Terms shall survive any such termination.
7. **Risks**.
   1. You acknowledge and understand that the Services, the Protocol and certain crypto assets, blockchain-based protocols and/or blockchain networks may not be available or appropriate for use in all jurisdictions and you may be subject to legal and regulatory compliance obligations in connection with your use of the Services in certain jurisdictions. By accessing or using the Services, you agree that you are solely and entirely responsible for compliance with all laws and regulations that may apply to you. You further agree that we have no obligation to inform you of any potential liabilities or violations of law or regulation that may arise in connection with your access and use of the Services, the Protocol via the Services, crypto assets, blockchain-based protocols and/or blockchain networks and that we are not liable in any respect for any failure by you to comply with any applicable laws or regulations.
   2. You acknowledge that the Services incorporate experimental and novel technology and that the use of such technology involves a high degree of risk. For example, there are numerous reasons the Services, the Protocol, a blockchain-based protocol or blockchain network that you use in connection with the Services could fail in an unexpected way, resulting in the total and absolute loss of your crypto assets. You hereby agree that you assume all risks in connection with your use of the Services and expressly waive and release Skip from any and all liability, claims, causes of action or damages arising out of or in any way relating to you obtaining or using Services.
   3. You understand and accept the risk of operational challenges related to the Services. For example, the Services, the Protocol, blockchain-based protocols and/or blockchain networks may experience cyber-attacks, unexpected surges in transaction volume, botting or activity or other operational or technical difficulties or vulnerabilities that may cause interruptions related to your use of the Services. You agree to accept the risk of a failure of the Services resulting from unanticipated or heightened technical difficulties or vulnerabilities, including those resulting from cyber-attacks. You agree to not hold Skip liable for any related losses.
   4. You agree that Skip is not responsible for any crypto asset that you receive, transfer, bridge, hold, lose or otherwise use or misuse in connection with the Services. Additionally, you agree that Skip is not responsible for any tax obligations that you incur in connection with your use of the Services.
   5. You understand that all transactions conducted through the Services and the Protocol via the Services are automatically processed onchain. By engaging in transactions using the Services, you acknowledge and consent to the automatic processing of all transactions in connection with the Services. You acknowledge and agree that onchain smart contracts may programmatically facilitate the transfer of crypto assets in connection with your transactions. You further acknowledge and agree that Skip does not take possession, custody or control over your crypto assets at any time or maintain administrative control over the smart contracts that comprise the Protocol.
   6. You understand that the Ethereum, Cosmos and Solana blockchain networks (and all other networks with which the Services may be compatible, such as IBC-compatible networks) remain under development, which creates technological and security risks when using the Services in addition to uncertainty relating to crypto assets and transactions. You acknowledge that the cost of transacting on blockchain networks is variable and may increase at any time, thereby impacting any activities taking place on such blockchains, which may result in significant price fluctuations or increased prices when using the Services.
   7. THE SERVICES RELY ON EMERGING TECHNOLOGIES, INCLUDING, BUT NOT LIMITED TO, CRYPTOGRAPHY, SMART CONTRACTS, ROUTERS, RELAYERS AND CROSS-CHAIN PROOFS. SOME FUNCTIONALITY IS SUBJECT TO INCREASED RISK THROUGH YOUR POTENTIAL MISUSE, SUCH AS MISUSES RELATED TO PUBLIC/PRIVATE KEY CRYPTOGRAPHY. BY USING THE SERVICES YOU EXPLICITLY ACKNOWLEDGE AND ACCEPT THESE HEIGHTENED RISKS. SKIP SHALL NOT BE LIABLE FOR THE FAILURE OF ANY MESSAGE TO SEND TO OR BE RECEIVED BY THE INTENDED RECIPIENT IN THE INTENDED FORM, OR FOR DIMINUTION OF VALUE OF ANY CRYPTO ASSET ON ANY BLOCKCHAIN NETWORKS, AND SKIP MAKES NO REPRESENTATIONS OR WARRANTIES WITH RESPECT TO SAME.
8. **Disclaimer of Warranties; Limitation of Liability; Indemnification**.
   1. EXCEPT AS EXPRESSLY SET FORTH HEREIN, THE SERVICES ARE ISSUED ON AN “AS-IS” AND “AS AVAILABLE” BASIS AND SKIP DOES NOT MAKE ANY WARRANTIES WITH RESPECT TO SUCH “AS-IS” AND “AS AVAILABLE” BASIS OR OTHERWISE IN CONNECTION WITH THE TERMS (EXCEPT AS EXPRESSLY PROVIDED HEREIN) AND SKIP HEREBY DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES AND CONDITIONS, INCLUDING ANY WARRANTIES OR CONDITIONS OF NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AVAILABILITY, ERROR-FREE OR UNINTERRUPTED OPERATION, AND ANY WARRANTIES ARISING FROM A COURSE OF DEALING, COURSE OF PERFORMANCE OR USAGE OF TRADE. TO THE EXTENT THAT SKIP MAY NOT, AS A MATTER OF APPLICABLE LAW, DISCLAIM ANY IMPLIED WARRANTY OR CONDITION, THE SCOPE AND DURATION OF SUCH WARRANTY OR CONDITION SHALL BE APPLIED TO THE MINIMUM EXTENT PERMITTED UNDER SUCH APPLICABLE LAW.
   2. IN NO EVENT SHALL SKIP BE LIABLE TO YOU FOR ANY CONSEQUENTIAL, INDIRECT, INCIDENTAL OR SPECIAL DAMAGES OF ANY TYPE OR NATURE HOWEVER ARISING, INCLUDING, WITHOUT LIMITATION, EXEMPLARY OR PUNITIVE DAMAGES, LOST DATA, LOST PROFITS OR REVENUES OR DIMINUTION IN VALUE, ARISING OUT OF OR RELATING TO THE SERVICES OR YOUR USE OF THE PROTOCOL VIA THE SERVICES, WHETHER OR NOT THE POSSIBILITY OF SUCH DAMAGES HAS BEEN DISCLOSED TO OR COULD HAVE BEEN REASONABLY FORESEEN BY YOU, REGARDLESS OF THE LEGAL OR EQUITABLE THEORY (WHETHER IN CONTRACT, TORT OR OTHERWISE) UPON WHICH THE CLAIM IS BASED. IN ADDITION, UNDER NO CIRCUMSTANCES SHALL SKIP’S AGGREGATE LIABILITY UNDER THE TERMS EXCEED ONE-HUNDRED U.S. DOLLARS (\$100.00).
   3. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF CERTAIN WARRANTIES OR THE LIMITATION OR EXCLUSION OF LIABILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES. ACCORDINGLY, SOME OF THE LIMITATIONS SET FORTH ABOVE MAY NOT APPLY TO YOU. IF YOU ARE DISSATISFIED WITH THE SERVICES, YOU UNDERSTAND AND AGREE THAT YOUR SOLE AND EXCLUSIVE REMEDY IS TO DISCONTINUE USING THE SERVICES.
   4. You agree, at your own expense, to indemnify, defend and hold harmless Skip and our partners and affiliates and their respective owners, members, agents, directors, officers, employees, representatives, affiliates, successors and assigns against any claim, suit, action or other proceeding from and against any and all claims, damages, liabilities, costs and expenses, including reasonable attorneys’ and experts’ fees, arising out of or in connection with the Services, or any third-party protocols, software or applications, links or blockchain-based protocols accessible via the Services, including but not limited to: (i) any breach or violation of the Terms by you; (ii) material, information or content submitted or provided by you; (iii) your use of the Services (including, for the avoidance of doubt, your use of the Services to access the Protocol) or (iv) any deletions, additions, insertions or alterations to, or any unauthorized use of, the Services by you. You agree to pay any and all costs, damages and expenses, including but not limited to reasonable attorneys’ fees and costs awarded against or otherwise incurred by or in connection with or arising from any such claim, suit, action or proceeding attributable to any such claim. We reserve the right, at our own expense, to assume the exclusive defense and control of any matter otherwise subject to indemnification by you, in which event you will fully cooperate with us in asserting any available defense.
9. **Dispute Resolution; Agreement to Arbitrate**.
   1. All disputes, claims and controversies, whether based on past, present or future events, arising out of or relating to statutory or common law claims, the breach, termination, enforcement, interpretation or validity of any provision of the Terms and the determination of the scope or applicability of your agreement to arbitrate any dispute, claim or controversy originating from the Terms, will be determined by binding arbitration in the State of Delaware, before a single arbitrator. The arbitration will be administered by the American Arbitration Association (“**AAA**”), in accordance with the AAA Consumer Arbitration Rules.
   2. The arbitrator will apply the substantive law of the State of Delaware, excluding its conflict or choice of law rules.
   3. Nothing in the Terms will preclude the parties from seeking provisional remedies in aid of arbitration from a court of appropriate jurisdiction.
   4. A party must notify the other party of its intent to commence arbitration prior to commencing arbitration. You may provide such notice to Skip at the email address set forth in Section 11.2. The notice must specify the date on which the arbitration demand is intended to be filed, which must be at least thirty (30) days after the date of the notice. During this time period, the parties will meet for the purpose of resolving the dispute prior to commencing arbitration.
   5. Subject to Section 9.4, each party may commence arbitration by providing to the AAA and the other party to the dispute a written demand for arbitration, stating the subject of the dispute and the relief requested.
   6. Subject to the disclaimers and limitations of liability stated in the Terms, the appointed arbitrators may award monetary damages and any other remedies allowed by the laws of the State of Delaware. In making a determination, the arbitrator will not have the authority to modify any term of the Terms. The arbitrator will deliver a reasoned, written decision with respect to the dispute to each party, who will promptly act in accordance with the arbitrator’s decision. Any award (including interim or final remedies) may be confirmed in or enforced by a court located in the State of Delaware. The decision of the arbitrator will be final and binding on the parties, and will not be subject to appeal or review.
   7. Subject to applicable law, the party initiating the arbitration will be responsible for paying the applicable filing fee. Each party will advance one-half of the fees and expenses of the arbitrator, the costs of the attendance of the arbitration reporter at the arbitration hearing and the costs of the arbitration facility. In any arbitration arising out of or relating to the Terms, the arbitrator will award to the prevailing party, if any, the costs and attorneys’ fees reasonably incurred by the prevailing party in connection with those aspects of its claims or defenses on which it prevails, and any opposing awards of costs and legal fees awards will be offset.
   8. The parties will keep confidential the existence of the arbitration, the arbitration proceeding, the hearing and the arbitrator’s decision, except: (i) as necessary to prepare for and conduct the arbitration hearing on the merits; (ii) in connection with a court application for a preliminary remedy, or confirmation of an arbitrator’s decision or its enforcement; (iii) Skip may disclose the arbitrator’s decision in confidential settlement negotiations; (iv) each party may disclose as necessary to professional advisors that are subject to a strict duty of confidentiality; and (v) as applicable law otherwise requires. The parties, witnesses and arbitrator will treat as confidential and will not disclose to any third person (other than witnesses or experts) any documentary or other evidence produced in any arbitration, except as applicable law so requires or if the evidence was obtained from the public domain or was otherwise obtained independently from the arbitration.
   9. In the case of a conflict between the provisions of this Section 9 and the rules of the AAA, the provisions of this Section 9 shall prevail.
   10. To the extent permitted by applicable law, any dispute arising out of or relating to the Terms, whether in arbitration or in court, shall be conducted only on an individual basis and not in a class, consolidated or representative action. Notwithstanding any other provision of the Terms or the rules of the AAA, disputes regarding the interpretation, applicability or enforceability of this class waiver may be resolved only by a court and not by an arbitrator. If this waiver of class or consolidated actions is deemed invalid or unenforceable, neither party is entitled to arbitration.
   11. If for any reason a claim or dispute proceeds in court rather than through arbitration, each party knowingly and irrevocably waives any right to trial by jury in any action, proceeding or counterclaim arising out of or relating to the Terms.
10. **Third-Party Services**.
    1. By using the Services, you may view and have access to the content, products, services, blockchain-based protocols, blockchain networks, software or applications of one or more third parties (“**Third-Party Services**”), via linked or plugged in technologies to the Services. Your reliance on, access or use of any Third-Party Services in connection with using the Services will also be governed by the terms and conditions and policies of the applicable third-party service provider (*e.g.*, a Wallet provider). You understand and agree that any such third-party terms and conditions and policies may involve fees or other charges and include disclaimers or particular risk warnings about the reliance on or the accuracy of any information or with using such third-party services. It is your responsibility to understand the terms and conditions and policies of any such third-party service provider, including how those service providers use any of your data or other information under their privacy policies. Any such terms and conditions and policies may provide for less security than Skip. You understand and agree that any Third-Party Services are provided for your convenience only. We do not verify or control any Third-Party Services, and as a result, we do not guarantee, endorse or recommend any Third-Party Services to any or all users of the Services. We are therefore not responsible for the availability, content, validity, timeliness, completeness, reliability, integrity, quality, legality, usefulness, safety or accuracy of any Third-Party Services, or any intellectual property rights therein, that may be linked to or from the Services. Your reliance on, access and use of any Third-Party Services is at your own risk, and we disclaim all responsibility and liability for any losses that result out of same. We have no responsibility for Third-Party Services that may be misleading, incomplete, erroneous, offensive, indecent or otherwise objectionable to you or under the law in your jurisdiction, or which contain malware, vulnerabilities or any other types of malicious software, smart contracts, domains or computer code. The choice to rely on, access and use Third-Party Services is in your own discretion, and you are solely responsible for ensuring that your reliance, access or use is in compliance with all applicable laws. For the avoidance of doubt, we do not: (i) make any warranty, express or implied, with respect to the use of the links provided on or to the Services; (ii) verify or guarantee the accuracy, completeness, usefulness or adequacy of any other websites, services, goods or other Third-Party Services that may be linked to or from the Services; or (iii) make any endorsement, express or implied, of any other websites, services, goods or other Third-Party Services that may be linked to or from Services. For the avoidance of doubt, this paragraph shall be interpreted broadly and covers websites, blockchain-based protocols and other crypto-native technologies, such as cross-chain bridges, decentralized exchanges and all other blockchain-based protocols accessible via the Services or any links made available through the Services. Any statements, opinions or other information made available by third parties, including users, are solely those of the respective author(s) or distributor(s). We reserve the right to change, suspend, remove, disable or impose access restrictions or limits on any Third-Party Service at any time and without prior notice to you.
    2. WE DISCLAIM ANY AND ALL LIABILITY, INCLUDING ANY EXPRESS OR IMPLIED WARRANTIES, WHETHER ORAL OR WRITTEN, FOR WEBSITES, SERVICES, GOODS, INFORMATION, ADVERTISEMENTS OR OTHER THIRD-PARTY SERVICES THAT MAY BE LINKED TO OR FROM, OR PROVIDED THROUGH, THE SERVICES. YOU ACKNOWLEDGE THAT NO REPRESENTATION HAS BEEN MADE BY US AS TO THE FITNESS OF THE WEBSITES, SERVICES, GOODS, ADVERTISEMENTS OR OTHER THIRD-PARTY SERVICES THAT MAY BE LINKED TO, FROM OR PROVIDED THROUGH, THE SERVICES. YOUR USE OF THIRD-PARTY SERVICES IS AT YOUR SOLE RISK AND IS SUBJECT TO ANY ADDITIONAL TERMS, CONDITIONS AND POLICIES APPLICABLE TO SUCH THIRD-PARTY SERVICES (SUCH AS TERMS OF USE OR THE PRIVACY POLICY OF THE PROVIDERS OF SUCH THIRD-PARTY SERVICES).
    3. You may also link to the Services provided that you do so in a way that indicates that the link is direct to the Services and is fair and not misleading. You may not integrate or make use of all or part of the Services in ways that would confuse or mislead visitors as to the nature and origin of the Services’ content.
11. **General Provisions**.
    1. Electronic Communications. By accessing or using the Services, you consent to receive electronic communications.
    2. Notices. Skip may provide you with notice and other communications via electronic communications as permitted by Section 11.1. You may provide us with notice by sending an email address to [support@skip.money](mailto:support@skip.money). All notices will be deemed effective upon dispatch.
    3. Waivers. For a waiver to be deemed effective, a waiver must be in a writing signed by the waiving party. The failure of either party to enforce any provision of the Terms will not constitute a waiver of that party’s rights to subsequently enforce the provision.
    4. Cumulative Rights; Injunctions. The rights and remedies of the parties under the Terms are cumulative, and each party may exercise any of its rights and enforce any of its remedies under the Terms, along with all other rights and remedies available to it at law, in equity or otherwise. Any material breach by a party of the Terms could cause the non-breaching party irreparable harm for which the non-breaching party has no adequate remedies at law. Accordingly, the non-breaching party is entitled to seek specific performance or injunctive relief for any such breach.
    5. Severability. If any provision of the Terms is declared to be invalid, illegal or unenforceable by a court of competent jurisdiction, then the validity, legality and enforceability of the remaining provisions contained herein shall not be affected thereby and the remainder of the provisions of the Terms shall remain valid, legal and enforceable to the fullest extent permitted by law.
    6. Accessibility. We are committed to helping those with disabilities access the Services. We strive to provide an excellent online experience for our users – including those with sight, hearing and other disabilities. If you have difficulty using or accessing any element of the Services or if you have any Feedback regarding accessibility of the Services, please feel free to contact us at [support@skip.money](mailto:support@skip.money).
    7. Force Majeure. Skip shall have no liability for any failure or delay resulting from any condition beyond our reasonable control, including but not limited to governmental action or acts of terrorism, earthquake, fire, flood, other acts of God, labor conditions, power failures, equipment failures and Internet or blockchain network disturbances.
    8. Successors and Assigns. You may not transfer or assign the Terms or any rights or obligations hereunder, by operation of law or otherwise and any such attempted assignment shall be void. Skip reserves the right to freely transfer or assign the Terms and the rights and obligations hereunder to any third party at any time without your consent and prior notice to you. If you object to any such transfer or assignment, you may stop using the Services.
    9. Relationship of the Parties. Nothing contained in the Terms shall constitute you and Skip as members of any partnership, joint venture, association, syndicate, unincorporated business or similar assignment as a result of or by virtue of the relationship established by the Terms.
    10. Governing Law. The Terms shall be solely and exclusively governed, construed and enforced in accordance with the laws of the State of Delaware without giving effect to conflict of law rules or principles that would cause the application of the laws of any other jurisdiction.
    11. Entire Agreement. The Terms constitute the entire agreement and understanding between you and Skip, and supersedes all previous communications, representations or agreements, whether written or oral, with respect to the subject matter hereof.
    12. No Third-Party Beneficiaries. The Terms are not intended and shall not be construed to create any rights or remedies in any parties other than you and Skip and other Skip affiliates, which each shall be a third-party beneficiary of the Terms, and no other person shall assert any rights as a third-party beneficiary hereunder.


# REST API
Source: https://skip-go.mintlify-go.com/go/release-notes/api

Selected updates and improvements to the Skip Go REST API.

## May 2025

* **Improved Cross-Chain Composability:** Execute EVM swaps immediately following a Eureka cross-chain transfer, enabling more sophisticated multi-step routes.
* **Enhanced Fee Transparency:** Fees associated with Eureka operations are now clearly displayed within the `estimated_fees` array in API responses from the `/v2/fungible/route` endpoint, providing better cost predictability. For example:
  ```json theme={null}
  "estimated_fees": [
    {
      "fee_type": "SMART_RELAY",
      "bridge_id": "EUREKA",
      "amount": "76099736314413",
      "usd_amount": "0.20",
      "origin_asset": {
        "denom": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
        "chain_id": "1",
        "symbol": "WETH",
        "name": "Wrapped Ether"
        // ... other asset details (like decimals, logo_uri etc.)
      }
    }
  ]
  ```
  ([See API Docs](/go/api-reference/prod/fungible/post-v2fungibleroute) for full response structures from the `/v2/fungible/route` endpoint.)
* **LayerZero and Stargate Integration:** Expanded cross-chain capabilities with the integration of LayerZero and Stargate protocols. This integration adds support for a wide variety of new assets, including USDT, USDe, and ZRO.

  **Usage:**

  * **REST API:** Include `"layer_zero"` and/or `"stargate"` in the `experimental_features` array in your POST request to `/v2/fungible/route`.
    ```json theme={null}
    {
      "source_asset_denom": "uatom",
      "source_asset_chain_id": "cosmoshub-4",
      "dest_asset_denom": "uusdc",
      "dest_asset_chain_id": "noble-1",
      "amount_in": "1000000",
      "experimental_features": ["layer_zero", "stargate"]
    }
    ```

  * **Client Library:** Add these features to the `experimentalFeatures` parameter.
    ```typescript theme={null}
    import { route } from '@skip-go/client';

    const response = await route({
      sourceAssetDenom: "uatom",
      sourceAssetChainId: "cosmoshub-4",
      destAssetDenom: "uusdc",
      destAssetChainId: "noble-1",
      amountIn: "1000000",
      experimentalFeatures: ["layer_zero", "stargate"]
    });
    ```

  * **Widget Integration:** Add LayerZero and Stargate to the `experimentalFeatures` array in the `routeConfig` prop of the Skip Widget component.
    ```jsx theme={null}
    import { Widget } from '@skip-go/widget';

    <Widget
      routeConfig={{
        experimentalFeatures: ["layer_zero", "stargate"]
      }}
    />
    ```

### Status Endpoint Enhancement (Late May)

* **Transaction Timestamp Information:** Added `on_chain_at` field to individual transaction detail objects (such as `send_tx`, `receive_tx`, `acknowledge_tx`, `execute_tx`) found within the specific transfer type objects (e.g., `ibc_transfer`, `cctp_transfer`, `axelar_transfer`) in the status endpoint response. This field provides RFC3339 formatted UTC timestamps of when each specific transaction landed on its respective chain.

## April 2025

* **Eureka Protocol Enhancements:**
  * Native token wrapping (e.g., ETH to WETH) is now supported within Eureka cross-chain transfers, with improved fee handling for routes involving native ETH.
  * Eureka Protocol now officially supports transfers to and from Ethereum Mainnet and the Cosmos Hub.

## September 28, 2024

* Speed and performance improvements for `/balances` endpoint

## August 21, 2024

* Add `/balances` endpoint


# Client Library
Source: https://skip-go.mintlify-go.com/go/release-notes/client

Selected updates and improvements to the `@skip-go/client` [npm package](https://www.npmjs.com/package/@skip-go/client).

## v1.5.0

### Major Features

* **Gas on Receive Support:** Added `executeMultipleRoutes` function that enables simultaneous execution of multiple routes. This powers the gas on receive feature, allowing users to automatically receive native gas tokens on destination chains during cross-chain swaps. The function accepts multiple routes (e.g., main swap + gas fee route) and executes them in a shared transaction for Cosmos chains. [Learn more about Gas on Receive](/go/widget/gas-on-receive#client-library-usage).

## v1.1.9

### Enhancements

* **Batch Transaction Signing:** Added `batchSignTxs` parameter to `executeRoute`. When enabled (default: true), all transactions in a multi-transaction route are signed upfront before broadcasting, reducing the number of user prompts and improving the overall user experience.

## v1.1.0

### Enhancements

* **Transaction Timestamps:** The `ChainTransaction` type now includes an `on_chain_ts` field, providing a timestamp for when the transaction was confirmed on-chain. This can be useful for tracking and display purposes.
* **Exported JSON Types:** Relevant JSON types used by the client are now exported, improving the developer experience for those working directly with these underlying types.

## v1.0.0

This major release brings significant improvements to the `@skip-go/client` library, focusing on bundle size, developer experience, and performance. If you are upgrading from a version prior to v1.0.0, please see the [Migration Guide](../client/migration-guide) for detailed instructions. **For the best experience, including all subsequent enhancements and patches since the initial v1.0.0 release, we recommend upgrading directly to v1.1.0 or the latest available stable version.**

### Key Changes:

* **Improved Tree-Shaking:** The client library has been refactored to export separate functions instead of a single class. This allows for better tree-shaking, reducing the impact on your application's bundle size.
* **Consistent Naming Conventions:** All properties and variables now strictly follow camelCase (and PascalCase for enums). This change facilitates the auto-generation of interfaces based on the OpenAPI spec (swagger.yml) and simplifies the conversion between camelCase and snake\_case for API consumption.

## v0.10.3

* The `executeRoute` method now accepts `beforeMsg` and `afterMsg`  parameter to allow for the execution of custom Cosmos messages before/after the route is executed. This is useful for executing custom messages that are not part of the route definition.

```typescript theme={null}
// An example of how to use the `beforeMsg` parameter with a MsgSend
const msg = JSON.stringify({
  fromAddress: 'cosmos1...',  // Replace with sender address
  toAddress: 'cosmos1...',    // Replace with recipient address
  amount: [{
    denom: 'uatom',           // Replace with the actual denom, e.g., 'uatom' for ATOM
    amount: '1000000'         // Replace with the actual amount (in smallest unit, e.g., micro-ATOM)
  }]
});

await skip.executeRoute({
  route,
  userAddresses,
  beforeMsg: { msg, msgTypeURL: '/cosmos.bank.v1beta1.MsgSend' }
});
```

## v0.9.3

* Update client to include solana support via public RPC and show warning when public infrastructure is not overriden.

## v0.9.0

* Add `/balance` methods query API endpoint. See the [documentation](../client/balance-gas-and-fee-tooling) and the [API reference](/go/api-reference/prod/info/post-v2infobalances) for more details.


# Overview
Source: https://skip-go.mintlify-go.com/go/release-notes/overview



Stay up to date with Skip Go's latest features and improvements.

<CardGroup>
  <Card title="Client Library" icon="code" href="/release-notes/client">
    A library that streamlines interaction with the Skip Go API, enabling cross-chain swaps and transfers across multiple ecosystems
  </Card>

  <Card title="Widget" icon="bolt-lightning" href="/release-notes/widget">
    Seamless cross-chain bridging, swapping, and transferring functionality in an easy to integrate React or Web component
  </Card>

  <Card title="REST API" icon="sliders" href="/release-notes/api">
    REST endpoints for low-level control over your interactions.
  </Card>
</CardGroup>


# Widget
Source: https://skip-go.mintlify-go.com/go/release-notes/widget

Selected updates and improvements to the `@skip-go/widget` [npm package](https://www.npmjs.com/package/@skip-go/widget).

## August 2025

### Gas on Receive Feature

* **Gas on Receive (v3.14.0+):** Intelligent gas management feature that helps users obtain native gas tokens on destination chains during cross-chain swaps. Prevents users from getting "stuck" with assets they can't use due to lacking gas for future transactions. The widget auto-detects insufficient gas balances and shows a toggle for users to enable gas top-up routes. Supports Cosmos chains (0.10 USD) and EVM L2 chains (2.00 USD). [Learn more about Gas on Receive](/go/widget/gas-on-receive).

## June 2025

### Visual Widget Builder Launch

We're excited to announce the launch of **[studio.skip.build](https://studio.skip.build)** - our new interactive widget builder.

**Key Features:**

* **Visual Configuration:** Experiment with themes, colors, and settings through an intuitive interface
* **Live Preview:** See your changes in real-time before implementing them in code
* **Asset & Route Testing:** Test different asset combinations and routing scenarios
* **Code Generation:** Generate the exact props needed for your widget implementation

This tool significantly reduces integration time and helps developers create the perfect widget experience for their users without trial and error in their development environment.

### Transaction Signing Enhancement

* Added `batchSignTxs` prop to control transaction signing behavior. When enabled (default: true), all transactions in a multi-transaction route are signed upfront.

## Recent Key Updates (Spring 2025)

The Skip Go Widget has seen several improvements focusing on core functionality, user experience, and developer integration.

* **Updated Core Client Dependency:** The widget now utilizes `@skip-go/client` v1.x. This update brings underlying improvements in efficiency and API consistency from the client library.
* **User Interface and Experience:**
  * Swap settings changes now trigger an automatic refetch of route information.
  * Display of asset amounts and number formatting has been refined for better clarity.
  * The "Signature Required" prompt is now hidden after a transaction is signed.
  * Improved the display of estimated transaction fees, providing a more transparent breakdown of potential costs for all routes.
* **Developer Integration:**
  * **New Visual Widget Builder:** Launched [studio.skip.build](https://studio.skip.build) - an interactive tool that allows developers to visually configure widget settings, customize themes, test different asset combinations, and preview changes in real-time before implementing them in code.
  * Introduced an `onSourceAndDestinationSwapped` callback, allowing integrators to add custom logic when users switch the source and destination assets.

For a detailed list of all changes, including dependency updates and minor fixes, please refer to the [full CHANGELOG.md on GitHub](https://github.com/skip-mev/skip-go/blob/main/packages/widget/CHANGELOG.md).

## v2.5.2

* Change default fee asset selection on chain change.

## v2.5.0

* Fix max button & corresponding gas calculation and
* Remove gas amount option in settings


# Skip Go Asset Registry & Overrides
Source: https://skip-go.mintlify-go.com/go/support-requirements/asset-registry-overrides



## Background

The Skip Go API aggregates asset metadata from multiple public registries, including:

* [Cosmos Chain Registry](https://github.com/cosmos/chain-registry)
* [Osmosis Assetlists](https://github.com/osmosis-labs/assetlists)
* [Keplr Chain Registry](https://github.com/chainapsis/keplr-chain-registry)
* [Astroport Token Lists](https://github.com/astroport-fi/astroport-token-lists)

While this multi-registry approach ensures broad coverage, it can sometimes lead to inconsistencies such as:

* **Mismatched logos** between token and chain representations
* **Missing or outdated logos** for newer tokens
* **Conflicting metadata** when different registries provide different information for the same asset
* **Low-quality or incorrect images** from less-maintained registries
* **Decimal display issues**

## The Skip Go Asset Registry

To resolve these issues and give teams control over how their assets appear across Skip Go, we can override these with the **[Skip Go Asset Registry](https://github.com/skip-mev/skip-go-registry)**.

## When to Submit an PR to override

You should submit an override to the Skip Go Asset Registry when:

1. **Logo Mismatch**: Your token logo differs from your chain logo when they should be the same
2. **Missing Logos**: Your token or chain has no logo in Skip Go integrations
3. **Incorrect Metadata**: Name, symbol, decimal or other metadata is incorrect or outdated
4. **Symbol Conflicts**: Need to differentiate between token versions on different chains (e.g., `USDC.e`, `aUSD.planq`)

## Repository Structure

The Skip Go Registry follows this directory structure:

```
chains/
├── [chain_id]/           # EVM chains use numeric chain IDs (e.g., 42161 for Arbitrum)
│   ├── chain.json       # Chain configuration
│   ├── assetlist.json   # Asset definitions
│   └── images/          # Asset logos (optional)
└── [chain_name]/        # Cosmos chains use chain names (e.g., cosmoshub-4)
    ├── chain.json       # Chain configuration
    ├── assetlist.json   # Asset definitions
    └── images/          # Asset logos (optional)
```

## How to Submit Custom Assets

### Step 1: Fork the Repository

Fork the [Skip Go Registry](https://github.com/skip-mev/skip-go-registry)

### Step 2: Add or Update Assets

#### For EVM Chain Assets

**ERC-20 Tokens:**

For ERC-20 tokens, include only required fields unless other meta data is incorrect e.g decimals:

```json theme={null}
{
    "asset_type": "erc20",
    "erc20_contract_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}
```

Additional fields to add when overriding metadata:

```json theme={null}
{
    "asset_type": "erc20",
    "erc20_contract_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "name": "USD Coin",
    "symbol": "USDC",
    "decimals": 6,
    "logo_uri": "https://raw.githubusercontent.com/...",
    "coingecko_id": "usd-coin"
}
```

#### For Cosmos Chain Assets

```json theme={null}
{
    "asset_type": "cosmos",
    "name": "Osmosis",
    "denom": "uosmo",
    "logo_uri": "https://raw.githubusercontent.com/...",
}
```

#### Symbol Overrides

Use `recommended_symbol` to set the display symbol in Skip Go. This is useful for chain-specific symbols (e.g., to differentiate bridged versions):

```json theme={null}
{
    "asset_type": "erc20",
    "name": "aUSD",
    "symbol": "aUSD",
    "decimals": 18,
    "erc20_contract_address": "0xA2871B267a7d888F830251F6B4D9d3DFf184995a",
    "recommended_symbol": "aUSD.planq"
}
```

Common symbol override patterns:

* `USDT.kava` - Chain suffix with dot notation
* `USDC.e` - Bridged token designation
* `TIA.n` - Network-specific versions

### Step 3: Asset Requirements

**Logo Requirements:**

* **Format**: PNG or SVG (host on GitHub or a permanent CDN)
* **Size**: Minimum 250x256px, Maximum: 800x800px for PNG, vector for SVG
* **URL**: Use permanent URLs (GitHub raw content URLs)

**Required Fields by Asset Type:**

**ERC-20 Tokens:**

* `asset_type`, `erc20_contract_address` (checksummed)
* Optional but recommended: `name`, `symbol`, `decimals`, `logo_uri`, `coingecko_id`

**Cosmos Assets:**

* `asset_type`, `name`, `symbol`, `denom`, `decimals`
* Recommended: `logo_uri`, `coingecko_id`

Always verify decimals with the official token contract or chain documentation.

### Step 4: Validate Your Changes

Run the validation scripts before submitting:

```bash theme={null}
cd scripts/config-validator
npm install
npm run validate
```

This checks for:

* Schema compliance
* Required fields
* Valid contract addresses
* Duplicate assets

### Step 5: Submit a Pull Request

In your PR description, include:

* **What you're adding/updating**: Token name, chain name, or symbol override
* **Why the change is needed**: E.g., "Logo mismatch" or "Missing metadata"
* **Verification**: Link to official project documentation confirming accuracy

### Step 6: PR Review and Merge

The Cosmos Labs team reviews submissions within **1-3 business days**

Once merged, updates appear in Skip Go integrations within **24 hours**.

## Advanced Features

## Verifying Your Assets

After your PR is merged, verify using the Skip Go API:

**Endpoint:** `https://api.skip.build/v2/fungible/assets`

**Query Parameters:**

* `chain_ids`: Limit response to specific chains
* `include_evm_assets=true`: Required to see EVM tokens
* `include_cw20_assets=true`: Include CW20 tokens
* `native_only`: Restrict to native assets only

**Example Response:**

```json theme={null}
{
  "chain_to_assets_map": {
    "42161": {
      "assets": [{
        "denom": "0x816E21c33fa5F8440EBcDF6e01D39314541BEA72",
        "chain_id": "42161",
        "symbol": "agETH",
        "name": "Kelp Gain",
        "logo_uri": "https://raw.githubusercontent.com/...",
        "decimals": 18,
        "coingecko_id": "kelp-gain",
        "recommended_symbol": "agETH"
      }]
    }
  }
}
```

## Common Issues & Solutions

### My token shows a different logo than my chain

**Solution**: Add both token and chain entries to the registry with matching logos.

### My logo isn't updating after PR merge

**Solution**: Wait up to 24 hours for cache invalidation. Check using the API endpoint above.

### My token needs a different symbol on different chains

**Solution**: Use the `recommended_symbol` field (e.g., `"USDC.e"` for bridged USDC).

### EVM assets not appearing in API

**Solution**: Query with `include_evm_assets=true` parameter.

## Support

If you encounter issues:

* [Interchain Discord](https://discord.com/invite/interchain)
* **GitHub Issues**: [Skip Go Registry Issues](https://github.com/skip-mev/skip-go-registry/issues)

## Related Documentation

* [Token & Route Support Requirements](./token-support-requirements): How to add new tokens to Skip Go
* [Chain Support Requirements](./chain-support-requirements): How to request chain integration
* [Skip Go API Reference](/go/api-reference/prod/fungible/get-v2fungibleassets): View asset metadata via API


# Chain Integration Request
Source: https://skip-go.mintlify-go.com/go/support-requirements/chain-integration-request





# Chain Support Requirements
Source: https://skip-go.mintlify-go.com/go/support-requirements/chain-support-requirements

This document describes what new chains need to do the support Skip Go API

## Background

* New chains often want Skip Go API to add support for their chain as a source + destination for tokens because the API powers cross-chain swaps + transfers in all the major cosmos wallets (Leap, Keplr, IBC Wallet, Metamask Snap) and many popular DeFi aggregators and dapp frontends (e.g. Stargaze). As a result, being added to the Skip Go API instantly offers distribution across the interchain
* This document covers the basic requirements chains must satisfy and steps their contributors must complete in order for Skip Go API to support them
* Once you've met the requirements below, submit an integration request through our [API Chain Integration Request Form](/go/support-requirements/chain-integration-request)

<Info>
  **Want help at the beginning of this process?**

  Getting connected to IBC, Axelar, CCTP, Layerzero or Hyperlane can be hard. Even choosing among them is a challenge. We're happy to provide guidance and hands-on support to serious teams early in their journey -- even before they've made a choice of interop protocol if helpful!
</Info>

<Warning>
  **This guide assumes using IBC for Interop**

  The rest of this guide assumes you want Skip to support users interacting with your chain primarily over IBC.

  The Skip Go API supports other bridges and interop protocols in addition to IBC, including Hyperlane, CCTP, and Axelar. If you're using one of these, please get in contact with us on [our Discord](https://discord.com/invite/interchain), and we will help guide you through it to the extent we can.

  These other interop protocols are less standardized and/or less permissionless than IBC, so the process of adding support for new chains is more bespoke and varies by protocol. We're happy to help where we can, providing guidance, implementation, and introductions where necessary
</Warning>

## 1. Satisfy the following basic requirements

1. Provides clear instructions for permissionlessly running a full node and joining the network. Commonly instructions should include:
   1. Link to genesis file
   2. Full node binary or instructions for building binary from source code
   3. Public peer / seeder nodes
   4. Public RPCs
2. Chain metadata is available in a commonly used chain registry (e.g. [https://github.com/cosmos/chain-registry](https://github.com/cosmos/chain-registry)). Metadata should include:
   1. Chain name (and optionally "pretty name"
   2. Website
   3. chain\_id
   4. Bech32 prefix
   5. slip44 (aka "coin type")
   6. Fee information (with denom, low price, average price, and high price)
   7. Logo URIs
   8. Persistent peer lists
   9. Public RPCs
      *This metadata and the chain registry of choice might differ for EVM chains. Please use your best judgement of whats required*
3. IBC, Axelar, Layerzero, Eureka, and/or Hyperlane support.

## 2. Configure IBC Machinery

*Here we set up IBC clients, channels, and relayers.*

<Info>
  **What is a relayer?**

  Relayers are the off-chain actors that:

  * Keep IBC light clients up to date (Regular updates are required to prevent "expiration")
  * Monitor chains for outbound IBC packets, grab them, and send the packet data and packet proof to the destination chain
</Info>

*The easiest way to complete the steps below is to use the ibc relayer software ([Hermes](https://github.com/informalsystems/hermes) or [Relayer](https://github.com/cosmos/relayer). The CLIs of both support channel and client instantiation.*

For each chain that you want your chain to have a direct IBC transfer path to, you must complete steps to ensure IBC works properly:

1. Create a light client of the remote chain on your chain, and a light client of your chain on the remote chain
2. Create a ICS-20 "transfer" channel between these two clients

<Warning>
  **Don't create more than 1 channel between your chain and a remote chain**

  Your chain only needs 1 transfer channel for each chain it should communicate with directly.

  All tokens from your chain can be transferred to a particular remote chain over the same channel.

  Additional transfer channels may create confusion and liquidity fragmentation since users will need to pick which channel to transfer over (The Skip Go API automates this choice for the apps and users that use it, but others might not be so lucky)
</Warning>

1. Ensure there is at least 1 reliable relayer covering the channel (who can keep the light clients up to date and ferry packets between the two chains over time)

<Info>
  **What if I don't want to run my own relayers?**

  Get in touch with us on [our Discord](https://discord.gg/interchain)

  We have great relationships with all the top relayer operators in the Cosmos ecosystem and can put you in touch with them.
</Info>

## 3. Configure support for each asset minted on your chain

For each native asset that you want to ensure users can transfer over the

1. Transfer a non-zero amount of the token over the channel
2. Confirm that the token successfully gets transferred to the destination chain
3. **Leave the transferred tokens on the destination chain**

## 4. What chains will be asked for when submitting to get added to the Skip API on discord

Please include the following:

* Team Name:
* Team Contact Name:
* Team Contact Telegram:
* Team Website:
* Swapping Venue Name\*\* (if different from team name):
* Swapping Venue Website\*\* (if different from team website):
* Swapping Venue Documentation:\*\*

Chain supported by the Skip API

* Use the [`/info/chains` endpoint](https://docs.skip.build/go/api-reference/prod/info/get-v2infochains) to verify: `/v2/info/chains`
* If not listed, follow the [Chain Support Requirements](https://docs.skip.build/go/support-requirements/chain-support-requirements)
* *This is a required prerequisite*

CosmWasm Support

* Include documentation or notes on any special setup or limitations

IBC Support

* Provide relevant details, especially if not using standard IBC-go

IBC-hooks Support

* Indicate if using upstream ibc-hooks or a modified version
* [Upstream ibc-hooks](https://github.com/cosmos/ibc-apps/tree/main/modules/ibc-hooks)

***

## **Additional Chain Questions**

* Does the chain support **Packet Forward Middleware (PFM)?**
* Is **CosmWasm contract deployment permissionless**?
  If not, what is the approval or governance process?

<Info>
  **Why is this required?**

  Warm starting the channels kicks off Skip's intelligent routing suggestions for folks bridging to and from your chain. We choose routes between chains that ensure users are always receiving the most desirable version of their chosen token on their destination chain.

  As a part of providing good user experiences for everyone using the API, we don't enable users to bridge assets to new chains where no one has previously bridged that asset. (Often times, for ordinary users, taking an existing token to a chain it doesn't exist leaves them stuck on that new chain with a useless token). That's why we need to "warm start" channels -- to enable recommending them as bridging routes.
</Info>

<Info>
  **Have questions or feedback? Help us get better!**

  Join [our Discord](https://discord.gg/interchain) and select the "Skip Go Developer" role to share your questions and feedback.
</Info>


# Swap Venue Requirements
Source: https://skip-go.mintlify-go.com/go/support-requirements/swap-venue-requirements

This document covers what Skip Go API requires of DEXes to support them as potential swapping venues within the API's cross-chain DEX aggregation functionality. At the end, the document provides instructions for helping the Skip team add your DEX to the API as a swapping venue

## Background

* DEXes often want Skip Go API to add support for their DEX as a swapping venue because the API powers cross-chain swaps + transfers in all the major cosmos and ethereum wallets (MM, Keplr, IBC Wallet, Metamask Snap) and cross-chain DEX aggregation to many popular defi aggregator and dapp frontends (e.g. Stargaze). As a result, being added to the Skip Go API instantly offers distribution across the interchain for your DEX
* The Skip Go API’s swapping system is currently built in CosmWasm and can support swapping assets on Cosmos SDK modules (ex: Osmosis Poolmanager) and other CosmWasm contracts (ex: Astroport DEX) that can be queried and executed by Skip Go API’s CosmWasm contracts. The API support's swapping EVM dexes. (Uniswap v2/v3, Aerodrome, Velodrome).

### Chain Requirements

1. The chain must already be supported by the Skip Go API
   1. Use the `/info/chains` endpoint to query a list of actively supported chains: [/v2/info/chains](/go/api-reference/prod/info/get-v2infochains)
   2. If your chain is not already supported, follow the instructions in [Chain Support Requirements](./chain-support-requirements) to request support
   3. ***This is a pre-requisite***
2. CosmWasm Support
3. IBC support
4. ibc-hooks Support (Check out [our blog post about ibc-hooks](https://ideas.skip.build/t/how-to-give-ibc-superpowers/81))

### Module / Contract Requirements

### General

1. The module / contract must be able to be called by the Skip Go API’s CosmWasm contracts. For Cosmos SDK modules, this will require the module queries described below to be whitelisted and queryable by CosmWasm contracts ([see Osmosis for an example](https://github.com/osmosis-labs/osmosis/blob/d7eb3b7018cde0557216237c84f063b3915af650/wasmbinding/stargate%5Fwhitelist.go#L169)).

#### Execution Messages

1. Supports a “Swap Exact In” method where a user specifies an input asset and path to swap, and the module / contract swaps the given user asset to the user’s desired output asset and sends it to the user ([see Osmosis for a module example](https://github.com/osmosis-labs/osmosis/blob/d7eb3b7018cde0557216237c84f063b3915af650/x/poolmanager/msg%5Fserver.go#L22), or [Astroport for a contract example](https://github.com/astroport-fi/astroport-core/blob/52af83eab04c620ac40019f7cc9cee433d0c601e/contracts/router/src/contract.rs#L74)).
   1. Inputs into the swap:
      1. An asset (Native cosmos coin or CW20 token, incl. denom and amount)
      2. A path (can be a single pool, or multiple pools if designed like a router)
   2. Outputs of the swap:
      1. An asset
2. NICE TO HAVE (Optional): Supports a “Swap Exact Out” method where a user specifies a desired output asset, a path to swap through to achieve that asset, and a maximum amount of an input asset to swap, and the module / contracts swaps in the exact input asset needed to acquire the specified output asset and sends it to the user ([see Osmosis for a module example](https://github.com/osmosis-labs/osmosis/blob/d7eb3b7018cde0557216237c84f063b3915af650/x/poolmanager/msg%5Fserver.go#L48)).

### Query Messages

3. Exposes a “Swap Exact In Simulation” method where a user can put the inputs that would be used in the “Swap Exact In” execution method, and gets a response from the query that specifies the asset they would receive if executing the method ([see Osmosis for a module example](https://github.com/osmosis-labs/osmosis/blob/d7eb3b7018cde0557216237c84f063b3915af650/x/poolmanager/client/grpc/grpc%5Fquery.go#L113), or [Astroport for a contract example](https://github.com/astroport-fi/astroport-core/blob/52af83eab04c620ac40019f7cc9cee433d0c601e/contracts/router/src/contract.rs#L240)).
4. Exposes a “Swap Exact Out Simulation” method where a user can input the asset desired and a given pool / path, and the query returns the asset required to swap in to receive the output asset desired ([see Osmosis for a module example](https://github.com/osmosis-labs/osmosis/blob/d7eb3b7018cde0557216237c84f063b3915af650/x/poolmanager/client/grpc/grpc%5Fquery.go#L93), or [Astroport for a contract example](https://github.com/astroport-fi/astroport-core/blob/52af83eab04c620ac40019f7cc9cee433d0c601e/contracts/pair/src/contract.rs#L892)).

## Getting Skip to Add Support for Your DEX

Once your DEX and its chain meet the requirements listed above, you can submit it for integration by opening a support ticket in our [Discord](https://discord.gg/interchain).

We may request additional information to help prioritize the integration of your swap venue based on:

* **Swap volume**
* **Liquidity**
* **Quality and clarity of technical documentation**

***

### Required Submission Info

#### General Information

* Team Name
* Contact Name
* Contact Telegram
* Team Website
* Swapping Venue Name (if different from team name)
* Swapping Venue Website
* Swapping Venue Documentation

***

#### Additional DEX Information

Please answer the following questions to help us assess integration suitability:

* **What kind of venue is it?**
  *e.g., AMM, CLOB, staking protocol*

* **If an AMM, what pricing curves are supported?**
  * Include documentation
  * Describe any non-standard logic

* **How are fees calculated?**
  * Pool fees, maker/taker fees, etc.
  * Include documentation and note any non-standard mechanisms

* **Which tokens typically offer better pricing on this venue?**

* **Which tokens or token pairs are the most popular**


# Token & Route Support Requirements
Source: https://skip-go.mintlify-go.com/go/support-requirements/token-support-requirements

This document describes the steps you must complete for the Skip Go API to begin providing new routes for users to transfer a token over to various remote chains using IBC.

## Background

* New tokens often want Skip Go API to add support for transferring their token to other chains because the API powers cross-chain swaps + transfers in all the major cosmos wallets (Leap, Keplr, IBC Wallet, Metamask Snap) and cross-chain DEX aggregation for many popular defi aggregator and dapp frontends (e.g. Stargaze). As a result, being added to the Skip Go API instantly offers distribution across the interchain for a new token
* This document covers the basic requirements tokens must satisfy and steps their contributors must complete in order for Skip Go API to support transferring them throughout the interchain

<Warning>
  **Guide assumes using IBC for interop**

  This guide assumes you're using IBC to transfer your token between chains.

  The Skip Go API supports other bridges and interop protocols in addition to IBC, including Hyperlane, CCTP, and Axelar. If you're using one of these, please get in contact with us on [our Discord](https://discord.com/invite/interchain).
  and we will help guide you through it to the extent we can.

  These other interop protocols are less standardized and/or less permissionless than IBC, so the process of adding support for transferring new tokens over them is more bespoke and varies by protocol. We're happy to help where we can, providing guidance, implementation, and introductions where necessary.
</Warning>

## 1. Satisfy the following basic requirements

1. The chain where the token is issued must already be supported by the Skip Go API
   1. Use the `/info/chains` endpoint to query a list of actively supported chains: [/v2/info/chains](/go/api-reference/prod/info/get-v2infochains)
   2. If the chain is not already supported, follow the instructions in [Chain Support Requirements](./chain-support-requirements) to request support
   3. ***This is a pre-requisite***
2. The Skip Go API must also support the remote chains to which you wish users to be able to transfer the asset

   1. Use the `/info/chains` endpoint to query a list of actively supported chains: [/v2/info/chains](/go/api-reference/prod/info/get-v2infochains)
   2. If the chain is not already supported, follow the instructions in [Chain Support Requirements](./chain-support-requirements) to request support
   3. ***This is a pre-requisite***

   **Note:** We are unable to support IBC tokens from a source chain that is not integrated with Skip Go. Skip Go requires direct integration with the source chain to query chain state and balances, submit and monitor transactions, calculate accurate gas fees and handle chain-specific token mechanics.
3. Token metadata is available in a commonly used chain registry (e.g. [Cosmos Chain Registry](https://github.com/cosmos/chain-registry)) . Metadata should include at least:

   1. Denom (programmatic string identifier)
   2. Symbol (aka "ticker")
   3. Asset name (human readable denom)
   4. Display name (aka pretty name)
   5. Decimals / exponent
   6. Images
   7. coingecko\_id (if applicable)
   8. Description

   <Info>
     **Need to customize your token's logo or metadata?**

     If your token has incorrect logos, conflicting metadata, or branding issues from external registries, you can submit overrides directly to the Skip Go Asset Registry. See [Asset Registry & Overrides](./asset-registry-overrides) for detailed instructions.
   </Info>
4. Ensure IBC relayers are actively monitoring and relaying packets on all channels over which you want users to transfer your token (See [Chain Support Requirements](./chain-support-requirements) for more info on relayers.)

## 2. "Warm Start" your Asset Routes

For each destination chain:

1. Pick a channel that you would like to be the canonical channel for transferring the asset to this destination chain
2. Transfer a non-zero amount of the token over the channel
3. Confirm that the token successfully gets transferred to the destination chain
4. **Leave the transferred tokens on the destination chain**

<Info>
  **How do I pick a channel for a destination chain?**

  If you're launching a new chain, you should just pick whatever channel your team has set up. Usually, there's just one highly-trafficked and well-relayed channel between two chains over which all assets are transferred. (In theory, there can be many because IBC is permissionless, but usually relayers are only monitoring 1 and creating more adds confusion for all parties)

  If you're launching a new token on a chain that already has a vibrant IBC ecosystem and has already issued tokens that are widely used throughout the interchain (e.g. Osmosis or Neutron), you should probably use the same channel the well-established tokens use, since relayers are most likely to support these ones. To see which channel this is, call the [/v2/fungible/recommend\_assets](/go/api-reference/prod/fungible/get-v2fungibleassets) endpoint with the following values:

  * `source_denom`: A well-established token on the chain where your asset is issued (e.g. `uatom`)
  * `source_chain_id`: The `chain_id` of the chain where your asset is issued (`e.g. cosmoshub-4`)
  * `dest_chain_id`: The `chain_id` of the chain to which you want to be able to transfer your asset (e.g. `osmosis-1`)

  The channel you want to use is available in the response in `recommendations[0].asset.trace`
</Info>

<Info>
  **How do I transfer tokens over my chosen channel before Skip Go API supports it?**

  The easiest way to transfer tokens over a channel before official Skip Go API support is to use Keplr's developer mode. To enable developer mode in the Keplr extension, open the hamburger menu, click on settings, then click advanced, then activate the toggle for "Developer Mode".

  Once developer mode is active, at the bottom of the main page you should see "Advanced IBC Transfer". Click on this then follow the instructions for inputting your token and desired channel ID.
</Info>

<Info>
  **Why is this required?**

  Warm starting the channels kicks off Skip's intelligent routing suggestions for folks bridging to and from your chain. We choose routes between chains that ensure users are always receiving the most desirable version of their chosen token on their destination chain.

  As a part of providing good user experiences for everyone using the API, we don't enable users to bridge assets to new chains where no one has previously bridged that asset. (Often times, for ordinary users, taking an existing token to a chain it doesn't exist leaves them stuck on that new chain with a useless token). That's why we need to "warm start" channels -- to enable recommending them as bridging routes.
</Info>

## 3. Wait up to 24 hours and verify

Skip's intelligent route detection should automatically detect new routes for all assets and chains that meet the above requirements in 4-8 hours. This will not happen immediately. Please ensure you wait the necessary amount of time.

After you've let enough time pass, you can verify that Skip Go API supports the new routes you've configured using the [/v2/fungible/recommend\_assets](/go/api-reference/prod/fungible/get-v2fungibleassets) endpoint. For each destination chain you've configured, call this endpoint with the following data:

* `source_denom`: Your token
* `source_chain_id`: The chain on which your token is issued
* `dest_chain_id`: The chain to which you've warm-started an IBC route in the previous step

## Common questions

### I want a CW20 token added to Skip Go, what do I need to do to add it?

1. To add a CW20 token, you should first make sure its usable (either has ibc20-cw20 converter contracts deployed to IBC transfer the token or source-chain swappable on a swap venue used by Skip Go).
2. Once confirmed usable, you must add the CW20 token's metadata to a registry we support indexing from. The easiest one is likely the [Cosmos Chain Registry](https://github.com/cosmos/chain-registry), you can check out an example of a CW20 token entry here in [Archway's assetlist.json](https://github.com/cosmos/chain-registry/blob/master/archway/assetlist.json).
3. Once the PR is merged into a registry, our indexing will add it to the API on our next indexing run (hourly).


# Configuration
Source: https://skip-go.mintlify-go.com/go/widget/configuration

This page details your widget configuration options. Tweak it to fit your exact user experience needs!

<Note>
  **Visual Configuration Tool:** Want to see how your configuration options look before implementing them? Try [studio.skip.build](https://studio.skip.build) - our interactive widget builder that lets you customize themes, assets, routes, and more with a live preview.
</Note>

# Component Props

The `Widget` component accepts the following props.

### `defaultRoute`

Customizes the initial route displayed on widget load. Query supported assets using the Skip Go API [/assets](https://docs.skip.build/go/api-reference/prod/fungible/get-v2fungibleassets) endpoint. Setting this triggers a route request on render.

```ts theme={null}
defaultRoute?: {
  amountIn?: number;
  amountOut?: number;
  srcChainId?: string;
  srcAssetDenom?: string;
  destChainId?: string;
  destAssetDenom?: string;
};
```

* `amountIn`: Preset input amount for exact amount in request.
* `amountOut`: Preset output amount for exact amount out request. If both specified, only `amountIn` is used.
* `srcChainId` : Source chain ID.
* `srcAssetDenom`: Source asset denomination.
* `destChainId`: Destination chain ID.
* `destAssetDenom`: Destination asset denomination.

### `routeConfig`

Customizes enabled route types.

```ts theme={null}
routeConfig?: {
  experimentalFeatures?: ['hyperlane', 'cctp', 'stargate', 'eureka'];
  allowMultiTx?: boolean;
  allowUnsafe?: boolean;
  bridges?: ('IBC' | 'AXELAR' | 'CCTP' | 'HYPERLANE' | 'GO_FAST')[];
  swapVenues?: {
    name: string;
    chainId: string;
  }[];
  goFast?: boolean;
  smartSwapOptions?: SmartSwapOptions;
  timeoutSeconds?: string; // Number of seconds for the IBC transfer timeout, defaults to 5 minutes
};
```

* `allowMultiTx`: Allow multi-transaction routes. Default: true.
* `allowUnsafe`: Allow unsafe routes. Default: false. [More info](../advanced-swapping/allow_unsafe-preventing-handling-bad-execution).
* `bridges`: Restrict routing to specific bridges. Default: empty (all bridges).
* `swapVenues`: Restrict routing to specific swap venues. Default: empty (all venues).
* `goFast`: Enable Go Fast transfers. Default: false. [More info](../advanced-transfer/go-fast).
* `experimentalFeatures`: Array of experimental features to enable. Include `'eureka'` to enable routing with Eureka assets.
* `smartSwapOptions`: Advanced swapping features like EVM Swaps and split trade routes. [More info](../advanced-swapping/smart-swap-options).

### `batchSignTxs`

Controls whether all transactions in a multi-transaction route should be signed upfront or individually as they are executed.

```ts theme={null}
batchSignTxs?: boolean;
```

* **Default:** `true`
* When enabled, all transactions in the route will be requested for signature at the beginning of the execution. They will then be broadcast one by one in sequence.
* When disabled, each transaction will be signed individually just before it is broadcast.

**Example scenario with `batchSignTxs: true`:**
For a route: Solana → Noble → Cosmos (3 transactions requiring signatures)

* All 3 transactions will be prompted for signature upfront
* After signing, they will be broadcast sequentially: Solana first, then Noble, then Cosmos

<Note>
  **EVM Transaction Limitation:** If an EVM transaction appears as the second or later transaction in a route, batch signing cannot be performed upfront. In such cases, the EVM transaction and any subsequent transactions will need to be signed individually when they are ready to be executed.
</Note>

### `filter`

Key value pair of chainIds or specific asset denoms allowed
on source and destination assets

```ts theme={null}
  filter?: {
    source?: Record<string, string[] | undefined>;
    destination?: Record<string, string[] | undefined>;
  };
```

Example:

```ts theme={null}
{
  source: {
    // only assets on this chainId is allowed
    'noble-1': undefined,
  },
  destination: {
    // these assets on this chainId are allowed
    'cosmoshub-4': ['uatom', 'ibc/2181AAB0218EAC24BC9F86BD1364FBBFA3E6E3FCC25E88E3E68C15DC6E752D86'],
    // these assets on this chainId are allowed
    'agoric-3': ['ibc/FE98AAD68F02F03565E9FA39A5E627946699B2B07115889ED812D8BA639576A9'],
    // any asset on this chainId are allowed
    'osmosis-1': undefined,
  }
}
```

### `filterOut`

Opposite of filter.
Key value pair of chainIds not allowed or specific asset denoms not allowed

```ts theme={null}
  filterOut?: {
    source?: Record<string, string[] | undefined>;
    destination?: Record<string, string[] | undefined>;
  };
```

Example:

```ts theme={null}
{
  source: {
    // only assets on this chainId is not allowed
    'noble-1': undefined,
  },
  destination: {
    // these assets on this chainId are not allowed
    'cosmoshub-4': ['uatom', 'ibc/2181AAB0218EAC24BC9F86BD1364FBBFA3E6E3FCC25E88E3E68C15DC6E752D86'],
  }
}
```

### `settings`

Sets defaults for user-customizable settings.

```ts theme={null}
settings?: {
  customGasAmount?: number;
  slippage?: number;
  useUnlimitedApproval?: boolean; // Set allowance amount to max if EVM transaction requires allowance approval
};
```

* `customGasAmount`: Gas amount for CosmosSDK chain transactions. Default: `300_000`.
* `slippage`: Default slippage percentage (0-100) for CosmosSDK chain swaps. Default: `1`.

### `onlyTestnet`

`onlyTestnet`: Boolean to show only testnet data. Default: false (mainnet data only).

### `endpointOptions`

Override default Skip proxied endpoints. Whitelisting required, reach out [here](https://discord.com/invite/interchain).

```ts theme={null}
endpointOptions?: {
    endpoints?: Record<string, EndpointOptions>;
    getRpcEndpointForChain?: (chainID: string) => Promise<string>;
    getRestEndpointForChain?: (chainID: string) => Promise<string>;
  };
```

### `apiUrl`

String to override default Skip Go API proxied endpoints. Whitelisting required, reach out [here](https://discord.com/invite/interchain).

### `brandColor`

Customizes the main highlight color of the widget

### `borderRadius`

Controls the corner roundness of cards and buttons in the widget

### `theme`

Advanced widget appearance customization options

```tsx theme={null}
  theme? = {
    brandColor: string;
    borderRadius: {
      main?: string | number;
      selectionButton?: string | number;
      ghostButton?: string | number;
      modalContainer?: string | number;
      rowItem?: string | number;
    };
    primary: {
      background: {
        normal: string;
      };
      text: {
        normal: string;
        lowContrast: string;
        ultraLowContrast: string;
      };
      ghostButtonHover: string;
    };
    secondary: {
      background: {
        normal: string;
        transparent: string;
        hover: string;
      };
    };
    success: {
      background: string;
      text: string;
    };
    warning: {
      background: string;
      text: string;
    };
    error: {
      background: string;
      text: string;
    };
  };
```

### `chainIdsToAffiliates`

Define fees per chain and recipient addresses.

<Info>
  Total basisPointsFee must be consistent across chains. Addresses must be valid for respective chains.
</Info>

```ts theme={null}
chainIdsToAffiliates: {
  'noble-1': {
    affiliates: [{
      basisPointsFee: '100', // 1% fee
      address: 'noble..1', // address to receive fee
    },
    {
      basisPointsFee: '100', // 1% fee
      address: 'noble...2', // address to receive fee
    }]
  },
  'osmosis-1': {
    affiliates: [{
      basisPointsFee: '200', // 2% fee
      address: 'osmo...1', // address to receive fee
    },]
  }
}
```

### `enableSentrySessionReplays`

Enables sentry session replays on the widget to help with troubleshooting errors. Default: false.

### `enableAmplitudeAnalytics`

Enable Amplitude analytics for the widget to improve user experience. Default: false.

### `disableShadowDom`

Disables shadow dom, useful if there are issues with libraries not supporting shadow-dom or for enabling server side rendering
Default: false. (shadow dom is enabled by default to avoid styling conflicts/issues)

### `hideAssetsUnlessWalletTypeConnected`

Filters assets based on connected wallet types (currently only supports Sei Cosmos/EVM). Added in v3.7.3. Default: false.

### `callbacks`

Event handling functions.

```ts theme={null}
onWalletConnected?: (params: {
  walletName?: string;
  chainIdToAddressMap: Record<string, string>;
  address?: string;
}) => void;

onWalletDisconnected?: (params: {
  walletName?: string;
  chainType?: string;
}) => void;

onTransactionSignRequested?: (props: onTransactionSignRequestedProps) => void;

onTransactionBroadcasted?: (params: {
  chainId: string;
  signerAddress?: string;
  txIndex: number;
}) => void;

onTransactionComplete?: (params: {
  txHash: string;
  chainId: string;
  explorerLink?: string;
  sourceAddress: string;
  destinationAddress: string;
  sourceAssetDenom: string;
  sourceAssetChainID: string;
  destAssetDenom: string;
  destAssetChainID: string;
}) => void;

onTransactionFailed?: (params: { error: Error }) => void;

onRouteUpdated?: (props: {
  srcChainId?: string;
  srcAssetDenom?: string;
  destChainId?: string;
  destAssetDenom?: string;
  amountIn?: string;
  amountOut?: string;
  requiredChainAddresses?: string[];
}) => void;

onSourceAndDestinationSwapped?: (props: {
  srcChainId?: string;
  srcAssetDenom?: string;
  destChainId?: string;
  destAssetDenom?: string;
  amountIn?: string;
  amountOut?: string;
}) => void;

onSourceAssetUpdated?: (props: {
  chainId?: string;
  denom?: string;
}) => void;

onDestinationAssetUpdated?: (props: {
  chainId?: string;
  denom?: string;
}) => void;
```

* `onWalletConnected`: Called when a wallet is connected.
* `onWalletDisconnected`: Called when a wallet is disconnected.
* `onTransactionBroadcasted`: Called when a transaction is broadcasted. This is called multiple times for multi-transaction routes.
* `onTransactionComplete`: Triggered when a transaction is completed.
* `onTransactionFailed`: Triggered when a transaction fails.

### `connectedAddresses` & `signers`

If your application has already connected to a user's wallet (e.g., via MetaMask for EVM networks, Phantom for Solana, or Keplr for Cosmos), you **must provide both** the `connectedAddresses` and corresponding signer functions in order to enable the widget's injected wallet functionality.
See an implementation example [here](https://github.com/skip-mev/skip-go/tree/staging/examples/nextjs/src/app/injected/page.tsx).

`WalletClient` comes from the [`viem` package](https://viem.sh/docs/clients/wallet.html). `Adapter` comes from the [`@solana/wallet-adapter-base` package](https://solana.com/developers/cookbook/wallets/connect-wallet-react). And `OfflineSigner` comes from the [`@cosmjs` package](https://docs.keplr.app/api/cosmjs.html).

* **Type:** `Record<ChainId, Address>`

**Example:**

```typescript theme={null}
const connectedAddresses: Record<string, string> = {
  "1": "0x123...abc",          // Ethereum mainnet address
  "cosmoshub-4": "cosmos1...", // Cosmos Hub address
  "solana": "3n9...xyz",       // Solana address
  // ... add more chain IDs and addresses as needed
};
```

### Signer Functions

Each signer function below must be implemented to fully leverage the injected wallet capabilities:

* **`getCosmosSigner(): Promise<OfflineSigner>`**
  Returns a Cosmos-compatible signer.

* **`getEvmSigner(): Promise<WalletClient>`**
  Returns an EVM-compatible signer (e.g., from `viem`).

* **`getSvmSigner(): Promise<PhantomWalletAdapter>`**
  Returns a Solana-compatible signer, such as a `PhantomWalletAdapter`.

**Complete Example for injected wallet functionality:**

```jsx theme={null}
<Widget
  connectedAddresses={connectedAddresses}
  getCosmosSigner={getCosmosSigner}
  getEvmSigner={getEvmSigner}
  getSvmSigner={getSvmSigner}
/>
```


# FAQ
Source: https://skip-go.mintlify-go.com/go/widget/faq



## How do I fix the "Buffer is not defined" error?

If you see a 'Buffer is not defined' error when using @skip-go/widget, it's likely because the widget depends on Node.js modules that aren't available in the browser. To fix this, you'll need to add polyfills for those modules.
Here are some polyfill plugins for common environments:

* [Webpack](https://www.npmjs.com/package/node-polyfill-webpack-plugin)
* [Rollup](https://www.npmjs.com/package/rollup-plugin-polyfill-node)
* [Vite](https://www.npmjs.com/package/vite-plugin-node-polyfills)
* [ESBuild](https://www.npmjs.com/package/esbuild-plugins-node-modules-polyfill)

## Should I put the widget inside a container with a fixed size?

It is recommended to wrap the widget with a container element that has a fixed size. This helps to prevent layout shifting as the widget uses the shadow-dom (which needs to be rendered client-side). We recommend a height of `640px` and a width of `500px`.

## Can I use Safe Multisig wallets with the Skip Go widget?

Yes! Safe wallets (the popular multisig wallet at [https://app.safe.global](https://app.safe.global)) can be used with the Skip Go widget through wallet providers that support importing Safe wallets:

* **Rabby Wallet**: Supports importing and using Safe wallets
* **WalletConnect**: Supports connecting Safe wallets through WalletConnect protocol

Both options allow you to use your Safe wallet for multi-chain swaps and transfers through the Skip Go widget.

**Important:** When using Safe wallets for cross-chain transactions, ensure that your Safe wallet is deployed on all relevant destination chains before initiating transfers. Safe wallets use deterministic addresses, but the wallet contract must be deployed on each chain where you plan to receive funds.

## Why am I getting a CORS error or blocked by CORS policy?

If you're seeing CORS errors when using the Skip Go widget, it means your domain needs to be whitelisted to access Skip Go's API endpoints.

To resolve this issue, please get your domain whitelisted by submitting a support ticket in our [Discord server](https://discord.gg/interchain).


# Gas on Receive
Source: https://skip-go.mintlify-go.com/go/widget/gas-on-receive

Automatically provide users with gas tokens on destination chains during cross-chain swaps

Gas on Receive helps users get native gas tokens on destination chains during cross-chain swaps. This prevents users from getting "stuck" with assets they can't use due to lacking gas for future transactions.

<Note>
  **Widget**: Auto-detects need, user toggles on/off (v3.14.0+)
  **Client Library**: Manual setup required (v1.5.0+)
</Note>

## How It Works

When Gas on Receive is enabled, the widget automatically:

1. **Detects insufficient gas balance** on the destination chain
2. **Splits the swap** into two parts:
   * **Main route**: Your primary swap transaction
   * **Fee route**: A smaller swap specifically for obtaining gas tokens
3. **Provides native tokens** for gas fees on the destination chain
4. **Displays the gas top-up** amount and status to users

## Supported Destination Chains

### Supported

* **Cosmos chains** (e.g., Osmosis, Juno, Stargaze)
* **EVM L2 chains** (e.g., Arbitrum, Polygon, Base)

### Not Supported

* **Ethereum mainnet** (disabled due to high gas costs)
* **Solana** (not currently supported)

## Default Gas Amounts

The feature automatically provides gas tokens worth:

* **Cosmos chains**: \$0.10 USD equivalent
* **EVM L2 chains**: \$2.00 USD equivalent

These amounts are designed to cover multiple transactions on the respective chain types.

## Automatic Activation

Gas on Receive automatically activates when:

* The destination chain is supported
* The user's destination address has insufficient gas balance (\< 3x current gas price)
* The destination asset is different from the chain's native gas token

Users can manually toggle the feature on/off via the widget interface.

**Cost Impact**: The gas route uses a small portion of your swap amount (e.g., $0.10-$2.00) which slightly reduces your main swap output.

## User Interface

The feature appears in the widget as:

* **Toggle switch**: Allows users to enable/disable the feature
* **Gas amount display**: Shows how much gas will be received (e.g., "Enable gas top up - You'll get \$2.00 in ETH")
* **Transaction status**: During execution, shows "Receiving \$2.00 in ETH as gas top-up"
* **Completion status**: After success, displays "Received \$2.00 in ETH as gas top-up"

## Configuration

### Widget Configuration

Gas on Receive requires no configuration - the widget auto-detects when it's needed and shows a toggle switch:

```tsx theme={null}
import { Widget } from "@skip-go/widget";

function MyApp() {
  return (
    <Widget
      defaultRoute={{
        srcChainId: "osmosis-1",
        destChainId: "42161", // Arbitrum
        srcAssetDenom: "uosmo",
        destAssetDenom: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" // WETH
      }}
      // Widget automatically:
      // 1. Detects when user lacks gas on destination chain
      // 2. Shows "Enable gas top up" toggle for supported chains
      // 3. User manually enables/disables the feature
    />
  );
}
```

### Client Library Usage

The client library requires manual setup using `executeMultipleRoutes` (v1.5.0+). Use this when building custom interfaces or need more control than the widget provides:

```typescript theme={null}
import { executeMultipleRoutes, route } from "@skip-go/client";

// Create your main route and a smaller gas route
const mainRoute = await route({
  amountIn: "1000000", // 1 OSMO
  sourceAssetChainId: "osmosis-1",
  sourceAssetDenom: "uosmo",
  destAssetChainId: "42161", // Arbitrum
  destAssetDenom: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1" // WETH
});

const gasRoute = await route({
  amountIn: "50000", // ~$2 worth for gas
  sourceAssetChainId: "osmosis-1",
  sourceAssetDenom: "uosmo",
  destAssetChainId: "42161",
  destAssetDenom: "0x0000000000000000000000000000000000000000" // Native ETH
});

// Execute both routes together
await executeMultipleRoutes({
  route: { mainRoute, gasRoute },
  userAddresses: {
    mainRoute: [
      { chainId: "osmosis-1", address: "osmo1..." },
      { chainId: "42161", address: "0x..." }
    ],
    gasRoute: [
      { chainId: "osmosis-1", address: "osmo1..." },
      { chainId: "42161", address: "0x..." }
    ]
  },
  slippageTolerancePercent: {
    mainRoute: "1",
    gasRoute: "10",
  },
  // Required signing functions
  getCosmosSigningClient: async (chainId) => {
    // Return your cosmos signing client for the chain
    return yourCosmosWallet.getSigningClient(chainId);
  },
  getEVMSigningClient: async (chainId) => {
    // Return your EVM signing client for the chain
    return yourEvmWallet.getSigningClient(chainId);
  },
  onRouteStatusUpdated: (status) => console.log(status)
});
```

<Note>
  **Tip**: Most developers should use the widget for automatic gas management. Only use the client library approach if you need custom gas amounts or are building a custom interface.
</Note>

### Manual Gas Route Setup

For more control, you can manually determine when to include gas routes based on user balances:

```typescript theme={null}
import { balances } from "@skip-go/client";

// Check if user has sufficient gas balance
const userBalances = await balances({
  chains: {
    "42161": { address: "0x..." } // User's Arbitrum address
  }
});

const chainBalances = userBalances.chains?.["42161"]?.denoms;
const nativeTokenBalance = chainBalances?.["0x0000000000000000000000000000000000000000"];

// Simple check: does user have any native token balance?
const hasEnoughGas = nativeTokenBalance?.amount && nativeTokenBalance.amount !== "0";

if (!hasEnoughGas) {
  // Include gas route in executeMultipleRoutes
  console.log("User needs gas - including gas route");
} else {
  // Execute only main route
  console.log("User has sufficient gas");
}
```

### Custom Gas Amounts (Advanced)

For advanced use cases, you can customize gas amounts by adjusting the `amountIn` when creating gas routes. The default equivalent amounts are:

* **Cosmos chains**: \$0.10 USD
* **EVM L2 chains**: \$2.00 USD

## Error Handling

**If gas route fails**: Your main swap continues normally, you just won't receive the gas tokens. No funds are lost.

**If main swap fails**: You receive the gas tokens you paid for, plus any remaining funds in your original source token.

## Troubleshooting

**Feature not appearing?**

* Ensure you're using Widget v3.14.0+ or Client Library v1.5.0+
* Check that the destination chain is supported (Cosmos chains, EVM L2s)
* Feature auto-disables if user already has sufficient gas or destination asset is the native gas token

**Transaction issues?**

* Gas top-up failures don't affect your main swap - assets are safely returned
* Main swap may succeed even if gas route fails

For advanced routing configuration, see [Configuration](/go/widget/configuration).


# Getting Started
Source: https://skip-go.mintlify-go.com/go/widget/getting-started



# Overview

The Skip Go `Widget` is the easiest way to onboard users and capital from anywhere in the world to your corner of the sovereign web! The widget provides seamless cross-chain bridging, swapping, and transferring functionality in an easy to integrate React or [Web component](./web-component.mdx).

<Info>
  Want to experiment with the widget before integrating it?
  Check out our interactive builder: [studio.skip.build](https://studio.skip.build) — experiment visually and generate ready-to-use code for your app!
</Info>

# Useful Links

* [Skip Go Repository](https://github.com/skip-mev/skip-go)
* [Example Widget Implementation](https://github.com/skip-mev/skip-go/tree/main/examples/nextjs)

# Quickstart Guide

This guide will walk you through how to integrate the `Widget` into your React app.

<Info>
  Starting from scratch? It's recommended to use a React framework like [Next.js](https://nextjs.org/docs/getting-started/installation) or [Create React App](https://create-react-app.dev/docs/getting-started) to get up and running quickly.
</Info>

<Steps>
  <Step title="Installation">
    <CodeGroup>
      ```shell NPM theme={null}
      npm install @skip-go/widget
      ```

      ```shell Yarn theme={null}
      yarn add @tanstack/react-query viem wagmi
      ```
    </CodeGroup>

    <Info>
      If you're using `yarn` (or another package manager that doesn't install peer dependencies by default)
      you may need to install these peer dependencies as well:

      ```bash theme={null}
        yarn add @tanstack/react-query viem wagmi
      ```
    </Info>
  </Step>

  <Step title="Import the Widget Component">
    Next, use the `Widget` component to render the swap interface:

    ```typescript theme={null}
    import { Widget } from '@skip-go/widget';

    const SwapPage = () => {
      return (
        <div
          style={{
            width: '100%',
            maxWidth: '500px',
            padding: '0 10px',
          }}
        >
          <Widget
            theme="light"
            brandColor="#FF4FFF"
          />
        </div>
      );
    };
    ```

    <Tip>
      You can use the code generated by [studio.skip.build](https://studio.skip.build) directly in your integration below.
    </Tip>
  </Step>

  <Step title="Configuration">
    Now that you have the widget integrated, it's time to configure the user experience. Find more details on widget configuration [here](./configuration).
  </Step>
</Steps>

<Info>
  If there's any functionality or configurations you'd like to see in the widget, we'd love for you to contribute by opening up an issue or pull request in [the repository](https://github.com/skip-mev/skip-go/tree/main/packages/widget) or by joining [our Discord](https://discord.com/invite/interchain) and giving us a shout!
</Info>


# Migration Guide
Source: https://skip-go.mintlify-go.com/go/widget/migration-guide



## @skip-go/widget v3.9.0

### Prop name changes

**Before:**

```tsx theme={null}
  <Widget
    getEVMSigner={}
    getSVMSigner={}
  />
```

**After:**

```tsx theme={null}
<Widget
getEvmSigner={}
getSvmSigner={}
/>
```

## @skip-go/widget v3.0.0

### 1. Update Dependency (`^3.0.0`)

<CodeGroup>
  ```shell NPM theme={null}
  npm install @skip-go/widget@latest
  ```

  ```shell Yarn theme={null}
  yarn add @skip-go/widget@latest
  ```
</CodeGroup>

<Info>
  If you're using `yarn` (or another package manager that doesn't install peer dependencies by default)
  you may need to install these peer dependencies as well:

  ```bash theme={null}
    yarn add @tanstack/react-query graz react react-dom viem wagmi
  ```
</Info>

### 2. `theme` Prop Changes

#### More Customization Options

You can pass either `light`, `dark`, or a custom theme object with granular
control over the widget's appearance.

**Before:**

```tsx theme={null}
  <Widget
    theme='{
        "backgroundColor": "#191A1C",
        "textColor": "#E6EAE9",
        "borderColor": "#363B3F",
        "brandColor": "#FF4FFF",
        "highlightColor": "#1F2022"
    }'
  />
```

**After:**

```tsx theme={null}
<Widget
theme="light" // or "dark"
// Note: you can pass a "brandColor" in addition to the selected "light" or "dark" theme
brandColor: "#FF4FFF"
// Or provide a custom theme object
theme={{
  brandColor: "#FF4FFF",
  primary: {
    background: {
      normal: "#191A1C",
      transparent: "rgba(25, 26, 28, 0.5)",
    },
    text: {
      normal: "#E6EAE9",
      lowContrast: "#B0B3B5",
      ultraLowContrast: "#7C7F81",
    },
    ghostButtonHover: "#1F2022",
  },
  // Define other theme properties as needed
}}
/>
```

The custom theme object has the following structure:

```tsx theme={null}
theme = {
  brandColor: string;
  borderRadius: number;
  primary: {
    background: {
      normal: string;
      transparent: string;
    };
    text: {
      normal: string;
      lowContrast: string;
      ultraLowContrast: string;
    };
    ghostButtonHover: string;
  };
  secondary: {
    background: {
      normal: string;
      transparent: string;
      hover: string;
    };
  };
  success: {
    text: string;
  };
  warning: {
    background: string;
    text: string;
  };
  error: {
    background: string;
    text: string;
  };
};
```

### 3. Prop Spelling Changes

#### `chainID` Renamed to `chainId`

#### `apiURL` Renamed to `apiUrl`

Update all instances of `chainID` to `chainId`, notably in the `defaultRoute` prop.

**Before:**

```tsx theme={null}
<Widget
  apiURL="..."
  defaultRoute={{
    amountIn: 1,
    srcChainID: "osmosis-1",
    srcAssetDenom: "uosmo",
    destChainID: "cosmoshub-4",
    destAssetDenom: "uatom",
  }}
/>
```

**After:**

```tsx theme={null}
<Widget
  apiUrl="..."
  defaultRoute={{
    amountIn: 1,
    srcChainId: "osmosis-1",
    srcAssetDenom: "uosmo",
    destChainId: "cosmoshub-4",
    destAssetDenom: "uatom",
  }}
/>
```

### 4. Temporarily Disabled Features

The following props will be reintroduced in future versions of `Widget`.

#### a. `connectedWallet` Prop

The connectedWallet prop, which allowed passing a custom wallet provider, isn't currently supported.

#### b. `CallbackStore` Callback Props

The `onWalletConnected`, `onWalletDisconnected`, `onTransactionBroadcasted`, `onTransactionComplete`, and `onTransactionFailed` callback props aren't currently supported.

### 5. Removed Features

#### a. `persistWidgetState`

This prop is no longer supported, as the `Widget` persists state by default.

#### b. `toasterProps`

The `toasterProps` prop has been removed because the `Widget` no longer generates notifications.

#### c. `makeDestinationWallets`

The `makeDestinationWallets` prop has been removed. The `Widget` now automatically generates destination wallets from connected wallets or manual user entry.

<Info>
  By implementing these changes, you can successfully migrate your application from Widget V1 to Widget V2. For further assistance, refer to the official documentation or reach out to the [support team](https://discord.com/channels/669268347736686612/1365254948782342175).
</Info>


# Web Component
Source: https://skip-go.mintlify-go.com/go/widget/web-component



For non-React applications, the Skip Go `Widget` is available as a web component.

# Installation

You can import the web component in two ways:

## 1. NPM

```ts theme={null}
import('@skip-go/widget-web-component');
```

<Info>
  Note: Ensure Node has sufficient memory allocated: `CopyNODE_OPTIONS=--max-old-space-size=32384`
  This can be added to npm scripts in `package.json`, a `.env file`, or used when running Node directly.
</Info>

## 2. Script Tag or CDN (Recommended)

```html theme={null}
<body>
  <script
    async
    src="https://unpkg.com/@skip-go/widget-web-component/build/index.js"
    type="module"
  ></script>
</body>
```

## Usage

Props are the exact same as [`WidgetProps`](./configuration) but you are required to pass them to the element via javascript/typescript.

```tsx theme={null}
<div style="width:100%; max-width:500px; padding:0 10px;">
  <skip-widget></skip-widget>
</div>
<script>
  const skipWidget = document.querySelector("skip-widget");
  if (skipWidget) {
    skipWidget.theme = {
      brandColor: "#FF4FFF",
      borderRadius: 30,
    };
    skipWidget.defaultRoute = {
      srcChainId: "osmosis-1",
      srcAssetDenom: "ibc/1480b8fd20ad5fcae81ea87584d269547dd4d436843c1d20f15e00eb64743ef4",
    }
  }
</script>
```

## Performance Considerations

It's recommended to lazy load this component as it comes pre-bundled with all dependencies, which may impact load times, especially in development environments.