Amatino Swift v0.0.7 Released

Amatino Swift 0.0.7 is now available! You can install it via Carthage or get the source code from GitHub. 0.0.7 is a major new release that adds significant capability. The powerful Tree, Position, and Performance objects are now available. Here’s the full change-log:

    • Remove InternalLibraryError, which sneakily survived the error consolidation purge in 0.0.6
    • Add Account.update() method
    • Add Account.delete() method
    • Add Account.deleteRecursively() method
    • Add Tree class
    • Add Position class
    • Add Performance class
    • Add Node protocol
    • Add Node conforming TreeNode and PlaceholderNode classes (used by Tree, Position, and Performance)
  • Consolidate SessionCreateArguments & SessionAttributes into Session
  • Consolidate BalanceRetrieveArguments into Balance
  • Drastically simplified and empowered the internal EntityObject protocol, reducing code complexity and duplication (does not affect public API)
  • Added unit tests for new features

Plant some Trees

Trees present the entire chart of accounts of an Entity as a hierarchical object. Each node in the Tree summarises an Account, including an individual and recursive balances.

Each node is represented by an instance of a class conforming to the Node protocol. Two such classes existing: TreeNode and PlaceholderNode.

TreeNodes present summarised account data, including individual and recursive balances. PlaceholderNodes stand in for TreeNodes where the requesting User does not have read permissions for the Account in question. A PlaceholderNode still includes children, which may include TreeNodes if the User has permission to read from accounts further down the hierarchy.

Determine Position

Positions are generic representations of the accounting construct variously known as a balance sheet, statement of financial position, or something else depending on your jurisdiction. They include hierarchical representations of all asset, liability, and equity Accounts inside an Entity.

Like the Tree, each Account is represented by an instance of an object conforming to the Node protocol.

Measure Performance

Performances are generic representations of the accounting construct variously known as an income statement, statement of financial performance, or comprehensive income statement, depending on your jurisdiction. They include hierarchical representations of all income and expense accounts inside an Entity.

Like the Tree and Position objects, each Account is represented by an instance of an object conforming to the Node protocol.

Updating & Deleting Accounts

Account instances now feature .update() and delete() methods, which do what it says on the tin. Here’s an example of an update operation:

Delete operations require a bit of thought. Deleting an Account does not delete any Transactions with Entries party to that Account. As such, you must supply an Account you wish to transfer any Entries to upon deletion. Here’s an example:

What next…

0.0.8 will probably focus on units of account, i.e. GlobalUnits & CustomUnits. In particular, loading CustomUnits into an Entity so that you can denominate Transactions in whatever unit suits you.

– Hugh

Amatino Swift v0.0.6 Released

Amatino Swift 0.0.6 has arrived! 0.0.6 makes lots of under the hood changes, the most important being to the error types emitted by the library. Here’s the changelog:

  • Added Transaction.update() method
  • Added Transaction.delete() method
  • Added session and entity properties to Transaction(A side-effect of the addition of .update() and .delete())
  • Consolidated all errors emitted by Amatino Swift under a single error type, AmatinoError
  • Potential API response errors (e.g. server errors) are now gracefully & descriptively emitted by instances of AmatinoError.
  • Consolidated creation, update, and retrieval argument structs into Transaction, e.g. TransactionCreateArguments -> Transaction.CreateArguments
  • Consolidated AccountCreateArguments struct into Account as Account.CreateArguments
  • Replaced overloaded Account.create() & .retrieve() with Account.createMany() & .retrieveMany()
  • Internally re-plumbed Transaction to conform to a new internal EntityObject protocol, reducing code duplication (causes no changes to API)
  • Renamed UrlParameters(:Entity:[UrlTarget]) entity label from entityWithTargets to entity
  • Removed defunct ObjectCore, AmatinoObjectError, and ConstraintError types
  • Consolidated EntityCreateArguments struct into Entity.CreateArguments
  • New unit tests for new features

New Error Handling

Before 0.0.6, errors thrown by Amatino Swift were an absolute mess. There was AmatinoObjectError, ConstraintError, ResponseError, and even just plain old Error. Now, you can be sure that any error thrown by Amatino Swift will be of type AmatinoError.

AmatinoError provides an enum, Kind, off of which you can switch via AmatinoError.kind. For example, a Transaction.retrieve() request might yield a .notFound case when the Amatino API returns 404. You can get a verbose String description of an error by examining the AmatinoError.message property.

Some objects, such as Transaction, provide a superclass of AmatinoError called ConstraintError, which provides more detailed information about input constraint violations. For example, when you supply  Transaction.create() with a description that is too long.

You can still handled these more verbose ConstraintError cases with a plain AmatinoError handler, as AmatinoError will flag them with the .constraintViolated case.

