Setting Up the Interface

First, clone the interface from github: git clone https://github.com/gnosis/pm-trading-ui.git

Setup

Run npm i to install all dependencies. Now you can already start the application like such: NODE_ENV=development npm start and it will run a local webpack server on which you can test.

In order to build a production version, run NODE_ENV=production npm build and it will create a /dist folder that will be filled with a minified and bundled interface application.

But first let’s configure the interface:

Configuration

The pm-trading-ui uses a runtime configuration so that we have the ability to deploy changes to the configuration at runtime. It works by having a default fallback configuration, and multiple different environments and configuration files.

Let’s look at a practical example, let’s say we want to setup an automated “staging” or pre-production environment. For this example I’ll use our mainnet configuration example:

/config
├── fallback.json  # the default configuration file, don't edit this file!
├── local.json
├── mainnet
│   ├── development.json
│   ├── production.json
│   └── staging.json # our desired environment configuration, do edit this file
└── olympia
    ├── production.json
    └── staging.json

You only need to define what you need in the specific configuration. Everything that is not defined, will be taken from fallback.json, which will run only the bare minimum of features.

Now, let’s build and deploy our application. First, we need to create the /dist folder by running NODE_ENV=production npm build. Now we need to copy our desired configuration into our build folder in a special way as config.js. This method allows us to easily exchange it later on, either automated using a CI system or manual, without having to build everything again.

In order to copy the configuration file, we prepared a script that will copy and prepare the configuration file automatically. node ./scripts/configuration.browser.js mainnet/staging

configuration.browser.js is a simple script to copy, minify and add a crucial window.__GNOSIS_CONFIG__= snippet in front of your JSON config (as you can’t embed JSON as script files in HTML)

After this step, your application is ready to be run. Deploy your application to your filehoster of choice and access the page - the previously mentioned config.js will be used to determine the configuration, at runtime.

Basic Configuration Documentation

A quick rundown of all configuration entries, their meanings and their possible values. Please note that the interface currently does not throw warnings or errors, if you mistype a config entry, and will probably just use the fallback configuration.

Trading DB

gnosisdb configures which trading-db you want to use to run the interface. The pm-trading-db package is required in order to keep track of previous markets, without having to fully sync an ethereum node, each time you want to access the interface.

protocol - either https or http

host - hostname for the database.

port - 443 is the default for SSL.

{
  "gnosisdb": {
    "protocol": "https",
    "host": "example.com/trading-db",
    "port": 443
  },

Ethereum Node

ethereum configures which ethereum node should be used to interact with the application. Infura is what we use and what is tested most in depth, but all other full-nodes should work too.

protocol - either https or http

host - hostname for the database.

port - 443 is the default for SSL.

  "ethereum": {
    "protocol": "https",
    "host": "rinkeby.infura.io",
    "port": 443
  },

Gas Price Calculation

In order to display the cost of transactions, we require an external gas-estimation service. Multiple different ones are available, ETHGasstation is the default but you can also define your own (take a look at the code).

external.url - the API url from which to fetch the gas price information

external.type - Which implementation does the API use? currently only available ETH_GAS_STATION but extendable, as mentioned above.

  "gasPrice": {
    "external": {
      "url": "https://ethgasstation.info/json/ethgasAPI.json",
      "type": "ETH_GAS_STATION"
    }
  },

If you rather use the built-in gas estimation, which is supectible to gas-price attacks, define this entry as such:

  "gasPrice": {
    "external": false
  }

Market Creator Whitelist

The whitelist defines which users are allowed to create markets on your interface. Currently there is no way to disable the whitelist.

The object keys define the allowed addresses, the values (currently unused) are simply used as a way to remember which address belongs to which user. Please enter all addresses (the keys) in lowercase

  "whitelist": {
    "0x123...": "Admin #1"
  },

Logo and Favicon

This property defines which icons the interface should use for different screensizes and as a favicon. All paths are defined from the root of the /src folder

  "logo": {
    "regular": "assets/img/gnosis_logo.svg",
    "small": "assets/img/gnosis_logo_icon.svg",
    "favicon": "assets/img/gnosis_logo_favicon.png"
  },

Tournament Mode

Enabling Tournament Mode will currently enable the following functionality

  • Custom Application Name will be used
  • Gamification Stats on /dashboard Page
  • Scoreboard, if desired
  • Gamerules, if desired
  "tournament": {
    "enabled": false,
    "name": "My Tournament"
  },

Scoreboard

If you want to use a scoreboard in your application, please take a look at pm-trading-db.

  "scoreboard": {
    "enabled": false
  },

Gameguide

The gameguide allows you to set rules and information for new users. In Olympia this is used to tell the user, how to use the interface if they’re new to ethereum and the blockchain.

  "gameGuide": {
    "enabled": false
  },

Define a Collateral Token

You can define which collateral token the application should use when interacting with markets. Setting this property will also filter all markets based on their collateral, meaning only markets with the same collateral token as the one that was defined here will be shown!

source - defines how you want the ERC20 token contract should be found

contract - means you define a contract thats available in pm-jss Contracts property. To implement this, take a look at how this was done for our olympia tournament contracts.

address - hardcoded address of the contract that’s available on the network defined in ethereum. This is probably the easiest to setup.

eth - uses a combination of Ether and WETH, a ERC20 wrapped Ether token. Take a look here, for more information on this contract

contractName - is only required when using source: "contract", defines the name of the contract to be loaded.

isWrappedEther - if your collateralToken is a derivative of ETH (WETH), setting this to true will combine this token balance with the users wallet balance. This way we can show a total balance, with already wrapped collateral and wallet balance.

symbol - is used to overwrite the symbol. If this is not defined, it will try to use the name of the ERC20 token after loading it.

icon - used to display next to the amount of collateral a user has. If not defined, will use a default ethereum style icon.

  "collateralToken":  {
    "source": "contract",
    "options": {
      "contractName": "etherToken",
      "isWrappedEther": true,
      "symbol": "ETH",
      "icon": "/assets/img/icons/icon_etherTokens.svg"
    }
  },

Wallet Integrations

There are multiple different built-in providers that can be used with the interface. The most tested provider is metamask. Take a look at the code in order to build your own. Currently, the following providers are available: parity, metamask, remote, uport. All providers are always available, as long as the correct network is used.

default - defines which provider to use when multiple providers were found, or if no provider was found to tell the user which provider is recommended to interact with the application.

requireTOSAccept - if you require the user to accept the terms and conditions before they can connect to the application and interact with it.

  "providers": {
    "default": "METAMASK",
    "requireTOSAccept": false
  },

Reward Claiming

See here

  "rewardClaiming": {
    "enabled": false,
    "claimReward": {
      "enabled": false,
      "claimStart": "2018-06-01T12:00:00",
      "claimUntil": "2018-07-01T12:00:00",
      "contractAddress": "0xe89f27dafb9ba68c864e47a0bf1e430664e419af",
      "networkId": 42
    }
  },
  "rewards": {
    "enabled": false,
    "rewardToken": {
      "symbol": "RWD",
      "contractAddress": "0x84b06a41095be5536b3e6db1ee641ebc2f38cfcb",
      "networkId": 3
    }
  },

Badges and Levels

You can enable user-badges for your tournament by enabling this feature. It will add a custom icon next to the users providers in the header, based on the amount of predictions they made.

  "badges": {
    "enabled": true,
    "ranks": [
      {
        "icon": "assets/img/badges/junior-predictor.svg",
        "rank": "Junior Predictor",
        "minPredictions": 0,
        "maxPredictions": 4
      },
      {
        "icon": "assets/img/badges/crystal-gazer.svg",
        "rank": "Crystal Gazer",
        "minPredictions": 5,
        "maxPredictions": 9
      },
      {
        "icon": "assets/img/badges/fortune-teller.svg",
        "rank": "Fortune Teller",
        "minPredictions": 10,
        "maxPredictions": 14
      },
      {
        "icon": "assets/img/badges/clairvoyant.svg",
        "rank": "Clairvoyant",
        "minPredictions": 15,
        "maxPredictions": 19
      },
      {
        "icon": "assets/img/badges/psychic.svg",
        "rank": "Psychic",
        "minPredictions": 20
      }
    ]
  }

Third party Services

In order to determine which third party integrations we want to use, we developed a plug-in system for integrations that can be included at a global scope, such as Google Analytics and the Chat Platform Intercom. To see how this was done, take a look at the code.

  "thirdparty": {
    "googleAnalytics": {
      "enabled": false,
      "config": {
        "id": "UA-000000-2"
      }
    },
    "intercom": {
      "enabled": false,
      "config": {
        "id": "INTERCOM_USERID"
      }
    }
  },
}

WIP: KYC/AML Customer Verification

For legal compliance, we integrated a KYC provider, which can be enabled if necessary. If you’re running on the test-net or a private interface, you most likely won’t need this.

  "verification": {
    "enabled": true,
    "handler": "onfido",
    "options": {
    }
  }

Misc Constants

These are configurable constants in the application.

LIMIT_MARGIN - during trading it can happen that the margin for trade has been reduced by another users trade, after the specified amount (in percent) the user will receive a warning that the trade has been chaged.

NOTIFICATION_TIMEOUT - how long it takes for transaction notifications to be considered timed out (milliseconds).

LOWEST_VALUE - lowest possible value to display in the interface. Any value below will be shown <${value}, e.g. Sell Price: <0.001

  "constants": {
    "LIMIT_MARGIN": 5,
    "NOTIFICATION_TIMEOUT": 60000,
    "LOWEST_VALUE": 0.001
  }