[PE-7191] External wallet swap flow - #13276
Conversation
|
| prefix: string = '$' | ||
| ): string => { | ||
| if (num === 0) return '$0.00' | ||
| if (num === 0) return `${prefix}0.00` |
There was a problem hiding this comment.
Allows replacing the $ that gets prefixed to these strings - in this case removing it
There was a problem hiding this comment.
still confused, seems like it's doing the same as before?
| selectedPair: safeSelectedPair, | ||
| onClose | ||
| swapHookData: swapHookState, | ||
| handleSwap: (params) => { |
There was a problem hiding this comment.
handleSwap: performSwap
| selectedPair, | ||
| onClose: () => navigation.goBack() | ||
| swapHookData: swapHookState, | ||
| handleSwap: (params) => { |
There was a problem hiding this comment.
same, is it the case the types are a bit different or something?
| const externalWalletAccount = appkitModal.getAccount() | ||
| const internalSwapHook = useSwapCoins() | ||
| const externalSwapHook = useExternalWalletSwap() | ||
| const { mutateAsync: performSwap, ...swapHookState } = |
| | typeof IconMetamask | ||
| | typeof IconSolana | ||
|
|
||
| const getWalletIcon = (): WalletIconComponent => { |
There was a problem hiding this comment.
in your demo video, looks like this is showing audio icon when it should show phantom?
|
|
||
| const tokenBalanceString = isUsingExternalWallet | ||
| ? externalWalletTokenBalance | ||
| ? formatCurrency( |
There was a problem hiding this comment.
we have a ton of helpers, but this still feels awk
There was a problem hiding this comment.
to follow on this:
- this nesting is not the clearest to read, can we break up pls
- we shouldn't default to showing
0balances ever in case there's an error upstream. we should only show0as a balance if the user truly has 0 balance
| border='default' | ||
| alignItems='center' | ||
| justifyContent='center' | ||
| css={(theme) => ({ |
There was a problem hiding this comment.
in your demo the circle seems a bit too large compared to the icon itself
| SwapStatus, | ||
| SwapTokensParams, | ||
| SwapTokensResult | ||
| } from '@audius/common/src/api/tan-query/jupiter/types' |
There was a problem hiding this comment.
should not import from source
| const outputAmount = result.outputAmount! | ||
| const outputAmount = result.outputAmount!.uiAmount | ||
| const newAmount = currentAmount + outputAmount | ||
| return new FixedDecimal(newAmount, oldBalance.decimalPlaces) |
There was a problem hiding this comment.
Excellent job in this file
| address: mintAddress, | ||
| decimals: LAUNCHPAD_COIN_DECIMALS | ||
| }, | ||
| inputMint: TOKEN_LISTING_MAP.AUDIO.address, |
There was a problem hiding this comment.
so just to confirm, you were able to use the same external swap flow for both buy audio and external buy/sell/swap?
There was a problem hiding this comment.
you mean the launchpad buy flow? Yes
| swapHookData: { | ||
| data?: SwapTokensResult | ||
| status: MutationStatus | ||
| error?: Error | null | ||
| } | ||
| // The swap is handled externally to allow for external wallet swaps | ||
| // Web and mobile use different services for these so we let each repo handle the logic | ||
| handleSwap: (params: { | ||
| inputMint: string | ||
| outputMint: string | ||
| amountUi: number | ||
| slippageBps: number | ||
| }) => void |
There was a problem hiding this comment.
can make these their own types
| import { useConnectExternalWallets } from 'hooks/useConnectExternalWallets' | ||
| import { env } from 'services/env' | ||
|
|
||
| const messages = { |
There was a problem hiding this comment.
nit: we have walletMessages.ts
| if (typeof window !== 'undefined' && window.ethereum) { | ||
| return IconMetamask |
There was a problem hiding this comment.
is this the spec from design?
| inputToken: { mint: string; symbol: string } | ||
| }) => { | ||
| const { data: currentUser } = useCurrentAccountUser() | ||
| const isAnonymousUser = !currentUser |
There was a problem hiding this comment.
nit: isLoggedOutUser feels more clear to me or isUnauthed tbh not bad to just use !currentUser everywhere isAnonymousUser is used. probably the most clear and is less chars haha
| } = useExternalWalletBalance({ | ||
| walletAddress: externalWalletAccount?.address, | ||
| mint: inputToken.mint | ||
| }) | ||
|
|
||
| const { | ||
| data: internalWalletTokenBalanceData, | ||
| isPending: isInternalWalletTokenBalanceLoading | ||
| } = useCoinBalance({ | ||
| mint: inputToken.mint, |
There was a problem hiding this comment.
should we not disable these if the other is being used?
| ? isExternalWalletTokenBalanceLoading | ||
| : isInternalWalletTokenBalanceLoading | ||
|
|
||
| const noCurrentWallet = isAnonymousUser && !isUsingExternalWallet |
There was a problem hiding this comment.
let's do const hasUnauthedWallet = isAnonymousUser && isUsingExternalWallet and then we dont' have to do the negation on a negative below
| ? messages.builtInWalletNotAvailable | ||
| : messages.tradeWith} | ||
| </Text> | ||
| {/* Wallet pill */} |
There was a problem hiding this comment.
don't we have a pill component in harmony?
| </Flex> | ||
| <TextLink | ||
| variant='visible' | ||
| href='#' |
| }, [coins, coinsLoading]) | ||
|
|
||
| // Get tokens that user owns (includes USDC if user has balance) | ||
| // TODO : modify this to account for external wallets |
| const shouldShowError = | ||
| !!displayErrorMessage || (activeTab === 'buy' && !hasSufficientBalance) | ||
|
|
||
| const userHasNoWallet = !externalWalletAccount?.address && !currentUser |
There was a problem hiding this comment.
we should try to use affirmative var names, so something like userHasWallet and using negation thing applies here as well
| @@ -4,15 +4,19 @@ import { | |||
| TEMP_ARTIST_COINS_PAGE_SIZE, | |||
| setCurrentStep(BuyModalStep.Loading) | ||
| } | ||
| if (swapError || swapData?.isError) { | ||
| if (swapError || swapData?.error) { |
| @@ -352,7 +356,7 @@ type AssetDetailProps = { | |||
|
|
|||
| const BalanceSectionContent = ({ mint }: AssetDetailProps) => { | |||
| const { data: coin, isPending: coinsLoading } = useArtistCoin(mint) | |||
| const { data: tokenBalance, isPending: tokenBalanceLoading } = useCoinBalance( | |||
| const { data: tokenBalance, isLoading: tokenBalanceLoading } = useCoinBalance( | |||
There was a problem hiding this comment.
just curious why we're using isLoading instead of isPending?
There was a problem hiding this comment.
isPending = "wait until data shows up" - if there's no data ever (cause no user) isPending is permanently false. isLoading just means "is it trying to fetch data right now"
| amountUi: number | ||
| walletAddress: string | ||
| isAMM: boolean | ||
| solanaConnection: any |
There was a problem hiding this comment.
can we avoid using any here
There was a problem hiding this comment.
also, there's a bit of overlap with these types. can we create a base types? maybe that's SwapTokenParams
| transaction: VersionedTransaction | ||
| inputAmount: { amount: number; uiAmount: number } | ||
| outputAmount: { amount: number; uiAmount: number } |
There was a problem hiding this comment.
nit: make into its own type
| quoteResponse: firstQuote.quote, | ||
| userPublicKey: walletAddress, | ||
| dynamicSlippage: true, | ||
| useSharedAccounts: false |
There was a problem hiding this comment.
have u tried with true?
| // Retry without shared accounts if it fails | ||
| swapRequest1.useSharedAccounts = false |
There was a problem hiding this comment.
it's already false. also, we try 3 more times in internal flow, can perhaps try more times here?
| }) | ||
| } catch (e) { | ||
| // Retry without shared accounts if it fails | ||
| swapRequest2.useSharedAccounts = false |
| } | ||
|
|
||
| // Convert instructions to TransactionInstructions | ||
| const firstSetupInstructions = convertJupiterInstructions( |
There was a problem hiding this comment.
can we just use convertJupiterInstructions([...allInstructions]) instead of having to use it for each ix?
|
|
||
| hookProgress.receivedQuote = true | ||
| let transaction: VersionedTransaction | ||
| let inputAmount: { amount: number; uiAmount: number } |
There was a problem hiding this comment.
we should make a type for { amount: number; uiAmount: number } it's used all over the place, maybe SwapAmount or something
| audioMint: env.WAUDIO_MINT_ADDRESS, | ||
| inputDecimals, | ||
| outputDecimals, | ||
| audioDecimals: 8, // AUDIO has 8 decimals |
There was a problem hiding this comment.
let's use this from TOKEN_LISTING_MAP
| // External wallet swaps require some extra params. These are unused for internal swaps | ||
| inputDecimals: swapTokens.inputTokenInfo!.decimals, | ||
| outputDecimals: swapTokens.outputTokenInfo!.decimals, | ||
| walletAddress: externalWalletAccount?.address as string |
There was a problem hiding this comment.
Bug: Token Info Nullability Causes Assertion Failures
Non-null assertions on swapTokens.inputTokenInfo!.decimals and swapTokens.outputTokenInfo!.decimals can cause runtime errors. This occurs because inputTokenInfo and outputTokenInfo can be null when currentTokenPair.baseToken or currentTokenPair.quoteToken are unavailable.
### Description Wallet connection flow  Swap Flow  - Adds UI for external wallet swaps - Updates useBuySellSwap hook to not handle the actual swap hook any more, this is now handled by web/mobile respectively - Aligns the input/output types of internal & external swap hooks ### How Has This Been Tested? ✅ internal wallet swaps still work ✅ launchpad swaps still work ✅ mobile swaps still work ✅ tested swaps for USDC<>Coin, Audio<>Coin, and Coin<>Coin --------- Co-authored-by: Farid Salau <faridsalau@gmail.com>
[4b1ce10] [PE-7239] Fix issues due to stale local storage data (#13311) Dylan Jeffers [7a88ddf] Artist coins page size 1000 (#13313) Reed [3d246f6] Some additional analytics around wallets & launchpad (#13312) JD Francis [f22659e] [PE-7238] Add analytics for external wallet swaps (#13309) JD Francis [421a9e9] 💚🟢🐸🥬 (#13308) JD Francis [ffb4af9] Fix wallet connect not triggering success in claim flow (#13305) JD Francis [68fa1a4] [PE-7229] Fix referrer signup (#13306) Dylan Jeffers [6ed86b5] Version Packages (#13254) github-actions[bot] [b9b22cd] [PE-7204] Associate wallets on solana /relay calls (#13299) JD Francis [ad01774] Revert "[PE-7211] Claim fees after connect" (#13303) JD Francis [1819c1e] fix mobile ci (#13302) JD Francis [afeceae] Fix AUDIO breakdown (#13298) Farid Salau [68eace6] birdeye.so (#13301) Marcus Pasell [30f3e66] [PE-7215] Add sol back into the list of tokens + Dont show 'add cash' (#13295) JD Francis [6e74a41] Fix CI (#13297) Farid Salau [e68b261] [PE-7212] Claim fees optimistic updates (#13290) Dylan Jeffers [d1000f1] [PE-7211] Claim fees after connect (#13291) Dylan Jeffers [f1f1e94] [PE-7210] Handle lowercase coin urls (#13284) Dylan Jeffers [8eade23] [PE-7226] Fix issues with confirmation screen (#13294) JD Francis [0b58a67] [PE-7198] Update mobile profile edit flow UI (#13271) Farid Salau [dd17039] eth key exporter (#13293) alecsavvy [a6d5e9d] Use production wAUDIO on stage (#13288) Marcus Pasell [0bd603d] [PE-7213] Prevent claiming dust (#13289) Dylan Jeffers [b4dde83] Add polling for audio balance changes (#13228) JD Francis [315865f] Fix lint (#13285) Dylan Jeffers [ee7ee7f] [PE-7209] External wallet coin dropdown (#13283) Dylan Jeffers [d4f7649] [PE-7191] External wallet swap flow (#13276) JD Francis [4a38e63] Rename asset to coin (#13275) Dylan Jeffers [c3ffa17] Show DAMM V2 Fees in UI (#13280) Marcus Pasell [172f129] Remove extra dbcpool arg (#13269) Ray Jacobson [3dafa35] [PE-7199] Refactor buy/sell flow coin filtering logic (#13272) Farid Salau [c1d796d] [PE-7193] Announcement notifs link to artist coin explore (#13266) Reed [3e561d2] [PE-7197] Update ArtistCoinHoverCard to include member vs creator (#13270) Farid Salau [50878b5] Small QA items (#13273) Farid Salau [932fbdb] Remove search explore flag (#13261) Dylan Jeffers [5da716e] [PE-7163] Redirect mispelled coins to 404 (#13274) Ray Jacobson [6866949] Finalize mobile search explore (#13260) Dylan Jeffers [0ec2f5f] [PE-7189] Add balance breakdown component (#13262) Farid Salau
Description
Wallet connection flow

Swap Flow

How Has This Been Tested?
✅ internal wallet swaps still work
✅ launchpad swaps still work
✅ mobile swaps still work
✅ tested swaps for USDC<>Coin, Audio<>Coin, and Coin<>Coin