{"id":50794392,"url":"https://github.com/squall-chua/go-ledger-microservice","last_synced_at":"2026-06-12T13:31:58.015Z","repository":{"id":342182964,"uuid":"1173022342","full_name":"squall-chua/go-ledger-microservice","owner":"squall-chua","description":"A highly reliable, double-entry accounting ledger microservice. This project takes significant inspiration from ledger-cli (https://ledger-cli.org), the powerful, command-line accounting tool. Specifically, it brings the fundamental philosophies of `ledger-cli` into a modern microservice.","archived":false,"fork":false,"pushed_at":"2026-05-31T11:55:38.000Z","size":327,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T13:20:02.138Z","etag":null,"topics":["double-entry-accounting","golang","grpc","ledger","ledger-cli","microservice","restful-api"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/squall-chua.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-04T23:44:32.000Z","updated_at":"2026-05-31T11:55:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/squall-chua/go-ledger-microservice","commit_stats":null,"previous_names":["squall-chua/go-ledger-microservice"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/squall-chua/go-ledger-microservice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squall-chua%2Fgo-ledger-microservice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squall-chua%2Fgo-ledger-microservice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squall-chua%2Fgo-ledger-microservice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squall-chua%2Fgo-ledger-microservice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/squall-chua","download_url":"https://codeload.github.com/squall-chua/go-ledger-microservice/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squall-chua%2Fgo-ledger-microservice/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34247461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["double-entry-accounting","golang","grpc","ledger","ledger-cli","microservice","restful-api"],"created_at":"2026-06-12T13:31:57.823Z","updated_at":"2026-06-12T13:31:58.005Z","avatar_url":"https://github.com/squall-chua.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go Ledger Microservice\n\nA highly reliable, double-entry accounting ledger microservice.\n\n## Inspired by ledger-cli\nThis project takes significant inspiration from [ledger-cli](https://ledger-cli.org/), the powerful, command-line accounting tool. Specifically, it brings the fundamental philosophies of `ledger-cli` into a modern microservice:\n\n- **Double-Entry Accounting Principles:** Every transaction must perfectly balance to zero (i.e. debits must equal credits).\n- **Familiar CLI Experience:** The included client tool deliberately mimics standard `ledger-cli` subcommands like `balance`, `register`, and `post`.\n- **Hierarchical Naming Structure:** Accounts use colon-delimited paths (e.g., `Assets:Checking`, `Expenses:Groceries`), allowing hierarchical roll-up of balances.\n- **Native Multi-Currency Support:** Amounts are paired with their currency identifiers (e.g., `1000USD`, `250MYR`), ensuring accuracy across varied financial flows.\n- **Immutability and Auditability:** Emulating appending to a journal file, transactions are recorded as an immutable sequence of events, accurately affecting a running balance.\n\nWhile `ledger-cli` operates entirely on local text files, this microservice scales those principles to a gRPC/HTTP backend architecture with robust SQL and MongoDB persistence layers, suited for multi-user distributed systems.\n\n## How to use the CLI\n\nThe project includes a CLI located in `./cmd/cli` that can be run natively to interact directly with the datastore. By default, it connects to a local SQLite database (`ledger.db`) but supports PostgreSQL, MySQL, and MongoDB via environment variables.\n\n### Available Commands\n\n*   `post`: Record a new transaction (requires note and at least 2 balanced postings).\n*   `balance` / `bal`: Get account balances.\n*   `register` / `reg`: List transactions and their running balances.\n\n## Detailed Steps for Manual Tests\n\nYou can perform manual testing of the ledger's core functionality via the CLI using the following steps:\n\n### 1. Record Initial Transactions\nYou can use the `post` command to record your transactions. Pass an arbitrary note/description, followed by the postings. The postings are constructed as `[account_name]:[amount][currency]`.\n\nCreate an initial balance:\n```bash\ngo run ./cmd/cli post \"Initial Deposit\" \"Assets:Checking:1000USD\" \"Equity:OpeningBalances:-1000USD\"\n```\n\nRecord an expense:\n```bash\ngo run ./cmd/cli post \"Purchase Groceries\" \"Expenses:Grocery:150.50USD\" \"Assets:Checking:-150.50USD\"\n```\n\n*Note: For these commands to succeed, their values must sum exactly to 0 (Double-entry principle).*\n\n### 2. View Account Balances\nUse the `balance` command to view the aggregated sum of all accounts.\n\n```bash\ngo run ./cmd/cli balance\n```\n\n**Expected output:**\n```\nASSETS:*:Checking    849.50 USD (Updated: 2026-03-04T15:38:59Z)\nEXPENSES:*:Grocery   150.50 USD (Updated: 2026-03-04T15:39:20Z)\n*:*:OpeningBalances  -1000 USD (Updated: 2026-03-04T15:38:59Z)\n```\n\nYou can optionally filter by a specific account prefix or currency:\n```bash\ngo run ./cmd/cli balance Assets\ngo run ./cmd/cli balance -c USD\n```\n\n### 3. Check the Transaction Register\nUse the `register` command to see the chronological transaction history. It tracks the running balances for each posting. \n\n```bash\ngo run ./cmd/cli register\n```\n\n**Output snippet:**\n```\n2026-03-04 15:38:59+08 - Initial Deposit\n    ASSETS:*:Checking          1000 USD   (=       1000 USD)\n    *:*:OpeningBalances       -1000 USD   (=      -1000 USD)\n2026-03-04 15:39:20+08 - Purchase Groceries\n    EXPENSES:*:Grocery       150.50 USD   (=     150.50 USD)\n    ASSETS:*:Checking       -150.50 USD   (=     849.50 USD)\n```\n\nTo list the latest transactions first, use the desc (descending) flag:\n```bash\ngo run ./cmd/cli register -d\n```\n\n### 4. Verify Double-Entry Constraint Rejections\nYou should test failure modes manually to ensure validity checks reject broken entries.\n\n**Unbalanced Transaction error:**\n```bash\ngo run ./cmd/cli post \"Unbalanced Post\" \"Assets:Checking:100USD\" \"Expenses:Food:-50USD\"\n# Log Output:\n# 2026/03/04 15:40:00 Error: Transaction is unbalanced (sum = 50)\n# exit status 1\n```\n\n**Parsing errors:**\n```bash\ngo run ./cmd/cli post \"Missing Colon\" \"Assets:Checking100USD\"\n# Log Output:\n# 2026/03/04 15:40:10 Invalid posting format: Assets:Checking100USD\n# exit status 1\n```\n\n## Server Setup \u0026 API Testing\n\nIn addition to the CLI, you can run the ledger directly as a gRPC/REST microservice. It uses the same persistent datastore. By default, it runs on port `8080`.\n\n### 1. Start the Server\n\n```bash\ngo run ./cmd/server/main.go --port 8080 --db-type sqlite --sql-dsn ledger.db\n```\n\n*Note: The server uses an inline multiplexer so both gRPC and HTTP/REST requests are served on the same port (`8080`).*\n\n### 2. Manual Testing using curl\n\nThe API endpoints are secured by JWT authentication. For local testing, you can manually generate a JWT token at [https://jwt.io/](https://jwt.io/).\n\n1. Go to **jwt.io** and ensure the Algorithm is set to `HS256`.\n2. Set the Payload (Data) to include the required roles:\n   ```json\n   {\n     \"sub\": \"test-user\",\n     \"roles\": [\"admin\", \"user\"]\n   }\n   ```\n3. Set the Verify Signature secret to the server's default symmetric key: `super-secret-key`.\n4. Copy the generated encoded token on the left panel and export it in your terminal:\n\n```bash\nexport LEDGER_TOKEN=\"your_generated_token_here\"\n```\n\n#### Record a Transaction\n\nHere is a `curl` example corresponding to the `post` CLI command:\n\n```bash\ncurl -X POST http://localhost:8080/v1/ledger/transactions \\\n  -H \"Authorization: Bearer $LEDGER_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"note\": \"Online purchase via API\",\n    \"postings\": [\n      {\n        \"account\": { \"type\": 5, \"name\": \"OnlineShopping\" },\n        \"amount\": { \"currencyCode\": \"MYR\", \"units\": 50, \"nanos\": 0 }\n      },\n      {\n        \"account\": { \"type\": 1, \"name\": \"wallet\" },\n        \"amount\": { \"currencyCode\": \"MYR\", \"units\": -50, \"nanos\": 0 }\n      }\n    ]\n  }'\n```\n\n#### Get Account Balance\n\nRetrieve all balances with an empty query struct. \n\n```bash\ncurl -X POST http://localhost:8080/v1/ledger/accounts/balance \\\n  -H \"Authorization: Bearer $LEDGER_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"account\": {}}'\n```\n\nTo limit it to a specific account root (e.g., all `ASSETS` - numerical enum `1` in proto):\n```bash\ncurl -X POST http://localhost:8080/v1/ledger/accounts/balance \\\n  -H \"Authorization: Bearer $LEDGER_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"account\": { \"type\": 1 }\n  }'\n```\n\n## Running the Web UI\n\nThe project now includes a beautiful, modern Nuxt.js 3 Web UI that allows you to interact with the Ledger microservice dynamically in your browser. It natively supports Dark Mode.\n\n### 1. Setup \u0026 Installation\nEnsure you have `Node.js` installed. The UI is located in the `webui` folder.\n\n```bash\ncd webui\nnpm install\n```\n\n### 2. Start the Development Server\nMake sure your Go Ledger microservice backend is running concurrently on port `8080` (as shown above).\n\n```bash\n# Inside the webui folder\nnpm run dev\n```\n\nThe Web UI will be accessible at **http://localhost:3000**. The Nuxt application is configured with a Nitro proxy (`/api/**` -\u003e `http://127.0.0.1:8080/**`) to seamlessly connect to the backend API without CORS issues.\n\n### 3. Using the Web UI\n\n1. **Authentication:**\n   When you first load the App, you will be directed to `/login`. Generate a JWT token via `jwt.io` (as explained in the *API Testing* section) with the `admin` role, and paste it into the UI login form. The UI will store your token securely in `localStorage`.\n2. **Dashboard Overview (`/`)**: \n   View high-level totals grouping all Assets, Revenues, and Expenses into intuitive cards.\n3. **Account Balances (`/balances`)**:\n   View a clean data-table of all hierarchical accounts in your ledger and their current running balances with currency indicators.\n4. **Transaction Register (`/transactions`)**:\n   A chronological timeline of every transaction recorded, displaying the descriptive note alongside its multi-layered postings.\n5. **Record Transaction Form (`/transactions/new`)**:\n   An interactive form ensuring double-entry principles. You can add as many debit/credit postings as required, and the UI will validate that the running sum equals zero before allowing you to commit the transaction to the backend.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsquall-chua%2Fgo-ledger-microservice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsquall-chua%2Fgo-ledger-microservice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsquall-chua%2Fgo-ledger-microservice/lists"}