Transaction Update & Deletion

Sometimes you might which to change a Transaction after storing it. Perhaps an error was made, or underlying facts have changed. You can now do so using the update() instance method. Here’s an example:

You may also flat out delete a Transaction using the delete() instance method. Example:

Consolidation of ancillary structs

Many Amatino Swift classes depend on a variety of ancillary structs to perform their work. For example, Transaction uses CreateArguments and UpdateArguments, as well as several internal types. These types were previously in their own files.

This arrangement was causing the Amatino Swift project to be a bit jumbled. Code completion when typing the start of an object name was also getting crowded. So, as a matter of preference, I’ve been moving all ancillary types into their relevant classes. For example, TransactionCreateArguments has become Transaction.CreateArguments.

This process started in 0.0.5, and is ongoing in 0.0.6. There are a few cases of the old style left, which I’ll probably get to in 0.0.7.


– Hugh

Amatino Swift v0.0.5 Released

Amatino is a double entry accounting API, and Amatino Swift allows macOS & iOS developers to utilise Amatino in a Swift application. v0.0.5 is a major new Alpha release introducing the Ledger class, and some attendant smaller changes.

  • Added new Ledger class
  • Added new RecursiveLedger class
  • Added new LedgerPage class, a low level class underpinning Ledger and RecursiveLedger
  • Added new LedgerRow struct, used by Ledgers
  • parentAccount renamed to parent in AccountCreateArguments initialisers
  • AccountType is now inferred by AccountCreateArguments when a parent is supplied
  • Added new Account.create() async initialisers for various attribute mixes
  • Transaction will now throw ConstraintError if debits & credits do not balance on creation
  • Fixed a bug whereby all times sent to the Amatino API were in local system timezone rather than UTC
  • Added new Ledger-related unit tests

Retrieving a Ledger

Multiple Ledger.retrieve() overloads are available, allowing you to tailor the Ledger to your needs. For example, you might want to retrieve a specific timeframe or denominate the ledger in a particular unit (e.g. a non-native currency). You can also reverse-order the Ledger such that the first pages retrieves the most recent transactions.

RecursiveLedger syntax is identical to Ledger, but delivers every Transaction in the target Account and all of its children.


Amatino Swift may be installed via Carthage. Add github "amatino-code/amatino-swift"to your Cartfile.

Enjoy, and be sure to tell me what you think!

– Hugh

API v0.0.5 Released – Ledger Changes

A new version of the Amatino API has been deployed to all regions. 0.0.5 contains breaking changes to the Ledger object, and is not backward compatible with 0.0.4.

  • Ledgers may now only be retrieved one at a time
  • Ledgers are now paginated in rows of 500
  • Ledgers may now be returned in order of ascending or descending transaction time
  • Ledgers now require a order_oldest_first boolean argument
  • Returned Ledger root type is now a JSON Object rather than a JSON Array
  • Returned Ledger start_time and end_time will now be the start and end of the Ledger window, rather than the earliest and latest Transaction in the Ledger
  • Ledger end_time will now default to now at UTC if supplied as null
  • Ledger start_time will now default to end_time – 1 year if supplied as null
  • Fixed a bug that could cause Amatino to return a stale cached Ledger when null had previously been provided as a Ledger start time
  • Fixed a bug that caused Transactions to be stored with incorrect times (The transaction_time field was not being properly interpreted as UTC)

All the above changes also apply identically to the RecursiveLedger object.

The Amatino API obeys the Semantic Versioning convention: Any version before 1.0.0 should be considered unstable, and breaking changes may occur at any time. Even so, I don’t want to cause breaking changes unnecessarily, and don’t take this lightly.

These changes are aimed at making Ledger objects more useful in real world applications. They are the result of experimentation during development of the upcoming Amatino Swift v0.0.5.

– Hugh

Api v0.0.4 Released – Position & Performance

A new version of the Amatino API, v0.0.4, is now live and running in all regions. 0.0.4 is backward-compatible with 0.0.3, and makes the following changes:

  • Add new ‘Position‘ object
  • Add new ‘Performance‘ object
  • Fix bug causing Trees to display negative balances in <> instead of ()
  • Fix bug causing Trees to sometimes miscalculate the balance of income or expenses accounts in non-native denominations

Position & Performance were not the features I expected to be working on this week. In fact, I had not ever thought of building them at all. Last weekend, I posted Amatino to HackerNews. Lots of great feedback flowed in.

A consistent theme was: “where are the reporting tools?” In my grand-vision, Amatino is a data layer sitting below reporting in an application stack. However, an email from a prospective customer gave me a jolt. They asked: ‘Can Amatino create a balance sheet?’

