What is Daedalus

In developing Cardano SL, the need arose for a UI from which users could access their funds, send and receive transactions, and perform other tasks related to managing a personal cryptocurrency wallet. The Daedalus wallet is the Cardano’s solution to these necessities.

Currently, it allows a user to use their ADA in the aforementioned actions, and support for other currencies is planned for the near future, as is the exchange between different currencies, both digital and not.

Building daedalus-client-api

To run daedalus-client-api locally you have to start the wallet-api of cardano-sl as follows. Make sure that you are in the root folder of cardano-sl.

# build app
stack build
# remove old PureScript types if they exist
rm -rf daedalus/src/Generated
# generate PureScript types
stack exec -- cardano-wallet-hs2purs

This should create PureScript modules with datatypes bridged from Haskell. You should have similar structure like:

$ tree daedalus/src/Generated/
daedalus/src/Generated/
└── Pos
	├── Types
	│   └── Core.purs
	├── Util
	│   └── BackupPhrase.purs
	└── Wallet
		└── Web
			├── ClientTypes.purs
			└── Error.purs

Running and testing daedalus-client-api

In order to see daedalus-client-api in action, first run a local Cardano network:

# run tmux in another window
tmux
# launch nodes
export WALLET_TEST=1; ./scripts/launch.sh

By default, this should launch Cardano network consisting of 3 nodes talking to each other. WALLET_TEST=1 tells the launcher script to run wallet-api with one node. This one node running wallet-api will behave the same as Daedalus wallet that is run in production. If you experience any issues, remove the following content first and build wallet-api again as described above.

