Skip to content

Vivek Yadav Wallet Transfer Assignment - #115

Open
vy8655-dev wants to merge 3 commits into
Robustrade:mainfrom
vy8655-dev:feat/Vivek_Yadav_Synechron
Open

Vivek Yadav Wallet Transfer Assignment#115
vy8655-dev wants to merge 3 commits into
Robustrade:mainfrom
vy8655-dev:feat/Vivek_Yadav_Synechron

Conversation

@vy8655-dev

Copy link
Copy Markdown

Wallet Transfer — Pull Request Description

Summary

This PR implements a minimal wallet-to-wallet transfer service in Go with the following guarantees:

  • API-level idempotency when idempotencyKey is provided
  • Atomic transfers: wallet balances, transfer state, and double-entry ledger write in a single DB transaction
  • Double-entry ledger (one DEBIT, one CREDIT per transfer)
  • Concurrency safety to prevent double-spend via an atomic conditional debit
  • A thin HTTP handler (POST /transfers), a service layer for orchestration, and a repository layer for DB access

AI disclosure

  • Tool used: GitHub Copilot Chat (assistant powered by GPT-5 mini).
  • How used: I used the assistant interactively to scaffold the project, write migrations, repository functions, service logic, handler, and tests. The assistant helped iterate on tests and fixes until the suite passed.
  • Prompts / interactions (high-level):
    • "Act as an expert Go developer. Your task is to build a robust, concurrently safe financial transfer service using Go. You must ensure clean architecture, proper error handling, and production-ready code."
    • "Scaffold Go project with go.mod and sqlite3 dependency"
    • "Add DB migrations and models for wallets, transfers, ledger_entries, idempotency_records"
    • "Implement repository methods for wallets, transfers, ledger entries, and idempotency"
    • "Implement service Transfer workflow with idempotency and transactional balance updates"
    • "Add HTTP handler for POST /transfers and tests"
    • "Write tests for transfer, idempotency, concurrency"
    • "Fix build/test issues and ensure tests pass"

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:

  • Foreign keys enforce referential integrity.
  • Balances stored as integers (cents). Avoid floats.
  • Recommended production indexes: ledger_entries(wallet_id), unique index on idempotency_records(idempotency_key) (already primary key).

Idempotency Strategy

  • Client provides idempotencyKey in request.
  • Service quick-checks idempotency_records for COMPLETED and returns stored transfer_id if present.
  • Otherwise service attempts to insert an IN_PROGRESS idempotency record inside the same transaction that creates the transfer; on success it marks COMPLETED and stores transfer_id.
  • If insert fails because another worker claimed the key, the service polls idempotency_records until status becomes COMPLETED and returns the recorded result.
  • Note: polling is simple for this assignment; in production prefer upsert + read or unique constraint + returning stored response to avoid polling.

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:

    • inserts the transfers row (PENDING),
    • applies credit to destination,
    • inserts two ledger entries (DEBIT and CREDIT),
    • marks transfers -> PROCESSED, and
    • completes idempotency record.
  • Because 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

  1. Build & run server:

    go run .
  2. Seed wallets (SQLite file wallets.db created automatically):

    sqlite3 wallets.db "INSERT INTO wallets (id, balance) VALUES ('wallet_1', 1000);"
    sqlite3 wallets.db "INSERT INTO wallets (id, balance) VALUES ('wallet_2', 100);"
  3. Send a transfer:

    curl -X POST http://localhost:8080/transfers \
      -H 'Content-Type: application/json' \
      -d '{"idempotencyKey":"abc123","fromWalletId":"wallet_1","toWalletId":"wallet_2","amount":100}'
  4. Run the included end-to-end script:

    chmod +x e2e.sh
    ./e2e.sh

How to Test

  • Unit & integration tests:
    • go test ./...
  • Coverage:
    • go test -covermode=count -coverprofile=coverage.out ./...
    • go tool cover -func=coverage.out and go tool cover -html=coverage.out -o coverage.html

Tradeoffs / Assumptions

  • Stored wallet balances (fast reads) vs deriving balance from ledger (canonical): chosen stored balances updated transactionally for simplicity and performance in this assignment.
  • Idempotency uses claim + polling for simplicity. Production should use unique constraints + UPSERT and return stored response.
  • SQLite specifics: tests restrict connections (SetMaxOpenConns(1)) to avoid SQLite write locking nondeterminism; production should use Postgres with row locks or SERIALIZABLE isolation for high concurrency.
  • No external queueing or distributed transaction system implemented — out of scope.

Checklist

  • Tests pass (go test ./...)
  • Format (gofmt) applied
  • Lint passed (run golangci-lint if desired)
  • README updated
  • Added e2e.sh script for demo

Next steps (optional)

  • Replace idempotency polling with an UPSERT-based idempotency store.
  • Add POST /wallets and GET /wallets/:id/balance endpoints.
  • Add reconciliation job: verify wallets.balance == sum(ledger_entries) per wallet.
  • Add observability: structured logs, metrics for retries/failures, and tracing.

Copilot AI review requested due to automatic review settings July 11, 2026 17:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.sh demo 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

Comment thread service.go
Comment thread service.go
Comment thread service.go
Comment thread service.go
Comment thread service.go
Comment thread service.go
Comment thread repository.go
Comment thread handler.go Outdated
Comment thread service.go
Comment thread service.go
vy8655-dev and others added 2 commits July 11, 2026 22:47
… same account

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants