🏛 A scriptable financial ledger, designed to make it easy to model complex financial transactions

Numary Ledger test

Numary is a programmable financial ledger that wants to make building financial apps safe, fun and cheap.

Building financial software is both critical and notably hard. The same bugs are repeated again and again, paving the highway to catastrophes.

Numary wants to tackle this issue with a ledger that provides atomic multi-postings transactions and is programmable in Numscript, a built-in language dedicated to money movements. It will shine for apps that require a lot of custom, money-touching code such as:

  • E-commerce with complex payments flows, payments splitting, such as marketplaces
  • Company-issued currencies systems, e.g. Twitch Bits
  • In-game currencies, inventories and trading systems, e.g. Fortnite V-Bucks
  • Payment gateways using non-standard assets, e.g. learning credits
  • Local currencies and complementary finance

Getting started

Numary works as a standalone binary, the latest of which can be downloaded from the releases page. You can move the binary to any executable path, such as to /usr/local/bin.

example.num numary exec quickstart example.num # Get the balances of drivers:042 curl -X GET http://localhost:3068/quickstart/accounts/drivers:042 # List transactions curl -X GET http://localhost:3068/quickstart/transactions ">
numary server start

# Submit a first transaction
echo "
send [USD/2 599] (
  source = @world
  destination = @payments:001
)

send [USD/2 599] (
  source = @payments:001
  destination = @rides:0234
)

send [USD/2 599] (
  source = @rides:0234
  destination = {
    85/100 to @drivers:042
    15/100 to @platform:fees
  }
)
" > example.num

numary exec quickstart example.num

# Get the balances of drivers:042
curl -X GET http://localhost:3068/quickstart/accounts/drivers:042

# List transactions
curl -X GET http://localhost:3068/quickstart/transactions

Documentation

You can find the complete Numary documentation at docs.numary.com

Dashboard

control-screenshot

A simple dashboard is built in the ledger binary, to make it easier to visualize transactions. It can be started with:

numary ui

Alpha & Roadmap

Please note that is currently in Alpha for a few weeks. The goal of the Alpha is to start taking early feedback from the community.

During the Alpha,

  • Breaking changes can happen between releases
  • Critical bugs can be discovered
  • Documentation will be incomplete

Beyond Alpha, the roadmap is:

  • Alpha: Feedback & Refining
  • Beta: Stabilizing
  • RC: API Freeze
  • 1.0.0: 🎉
