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.
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:
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:
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:
response.usd_amount_in
)response.usd_amount_out
)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.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)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)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 routeThe 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.
We recommend alerting users in the following three scenarios at least:
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 usingPRICE_IMPACT_THRESHOLD = 2.5
in your calculations(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
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:
For example, when a swap exceeds our PRICE_IMPACT_THRESHOLD
on go.skip.build, we auto-open the drop-down that normally hides price impact and highlight the whole field in red.
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:
(usd_amount_in - usd_amount_out)/usd_amount_in)*100 > 10
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.
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:
We recommend requiring additional steps of user approval in the following cases:
(usd_amount_in - usd_amount_out)/usd_amount_in)*100 > 5
swap_price_impact > 5
)swap_price_impact
, usd_amount_out
, and/or usd_amount_in
are missing)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:
Here are some suggestions for navigating this design space:
Have questions or feedback? Help us get better!
Join our Discord and select the “Skip Go Developer” role to share your questions and feedback.
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.
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:
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:
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:
response.usd_amount_in
)response.usd_amount_out
)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.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)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)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 routeThe 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.
We recommend alerting users in the following three scenarios at least:
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 usingPRICE_IMPACT_THRESHOLD = 2.5
in your calculations(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
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:
For example, when a swap exceeds our PRICE_IMPACT_THRESHOLD
on go.skip.build, we auto-open the drop-down that normally hides price impact and highlight the whole field in red.
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:
(usd_amount_in - usd_amount_out)/usd_amount_in)*100 > 10
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.
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:
We recommend requiring additional steps of user approval in the following cases:
(usd_amount_in - usd_amount_out)/usd_amount_in)*100 > 5
swap_price_impact > 5
)swap_price_impact
, usd_amount_out
, and/or usd_amount_in
are missing)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:
Here are some suggestions for navigating this design space:
Have questions or feedback? Help us get better!
Join our Discord and select the “Skip Go Developer” role to share your questions and feedback.