Implement Go wallet transfer service#112
Open
vardaanmittal09 wants to merge 3 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
Implements a Go-based wallet transfer HTTP service backed by GORM + SQLite, aiming to provide idempotent transfer creation, stored wallet balances, and double-entry ledger entries with basic concurrency safety.
Changes:
- Added transfer creation/read APIs with layered handler/service/store design.
- Implemented SQLite persistence (AutoMigrate schema + transactional debit/credit + ledger writes) and behavioral tests for core scenarios including concurrent debits.
- Updated CI workflow to run
go vet,gofmtcheck, andgo test, and expanded repository documentation/design notes.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds run/test instructions and implementation notes for the Go service. |
| internal/service/transfer.go | Core transfer orchestration: validation, idempotency handling, transactional balance + ledger updates. |
| internal/service/transfer_test.go | Behavioral tests for processing, idempotency, failures, and concurrent overspend prevention. |
| internal/repository/sqlite/store.go | GORM store/transaction wrapper + wallet/transfer/ledger/idempotency persistence operations. |
| internal/repository/sqlite/models.go | SQLite schema models and domain mappers (tables + constraints). |
| internal/port/transfer.go | Defines store/transaction interfaces used by the service layer. |
| internal/handler/http.go | HTTP routing and JSON error/status mapping for transfer/wallet endpoints. |
| internal/domain/models.go | Domain models and state/ledger enums. |
| internal/domain/errors.go | Domain error definitions used across layers. |
| go.mod | Introduces Go module + GORM/SQLite dependencies. |
| docs/DESIGN.md | Documents API contract, persistence approach, idempotency, and concurrency strategy. |
| cmd/server/main.go | Wires up DB, migrations, seeding, and HTTP server startup. |
| AI_USAGE.md | Records AI tool usage disclosure for the work. |
| .github/workflows/ci.yml | Updates CI to install gcc, enable CGO, and run vet/format/tests with Go. |
Comment on lines
+1
to
+8
| module github.com/vardaanmittal09/wallet-transfer-assignment | ||
|
|
||
| go 1.24 | ||
|
|
||
| require ( | ||
| gorm.io/driver/sqlite v1.6.0 | ||
| gorm.io/gorm v1.30.0 | ||
| ) |
Comment on lines
+243
to
+248
| func newID(prefix string) string { | ||
| var bytes [16]byte | ||
| if _, err := rand.Read(bytes[:]); err != nil { | ||
| panic(fmt.Sprintf("generate id: %v", err)) | ||
| } | ||
| return prefix + "_" + hex.EncodeToString(bytes[:]) |
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.
Summary
Implemented a Go wallet transfer service with GORM-backed SQLite persistence, layered architecture, idempotent transfer creation, stored wallet balances, double-entry ledger entries, and behavioral tests for core transfer scenarios.
AI disclosure
Tool used: OpenAI Codex in the Codex desktop app.
How I used it: I used Codex as a pair-programming assistant to inspect the assignment, create the solution branch, scaffold the Go service, implement the layered design, write tests, and prepare documentation. I reviewed the generated implementation decisions and kept the scope focused on idempotency, ledger consistency, and concurrency control.
Prompts used:
connect with my githubwe will do this in go make branch as Wallet Transfer Assignment Repository ... Your PR branch should be named: solution/<your-name> (e.g., solution/jane-doe).do againTranscript note: The full interactive transcript is available in the Codex desktop thread. I also added
AI_USAGE.mdwith the tool, usage summary, and prompts.Schema Design
The SQLite schema is defined through GORM repository models and
AutoMigrate. It introduces:wallets: wallet id, stored integer balance, timestamps, andCHECK (balance >= 0).transfers: transfer id, idempotency key, source/destination wallet ids, amount, state, failure reason, timestamps, and state/amount checks.ledger_entries: one debit and one credit row per processed transfer, with type and amount checks, foreign keys to wallets/transfers, andUNIQUE (transfer_id, type).idempotency_records: unique idempotency key, canonical request hash, original transfer id, and a foreign key back to transfers.Indexes were added for ledger lookup by transfer and wallet.
Idempotency Strategy
POST /transfersrequires anidempotencyKey. The service stores the key and a SHA-256 hash of the canonical request payload inside the same database transaction as the transfer.replay: true.409 Conflict.Concurrency Strategy
Each transfer runs in a serializable SQLite transaction. The store uses one open database connection plus SQLite busy timeout, so writes are serialized for this small service. The debit operation also uses a guarded update:
That guarded update prevents overspending even when multiple transfers target the same source wallet. Terminal state updates also require
state = 'PENDING', making retries safe.How to Run
github.com/mattn/go-sqlite3.go run ./cmd/server.HTTP_ADDR=:9090 DB_PATH=/tmp/wallets.db go run ./cmd/server.POST /transfers.GET /wallets/{id}andGET /transfers/{id}.How to Test
go test ./....go vet ./...,gofmtcheck, andgo test ./....Tradeoffs / Assumptions
goon PATH, so I could not run the Go test suite locally before pushing. The tests and CI workflow are included for verification in an environment with Go installed.Checklist