Well no, it can’t, I answered. I started to type a response about how a balance sheet is too domain-specific, not a generic enough construct, and that it could be constructed in application logic out of the base components Amatino provides. Then it hit me that I was very wrong.

Abstract it back far enough, and a balance sheet is a snapshot of the position of an entity in time. We call it various names and format it in various ways, but it is at its core a very simple way of observing asset, liability, and equity accounts.

The same appears to hold true for income statements. They are, in their most generalised form, a measurement of the performance of an entity over a period of time.

Thought of in this way, balance sheets and income statements become generic objects. They are fully compatible with Amatino’s mission as a provider of generic, jurisdiction-agnostic functions for manipulating financial data.

Armed with this new thinking, I set out to add in-built capability to produce Position and Performance objects, which may be extended by an application to produce balance sheets and income statements.

Creating these objects was, fortunately, quite painless. Most of the machinery used to build them is repurposed from the Tree production line. In particular, the ability to generate a Position or Performance in any denominating unit is lifted straight from the code that builds Trees.

Trees, Positions, and Performances are by far the most complex objects Amatino can synthesise. The algorithms that compute them make my head spin.

That’s a roundabout way of saying: There will be bugs. Positions and Performances have been integrated into the API unit-testing suite at a shallow level. It will take time to build more comprehensive testing. More testing is most especially required around the production of Positions and Performances in arbitrary denominations featuring heterogeneous underlying native units.

The most important takeaway from all this is: Thank you for your feedback. By telling me what you want, you can shape Amatino’s development.

– Hugh

Documentation update: Trees

This morning I realised, to my substantial embarrassment, that Trees were missing from the Amatino API HTTP documentation.

Trees are, in my humble opinion, the most exciting object the Amatino API can build. They are hierarchical structures of every Account in an Entity, including balances, recursive balances. They are a great way to get a whole-Entity picture.

Somehow, I had ommitted them from the docs. That omission is now fixed! In future, I will need to do some work to flesh out the related Tree Node documentation. It is not yet clear how the Tree Node behaves when it omits data due to a lack of read permissions on a particular Account.

– Hugh

Documentation update: Unit Identifiers

The Amatino API HTTP documentation has been updated. This update corrects errors in references to Global Units and Custom Units. Previously, the documentation stated that such units should be identified by their string codes. For example, 'usd' for U.S. Dollars.

Now, the documentation states that units should be identified by their integer identifiers. For example, 5 for U.S. Dollars.

This error was the result of some earlier experiments with removing integer unit identifiers in favour of string identifiers. The experiments did not go well, and lots of problems resulted. So, I reverted to integer identifiers, but forgot to update the documentation.

Amatino Swift v0.0.4 Released

Amatino Swift allows MacOS and iOS developers to build double-entry accounting functionality into their apps. Until today’s v0.0.4 release, it was a bit tricky to install. To make installation easy, Amatino Swift is now compatible with Carthage. Carthage is a Swift dependency manager. In the project’s own words:

Carthage is intended to be the simplest way to add frameworks to your Cocoa application.

Carthage builds your dependencies and provides you with binary frameworks, but you retain full control over your project structure and setup. Carthage does not automatically modify your project files or your build settings.

You can install Carthage by downloading and running Carthage.pkg from the Carthage project releases page.

Installing Amatino Swift with Carthage

Navigate to your project directory, and create a file named “Cartfile“. Inside that file, add the line github "amatino-code/amatino-swift". You can create the file, and insert the required line into the file, with the following command:

$ echo 'github "amatino-code/amatino-swift"' > Cartfile

Next, tell Carthage to download the Amatino Swift repository and compile MacOS and iOS frameworks, by running the following command inside your project directory:

$ carthage update

Once the process is complete, you should have Amatino.framework binaries available in the Carthage/Build/Mac and Carthage/Build/iOS directories.

The following instructions are applicable to MacOS applications. Instructions for iOS are broadly similar, and all instructions are available in detailed form in the Carthage project documentation.

Embedding Amatino in a MacOS application

Drag the binaries for your target platforms to the Embedded Binaries section of your Xcode project.

Next, to enable debugging, create a Copy Files phase in your target’s Build Phases tab:

Inside the phase, select Products Directory from the Destination drop down menu.

Finally, drag the Amatino.framework.dSYMfile into the Add files here section.

For more detailed instructions, check out the Carthage project documentation.

Where to next?

Now that Amatino Swift is easier to install, it’s time to smash together more functionality. In particular, I’d like to get Ledgers working as soon as possible.

Have a preferred method of installing Swift Frameworks? Please tell me about it on Twitter, on the forums, or via email. I would love to hear from you, and develop Amatino Swift in such a way as to make it easy for you to install.

– Hugh