Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Your app's own DSM account

Your app gets a DSM account. Not an API key, not a merchant id: an account like a wallet's, with its own identity, running the same code a phone runs.

your web app→loopback ingress
+ per-launch secret
→dsm-app-host
your account
→storage nodes

Your web app stays what it is: Node, Python, whatever it is today. Beside it runs one process, the app host, and that process is your account. Your app talks to it over a local socket on the same machine, loopback only, with a secret the host writes for each launch. Wallets reach the host over TLS, through its relay.

1. Start it

In your app's folder:

dsm-app up

This runs dsm-app-host in the background with a data directory, a directory for the ingress secret, and the beta network's client config, which the host carries: the same five storage nodes the wallet ships with. It keeps them under .dsm-dev in this folder.

The first launch creates the account. It writes a recovery mnemonic once to the data directory, readable by you alone, and makes the account the way a phone does. The host waits until the network holds the account's directory entry, and only then opens its ingress. Then the account is funded from the network's faucet.

What it prints, from a run on the beta network (13 seconds, on a Mac):

[dsm-app] app account running
  storage set:    the beta network (carried in dsm-app-host)
  ingress:        http://127.0.0.1:8787   (your server calls this)
  ingress secret: …/.dsm-dev/app/ingress/ingress-token
  relay:          https://127.0.0.1:8443   (wallets reach this)
  recovery:       …/.dsm-dev/app/data/RECOVERY_MNEMONIC
  log:            …/.dsm-dev/app/host.log
funded: claimed 100.00 ERA (economic position 1)

… is your app's folder. Line by line:

  • storage set: the beta network, hosted.
  • ingress, on loopback port 8787: your server calls this.
  • ingress secret: in its own directory, so your app can read the secret and nothing else of the account.
  • relay, on port 8443: wallets reach this.
  • recovery: the recovery mnemonic.
  • funded: 100 ERA from the faucet.

Warning

Back up the recovery mnemonic like a wallet's, because that is what it is. Whoever can read the data directory controls the account.

dsm-app up returns once the account is running; the host keeps running in the background. dsm-app down stops it, and dsm-app status says whether it runs. Run dsm-app up again whenever you like: it keeps the same account, and claims nothing more from the faucet once the account holds ERA (it says already holds and the amount).

2. Look at it

dsm-app talks to the account through the same ingress your code will. id prints the account's identity:

dsm-app id
P1TTQ65K20YCW6FCHVJ8A8V0VQ55NN3DZK6KCBFMCC3M98KN3X2G

owned prints what it holds: a hundred ERA from the faucet, and nothing of dBTC yet.

dsm-app owned
ERA                100.00   currency NNG176RZ6ACTWCDPRNYHXZK2DCZ72SPA9Q6XWGRGQ9JGKZYTESG0
dBTC           0.00000000   currency 0EJ2PSRS2YQR8BR77P3WZ92SV12VJT7XP6NWP0SH5P8MWD81C8H0

Each line is an object: its symbol, the amount in its own units, its kind, and its id.

activity is the account's own record of every call made through the ingress:

dsm-app activity
account P1TTQ65K20YCW6FCHVJ8A8V0VQ55NN3DZK6KCBFMCC3M98KN3X2G
1  ROUTE  faucet.claim  claim ERA from the network's faucet  -> claimed 100.00 ERA (economic position 1)

Your app can read the activity too, from any point. That is how it learns what happened without trusting anyone's say-so. Your identity and ids will differ from these; everything else reads the same.

3. The ingress

Three routes make the ingress:

RouteWhat it does
POST /ingressMakes a call, and records it in the account's activity.
POST /ingress/quietMakes a call that is not recorded: what your app polls with.
GET /activity/{after}Reads what was recorded after that point.

Every call carries the launch's secret as Authorization: Bearer <secret>, must name the ingress as its Host, and may come from no other web origin. A web page in a browser on the same machine can neither read the secret nor send it. The clients wrap all of this; you will not write these requests by hand.

4. The wire

On the wire, each call is one protobuf message, the route's name and its arguments, answered with one message back. The schema is one file, proto/dsm_app.proto, and the TypeScript and Python clients are generated from it. For a client in another language, that file is all you need: send an IngressRequest (a RouterInvokeOp or RouterQueryOp: the route's name and an ArgPack holding its request message) to POST /ingress, and an IngressResponse comes back. clients/typescript/src/ingress.ts is the whole exchange, in one short file.

5. The first call

Here is the first call in TypeScript and in Python: open the local account, and ask for its connections. First the client, into your app's folder. TypeScript, from the package the install put in ~/.local/share/dsm/clients:

npm init -y
npm install ~/.local/share/dsm/clients/dsm-app-client-0.1.0-beta.4.tgz

npm init -y makes a package.json if your folder has none. The client's types are inside the package, so nothing is compiled. Then:

import { localAccount } from "dsm-app-client";

const app = await localAccount("app");
console.log(await app.connections());
from dsm_app_client import local_app

app = local_app()
print(app.connections())

Each prints an empty list: nothing is connected yet. localAccount("app") and local_app() find the account dsm-app up started by looking for the .dsm-dev folder above the folder you run in; from anywhere else, name it with DSM_DEV_DIR. Write it into your app runs whole programs.

The Python client goes into a virtual environment, from its package beside the TypeScript one:

python3 -m venv .venv && . .venv/bin/activate
pip install ~/.local/share/dsm/clients/dsm_app_client-0.1.0b4-py3-none-any.whl
python3 ~/.local/share/dsm/examples/account_status.py

account_status.py prints your account at a glance: its identity, what it owns, every connected wallet with what it may do, and the latest activity. Its types are inside the package too, so pip installs it with nothing to compile; it fetches one dependency, protobuf.

The whole page, as one script

dsm-app up
dsm-app id
dsm-app owned
dsm-app activity

Next: Make an offer, connect a wallet.