fix: add POST /api/donations/submit endpoint#87
Merged
ayshadogo merged 1 commit intoJun 24, 2026
Merged
Conversation
Resolves Dfunder#69. - Adds src/api/{mod,error,server,handlers}.rs implementing the endpoint that accepts a signed Soroban TransactionEnvelope XDR, submits it via the RPC client, polls for terminal status, and persists confirmed donations. - Introduces a SorobanRpc async trait in src/soroban/rpc_client.rs so handlers can be unit-tested with a mock implementation. - Wraps DonationsRepo.connection in std::sync::Mutex<Connection> (rusqlite::Connection is !Sync) so AppState is Send+Sync for axum. - Wires main.rs to bootstrap the axum server over HTTP_BIND_ADDR (default 0.0.0.0:8080) using DATABASE_PATH (default ./stellar-aid.db). - Extends StellarAidError with a DatabaseError variant and From impls for RpcError / DbError so API-layer error mapping is uniform. - 17 new tests cover the happy path, short-circuit on send.status==Failed, polling timeout, every validation rule, and the test-public-key round trip.
ayshadogo
approved these changes
Jun 24, 2026
ayshadogo
left a comment
Contributor
There was a problem hiding this comment.
This Looks Good
Job Well Done '🤝
5 tasks
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.
Summary
Implements
POST /api/donations/submit, a new HTTP endpoint that accepts a signed Soroban donation transaction, submits it to the Soroban RPC, polls for terminal status, and persists aconfirmeddonation record in SQLite.Closes #69.
Changes
campaign_id, numericamount, valid Stellar strkey viastellar-strkey), submits viaSorobanRpc::send_transaction, short-circuits on synchronousFailed, polls up to 10 attempts at 1-second intervals, persists aconfirmedrow onSuccess, and returns 200 / 202 / 400 / 500 with a structured JSON body.SorobanRpcasync trait and implements it forSorobanRpcClientso handlers can be unit-tested with a mock.Connectionin astd::sync::Mutex(rusqlite’sStatementCachemakes the raw connection!Sync, blockingaxum’sSend + Syncrequirement). Adds#[derive(Clone)]toNewDonation. Public API unchanged. Adds aSend + Synctest.DatabaseErrorvariant andFrom<RpcError>/From<DbError>impls so the API layer has a uniform error model.axumserver onHTTP_BIND_ADDR(default0.0.0.0:8080) withDATABASE_PATH(default./stellar-aid.db) and the productionAppState. Keeps the original config-validation path so missing env vars fail fast at startup.axum = "0.7",async-trait = "0.1", and dev-depstower = "0.5"/http-body-util = "0.1"; switchestokiofeatures tofullso the new server can bind TCP.Testing
src/api/handlers.rscover the happy-path persist + 200 response, synchronousFailedshort-circuit (assertsget_transaction_statusis never called), polling-budget exhaustion → 202pending, every validation rule (empty XDR / zero campaign id / non-numeric or zero amount / invalid donor address), and a real Stellar ed25519 public-key round-trip viastellar-strkey.cargo fmt --all,cargo clippy --all-targets,cargo build --all-features, andcargo test --all-featuresall pass on the root crate (94/94 tests).confirmed/failed/pendingmatches Issue Build Donation Submission Endpoint (Rust HTTP) #69’s spec.Notes
donor_user_idfield remainsNone; the existingDonationsRepo.get_campaign_donationsalready renders such records asAnonymous Donor. A follow-up PR can wire auth +donor_user_idlinking.services::donation_verifieris intentionally not called in this PR (out of scope per Issue Build Donation Submission Endpoint (Rust HTTP) #69); aTODO(post-merge)comment insrc/api/handlers.rsflags where it would slot in.