Open
Conversation
…and the ramp/deposit feature flow
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR implements the private withdraw flow, allowing users to withdraw assets
from a Privacy Channel directly to an external Stellar G account address. The
implementation follows the same patterns as the send flow and aligns with the
sandbox reference implementation, including a dedicated confirmation screen with
a preview of WITHDRAW, CREATE (change), and SPEND operations before submission.
Overview
Users can now withdraw funds from a private channel to an external Stellar G
account address by specifying:
splitting
The system will:
UtxoBasedStellarAccountspecified G account
Features
Withdraw Form (
WithdrawPage)Withdraw Confirmation (
WithdrawConfirmationPage)Home Integration
Technical Changes
Backend
Handler:
src/background/handlers/private/withdraw.tsStrKey.isValidEd25519PublicKeyUtxoBasedStellarAccountselectUTXOsForTransferwith a random strategy and retry logicCREATEs)
partitionAmountRandomtorandomize change distribution
WITHDRAW operation and change CREATE operations
PrivacyProviderClientprepareWithdrawOperationsfunction for theprepare/preview flow
"Prepare" handler:
handlePrepareWithdrawprepareWithdrawOperationsto:operationsMLXDRarray ready for submissionCREATEs/SPENDs
Types:
src/background/handlers/private/withdraw.types.tsWithdrawRequest: network, channelId, providerId, accountId,destinationAddress, amount, entropyLevel, optional
preparedOperationsMLXDRWithdrawResponse: ok, id, hash, errorPrepareWithdrawRequest: same shape asWithdrawRequest(without preparedoperations)
PrepareWithdrawResponse: ok,withdrawOperation,changeOperations,spendOperations,operationsMLXDR, totals/counters, errorMessage system:
src/background/messages.tsMessageType.Withdraw = "WITHDRAW"MessageType.PrepareWithdraw = "PREPARE_WITHDRAW"WithdrawRequest/WithdrawResponseandPrepareWithdrawRequest/PrepareWithdrawResponseBackground router:
src/background/handler.tshandleWithdrawforMessageType.WithdrawhandlePrepareWithdrawforMessageType.PrepareWithdrawFrontend
API services:
src/popup/api/withdraw.tswithdraw(params: WithdrawRequest): Promise<WithdrawResponse>MessageType.WithdrawprepareWithdraw(params: PrepareWithdrawRequest): Promise<PrepareWithdrawResponse>MessageType.PrepareWithdrawState management:
src/popup/hooks/state.tsxwithdrawwithdraw-confirmationwithdrawFormData?: { channelId, providerId, destinationAddress, amount, entropyLevel }withdrawResult?: { withdrawOperation, changeOperations, spendOperations, operationsMLXDR, totalSpendAmount, changeAmount, withdrawAmount, numSpends, numCreates }goWithdraw(channelId?, providerId?)goWithdrawConfirmation()setWithdrawFormData(data)setWithdrawResult(data)clearWithdrawData()Pages:
src/popup/pages/withdraw-page.tsxStrKey.isValidEd25519PublicKeyprepareWithdraw()on "Review Withdraw":withdrawFormDatain statePrepareWithdrawwithdrawResult(operations and summary) in statewithdraw-confirmationsrc/popup/pages/withdraw-confirmation-page.tsxwithdrawFormDataandwithdrawResultfrom state1 WITHDRAW operation, <numSpends> SPEND operations, <numCreates> CREATE operationswithdraw()withpreparedOperationsMLXDRfromwithdrawResultRouter:
src/popup/app.tsxwithdrawandwithdraw-confirmationHome integration:
src/popup/templates/home-template.tsxonStartWithdrawcallback prop for the private Withdraw buttonsrc/popup/pages/home-page.tsxonStartWithdraw={(channelId, providerId) => actions.goWithdraw(channelId, providerId)}Implementation Details
Entropy mapping:
Slots are allocated between:
UTXO selection:
UtxoBasedStellarAccount.selectUTXOsForTransfer(totalToSpend, "random")UTXOs
Change distribution:
partitionAmountRandomto randomly split change across reserved changeUTXOs
Withdraw conditions:
operation
Operation order:
Expiration handling:
latestLedger.sequence + 1000for SPEND signingError handling:
LOCKED,NOT_FOUND,INVALID_ADDRESS,INSUFFICIENT_BALANCE,INVALID_SESSION,AUTH_FAILED,WITHDRAW_FAILED,PREPARE_WITHDRAW_FAILED)PrivacyProviderAuthErrorFiles Changed
New / Significantly Updated Backend Files:
src/background/handlers/private/withdraw.types.tssrc/background/handlers/private/withdraw.tsBackend Integration:
src/background/messages.ts— AddedWithdrawandPrepareWithdrawmessagetypes and mappings
src/background/handler.ts— RegisteredhandleWithdrawandhandlePrepareWithdrawNew / Updated Frontend Files:
src/popup/api/withdraw.tssrc/popup/pages/withdraw-page.tsxsrc/popup/pages/withdraw-confirmation-page.tsxState & Routing:
src/popup/hooks/state.tsx— Added withdraw routes and state(
withdrawFormData,withdrawResult)src/popup/app.tsx— Addedwithdrawandwithdraw-confirmationroutehandling
Home Integration:
src/popup/templates/home-template.tsx— Added withdraw action propsrc/popup/pages/home-page.tsx— Wires withdraw button togoWithdrawTesting Notes
Form validation
checks
Prepare flow
prepareWithdrawwith valid G account address and various entropylevels
withdrawOperation,changeOperations, andspendOperationsarepopulated
operationsMLXDRlength matches1 + numCreates + numSpends(1 forWITHDRAW)
totalSpendAmount,changeAmount,withdrawAmount) make senseConfirmation UI
channel)
Execution
preparedOperationsMLXDRis submitted (no re-preparation)Navigation
Edge cases
Future Enhancements
available)