Quickstart
This guide steps through how to use the DRM SDK & Command-Line Interface (CLI) to create a new digital currency called "My Bucks" with the currency code MYB
.
To better understand how the DRM Platform serves as an API for the interaction between all network members you'll step through the entire process:
- As the Central Bank
- Create digital currency
- Create two bank issuance accounts
- Issue funds
- As the Commercial Bank
- As Bank One, create Alice's account and inssue funds
- As Bank Two, create Bob's account
- As Alice, send digital currency to Bob
- As Bob, confirm receipt of funds
Before getting started, you'll need a root issuance account issued to you by DRM and the associated private key. You'll also need the latest SDK version from Github. The REPL provided throughout this guide already has these provided for your easy exploration.
Before we start
Depending on which SDK or terminal interface you're using, modify the following required code to match your environment:
- CLI
- TypeScript
- Rust
As the Central Bank
You start as the central bank to create and issue a new digital currency. Then you onboard commercial banks and create accounts for them before finally issuing money to them.
Create digital currency
Create central bank key pair
You need your central bank key pair in the PKCS8 format. To generate a new key-pair, enter the following command:
- CLI
- TypeScript
- Rust
Output
You should see something like this:
created key pair file: "central-bank.pkcs8"
public key is:
"hOJIkyqJ7/dUStWzcgj+afT1dBvJKczPvl5q70MpMaY="
Create the root account
Create the root account for the new digital currency associated with the central bank public key:
- CLI
- TypeScript
- Rust
The system supports a maximum of 256 root accounts. Once you reach this limit, you cannot create additional root accounts. This is a hard limit - make sure to plan account creation carefully to avoid hitting this ceiling unexpectedly.
Output
You should see something like:
1a000000000000000000000000000000
Create the role and role-binding
The central bank must be given permission to create issuance accounts for banks. We do that by creating a role with the appropriate permissions that is then associated with the central bank's public key.
- CLI
- TypeScript
- Rust
Create issuance accounts for two banks
The process for creating bank keys and issuance accounts is similar to the steps for the central bank. Using the public keys for Bank One and Bank Two, we create issuance accounts for their commercial use and grant them permissions via new roles and role bindings.
Bank One
- CLI
- TypeScript
- Rust
Bank Two
- CLI
- TypeScript
- Rust
Issue funds - Bank One
To issue funds to Bank One from the central bank, we create a transfer from the root account to Bank One's account:
- CLI
- TypeScript
- Rust
Transfer information
We retrieve information about the transfer by using the transaction ID (tx_id
) from the output:
- CLI
- TypeScript
- Rust
Output
You should see something like this:
(
tx_id: 129630000,
context_id: [],
timestamp: "2023-08-25 10:39:55.210130",
steps: [
(
from: "0c000000000000000000000000000000",
to: "0c800000000000000000000000000002",
amount: 100000,
metadata: [
Memo((plaintext:"Funds")),
],
),
],
success: true,
state: Accepted,
)
Check the balance
In the Central Bank root account, after the transfer, notice the change in the issuance.balance
field:
- CLI
- TypeScript
- Rust
Output
You should see something like this:
(
id: 0c000000000000000000000000000000,
balance: 0,
frozen: false,
code: "MYB",
decimals: 2,
balance_limit: 18446744073709551615,
issuance: Some((
balance: 100000,
issuance_accounts: 2,
holding_accounts: 0,
)),
)
As the Commercial Bank
After a bank has been onboarded, the bank can use the API to create and manage accounts for their customers. Here we will use the API as two different commercial banks titled:
- "Bank One"
- "Bank Two"
Each of these banks have a new customer that we will create accounts for, and deposit funds to.
Bank One - find my issuance account
Let's use the SDK to find Bank One's issuance account that was just created by the Central Bank. We can list all accounts by owner. Since we only created one account in this tutorial, we will get one account returned, which is Bank One's issuance account.
The following code creates a new ListAccountsRequest
filtering by our public_key
as the owner. It then signs the request using our private key and submits the request to the ledger.
- CLI
- TypeScript
- Rust
Output
You should see something like this:
[
(
id: "0c800000000000000000000000000002",
owner: "i+VZtoZhwLhfMZ2Etv23029ulURf1yz4Gb6RaqSGS9Y=",
name: "Bank One MYB",
public_name: "Bank One MYB Issuance Account",
profile_image_url: "",
),
]
Bank One - create Alice's customer account
Now we will create a new child account for a customer named Alice under Bank One's issuance account. Alice needs her own key pair to sign transactions with, so first we generate her key (normally, Alice would generate her key pair herself in a client app):
- CLI
- TypeScript
- Rust
Create role and role-binding for Bank One
Bank One doesn't yet have any roles that we can use to assign permissions. Therefore, we create a customer
role and a role-binding where we use Alice as a subject:
- CLI
- TypeScript
- Rust
Create an account for Alice in Bank One
Now we can create an account
for Alice:
- CLI
- TypeScript
- Rust
Bank One - issue funds to Alice's customer account
Alice's new account has a balance of zero, so we will issue funds from her bank (Bank One) to Alice's new account:
- CLI
- TypeScript
- Rust
Bank Two - create Bob's customer account
To setup Bob as a customer of Bank Two, we go through the same process as for Alice at Bank One:
- CLI
- TypeScript
- Rust
Create roles and role-binding for Bank Two
- CLI
- TypeScript
- Rust
Create account for Bob in Bank Two
- CLI
- TypeScript
- Rust
As Alice, send digital currency to Bob
Now that Alice and Bob have accounts on the ledger and appropriate permissions, they can use the API (or one of the SDKs or the CLI) to send and receive "My Bucks" to each other.
The hierarchical ledger tree of accounts enables a double-entry accounting system, creating atomic transactions that all participants in the activity can observe and respond to.
Check current balance
First we check Alice's account balance (it should be 1000 MYB, since we previously issued that from Bank One into Alice's account):
- CLI
- TypeScript
- Rust
Output
You should see something like the following, which includes balance: 100000
(the two last digits are the two decimals):
(
id: "0c800000000000000000000000000003",
balance: 100000,
frozen: false,
code: "MYB",
decimals: 2,
balance_limit: 18446744073709551615,
issuance: None,
)
Transfer funds to Bob
Since Alice has funds in her account, she can transfer 100 MYB to Bob:
- CLI
- TypeScript
- Rust
Look up recent transfers to confirm delivery
The following code gets a list of transfers. We filter the output by account
.
- CLI
- TypeScript
- Rust
There are other filter options as well:
Filter option | Description |
---|---|
-m, --min-tx-id <MIN_TX_ID> | Set minimum transaction ID [default: 0] |
-x, --max-tx-id <MAX_TX_ID> | Set maximum transaction ID |
-a, --account <ACCOUNT> | Set account filter |
-c, --context-id <CONTEXT_ID> | Set contextID filter |
-l, --limit <LIMIT> | Set limit of results [default: 20] |
For more filter details, see the Create transfer endpoint.
The purpose of the context_id
is to provide a unique identifier that links together multiple transactions that are part of a larger, multi-legged operation, particularly across different ledgers. This is crucial for scenarios like foreign exchange transfers where a single user action results in separate transactions on different ledgers (e.g., USD ledger and EUR ledger).
The context_id
allows:
- Tracking related transactions - It provides a way to tie together the various legs of a multi-ledger transfer, enabling tracking of the entire operation’s status and progress. This is important for users to be able to see the complete picture of their transfer, even if parts of it are happening on different ledgers.
- Simplified remote lookup and authorization - It acts as a shared secret, enabling users involved in a multi-ledger transfer to look up the status of remote transactions without needing to have direct access or authorization to the remote ledger. This allows users to verify that all parts of their transfer have been completed successfully.
- Resolution of ambiguity in transaction matching - In cases where multiple similar transactions occur (e.g., multiple transfers of the same amount to the same account), the context_id helps disambiguate which transactions are related to a specific user’s initial request.
In essence, the context_id
provides the glue that holds together the different pieces of a complex, distributed transaction and enables a coherent view of the entire operation.
Output
The output of the above request returns the transfers made by Alice with the most recent transaction at the top:
[
(
tx_id: 133930000,
context_id: [],
timestamp: "2023-08-25 10:42:42.786861",
steps: [
(
from: "0c800000000000000000000000000003",
to: "0c800001000000000000000000000003",
amount: 10000,
metadata: [Memo((plaintext:"groceries"))],
),
],
success: true,
state: Accepted,
),
(
tx_id: 132160000,
context_id: [],
timestamp: "2023-08-25 10:41:53.310156",
steps: [
(
from: "0c800000000000000000000000000002",
to: "0c800000000000000000000000000003",
amount: 10000,
metadata: [Memo((plaintext:"Funds"))],
),
],
success: true,
state: Accepted,
),
]
Check Alice's balance to confirm debit of funds
You can make sure there was a debit of Alice's funds, and you can check that with the following code:
- CLI
- TypeScript
- Rust
Output
You should see something like the following where the balance
field is less than before:
(
id: "0c800000000000000000000000000003",
balance: 90000,
frozen: false,
code: "MYB",
decimals: 2,
balance_limit: 18446744073709551615,
issuance: None,
)
As Bob, confirm receipt of funds
The following code checks Bob's balance to confirm credit of Alice's funds:
- CLI
- TypeScript
- Rust
Output
You should see something like the following with balance: 10000
:
(
id: "0c800001000000000000000000000003",
balance: 10000,
frozen: false,
code: "MYB",
decimals: 2,
balance_limit: 18446744073709551615,
issuance: None,
)
Now that you've taken the first steps in exploring the fundamental functions of the DRM platform, it's time to venture further and try the following:
- Request transaction and account information using the different keys you've created.
- Consider which personas can see which activities.
A key area of mastery that will enhance your understanding and utilization of the DRM platform is understanding how RBAC and the ledger hierarchy influence access and how they model the compliance requirements in financial services.