Minka Ledger Docs
Tutorials

Getting started with ledger

DateResponsibleChanges
September 7, 2022@Željko RumenjakInitial version
February 2, 2023@Alen KraljDestroy intent corrected
February 27, 2023@Omar MonterreyAdded Version to Ledger URL
March 7, 2023@Filip HercegChanged the URL to ldg-stg.one
March 10, 2023@Tomislav Herman• Using placeholders for Ledger URL when connecting and explained the format of this URL.
• Updated cli inputs and outputs according to latest CLI.
June 5, 2024@Omar MonterreyUpdated signer create examples with latest UX

Getting Started

In this tutorial you are going to build a ledger that manages business account balances and allows businesses to make payments to other businesses using a simple REST API.

This example represents a simplified banking core.

In order to follow this tutorial you have to have nodeJS v18 or newer installed on your machine. This tutorial uses a Minka Ledger, so our first task is to connect to it, for this we will use the Minka CLI tool.

Install the Minka CLI through your terminal:

$ npm install -g @minka/cli

After installing the CLI tool, you will be able to interact with local or remote ledger instances by using the minka command. Checkout all t he commands available by typing minka --help.

After we have installed a CLI, we can connect to a ledger by typing:

$ minka server connect
? Server URL: <ledger URL>
 
✅ Connected to server <server name> (<server URL>)
 
Active ledger: <ledger name>

Ledger URL required as input has the following format:

  • https://<ledger name>.<server domain>/api/v2
  • ledger referenced by <ledger name> will automatically be set as active ledger which can be later changed with minka ledger select command
  • if you haven’t received a Ledger URL, you can ask responsible person to send it to you

Now we have everything ready to start tracking balances in the ledger.

Before storing data in the ledger, we need to create a signer.

Initial configuration

Minka Ledger security model is based on asymmetric cryptography, because of that we need to sign each request using a public and private key pair. A signer is a ledger concept that encapsulates those keys with optional metadata.

First, we will create a treasury key that we will use to control the money supply of our system:

$ minka signer create
? Handle: treasury
? Key pair source: Generate new key pair
? Add custom data (y/N)? No
? Signer password: [hidden]
? Repeat password: [hidden]
? Store to ledger? No
 
✅ Signer created successfully:
Handle: treasury
Public: Zxy3I/cezrqMf4mlpVlA86gapO5syX+Dt/Y5hnHvvNk=
Secret: *[value is hidden]*
 
⚠️ WARNING: Secret or private key is critical data that should be handled
with care. Private keys are used to modify balances and it is important to
understand that anyone who has access to that key can perform sensitive
ledger operations.

Created signer is stored locally and can be referenced in other commands by using its handle, in this case treasury.

Next, we will create a symbol. Symbols are used to issue balances to the system, they can represent currencies or anything that can be counted, for example, loyalty points, tokens, cryptocurrency etc.

You can create a symbol secured by our treasury key with the following command:

$ minka symbol create
? Handle: usd
? Factor: 100
? Add custom data (y/N): No
? Signer: treasury
 
✅ Symbol created successfully:
Handle: usd
Factor: 100
Signer: Zxy3I/cezrqMf4mlpVlA86gapO5syX+Dt/Y5hnHvvNk= (treasury)

Provided signer (treasury) has full access to this symbol by default, that means all operations related to this symbol need to be signed with a private key of that signer.

Now we have a basic monetary model of our ledger in place. We have a symbol that represents a fiat currency and we can allow businesses to join our ledger.

Onboarding businesses

Businesses can join by creating their wallet. Wallets are similar to bank accounts only more flexible because they can represent anything that can hold a balance, for example, checking or savings accounts, gift cards, phone numbers, etc.

A business can join our ledger in a similar way we have created our symbol earlier. First, they need to create their signer:

$ minka signer create
? Handle: zet
? Key pair source: Generate new key pair
? Add custom data (y/N)? No
? Signer password: [hidden]
? Repeat password: [hidden]
? Store to ledger? No
 
✅ Signer created successfully:
Handle: zet
Public: /hICkEzKuSMeJ5b/T7A2qKL3Mml7avznoV2/chwqDh4=
Secret: [value is hidden]
 
⚠️ WARNING: Secret or private key is critical data that should be handled
with care. Private keys are used to modify balances and it is important to
understand that anyone who has access to that key can perform sensitive
ledger operations.

After that they would create a wallet:

$ minka wallet create
? Handle: zet
? Bridge: [none]
? Add custom data (y/N): No
? Add routes (y/N): No
? Signer: zet
 
✅ Wallet created successfully:
Handle: zet
Signer: /hICkEzKuSMeJ5b/T7A2qKL3Mml7avznoV2/chwqDh4= (zet)

We can also check the balance of our new wallet by typing:

$ minka wallet balances zet
Balances:
No balances found

Although anyone can create new wallets using this process, these wallets don’t hold any balance. The only currency we are going to accept is usd and that currency is controlled by us (a bank).

We can now validate all required business documentation and issue a balance to that business once we receive a deposit from them.

Balance changes are represented in the Minka Ledger as signed intents. Let’s issue a balance of 10.000,00 USD to zet:

$ minka intent create
? Handle: 01LAZz_MfjtkP6BPu
? Action: issue
? Target: zet
? Symbol: usd
? Amount: 10000
? Add another action (y/N): No
? Add custom data (y/N): No
? Signers: treasury
 
