pledge

Accounts

Create an account #

SELECT id, name, currency, balance
FROM pledge.create_account('bank', 'USD');
               id               | name | currency | balance
--------------------------------+------+----------+---------
 pla_01M730CQFEF2CR8VRK2DCTVZ7P | bank | USD      |       0

pledge picks the id. Account ids start with pla_. Store the id in your own tables to link your data to the account.

You can attach your own data as JSON:

SELECT id FROM pledge.create_account('alice', 'USD', metadata => '{"user_id": 42}');

The currency is any text you like ('USD', 'EUR', 'points'). Money only moves between accounts with the same currency.

Stop overdrafts #

Every account has two flags. Both are true unless you say otherwise.

Flag Set to false and…
allow_negative_balance the balance can never go below zero
allow_positive_balance the balance can never go above zero

A customer wallet should never go below zero:

SELECT id FROM pledge.create_account('alice', 'USD', allow_negative_balance => false);

A transfer that breaks a flag fails with pledge.negative_balance_not_allowed (or positive_…), and nothing is written.

Which accounts can go negative?

Money has to come from somewhere. Give the outside world an account that may go negative, like bank or world. When a customer tops up, move money from bank to their wallet. The bank’s balance goes negative: that’s the money that came into your system.

Close an account #

Accounts are never deleted. Close them instead:

SELECT name, balance, closed_at FROM pledge.close_account('pla_01M730CQFZE8ZAPGZK6T3BVSQX');

A closed account keeps its full history. Any new transfer to or from it fails with pledge.account_closed.

Only an account with a zero balance can be closed. If it still holds money, move it out first, in the same transaction:

BEGIN;
SELECT balance FROM pledge.accounts_view WHERE id = 'pla_01M730CQFZE8ZAPGZK6T3BVSQX';      -- 42.10
SELECT * FROM pledge.create_transfer('pla_01M730CQFZE8ZAPGZK6T3BVSQX', 'pla_01M730CQFEF2CR8VRK2DCTVZ7P', 42.10);
SELECT * FROM pledge.close_account('pla_01M730CQFZE8ZAPGZK6T3BVSQX');
COMMIT;

If another transfer lands in between, close_account fails with pledge.account_not_empty and the whole transaction rolls back. Nothing is half done. Just try again.