Vivek Yadav Wallet Transfer Assignment - #115
Open
vy8655-dev wants to merge 3 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
Implements a minimal Go wallet-to-wallet transfer service backed by SQLite, aiming to provide idempotent POST /transfers semantics, transactional balance updates, and a double-entry ledger.
Changes:
- Added service/repository layers for transfers, idempotency records, and ledger entries.
- Added HTTP handler + server wiring for
POST /transfers. - Added migrations, tests (including concurrency/idempotency scenarios), and an
e2e.shdemo script; updated README/gitignore; removed CI/SonarQube workflows and PR templates.
Reviewed changes
Copilot reviewed 18 out of 21 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| service.go | Core transfer workflow (tx + idempotency + ledger) |
| repository.go | DB access methods for wallets, transfers, ledger, idempotency |
| handler.go | POST /transfers HTTP endpoint |
| main.go | SQLite open/migrate + server startup |
| migrations.go | Creates wallets/transfers/ledger_entries/idempotency_records tables |
| models.go | Data model structs |
| service_test.go | Basic transfer/idempotency/concurrency tests |
| service_extra_test.go | Additional idempotency + insufficient funds + server creation tests |
| handler_test.go | HTTP handler tests |
| README.md | Run/test instructions and expected behaviors |
| e2e.sh | End-to-end demo script |
| go.mod / go.sum | Go module + sqlite dependency |
| .gitignore | Ignore coverage artifacts |
| .github/workflows/sonarqube.yml | Removed workflow |
| .github/workflows/ci.yml | Removed workflow |
| .github/pull_request_template.md | Removed template |
| .github/copilot-instructions.md | Removed instructions file |
| .github/CODEOWNERS | Removed codeowners |
… same account Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
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.
Wallet Transfer — Pull Request Description
Summary
This PR implements a minimal wallet-to-wallet transfer service in Go with the following guarantees:
idempotencyKeyis providedPOST /transfers), a service layer for orchestration, and a repository layer for DB accessAI disclosure
Schema Design
wallets(id TEXT PK, balance INTEGER NOT NULL, created_at DATETIME)transfers(id TEXT PK, from_wallet_id TEXT FK->wallets, to_wallet_id TEXT FK->wallets, amount INTEGER, state TEXT, created_at DATETIME)ledger_entries(id INTEGER PK AUTOINC, wallet_id TEXT FK->wallets, transfer_id TEXT FK->transfers, type TEXT (DEBIT|CREDIT), amount INTEGER, created_at DATETIME)idempotency_records(idempotency_key TEXT PK, transfer_id TEXT, status TEXT (IN_PROGRESS|COMPLETED), response TEXT, created_at DATETIME)Constraints & notes:
ledger_entries(wallet_id), unique index onidempotency_records(idempotency_key)(already primary key).Idempotency Strategy
idempotencyKeyin request.idempotency_recordsforCOMPLETEDand returns storedtransfer_idif present.IN_PROGRESSidempotency record inside the same transaction that creates the transfer; on success it marksCOMPLETEDand storestransfer_id.idempotency_recordsuntil status becomesCOMPLETEDand returns the recorded result.Concurrency Strategy
The critical step is the conditional atomic debit implemented by:
UPDATE wallets SET balance = balance - ? WHERE id = ? AND balance >= ?This update only succeeds if sufficient funds exist. It is executed inside the same DB transaction that:
transfersrow (PENDING),transfers->PROCESSED, andBecause all side effects occur in one transaction, either everything commits or nothing does, preventing half-applied transfers and double-spend.
Tests include a concurrent debit stress test that asserts only available funds are consumed.
How to Run
Build & run server:
go run .Seed wallets (SQLite file
wallets.dbcreated automatically):Send a transfer:
Run the included end-to-end script:
How to Test
go test ./...go test -covermode=count -coverprofile=coverage.out ./...go tool cover -func=coverage.outandgo tool cover -html=coverage.out -o coverage.htmlTradeoffs / Assumptions
SetMaxOpenConns(1)) to avoid SQLite write locking nondeterminism; production should use Postgres with row locks or SERIALIZABLE isolation for high concurrency.Checklist
go test ./...)golangci-lintif desired)e2e.shscript for demoNext steps (optional)
POST /walletsandGET /wallets/:id/balanceendpoints.wallets.balance == sum(ledger_entries)per wallet.