Intent summary:
------------------------------------------------------------------------
Handle: 01LAZz_MfjtkP6BPu
 
Action: issue
 - Target: zet
 - Symbol: usd
 - Amount: $10,000.00
 
? Sign this intent using signer treasury (y/N)? Yes
 
✅ Intent signed and sent to ledger <ledger name>.
Intent status: pending

If we now check the balance of zet wallet we will see the issued amount is available:

$ minka wallet balances zet
Balances:
$10.000,00 (usd)

Making payments

We can now add one more business to show how B2B payments would work. Let’s create a business called hep. First, we create a signer:

$ minka signer create
? Handle: hep
? Key pair source: Generate new key pair
? Add custom data (y/N)? No
? Signer password: [hidden]
? Repeat password: [hidden]
? Store to ledger? No
 
✅ Signer created successfully:
Handle: hep
Public: CqopzcoGI8PoygX5uGNEn5nTx+RkDI3rwkeD56226ho=
Secret: [value is hidden]
 
⚠️ WARNING: Secret or private key is critical data that should be handled
with care. Private keys are used to modify balances and it is important to
understand that anyone who has access to that key can perform sensitive
ledger operations.

And a wallet using that signer:

$ minka wallet create
? Handle: hep
? Bridge: [none]
? Add custom data (y/N): No
? Add routes (y/N): No
? Signer: hep
 
✅ Wallet created successfully:
Handle: hep
Signer: CqopzcoGI8PoygX5uGNEn5nTx+RkDI3rwkeD56226ho= (hep)

Now we can send a payment from zet to hep using a simple intent again:

$ minka intent create
? Handle: CWuH_N4Ah_jyW7Ffi
? Action: transfer
? Source: zet
? Target: hep
? Symbol: usd
? Amount: 3000
? Add another action (y/N): No
? Add custom data (y/N): No
? Signers: zet
 
Intent summary:
------------------------------------------------------------------------
Handle: CWuH_N4Ah_jyW7Ffi
 
Action: transfer
 - Source: zet
 - Target: hep
 - Symbol: usd
 - Amount: $3,000.00
 
? Sign this intent using signer zet (y/N)? Yes
 
✅ Intent signed and sent to ledger <ledger name>.
Intent status: pending

If we now check balances of both business wallets we will see that they reflect the payment we just made:

$ minka wallet balances zet
Balances:
$7.000,00 (usd)
$ minka wallet balances hep
Balances:
$3.000,00 (usd)

With everything we did until now, we have a ledger that allows us to easily onboard new business, track their balances and enable them to make payments between each other.

Withdrawing deposits

The last part we will add in this tutorial is a way for businesses to withdraw money from the system. We will model the withdrawal process in multiple steps to demonstrate how settlements can be modeled using wallets.

We will create a special settlement wallet (sw) that is going to hold balances until they are settled manually by our treasury team. After external payment is confirmed the reserved amount is going to be destroyed to record that it left the system.

First, we create our sw using our existing treasury key because it is going to be managed by the same team:

$ minka wallet create
? Handle: sw
? Bridge: [none]
? Add custom data (y/N): No
? Add routes (y/N): No
? Signer: treasury
 
✅ Wallet created successfully:
Handle: sw
Signer: Zxy3I/cezrqMf4mlpVlA86gapO5syX+Dt/Y5hnHvvNk= (treasury)

When a business wants to withdraw money from the system, they will transfer this amount to this new wallet where it will wait for the treasury team to manually make a payment in external systems. This is how we would withdraw $1.000,00 from hep wallet:

$ minka intent create
? Handle: 8AKKgcdRDTvwS1w5k
? Action: transfer
? Source: hep
? Target: sw
? Symbol: usd
? Amount: 1000
? Add another action (y/N): No
? Add custom data (y/N): No
? Signers: hep
 
Intent summary:
------------------------------------------------------------------------
Handle: 8AKKgcdRDTvwS1w5k
 
Action: transfer
 - Source: hep
 - Target: sw
 - Symbol: usd
 - Amount: $1,000.00
 
? Sign this intent using signer hep (y/N)? Yes
 
✅ Intent signed and sent to ledger <ledger name>.
Intent status: pending

After this intent is successfully cleared in the ledger, a treasury team employee would manually make a required payment and send an intent to destroy this amount in the ledger:

$ minka intent create
? Handle: 8KInmo5vlo270zYnd
? Action: destroy
? Source: sw
? Symbol: usd
? Amount: 1000
? Add another action (y/N): No
? Add custom data (y/N): No
? Signer: treasury
 
Intent summary:
------------------------------------------------------------------------
Handle: 8KInmo5vlo270zYnd
 
Action: destroy
 - Source: sw
 - Symbol: usd
 - Amount: $1,000.00
 
? Sign this intent using signer treasury (y/N)? Yes
 
✅ Intent signed and sent to ledger <ledger name>.
Intent status: pending

You have built a simple and secure ledger that supports tracking business account balances, allows those businesses to make deposits and withdrawals to external systems and gives them API access to make payments in a very simple way.

What’s next?

This solution can be further improved by adding integrations to connect to external systems automatically instead of relying on people to perform those operations manually.

You can find more details on how to do that in our other tutorials and how to guides.

On this page