Owner
Numary
Making money programmable
Numary
Comments
  • Duplicate key violation on id when handling concurrent requests

    Duplicate key violation on id when handling concurrent requests

    Describe the bug I noticed when I benchmarked ledger, I sometimes would get a 200 response with no content in the response body, but the ledger logs would indicate: internal errors executing script: conflict error on reference.

    After doing some digging, the true cause is duplicate key value violates unique constraint "transactions_id_key" when inserting into transactions table (possibly same issue could be present with other tables too).

    The issue happens becomes you seem to be incrementing the ID in code, and not by using a db auto increment feature. Since there is no locking around this this kind of conflict is going to arise sooner or later when handling concurrent requests.

    To Reproduce Steps to reproduce the behavior: Just have a script/benchmarking tool do a few requests to ledger at the same time.

    For instance, I use Bombardier:

    bombardier -c 50 -m POST -f bench.json -d 10s http://localhost:3068/example/script
    

    Where bug.json can be any script posting, but for instance:

    {"plain":"vars {\n  monetary $money_authorized\n  account $destination\n}\n\nsend $money_authorized (\n  source = @world\n  // @user:c36a3385-d94e-485d-9ccd-3682507d0fc2:authorized:b394c68d-0e4b-4e09-a634-3449d054edd5\n  destination = 
    $destination\n)","vars":{"money_authorized":{"amount":2,"asset":"EUR/2"},"destination":"user:bf11c59beaca47cda9d477cd62181e55:authorized:47aa2ce0db61498bb02d9f0ca2728425"}}
    

    Expected behavior I expect a bunch of things:

    1. Ledger should be able to handle this case, worst case by locking when incrementing the id. But perhaps a better solution would be to use UUIDs as IDs in the database OR use the database auto increment feature
    2. For such kind of fatal issues that do still occur, he HTTP request should not yield a 200 OK response with an empty body, but probably a 500 error

    Environment:

    • Numary Version 1.8.0
  • feat(client): add generator config to generate Ledger java client

    feat(client): add generator config to generate Ledger java client

    Add generator config to generate Ledger java client

    I’ve tried to mimic what you did for the SDKs for other languages. There’s a few open things though which are probably best for Formance to pick up.

    • [ ] Formance needs to define release process (.github/workflows/release.yml.mustache) + create repo
    • [ ] Formance needs to define licenseName/licenseUrl (in additionalProperties)
    • [ ] Please define servers url in swagger.json so that when generating not the hardcoded “localhost” is used. This needs to be fixed before the SDK can really be used by others. Please see https://stackoverflow.com/a/72182063/1422070 for a good approach I believe
    • [ ] For some reason, a few classes are named like GetAccount200Response by default. I use inlineSchemaNameMappings setting to manually override this to a normal name (like GetAccountResponse). There are also classes for error status codes like GetAccount400Response, but although these are generated they are not used by other classes, so I don’t bother with renaming those at this time. But perhaps we can skip generation somehow?
    • [ ] Tests are generated but they don’t actually do anything. I can define some manual tests, just not sure what your strategy is here. Just define them manually and include them in the final repo? It seems that’s what you do for the Python SDK

    Type of change

    • [ ] Bug fix (non-breaking change which fixes an issue)
    • [X] New feature (non-breaking change which adds functionality)
    • [ ] Refactoring / Technical debt

    What parts of the code are impacted ?

    No direct impact, since the github workflows still need to be modified to call the generation task for Java.

    Checklist:

    • [X] My code follows the style guidelines of this project
    • [X] I have performed a self-review of my code
    • [ ] I have commented my code, particularly in hard-to-understand areas
    • [ ] I have made corresponding changes to the documentation
    • [ ] My changes generate no new warnings
    • [ ] I have added tests that prove my fix is effective or that my feature works
    • [X] New and existing unit tests pass locally with my changes
  • Numary UI not displaying any Data

    Numary UI not displaying any Data

    Hi there,

    i tried displaying the UI right now and it comes up with this: image

    there is data in the quickstart ledger: {"cursor":{"page_size":15,"has_more":false,"total":3,"remaning_results":0,"data":[{"address":"world","contract":"default"},{"address":"users:001","contract":"default"},{"address":"central_bank","contract":"default"}]},"ok":true}

  • Credit support?

    Credit support?

    Is your feature request related to a problem? Please describe. A way to represent negative amounts, i.e. deficiency of funds.

    Summary If the ledger is used to mirror real world accounts (shortage of) assets, it should support negatives.

    Solution proposal A "limit" attribute on accounts. The transaction engine would guarantee I don't exceed that limit (just like it currently guarantees the limit of 0).

    Additional context Credits would expand the ledger's realm of use-cases, to performing FX between currencies with double-entry book-keeping (which @world can provide in a sense, albeit at the cost of complexity), interest calculations and cash optimisation.

  • NUM-384 filters account by their balance

    NUM-384 filters account by their balance

    This feature allows us to filters the accounts we get using the /{ledger}/accounts route by their balance

    The request now takes two more optionnal parameters, and <balance_operator>

    • balance : int64 that represents the balance volume of the account
    • balance_operator : comparison operator, can be gt, gte, e, lt, lte

    I also tried to make the tests easier to read by bracketing them

  • Numary UI

    Numary UI

    HI there,

    I tried opening the Dashboard via the SSH link i have, but it just came up with the following error: 2021/07/22 12:57:08 exec: "xdg-open": executable file not found in $PATH I have already changed the HTML bind address to the external IP. Is there some URL I can visit to open the Dashboard or does it have to be started manually?

    thanks, Philip

  • chore: remove duplicate go mod vendor

    chore: remove duplicate go mod vendor

    Title

    Test already depends on vendor task, which already runs go mod vendor

    Type of change

    • [ ] Bug fix (non-breaking change which fixes an issue)
    • [ ] New feature (non-breaking change which adds functionality)
    • [X] Refactoring / Technical debt

    What parts of the code are impacted ?

    Taskfile for Go SDK

    Checklist:

    • [X] My code follows the style guidelines of this project
    • [X] I have performed a self-review of my code
    • [X] I have commented my code, particularly in hard-to-understand areas
    • [X] I have made corresponding changes to the documentation
    • [X] My changes generate no new warnings
    • [X] I have added tests that prove my fix is effective or that my feature works
    • [X] New and existing unit tests pass locally with my changes
  • Bug: with --telemetry-enabled=false flag numary still sends data to twilio

    Bug: with --telemetry-enabled=false flag numary still sends data to twilio

    Describe the bug

    No words guys:

    $ numary --telemetry-enabled=false server start
      loading config file: Config File "numary" Not Found in "[/Users/r0ck3t/.numary /etc/numary]"
      segment 2022/11/15 23:58:59 ERROR: sending request - Post "https://api.segment.io/v1/batch": dial tcp: lookup api.segment.io: no such host
      segment 2022/11/15 23:58:59 ERROR: sending request - Post "https://api.segment.io/v1/batch": dial tcp: lookup api.segment.io: no such host
      segment 2022/11/15 23:58:59 ERROR: sending request - Post "https://api.segment.io/v1/batch": dial tcp: lookup api.segment.io: no such host
    

    To Reproduce

    1. Run numary --telemetry-enabled=false server start
    2. See logs in firewall or in wireshark.

    Expected behavior

    Disable telemetry by default!

    Environment (please complete the following information):

    • MacOS Monterey, Macbook on M1

    • Numary Version:

      Version: 1.8.0 
      Date: 2022-10-31T08:29:29Z 
      Commit: a55756b 
      

    Additional context

    You are doing something wrong guys, telemetry must be disabled by default in opensource apps, especially if they were build from source code. It's super stupid.

  • Ledger creates a segment connection / client even when Segment is disabled.

    Ledger creates a segment connection / client even when Segment is disabled.

    Describe the bug Ledger is making a connection to segment even when Segment integration is disabled. I use Pi-Hole blocker and this results in an error log printed in the log.

    To Reproduce Block api.segment.io DNS resolution via some means like Pi-Hole etc.

    Expected behavior Since the integration is disabled, there should be no client created / connection attempted.

    Logs segment 2022/10/17 21:34:23 ERROR: sending request - Post "https://api.segment.io/v1/batch": dial tcp [::]:443: connect: connection refused segment 2022/10/17 21:34:23 ERROR: sending request - Post "https://api.segment.io/v1/batch": dial tcp [::]:443: connect: connection refused segment 2022/10/17 21:34:23 ERROR: sending request - Post "https://api.segment.io/v1/batch": dial tcp [::]:443: connect: connection refused

    Environment (please complete the following information):

    • OS: Osx 12.5.1
    • Numary Version Version: 1.7.4 Date: 2022-09-02T12:29:05Z Commit: ceeef7f

    Additional context the problem goes away if I disable Pi-Hole blocking

  • Negative values for account balance

    Negative values for account balance

    Is your feature request related to a problem? Please describe. About the fact that accounts can't have negative values, is it possible to overcome this in some way ? (In the formance documentation: Accounts in Formance Ledger cannot go negative! (Except for the special @world account).)

  • feat: SDK java

    feat: SDK java

    SDK : Add java

    From #261

    How to deploy

    Create a sonatype account and follow the guide : https://central.sonatype.org/publish/publish-guide/#introduction

    Once sonatype account configured, you have to create a file ~/.m2/settings.xml :

    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
        <servers>
          <server>
              <id>ossrh</id>
              <username>******</username>
              <password>******</password>
          </server>
      </servers>
    </settings>
    

    To deploy, you can use the following command to deploy snapshot version :

     mvn -B deploy -Psign-artifacts -DaltDeploymentRepository=ossrh::default::https://s01.oss.sonatype.org/content/repositories/snapshots/
    

    To deploy a release version :

     mvn -B deploy -Psign-artifacts -DaltDeploymentRepository=ossrh::default::https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
    
  • feat: keep in cache already created ledgers

    feat: keep in cache already created ledgers

    Remember already initialized ledgers

    Just remember what ledgers has already been initialized and avoid sql queries.

    Type of change

    • [X] Bug fix (non-breaking change which fixes an issue)
    • [ ] New feature (non-breaking change which adds functionality)
    • [ ] Refactoring / Technical debt
  • Support for back dated transactions

    Support for back dated transactions

    Is your feature request related to a problem? Please describe. In some scenarios it is needed to create transactions that happened in the past and not in the moment they were committed.

    Summary

    Solution proposal Make the api accept a backdate property

    {
      "postings": [
        {
          "source": "alice",
          "destination": "teller",
          "amount": 100,
          "asset": "COIN"
        },
        {
          "source": "teller",
          "destination": "alice",
          "amount": 5,
          "asset": "GEM"
        }
      ],
      backdate: $timestamp
    }
    

    This should update the balances accordingly or throw an error if subsequent transactions cannot be applied to avoid leaving the system in an invalid state

  • Adding numary to nixos package directory

    Adding numary to nixos package directory

    I'm trying to learn and use Nix, so to test that and numary at the same time I've proposed adding numary to the Nixos package directory.

    https://github.com/NixOS/nixpkgs/pull/191106

    I've followed the instructions for building present at the current Dockerfile but I could use some help with the tests.

  • feat: use sharedanalytics package

    feat: use sharedanalytics package

    feat: use sharedanalytics package

    This basically extract the analytics code to go-libs library (https://github.com/numary/go-libs/pull/9). Please review go-libs before.

    Type of change

    • [ ] Bug fix (non-breaking change which fixes an issue)
    • [X] New feature (non-breaking change which adds functionality)
    • [ ] Refactoring / Technical debt
  • refactor: volumes aggregation

    refactor: volumes aggregation

    Remove post commit volumes and pre commit volumes calculation from transaction batches. Aggregation is provided by the core using functions AggregatePostCommitVolumes() and AggregatePreCommitVolumes(). This simplify a bit the transaction processing and remove duplicate codes.

Related tags
Go library containing a collection of financial functions for time value of money (annuities), cash flow, interest rate conversions, bonds and depreciation calculations.

go-finance Go library containing a collection of financial functions for time value of money (annuities), cash flow, interest rate conversions, bonds

Jan 2, 2023
A go port of numpy-financial functions and more.

go-financial This package is a go native port of the numpy-financial package with some additional helper functions. The functions in this package are

Dec 31, 2022
Embedded database for accounts transactions.
Embedded database for accounts transactions.

transaction Embedded transactional database of accounts, running in multithreaded mode. Coverage 92.8% The library operates only with integers. If you

Dec 27, 2022
Converts grouped transactions in a ZKB transaction CSV (incl. details) to single transactions

ZKB Converter Converts grouped transactions in a ZKB transaction CSV (incl. deta

Dec 26, 2021
CRUDist Model Driven Web Development. Automagically generate CRUD APIs from your model.

CRUDist - Model Driven API Development Automagicaly create CRUD APIs for your gorm models. Example Model definition type BaseModel struct { ID

Nov 15, 2021
Transmo - Transform Model into another model based on struct for Go (Golang).

Transmo Transmo is a Go library for transform model into another model base on struct. This library detect your field name to copy that into another m

Jan 7, 2022
A distributed, proof of stake blockchain designed for the financial services industry.

Provenance Blockchain Provenance is a distributed, proof of stake blockchain designed for the financial services industry.

Dec 14, 2022
An easy-to-use platform for creating microservices without complex infrastructure solutions.

RPCPlatform An easy-to-use platform for creating microservices without complex infrastructure solutions. Only etcd required. Out of the box you get a

Jan 4, 2022
Scriptable interpreter written in golang
Scriptable interpreter written in golang

Anko Anko is a scriptable interpreter written in Go. (Picture licensed under CC BY-SA 3.0, photo by Ocdp) Usage Example - Embedded package main impor

Jan 1, 2023
Scriptable interpreter written in golang
Scriptable interpreter written in golang

Anko Anko is a scriptable interpreter written in Go. (Picture licensed under CC BY-SA 3.0, photo by Ocdp) Usage Example - Embedded package main impor

Dec 23, 2022
Instant messaging platform. Backend in Go. Clients: Swift iOS, Java Android, JS webapp, scriptable command line; chatbots
Instant messaging platform. Backend in Go. Clients: Swift iOS, Java Android, JS webapp, scriptable command line; chatbots

Tinode Instant Messaging Server Instant messaging server. Backend in pure Go (license GPL 3.0), client-side binding in Java, Javascript, and Swift, as

Jan 6, 2023
Scriptable interpreter written in golang
Scriptable interpreter written in golang

Anko Anko is a scriptable interpreter written in Go. (Picture licensed under CC BY-SA 3.0, photo by Ocdp) Usage Example - Embedded package main impor

Dec 23, 2022
BackEndForEverything a scriptable reverse proxy

BEFE the BackEnd For Everything BEFE is a scriptable reverse proxy. It simplifies checking, rewriting and transforming incoming request through the he

Dec 14, 2022
Simple and easy to use client for stock market, forex and crypto data from finnhub.io written in Go. Access real-time financial market data from 60+ stock exchanges, 10 forex brokers, and 15+ crypto exchanges

go-finnhub Simple and easy to use client for stock, forex and crpyto data from finnhub.io written in Go. Access real-time market data from 60+ stock e

Dec 28, 2022
An easy tool to apply transactions to the current EVM state. Optimized for MEV.

sibyl A more embedded version of fxfactorial/run-evm-code. This tool makes it easy to apply transactions to the current EVM state. Call it a transacti

Dec 25, 2022
An open-source, distributed, cloud-native CD (Continuous Delivery) product designed for developersAn open-source, distributed, cloud-native CD (Continuous Delivery) product designed for developers
An open-source, distributed, cloud-native CD (Continuous Delivery) product designed for developersAn open-source, distributed, cloud-native CD (Continuous Delivery) product designed for developers

Developer-oriented Continuous Delivery Product ⁣ English | 简体中文 Table of Contents Zadig Table of Contents What is Zadig Quick start How to use? How to

Oct 19, 2021
A terminal designed for anyone to use and designed for any platform

A terminal designed for anyone to use and designed for any platform. Which includes the basic features of any terminal and includes friendly commands to perform tools such as ping, traceroute, generate key pairs, encrypt/decrypt, router security actions, etc. All of the source code is done in Go.

Jan 25, 2022
CapMonsterTool is a set of Go tools designed to simply make requests to the CapMonster Cloud API.

✨ CapMonsterTool ✨ About this module What is ✨ CapMonsterTool ✨ ? CapMonsterTool is a set of Go tools designed to simply make requests to the CapMonst

Dec 1, 2022
TLDR Page Creator is a program designed to help users make TLDR pages

TLDR Page Creator is a program designed to help users make TLDR pages, while avoiding syntax errors from TLDR-style markdown.

Dec 3, 2022