-
Notifications
You must be signed in to change notification settings - Fork 146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: bitflow implemenation, #5860
Conversation
9ad07b6
to
f1cc29a
Compare
This PR implements Bitflow as the provider of swap functionality. Overview
Implementation Details
Screenshots
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey Alex, great work. Left some comments, but otherwise looks like a pretty solid implementation
}; | ||
} | ||
|
||
export function useGetBitflowPossibleSwapsQuery(token: string): UseQueryResult<SwapOptions, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this typing needed, or is it implicit given return value? Normally find it's more reliable to use the inferred type vs setting manually
src/app/pages/swap/swap.utils.ts
Outdated
export function estimateLiquidityFee(dexPath: string[]) { | ||
return 0.3 * dexPath.length; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export function estimateLiquidityFee(dexPath: string[]) { | |
return 0.3 * dexPath.length; | |
} | |
export function estimateLiquidityFee(dexPath: string[]) { | |
return new BigNumber(dexPath.length).times(0.3).toNumber(); | |
} |
if (!signedTx) | ||
return logger.error('Attempted to generate raw tx, but signed tx is undefined'); | ||
return await broadcastStacksSwap(signedTx); | ||
} catch (error) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if the swap fails?
value={`${Array.from(new Set(swapSubmissionData.dexPath)) | ||
.map(x => capitalize(x.toLowerCase())) | ||
.join(', ')} via ${swapSubmissionData.protocol}`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally this component remains agnostic from any specific dex implementation. e.g. the dexPath
property is specific to Bitflow right?
Wonder if this logic value/formatting logic could be defined in BitflowSwapContainer
and pass in via the context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either way, would be nice to move into a function that lives outside the JSX
}; | ||
|
||
if (token.tokenId === BITFLOW_STX_CURRENCY) { | ||
const price = convertAmountToFractionalUnit(new BigNumber(prices[Currency.STX] ?? 0), 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magic number. What's 2
here?
|
||
const swapAsset = { | ||
currency: token.tokenId as Currency, | ||
fallback: token.symbol.slice(0, 2), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not clear what this does? Helper function might explain better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Essentially fetching price data and building the SwapAsset
.
A lot of this is from alex-sdk.hooks.ts
, which is where SwapAsset
is defined. Most of the swap functionality is built around the SwapAsset
concept so I've had to repurpose it to fit Bitflow types.
I'm sure this could be made more clear / efficient but we might want to first migrate the bitflow functionality into mono
to keep it DRY.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a comment somewhere to revisit SwapAsset so that it before follows patterns we use with building our crypto assets in other parts of the app. Def a good idea to revisit once in the mono repo.
fs: require.resolve('browserify-fs'), | ||
path: require.resolve('path-browserify'), | ||
os: require.resolve('os-browserify/browser'), | ||
process: require.resolve('process/browser'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guess Bitflow isn't the best authored lib if we have to add tonnes of node polyfills 🤦🏼
@@ -76,8 +79,8 @@ export function SwapDetails() { | |||
/> | |||
<SwapDetailLayout | |||
title="Liquidity provider fee" | |||
tooltipLabel="To receive a share of these fees, become a Liquidity Provider on app.alexlab.co." | |||
value={`${swapSubmissionData.liquidityFee} ${swapSubmissionData.swapAssetBase.name}`} | |||
tooltipLabel="To receive a share of these fees, become a Liquidity Provider on app.bitflow.finance." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be dynamic and change between alexlab.co
& bitflow.finance
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. Technically the underlying liquidity pools can span multiple DEXes. Might be weird to try and accommodate any / all LPs Bitflow could use in a swap. Maybe better to remove the comment? @markmhendrickson thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove this tooltip in general and revisit later when we redesign swaps for mobile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As Mark says we can remove, but to make generic we could add a providerDomain
to the context, and read that so <SwapDetails />
doesn't know about any given provider
@@ -41,7 +41,7 @@ import { RequestError } from '@app/pages/request-error/request-error'; | |||
import { BroadcastError } from '@app/pages/send/broadcast-error/broadcast-error'; | |||
import { sendOrdinalRoutes } from '@app/pages/send/ordinal-inscription/ordinal-routes'; | |||
import { sendCryptoAssetFormRoutes } from '@app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes'; | |||
import { alexSwapRoutes } from '@app/pages/swap/alex-swap-container'; | |||
import { bitflowSwapRoutes } from '@app/pages/swap/bitflow-swap-container'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we replacing alex-swap-container
with bitflow-swap-container
?
Maybe we can get rid of the ALEX code then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it's replacing. Wasn't sure if there'd be any value in keeping the ALEX stuff around, but it probably makes sense to just clear it out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say if it's not much extra work, clear it out and add a comment to https://github.com/leather-io/issues/issues/99 to explain it's being removed.
We will be able to remove "alex-sdk": "2.1.3",
then also and close off this #5852
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the existing ALEX swap components but the SwapAsset
interface imported from mono
has a reference to an ALEX SDK type that needs to be referenced. We should be able to refactor that in mono
and remove that dependency here but for now it would be difficult to remove the SDK package entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds great 👍 Nice work
Nice work @alexp3y 👏 It's unclear to me if we are replacing ALEX swap with Bitflow. I thought we were keeping both and letting the user choose the best option? If we are removing ALEX lets also get rid of the ALEX code |
I tested building this branch and I couldn't get it up and running. I guess as it's still in flight. I hit this error on fresh install: I just wanted to double check how the (Action popup is what we call the non-full screen mode called from the extension button, we have a glossary here in case thats helpful) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work @alexp3y, great to see this being added into swaps.
Nice work, @alexp3y! Can we get a developer build attached to this PR for QA? 🙏 |
f1cc29a
to
78414cb
Compare
Just to confirm – are we filtering the tokens we show under balances with the BitFlow SDK now as well? Per this thread I.e. we'll want to show by default all tokens that appear in either the BitFlow SDK and the ALEX SDK (unless the former SDK is essentially a superset of the latter, in which case we can just use BitFlow's), hiding all tokens that don't appear in the SDK(s) |
9cc8be0
to
4e902ac
Compare
@@ -13,6 +13,10 @@ env: | |||
SEGMENT_WRITE_KEY: ${{ secrets.SEGMENT_WRITE_KEY_STAGING }} | |||
TRANSAK_API_KEY: ${{ secrets.TRANSAK_API_KEY }} | |||
BESTINSLOT_API_KEY: ${{ secrets.BESTINSLOT_API_KEY }} | |||
BITFLOW_API_HOST: ${{ secrets.BITFLOW_API_HOST }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if I needed to add the " "
around the value in GH secrets? I didn't so that might be why not working?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I'll change and rerun the tests to see if they pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That isn't right but I wonder if the urls are running into this? https://www.ssw.com.au/rules/handle-special-characters-on-github/
Do we need to keep the urls private, or can those just be exposed in the code as constants?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I forgot to add the Bitflow variables to the playwright.yml workflow so the integration tests all broke.
Just added them and tests are passing now.
@314159265359879 could you and/or @DeeList QA this change with a few test swaps? 🙏 |
4e902ac
to
f070d54
Compare
WIll have a look and test today. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall swapping works well. I know that setting custom fee and nonce will be covered in a later update, as well as the option to set a custom slippage percentage, those are high on my wish list to make the swap more pro-friendly. I think it is really great to have the Bitflow integration there is support for so many more tokens all at once. Great for anyone who wants to do a quick swap.
I only tested with software wallet because the hardware wallet with app version 0.24.2 has a known issue.
-
There are so many tokens that it would make sense to add a filter bar at the top so users can type in a partial name or ticker to limit the amount that has to be scrolled through.
-
The amount on the other side isn't calculated until the user deselects the textbox/moved the cursor elsewhere. I think it is okay to have some delay after the user starts typing but generally it would be a better UX if the other side is calculated without having to click outside the the textbox.
2024-09-29_17-03-42.mp4
I expect this kind of loading as I type the value I want to swap I see how it changes the output I will get:
2024-09-29_17-13-22.mp4
If these changes can't be part of the current scope, lets make new issues for them to cover later.
It seems we're ordering alphabetically by ticker but then the ordering restarts towards the end of the list, perhaps because there are two separate lists of tokens getting concatenated? My sense is that it would be better to order (the two lists) in aggregate alphabetically by name instead of ticker. @fabric-8 to confirm the approach he prefers Screen.Recording.2024-09-30.at.10.16.43.mov |
It appears for tokens that don't have fiat values that we need to hide (or display Edit: It should actually be possible calculate the fiat value of the received token by comparing to the value of the sent token? |
@markmhendrickson Looking at this now. The token filtering logic used in the Asset list is coming from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs some minor adjustments but otherwise looks great! 🚀
f070d54
to
8e0548f
Compare
@markmhendrickson @fabric-8 Made the following adjustments -
|
53a0394
to
47937da
Compare
See @alexp3y's comments below