-
Notifications
You must be signed in to change notification settings - Fork 37
Add collectibles to send flow #2473
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
Conversation
| return { assetsLists: response.assetsLists, error: response.error }; | ||
| }; | ||
|
|
||
| export const simulateSendCollectible = async (args: { |
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.
this mirrors the code simulateTokenTransfer
| await stubSimulateSendCollectible(page); | ||
| await stubScanTx(page); | ||
| await stubSubmitTx(page); | ||
| await stubFeeStats(page); |
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.
these tests completely stub out interactions with Horizon and the network, so it should be fast and reliable 🎉 . This is a model we can start using for other tests that submit tx's, which are often flakey due to real world network conditions
| } from "helpers/stellar"; | ||
|
|
||
| import { SimulateTxData } from "popup/components/sendPayment/SendAmount/hooks/useSimulateTxData"; | ||
| import { SimulateTxData } from "popup/components/send/SendAmount/hooks/useSimulateTxData"; |
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.
Renaming SendPayment to Send as this flow can now send things that are not assets
| </div> | ||
| ); | ||
| })} | ||
| <TabButtons /> |
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.
We'll reuse these in the Send flow
| const handleSendCollectible = () => { | ||
| // prepopulate the collectible data in the redux state before navigating to the send flow | ||
| dispatch(saveIsCollectible(true)); | ||
| dispatch( |
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.
this is slightly different than how we do this with assets. With assets, we send over query params for the asset and destination. The view decodes them and sets them in Redux
I thought it was a bit cleaner to set all these params at once directly into redux
| </div> | ||
| </div> | ||
| )} | ||
| <CollectibleInfo |
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.
All of these components will be reused in the Send flow
| return name || `Token #${tokenId}`; | ||
| }; | ||
|
|
||
| export const CollectibleInfoBlock = ({ |
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.
most of these components are ported over from the CollectibleDetail view
| <div className="SendAmount__collectible-display"> | ||
| <SelectedCollectible goToChooseDest={goToChooseDest} /> | ||
| </div> | ||
| ) : ( |
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 show the Collectible or the Amount selector
| }; | ||
| }; | ||
|
|
||
| function useSimulateTxData({ |
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.
this hook is similar to the simulateTx hook used by sending a token
| return ( | ||
| <div | ||
| className="CollectiblesList__collection" | ||
| key={title} |
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 a unique key? I'd suggest ${collection.collectionAddress}-${collection.tokenId}
extension/src/popup/components/sendCollectible/SelectedCollectible/hooks/useSimulateTxData.ts
Show resolved
Hide resolved
| xdr={simulationState.data?.transactionXdr!} | ||
| xdr={ | ||
| isCollectible | ||
| ? collectibleSimulationState.data?.transactionXdr! |
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.
it shouldn't be necessary to assert these as non-null since the data hook gives us a way to narrow the type down to a success or error before the render happens. It would be safer to explicitly handle these states since TransactionConfirm expects that data in a non nullable way.
extension/src/popup/components/account/CollectibleDetail/index.tsx
Outdated
Show resolved
Hide resolved
63b28b2 to
bba1d4c
Compare
* Reapply "add collectibles to the Send flow" This reverts commit be2a075. * fix incorrect fee * code cleanup * pr comments * check for found collectible * add unit tests
Closes #2329
This adds collectibles to Freighter's internal send flow. Users can send a collectible by either using the Send button on the Account view or they can use the Send button from the detail view. This makes sure to handle the UI for both collectibles that have metadata properly configured and those that do not.
I spent a good amount of time thinking through how we can add this flow to the app in a way that makes sense. My 2 main options were to either 1) make a new, separate view that implements its own standalone flow (similar to how Swap is separate from SendPayment) or 2) add a configuration in the existing SendPayment flow that toggles on/off some collectibles elements when needed.
I decided to do the latter for a few reasons. Ultimately, sending a collectible is so similar to sending a payment, there was going to be a lot of duplication making a separate flow. In both flows,
In addition, because of CAP-67, memo validation is about to get a bit more complex. I'd like to be able to easily keep memo validation in sync between tokens/collectibles. Finally, sending collectibles doesn't really have its own standalone flow, begin to end. You can only send a collectible by starting a token payment flow. The UX flow is a branch off the existing token Send flow.
The downside is we have a few spots with
isCollectiblechecks, but I tried to keep it as minimal and as clean as possibleVIDEO EXAMPLES:
Sending a collectible for a collectible with metadata
Screen.Recording.2025-12-19.at.5.42.06.PM.mov
Sending a collectible for a collectible without metadata
Screen.Recording.2025-12-19.at.8.05.23.PM.mov
An empty state for an account with no collectibles. This mirrors the empty state for assets:
