developers.diem.com/docs/wallets-and-merchant-stores/diem-reference-wallet/reference-wallet-set-up-modules.md
To set up your environment or deploy the Diem Reference Wallet, please refer to the latest information in the Backend README here.
The Reference Wallet is available as a web and mobile application.
The following API methods provide the backend interface for frontend client requests. The dedicated Flask blueprint under wallet/routes/cico.py handles all calls related to liquidity.
| Methods | Description |
|---|---|
GET /account/rates | Return to the client all available conversion rates between currency pairs. |
POST /account/quotes | Request for a quote for a currency pair exchange. Return a quote id. |
POST /account/quotes/<quote_id>/actions/execute | Execute the quote. At the end of execution, user balance will reflect the currency exchange. |
GET /account/quotes/<quote_id> | Return the quote execution status. |
This module is located under wallet/liquidity.
It contains all the utilities for rate calculation and client order processing, as well as a client to communicate with an external liquidity provider.
The client simulates a client SDK that interacts with an external liquidity provider. It allows its user to ask for quotes from the liquidity provider, execute a trade with the liquidity provider on a given quote, and demonstrate the fiat settlement interface.
This contains the code that handles the end-user order creation, status updates, and utility functions that contain the logic required for the order execution and cover processes.
This is a utility code that demonstrates rate calculation for different currency pairs with a fixed conversion table.
Exchange rates are pre-defined. The liquidity provider supports a predefined set of currency pairs with fixed conversion rates. The Diem Reference Wallet supports a richer set of conversions by managing a conversion table. This table describes the steps required to convert between currencies that do not have a direct conversion between them.
Virtual Asset Service Providers (VASPs), including custodial wallet providers operating on the Diem Payments Network (DPN), will be required to:
When a new user wishes to create a Diem wallet account, a VASP, in accordance with its compliance program, would assess the AML and sanctions risks of maintaining a business relationship with the user. The compliance module assesses these risks at the time of customer onboarding and on an ongoing basis through Know Your Customer (KYC) procedures and transaction monitoring.
KYC procedures are intended to allow the wallet provider to identify, and confirm if required, the identity of a prospective user and to assess the AML and sanctions risk of the user at onboarding and on an ongoing basis.
The nature of a wallet provider’s KYC assessment is governed by applicable AML and sanctions laws and regulations, and may differ by jurisdiction and the specific policies and procedures established by the VASP with respect to AML and sanctions compliance, including in the context of the customer onboarding process.
The Reference Wallet demonstrates an example of a risk-based KYC procedure that requests the user to provide personal identification information such as:
The type of information requested of a user, including follow-up information or documentation, may vary depending on certain risk factors (e.g., customer geography, expected activity, and product type).
The wallet provider must assess the risk of the client and ensure all the required regulatory checks take place. The wallet provider may undertake these checks themselves or may involve one or more service providers. Certain checks may be automated while others may be manual.
In this demo, the user data is sent to an external KYC provider to assess the user. Though in this project, the KYC provider is not actually checking the user, and all users are automatically approved.
But, in a real-world scenario, such an external provider would undertake certain checks of the prospective user. Examples of such checks include sanctions screening, negative news screening, black-listed country screening, and document verification. Based on this information, the provider would assign a risk rating that would help the wallet provider decide whether to onboard the customer or whether certain controls (e.g., product or transaction limitations) may be appropriate in light of the user's risk.
After a user has been onboarded, the wallet provider, pursuant to relevant laws and regulations, Diem Network standards, and its compliance program, must continue to assess the risk related to maintaining a business relationship with the user.
<BlockQuote type="warning"> The compliance processes depicted in this document are for demonstration purposes only and do not reflect the specific compliance obligations of VASPs under applicable regulatory frameworks, their compliance programs, and/or standards imposed by Diem Networks. </BlockQuote>Wallet providers generally must also conduct transaction monitoring on an ongoing basis to prevent their services from being used to conduct or facilitate illicit activity such as money laundering, terrorist financing, and/or violation of applicable sanctions. Transaction monitoring procedures must be designed to comply with relevant laws and regulations, Diem Network standards, and should be commensurate with a wallet provider’s risk profile.
In a real-world scenario, transaction monitoring would generally encompass both inbound and outbound payments. Examples of behaviors that transaction monitoring may seek to identify are:
As with KYC, a wallet provider may conduct transaction monitoring themselves (e.g., through a financial intelligence function) or engage a service provider to assist in this process. In any case, the wallet provider remains ultimately responsible for its compliance with applicable laws and regulations and Diem Network standards.
In a real world scenario, transaction monitoring may lead to various outcomes depending on the activity identified. These include but are not limited to:
In a real-world situation, a wallet provider conducts continuous monitoring of its customers through periodic and risk-based KYC refreshes and transaction monitoring procedures. In addition, transactions on the DPN will be subject to Diem Networks' Financial Intelligence Function (FIF) network monitoring. This network-wide monitoring, together with transaction monitoring undertaken by DPN service providers, will seek to detect illicit activity, including with respect to money laundering, terrorist financing, and other potentially evasive uses of the platform. The FIF will report identified activity to relevant regulators and law enforcement, where appropriate.
In this demo project, we use an external risk provider as a placeholder for transaction monitoring and regulatory checks. The service will always approve the transactions since no actual checks are performed. Since no specific reviews are actually being performed and no activity is actually being monitored in the demo project, no payments will be blocked, denied, or reported.
As a custodial wallet, all blockchain transactions must use the wallet provider signature. When a transaction is approved on-chain, there is no way to reverse it. The wallet provider should take whatever measures it determines appropriate to ensure that the transaction request was made by the user and is not a fraud attempt, before submitting the transaction.
In the DPN, the transactions are done between VASPs and then allocated to the end users. A fraudulent transaction can be reversed if the VASPs recognize it as such.
The Custody module handles crafting and signing transactions. Once a VASP is ready to settle a transaction on-chain, the custody module needs to craft the transactions, sign with its private key, and return the signed transaction. The custody module should be the only service that has access to the wallet’s private key.
| Implementation | Description |
|---|---|
| Private Keys | For the local development of the Reference Wallet, the private key is randomly generated on instantiation of the wallet app. It can also take a private key via environment variable as _CUSTODIAL_PRIVATE_KEY_. |
For this demo wallet, we do not show an implementation of providing secure storage of private keys. Custody uses the pydiem library to create signed transactions. |
| Extend Functionality | Description |
|---|---|
| Custody solution | A robust custody solution should be plugged in for a production-level product. |
The liquidity inventory setup is part of the backend startup sequence. At start, an internal inventory user is created. This internal user manages the balance of the internal custody wallet inventory. After its creation, the backend “buys” its initial Diem Coins from the external liquidity provider. The custodial wallet provider directs the liquidity provider to send purchased Diem Coins to the custody wallet’s Diem blockchain address.
From this point, the custodial wallet service can engage in transfers between its inventory account and the wallet user accounts to transfer the requested funds.
A wallet user can select the following transfer types in the reference wallet
This transfer type is when a user wants to add funds to their wallet balance.
For example, if a user wants to add 100 Coin1 and clicks “Add”.
Usually, the cover process is independent of the order execution process and contains elements like exposure management, risk management, trading strategies, spread management, and more.
The cover process in the Reference Wallet is executed back-to-back with the order execution. In our example, the backend will be covered by trade with the liquidity provider.
The wallet uses the cover process to balance its inventory after transactions with user accounts. In this example, the wallet exchanges 100 USD for 100 Coin1 from the liquidity provider to balance its inventory.
In the withdrawal process, things work the other way around. The user payment method is refunded, an internal transaction moves Diem Coins from the user account (off-chain) to the inventory account, and then in the cover process Diem Coins are traded in exchange for fiat back-to-back with the liquidity provider.
For the purpose of simplifying this Reference Wallet, the conversion between Diem Coins of different currencies is represented by transactions between the custodial wallet and the user and reflected by internal transfers (off-chain) between the user account and the inventory account.
Settlement flow is not implemented at this point. This is the process where the liquidity provider and custody wallet settle the fiat balances owed to each other by passing a reference for fiat wire transfers between the custody wallet bank account and the liquidity provider bank account and vice versa to settle the debt. The settlement interface and internal structures are demonstrated in the liquidity provider-client implementation.
The wallet UI is fully translatable using standard React i18n library react-i18next. All texts are mapped in JSON files located at frontend/src/locales/LANGUAGE.
To generate new translations, a script is available for auto-generating new translations using a third-party translation service or exporting all existing text into a CSV file for manual translation.
Located at scripts/generate_i18n.py are usage examples for translating from English to Spanish. ./scripts/generate_i18n.py -s en -d es -a this will use EN JSON files located at frontend/src/locales/en and generate new JSON files at frontend/src/locales/es.
Instructions for using the newly generated files will be shown upon completing these steps:
import ES from "./es"; to frontend/src/locales/index.tses: ES; to the default Resource object in thereTo extract translations into a CSV file for manual translations, you can use the export flag:
./scripts/generate_i18n.py -s en -d es -e ./english_texts.csv
To import manually translated CSV you can use the import flag:
./scripts/generate_i18n.py -s en -d es -i ./english_texts.csv
Login and authentication deals with all logic related to a user creating a new account, signing in, logging out, and keeping a session.
The main features of this module's implementation in the Reference Wallet include:
| Implementation | Description |
|---|---|
| User registration | * During registration, the user will choose a unique username and password, and provide information such as name, date of birth, and other Know Your Customer (KYC) related information. |
| Extend Functionality | Description |
|---|---|
| Session management | The bearer token is just one way of doing session management. Other forms of authentication can be used to make server calls more secure. |
| Login and authentication | Login and authentication can be made more secure by incorporating two-factor authentication. |
https://github.com/diem/reference-wallet/blob/master/backend/wallet/services/account.py
PubSub allows us to continually poll the blockchain and respond to events on-chain. Specifically, for the Reference Wallet, we’re listening to payments made to a VASPs’ public on-chain addresses.
| Implementation | Description |
|---|---|
| Pubsub module | Our pubsub module is based on an open source project called pubsub_proxy, a lightweight wrapper around pydiem. For the Reference Wallet, we redirect all events delivered by pubsub_proxy directly to our wallet service’s on-chain module for internal processing. |
PubSub depends on the PUBSUB_ADDR environment variable. |
| Extend Functionality | Description |
|---|---|
| Pubsub module | Pubsub_proxy is designed to be extensible. You can extend BasePubSubClient to determine how to handle incoming payment events. |
| Implementation | Description |
|---|---|
| Risk module | The Reference Wallet has a very simple risk check that happens synchronously with each transaction; it is a mocked out API that is simply based on the amount of the transaction. In production, the VASP will need to determine the risk check that is necessary to comply with AML and fraud prevention. |
A VASP needs to be able to handle the following on-chain transactions:
The Reference Wallet shows the workflow of each of these transaction types.
| Implementation | Description |
|---|---|
| Internal P2P transfer | Internal P2P transfer entails a simple balance check and storage update, and does not require any on-chain settlement. |
| External P2P Transfer | External P2P transfers are transactions between users in different VASP networks. This type of transaction requires an on-chain settlement. |
For any amount less than the amount needed for compliance, a VASP can directly send the transaction on-chain without doing any KYC validation. This type of transaction uses pydiem. |
| Extend Functionality | Description |
|---|---|
| Types of transactions | Currently the Reference Wallet only implements three types of transactions. However, as the scope increases, other types of transactions, such as merchant pull request flow, could be added to extend the functionality of the Reference Wallet. |
The Reference Wallet uses SQL as its data store, and SQLAlchemy as the Python toolkit and object relational mapper. Storage is part of the Wallet module, and consists of models and utils. In wallet/storage, models.py defines the tables, and utils are divided into respective modules based on which object the util reads or modifies.
User table stores all information related to the user’s identity, registration, and KYC information. On user registration, username, and password information are stored. KYC information such as full name, dob, address, and phone number are also stored during the registration process.
While the user table deals with a user’s identification and login information, the account table purely deals with the user’s transactions. Each user has an account, in which all transactions and balances are stored. There is a special case for the admin user, who does not have any corresponding account. Currently each user has a single account, but the wallet could be extended for a user to hold multiple accounts. Another special case is the inventory account, which doesn’t have any corresponding user.
Transactions table stores all the metadata of sending or receiving transactions. Depending on the transaction type, each transaction object may not have certain rows filled. For example, in the case of an in-network transaction, blockchain_version and sequence will be None since an in-network transaction does not require a blockchain transaction. In the case of an external transaction, either the source_id or the destination_id may be missing, since we will not have an ID for the external user.
Transaction log table stores the status of transactions as they get processed. These logs can be exposed to the user to show which stage a transaction is at. Example logs include “Settled on-chain” and “Transaction complete.”
Subaddress is the internal user address of the Reference Wallet. A subaddress is an 8-byte string that is meant to be one-time use. A new subaddress is generated each time a user generates a receiving address to send to a sender.
Token table stores user session tokens for session authentication. When a user creates an account or signs in to their account, the server generates a token and stores it in the token table along with user_id and expiration_time. Whenever a user makes an API call, we check if the token exists in the table and that expiration_time has not passed.
The execution log table is used for debugging and the data is not exposed to the user. Execution logs can easily be added in any function using add_execution_log().
Service APIs are a set of backend APIs that are organized in terms of high-level wallet functionalities. They are defined in the webapp layer, and the frontend uses these APIs to communicate with the backend. The service APIs are RESTful APIs that are divided into user, account, CICO, and admin.
Docs can be generated locally using SwaggerUI. Instructions for how to get that set up can be found in the backend README under “Getting Started”, linked here.
User APIs handle user creation, and information management and updates.
<small className="figure">Figure 1.0 User APIs</small>
Account APIs deal with an account’s address and transactions management.
<small className="figure">Figure 1.1 Account APIs</small>
CICO handles all cash-in and cash-out flows, including getting rates and executing a given quote.
<small className="figure">Figure 1.2 CICO APIs</small>
Admin APIs fetch admin user account information and have debt settlement logic.
<small className="figure">Figure 1.3 Admin APIs</small>