rm -rf ./run/*
rm -rf wallet-db
rm node-*.*.key

With a running wallet-api you can run daedalus-client-api locally as follows. Please note that npm is required to build daedalus-client-api.

cd daedalus
npm install
npm run build:prod

Now we can try using the client API with nodejs:

$ node
> var api = require('../output/Daedalus.ClientApi')
undefined
> api
{ applyUpdate: [Function],
  blockchainSlotDuration: [Function],
  deleteWallet: [Function],
  generateMnemonic: [Function: generateMnemonic],
  getHistory: [Function],
  getProfile: [Function],
  getWallet: [Function],
  getWallets: [Function],
  importKey: [Function],
  isValidAddress: [Function],
  isValidMnemonic: [Function],
  newWallet: [Function],
  nextUpdate: [Function],
  notify: [Function],
  redeemADA: [Function],
  restoreWallet: [Function],
  restoreWalletIgnoreChecksum: [Function],
  searchHistory: [Function],
  send: [Function],
  sendExtended: [Function],
  syncProgress: [Function],
  systemVersion: [Function],
  testReset: [Function],
  updateProfile: [Function],
  updateTransaction: [Function],
  updateWallet: [Function] }

This will load and show all functions that can be run from from this library to interact with the wallet. For example, to fetch all available wallets we can do:

> api.getWallets().then(console.log).catch(console.log)
Promise { <pending> }
> [ { cwMeta:
	 { cwType: 'CWTPersonal',
	   cwName: 'Personal Wallet',
	   cwCurrency: 'ADA' },
	cwAmount: { getCoin: 33333 },
	cwAddress: '1gLFDJAKutVJCYioMANx4gthHru5K12Tk9YpEmXKQfggKZu' } ]

Note: daedalus-client-api is not optimized/compressed. This is will be a job for Daedalus.

Wallet Frontend API

Currently, the wallet’s API provides a series of methods to work with wallets. The servant Haskell library that provides a modular approach to API-building is used. This library uses combinators to both build atomic HTTP actions and to glue these atomic methods together to form larger and more complete APIs.

If the event requests fail, there is a WalletError type, which is just a wrapper over Text to show what has happened.

Please note that:

  • The code Post '[JSON] and Get '[JSON] indicates that the type of the contents in the message will be [JSON].
  • ReqBody '[JSON] t extracts the request body [JSON] as a value of type t.

Currently, the wallet’s API supports the following operations (see Comments below):

API Endpoint Parameter Optional parameters Description
GET /api/addresses     Returns all addresses contained in wallet.
GET /api/addresses/:address/currencies/:currency address - Address
currency - Currency
  Reply with True if the address is valid, and False otherwise. [4]
GET /api/profile     Fetch the client’s current user profile - the datatype CProfile. [5]
POST /api/profile     Update the user’s profile, returning the new one in the process.
POST /api/redemptions/ada     Redeem ADA from a token [6], create and return a wallet with the redeemed ADA.
POST /api/reporting/initialized     Initialize reporting.
GET /api/settings/slots/duration     Fetch the value of current slot duration.
GET /api/settings/sync/progress     Synchronization progress.
GET /api/settings/version     Fetch the system’s version.
POST /api/test/reset     The key reset when running dev mode.
GET /api/txs/histories/:address address - Address, history of which should be fetched
skip - Skip this many transactions
limit - Max numbers of transactions to return
Fetch a tuple with the list of transactions where the address took part in the index interval [skip + 1, limit], and its length. [2]
GET /api/txs/histories/:address/:search address - Address, history of which should be fetched
search - Wallet title search pattern
skip - Skip this many transactions
limit - Max numbers of transactions to return
Fetch a tuple with the list of transactions whose title has search as an infix, in the index interval [skip + 1, limit], and its length. [2]
POST /api/txs/payments/:address/:transaction address - Address, history of which should be fetched
transaction - Transaction id
  Add the transaction that has the given ID to the wallet’s transaction history, if such a transaction exists.
POST /api/txs/payments/:from/:to/:amount from - Address which coins should be sent from.
to - Destination address.
amount - Amount of coins to send.
  Send coins in the default currency (presently, ADA) from an origin address to a destination address, without any transaction message or description. [1]
POST /api/txs/payments/:from/:to/:amount/:currency/:title/:description from - Address from which coins should be sent.
to - Destination address.
amount - Amount of coins to send.
currency - Currency
title - Transaction title
description - Transaction description
  Send coins with currency (presently, ADA) from an origin address to a destination address, with title and description.
GET /api/update     Fetch information related to the next update.
POST /api/update     Apply the system’s most recent update.
GET /api/wallets     Fetch all wallets which the system has access to.
POST /api/wallets     Create a new wallet.
DELETE /api/wallets/:walletId walletId - WalletId, walletId = address, future versions should have HD wallets, and then it should have multiple addresses
  Delete the wallet associated to an address.
GET /api/wallets/:walletId walletId - WalletId, walletId = address, future versions should have HD wallets, and then it should have multiple addresses
  Fetch the wallet related to a given address address, if it exists.
PUT /api/wallets/:walletId walletId - WalletId, walletId = address, future versions should have HD wallets, and then it should have multiple addresses
  Given an address and wallet meta-information, update the address’ wallet.
POST /api/wallets/keys     Import wallet from a key.
POST /api/wallets/restore     Recover the wallet associated to the given backup information [3], if it exists.

Comments:

  • [1]: Neither of these methods presently support many-to-many transactions.
  • [2]: The transactions are in ascending order of age, i.e. newer transactions come first.
  • [3]: https://github.com/bitcoinjs/bip39#reminder-for-developers
  • [4]: Presently, any currency other than ADA results in a False.
  • [5]: CProfile has several fields, among them: the user’s name, their email, their phone number, the hash of their password, the POSIX-formatted time at which the account was created, their location, and the account’s picture.
  • [6]: An ADA redemption token is represented by the datatype CWalletRedeem, which has the address where the ADA intended to be redeemed will go to, and a redemption seed.

Wallet events

Aside from these HTTP endpoints there is one unidirectional websocket channel opened from server to client. This channel serves as notification system so that Daedalus UI can be informed about events. Currently supported events are:

  • LocalDifficultyChanged - local blockchain height
  • NetworkDifficultyChanged - global blockchain height
  • UpdateAvailable - new system update available
  • ConnectedPeersChanged - number of peers connected to the node changed
  • ConnectionOpened - websocket connection opened
  • ConnectionClosed - websocket connection closed

As this channel is unidirectional, any message sent to the channel from the client will be ignored.