chores: implemented the transfer of p2p and external movement#90
Merged
anonfedora merged 3 commits intoFracverse:masterfrom Feb 26, 2026
Merged
chores: implemented the transfer of p2p and external movement#90anonfedora merged 3 commits intoFracverse:masterfrom
anonfedora merged 3 commits intoFracverse:masterfrom
Conversation
Contributor
Author
|
@anonfedora please check and review asap!!! |
anonfedora
approved these changes
Feb 26, 2026
anonfedora
approved these changes
Feb 26, 2026
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.
CLOSES #66
User-to-User Transfers (Protected)
Direct transfers between two BLINKS users are exposed via the Transfers API. These endpoints construct an unsigned Stellar transaction XDR that the client signs and submits, keeping funds non-custodial.
POST /transfers/transfers- Build an unsigned user-to-user transfer XDRGET /transfers/transfers/{id}- Get transfer details (skeletal, subject to extension)GET /transfers/transfers/{id}/status- Get transfer status (skeletal, subject to extension)POST /transfers/transfers– Build unsigned XDR for a direct transferPurpose
from_user_id) to another BLINKS user (to_user_id).Authentication
sub) and injected asAuthenticatedUserby the auth middleware.Request Body
{ "to_user_id": "alice", "amount": 1000000, "asset": "USDC", "memo": "Rent payment January" }to_user_id: Target BLINKS user identifier. Must correspond to an existing row in theuserstable.amount: Integer amount in the smallest unit for the given asset (e.g. 1 USDC = 1_000_000 if using 7 decimals). Must be> 0.asset: Logical asset code used by your application (e.g.USDC).memo(optional): Free-text memo attached to the logical transfer for downstream reconciliation and user UX.Validation Rules
amountmust be strictly greater than zero; otherwise the handler returns:400 BAD_REQUESTwitherror="VALIDATION_ERROR".to_user_idmust resolve to an existing user:IdentityService::get_user_by_id.404 NOT_FOUNDwitherror="NOT_FOUND".G.400 BAD_REQUESTwitherror="VALIDATION_ERROR"and message"Recipient has an invalid Stellar address".from_user_id) is taken from the authenticated JWT subject and resolved viaIdentityService::get_user_walletto obtain the sender’s Stellar address.Backend Flow
Implementation lives in
backend/src/http/transfers.rs:AuthenticatedUser(via middleware) to obtainfrom_user_id.IdentityServiceto:get_user_wallet) and derive the sender Stellar address.to_user_idinto aUserand obtain the recipient Stellar address.BuildTransactionDtowith:contract_id = "user_to_user_transfer"– a logical identifier for the user-to-user transfer contract or flow.method = "transfer"– the contract method being invoked.args– JSON-encoded argument list containing:from_user_id,from_addressto_user_id,to_addressasset,amountmemo(optional)SorobanService::build_transaction(dto)which returns a mock unsigned XDR string (in production this would be a real Stellar/Soroban transaction XDR).Uuid::new_v4()) and returns it alongside the unsigned XDR.Response
{ "id": "00000000-0000-0000-0000-000000000000", "from_user_id": "bob", "to_user_id": "alice", "amount": 1000000, "asset": "USDC", "status": "pending", "memo": "Rent payment January", "unsigned_xdr": "mock_xdr_invoke_user_to_user_transfer_transfer_[...]" }id: UUID generated server-side for this transfer request. Currently ephemeral until a full persistence layer for transfers is added.from_user_id: The authenticated user (JWT subject).to_user_id: Recipient BLINKS user ID.amount: Requested transfer amount.asset: Asset code.status: Currently fixed to"pending"to reflect that the transfer has not yet been signed or submitted.memo: Echoes the request memo, if provided.unsigned_xdr: Base64-encoded (mock) unsigned transaction XDR that the client must sign and submit to the Stellar network.Client Responsibilities
unsigned_xdrwith the user’s Stellar private key on the client side.idandmemofor user receipts and history views.