Diff
Not logged in

Differences From Artifact [a4b120450a]:

To Artifact [3d251bcce4]:


    66     66   
    67     67   Each ILSP needs to have one or more connectors to route the ILP packets from its customers to the Interledger and vice versa.
    68     68   
    69     69   Some ILSPs are simply customers of a larger ILSP. Others are so-called tier-1 ILSPs. Tier-1 ILSPs have a special responsibility, they provide routing services for the network.
    70     70   
    71     71   This implementation of the connector contains a routing protocol implementation for tier-1 connectors. Please note that in order to become a tier-1 connector you need to have a relationship with one or more existing tier-1 connectors and they need to trust you not to overwhelm them with traffic or harbor malicious customers on your network.
    72     72   
           73  +## Timekeeping
           74  +
           75  +Timekeeping is an important part of processing transactions. Your node must have the right time set to make sure it can handle packets from peers correctly. If you drift too far from the current time, your node will have a different time to your peers and might start to experience strange issues and/or accept/reject packets incorrectly. 
           76  +
           77  +It is highly recommended you run some kind of time synchronisation service on your server. If you need help to install tools for keeping your clock in sync, this article describes how to do it:
           78  +https://www.techrepublic.com/blog/data-center/syncing-time-in-linux-and-windows-with-ntp/
           79  +
    73     80   ## Quickstart
    74     81   
    75     82   ```sh
    76     83   npm install -g ilp-connector ilp-plugin-btp
    77         -CONNECTOR_STORE_PATH=~/.connector-data CONNECTOR_ACCOUNTS='{}' CONNECTOR_ILP_ADDRESS=test.quickstart ilp-connector
           84  +CONNECTOR_STORE_PATH=~/.connector-data CONNECTOR_ACCOUNTS='{}' CONNECTOR_ADMIN_API=true CONNECTOR_ILP_ADDRESS=test.quickstart ilp-connector
    78     85   ```
    79     86   
    80     87   You are now running a connector!
    81     88   
    82     89   ##### What's next?
    83     90   
    84     91   * [Connect your connector to the Interledger](#connect-your-connector-to-the-interledger)
................................................................................
   205    212   
   206    213   #### `accounts`
   207    214   
   208    215   * Environment: `CONNECTOR_ACCOUNTS`
   209    216   * Type: `object`
   210    217   * Default: `{}`
   211    218   
   212         -| Name                          | Type    | Description                                                                                                                                                                                                                                                                                                                                                                             |
   213         -| ----------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   214         -| `*`                           | object  | Description of individual account.                                                                                                                                                                                                                                                                                                                                                      |
   215         -| `*.relation`                  | string  | Relationship between the connector and the counterparty that the account is with.                                                                                                                                                                                                                                                                                                       |
   216         -| `*.plugin`                    | string  | Name of the ILP plugin that should be used for this account.                                                                                                                                                                                                                                                                                                                            |
   217         -| `*.assetCode`                 | string  | Currency code or other asset identifier that will be passed to the backend to select the correct rate for this account.                                                                                                                                                                                                                                                                 |
   218         -| `*.assetScale`                | integer | Interledger amounts are integers, but most currencies are typically represented as fractional units, e.g. cents. This property defines how many Interledger units make up one regular units. For dollars, this would usually be set to 9, so that Interledger amounts are expressed in nanodollars.                                                                                     |
   219         -| `*.balance`                   | object  | _Optional_ Defines whether the connector should maintain and enforce a balance for this account. The balance is always from the connector's perspective. Therefore, a negative balance implies the connector owes money to the counterparty and a positive balance implies the counterparty owes money to the connector. This setting is enforced by the built-in `balance` middleware. |
   220         -| `*.balance.maximum`           | string  | Maximum balance (in this account's indivisible base units) the connector will allow. The connector will reject incoming packets if they would put it above this balance. The format is a string containing an integer (which may be prefixed with `-` to indicate a negative value), `"-Infinity"` or `"Infinity"`.                                                                     |
   221         -| `*.balance.minimum`           | string  | _Optional_ Minimum balance (in this account's indivisible base units) the connector must maintain. The connector will reject outgoing packets if they would put it below this balance. The format is a string containing an integer (which may be prefixed with `-` to indicate a negative value), `"-Infinity"` or `"Infinity"`.                                                       |
   222         -| `*.balance.settleThreshold`   | string  | _Optional_ Balance (in this account's indivisible base units) numerically below which the connector will automatically initiate a settlement. The format is a string containing an integer (which may be prefixed with `-` to indicate a negative value) or `"-Infinity"`.                                                                                                              |
   223         -| `*.balance.settleTo`          | string  | _Optional_ Balance (in this account's indivisible base units) the connector will attempt to reach when settling. The format is an integer (which may be prefixed with `-` to indicate a negative value) as a string.                                                                                                                                                                    |
   224         -| `*.ilpAddressSegment`         | string  | _Optional_ What segment will be appended to the connector's ILP address to form this account's ILP address. Only applicable to accounts with `relation=child`. Defaults to the id of the account, i.e. the key used in the `accounts` config object.                                                                                                                                    |
   225         -| `*.maxPacketAmount`           | string  | _Optional_ Maximum amount per packet for incoming prepare packets. Connector will reject any incoming prepare packets from this account with a higher amount. Amount should be provided as an integer in a string (in atomic units). This setting is enforced by the built-in `maxPacketAmount` middleware.                                                                             |
   226         -| `*.options.*`                 | object  | _Optional_                                                                                                                                                                                                                                                                                                                                                                              |
   227         -| `*.rateLimit`                 | object  | _Optional_ Maximum rate of incoming packets. Limit is implemented as a token bucket with a constant refill rate. When the token bucket is empty, all requests are immediately rejected. This setting is enforced by the built-in `rateLimit` middleware.                                                                                                                                |
   228         -| `*.rateLimit.capacity`        | integer | _Optional_ Maximum number of tokens in the bucket.                                                                                                                                                                                                                                                                                                                                      |
   229         -| `*.rateLimit.refillCount`     | integer | _Optional_ How many tokens are refilled per period. The default refill period is one second, so this would be the average number of requests per second.                                                                                                                                                                                                                                |
   230         -| `*.rateLimit.refillPeriod`    | integer | _Optional_ Length of time (in milliseconds) during which the token balance increases by `refillCount` tokens. Defaults to one second.                                                                                                                                                                                                                                                   |
   231         -| `*.receiveRoutes`             | boolean | _Optional_ Whether we should receive and process route broadcasts from this peer. Defaults to `false` for `relation=child` and `true` otherwise.                                                                                                                                                                                                                                        |
   232         -| `*.sendRoutes`                | boolean | _Optional_ Whether we should broadcast routes to this peer. Defaults to `false` for `relation=child` and `true` otherwise.                                                                                                                                                                                                                                                              |
   233         -| `*.throughput`                | object  | _Optional_ Configuration to limit the total amount sent via Interledger per unit of time. This setting is enforced by the built-in `throughput` middleware.                                                                                                                                                                                                                             |
   234         -| `*.throughput.incomingAmount` | string  | _Optional_ Maximum incoming throughput amount (in atomic units; per second) for incoming packets. If this setting is not set, the incoming throughput limit is disabled.                                                                                                                                                                                                                |
   235         -| `*.throughput.outgoingAmount` | string  | _Optional_ Maximum throughput amount (in atomic units; per second) for outgoing packets. If this setting is not set, the outgoing throughput limit is disabled.                                                                                                                                                                                                                         |
   236         -| `*.throughput.refillPeriod`   | integer | _Optional_ Length of time (in milliseconds) during which the token balance increases by `incomingAmount`/`outgoingAmount` tokens. Defaults to one second.                                                                                                                                                                                                                               |
          219  +| Name                            | Type    | Description                                                                                                                                                                                                                                                                                                                                                                             |
          220  +| ------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
          221  +| `*`                             | object  | Description of individual account.                                                                                                                                                                                                                                                                                                                                                      |
          222  +| `*.relation`                    | string  | Relationship between the connector and the counterparty that the account is with.                                                                                                                                                                                                                                                                                                       |
          223  +| `*.plugin`                      | string  | Name or instance of the ILP plugin that should be used for this account. A plugin instance can only be passed when instantiating the connector from JavaScript.                                                                                                                                                                                                                         |
          224  +| `*.assetCode`                   | string  | Currency code or other asset identifier that will be passed to the backend to select the correct rate for this account.                                                                                                                                                                                                                                                                 |
          225  +| `*.assetScale`                  | integer | Interledger amounts are integers, but most currencies are typically represented as fractional units, e.g. cents. This property defines how many Interledger units make up one regular units. For dollars, this would usually be set to 9, so that Interledger amounts are expressed in nanodollars.                                                                                     |
          226  +| `*.balance`                     | object  | _Optional_ Defines whether the connector should maintain and enforce a balance for this account. The balance is always from the connector's perspective. Therefore, a negative balance implies the connector owes money to the counterparty and a positive balance implies the counterparty owes money to the connector. This setting is enforced by the built-in `balance` middleware. |
          227  +| `*.balance.maximum`             | string  | Maximum balance (in this account's indivisible base units) the connector will allow. The connector will reject incoming packets if they would put it above this balance. The format is a string containing an integer (which may be prefixed with `-` to indicate a negative value), `"-Infinity"` or `"Infinity"`.                                                                     |
          228  +| `*.balance.minimum`             | string  | _Optional_ Minimum balance (in this account's indivisible base units) the connector must maintain. The connector will reject outgoing packets if they would put it below this balance. The format is a string containing an integer (which may be prefixed with `-` to indicate a negative value), `"-Infinity"` or `"Infinity"`.                                                       |
          229  +| `*.balance.settleThreshold`     | string  | _Optional_ Balance (in this account's indivisible base units) numerically below which the connector will automatically initiate a settlement. The format is a string containing an integer (which may be prefixed with `-` to indicate a negative value) or `"-Infinity"`.                                                                                                              |
          230  +| `*.balance.settleTo`            | string  | _Optional_ Balance (in this account's indivisible base units) the connector will attempt to reach when settling. The format is an integer (which may be prefixed with `-` to indicate a negative value) as a string.                                                                                                                                                                    |
          231  +| `*.deduplicate.cleanupInterval` | integer | _Optional_ Frequency at which the connector removes old deduplicate records. (in milliseconds; defaults to 30 seconds)                                                                                                                                                                                                                                                                  |
          232  +| `*.deduplicate.packetLifetime`  | integer | _Optional_ Lifetime of a cache record. (in milliseconds; defaults to 30 seconds)                                                                                                                                                                                                                                                                                                        |
          233  +| `*.ilpAddressSegment`           | string  | _Optional_ What segment will be appended to the connector's ILP address to form this account's ILP address. Only applicable to accounts with `relation=child`. Defaults to the id of the account, i.e. the key used in the `accounts` config object.                                                                                                                                    |
          234  +| `*.maxPacketAmount`             | string  | _Optional_ Maximum amount per packet for incoming prepare packets. Connector will reject any incoming prepare packets from this account with a higher amount. Amount should be provided as an integer in a string (in atomic units). This setting is enforced by the built-in `maxPacketAmount` middleware.                                                                             |
          235  +| `*.options.*`                   | object  | _Optional_                                                                                                                                                                                                                                                                                                                                                                              |
          236  +| `*.rateLimit`                   | object  | _Optional_ Maximum rate of incoming packets. Limit is implemented as a token bucket with a constant refill rate. When the token bucket is empty, all requests are immediately rejected. This setting is enforced by the built-in `rateLimit` middleware.                                                                                                                                |
          237  +| `*.rateLimit.capacity`          | integer | _Optional_ Maximum number of tokens in the bucket.                                                                                                                                                                                                                                                                                                                                      |
          238  +| `*.rateLimit.refillCount`       | integer | _Optional_ How many tokens are refilled per period. The default refill period is one second, so this would be the average number of requests per second.                                                                                                                                                                                                                                |
          239  +| `*.rateLimit.refillPeriod`      | integer | _Optional_ Length of time (in milliseconds) during which the token balance increases by `refillCount` tokens. Defaults to one second.                                                                                                                                                                                                                                                   |
          240  +| `*.receiveRoutes`               | boolean | _Optional_ Whether we should receive and process route broadcasts from this peer. Defaults to `false` for `relation=child` and `true` otherwise.                                                                                                                                                                                                                                        |
          241  +| `*.sendRoutes`                  | boolean | _Optional_ Whether we should broadcast routes to this peer. Defaults to `false` for `relation=child` and `true` otherwise.                                                                                                                                                                                                                                                              |
          242  +| `*.throughput`                  | object  | _Optional_ Configuration to limit the total amount sent via Interledger per unit of time. This setting is enforced by the built-in `throughput` middleware.                                                                                                                                                                                                                             |
          243  +| `*.throughput.incomingAmount`   | string  | _Optional_ Maximum incoming throughput amount (in atomic units; per second) for incoming packets. If this setting is not set, the incoming throughput limit is disabled.                                                                                                                                                                                                                |
          244  +| `*.throughput.outgoingAmount`   | string  | _Optional_ Maximum throughput amount (in atomic units; per second) for outgoing packets. If this setting is not set, the outgoing throughput limit is disabled.                                                                                                                                                                                                                         |
          245  +| `*.throughput.refillPeriod`     | integer | _Optional_ Length of time (in milliseconds) during which the token balance increases by `incomingAmount`/`outgoingAmount` tokens. Defaults to one second.                                                                                                                                                                                                                               |
   237    246   
   238    247   #### `defaultRoute`
   239    248   
   240    249   * Environment: `CONNECTOR_DEFAULT_ROUTE`
   241    250   * Type: `string`
   242    251   * Default: `"auto"`
   243    252   
................................................................................
   307    316   
   308    317   * Environment: `CONNECTOR_ROUTE_EXPIRY`
   309    318   * Type: `integer`
   310    319   * Default: `45000`
   311    320   
   312    321   The maximum age of a route provided by this connector. (in milliseconds)
   313    322   
   314         -#### `quoteExpiry`
   315         -
   316         -* Environment: `CONNECTOR_QUOTE_EXPIRY`
   317         -* Type: `integer`
   318         -* Default: `45000`
   319         -
   320         -The maximum age of a quote provided by this connector. (in milliseconds)
   321         -
   322    323   #### `routingSecret`
   323    324   
   324    325   * Environment: `CONNECTOR_ROUTING_SECRET`
   325    326   * Type: `string`
   326    327   * Default: `""`
   327    328   
   328    329   Seed used for generating routing table auth values.
   329    330   
   330    331   #### `backend`
   331    332   
   332    333   * Environment: `CONNECTOR_BACKEND`
   333    334   * Type: `string`
   334         -* Default: `"fixerio"`
          335  +* Default: `"ecb"`
   335    336   
   336         -Name of the backend (can be built-in or a require-able module name). Built-in modules are: fixerio, fixerio-plus-xrp, fixerio-plus-coinmarketcap, one-to-one
          337  +Name of the backend (can be built-in or a require-able module name). Built-in modules are: ecb, ecb-plus-xrp, ecb-plus-coinmarketcap, one-to-one
   337    338   
   338    339   #### `backendConfig`
   339    340   
   340    341   * Environment: `CONNECTOR_BACKEND_CONFIG`
   341    342   * Type: `object`
   342    343   * Default: `{}`
   343    344   
................................................................................
   385    386   * Type: `array`
   386    387   * Default: `[]`
   387    388   
   388    389   | Name | Type   | Description                           |
   389    390   | ---- | ------ | ------------------------------------- |
   390    391   | `[]` | string | Name of the middleware to be removed. |
   391    392   
   392         -#### `broadcastCurves`
   393         -
   394         -* Environment: `CONNECTOR_BROADCAST_CURVES`
   395         -* Type: `boolean`
   396         -* Default: `true`
   397         -
   398         -Whether to include liquidity curves when broadcasting routes.
   399         -
   400    393   #### `reflectPayments`
   401    394   
   402    395   * Environment: `CONNECTOR_REFLECT_PAYMENTS`
   403    396   * Type: `boolean`
   404    397   * Default: `true`
   405    398   
   406    399   Whether to allow routing payments back to the account that sent them.
................................................................................
   433    426   
   434    427   * Environment: `CONNECTOR_ADMIN_API_HOST`
   435    428   * Type: `string`
   436    429   * Default: `"127.0.0.1"`
   437    430   
   438    431   Host to bind to. Warning: The admin API interface should never be made public! Default: '127.0.0.1'
   439    432   
          433  +#### `collectDefaultMetrics`
          434  +
          435  +* Environment: `CONNECTOR_COLLECT_DEFAULT_METRICS`
          436  +* Type: `boolean`
          437  +* Default: `false`
          438  +
          439  +Whether the Prometheus exporter should include system metrics or not. Default: false (no)
          440  +
   440    441   ### API Reference
   441    442   
   442    443   ### Extensibility: Plugins
   443    444   
   444    445   Plugins represent different ways to link senders, receivers and connectors together. Most plugins use [Bilateral Transfer Protocol (BTP)](https://github.com/interledger/rfcs/blob/master/0023-bilateral-transfer-protocol/0023-bilateral-transfer-protocol.md) in order to communicate. The main differences between plugins are whether they are **multi-user** and which **settlement ledger** they use.
   445    446   
   446    447   Multi-user plugins are plugins which connect to multiple counterparties, rather than just one. They are usually used as server-side plugins to serve a large number of clients. An example is [**ilp-plugin-mini-accounts**](https://github.com/interledgerjs/ilp-plugin-mini-accounts). Multi-user plugins actually contain a little mini connector internally which knows how to route packets to the correct client.
................................................................................
   495    496   
   496    497   Pure in-memory store. Resets every time the connector is run. Useful for development and testing.
   497    498   
   498    499   ### Extensibility: Middlewares
   499    500   
   500    501   #### Built-in: errorHandler
   501    502   
   502         -* Pipelines: incomingData, incomingMoney
          503  +* Pipelines: `incomingData`, `incomingMoney`
   503    504   
   504    505   First middleware in the pipeline. Handles any errors that occur anywhere else and converts them into ILP rejections.
   505    506   
   506    507   The `errorHandler` middleware will check the thrown error for a field called `ilpErrorCode` which should contain a three-character ILP error code. Otherwise it uses `'F00'` by default. For the `message` it uses the error message and for `triggeredBy` the connector's address. If the error object has a field `ilpErrorData` which is a `Buffer`, it will also attach the provided data to the error. Otherwise, it will attach an empty `data` buffer.
   507    508   
   508    509   #### Built-in: deduplicate
   509    510   
   510         -* Pipelines: outgoingData
          511  +* Pipelines: `startup`, `teardown`, `outgoingData`
   511    512   
   512    513   Prevents sending duplicate packets which helps reduce the impact of routing loops.
   513    514   
   514    515   This middleware keeps track of all prepared transfers. If there is a transfer with the same `destination`, `executionCondition`, `data` and an equal or greater `amount` and `expiresAt` already prepared, then we simply link the new packet to the existing packet's outcome. If a packet is being routed in a loop, it will fulfill these requirements, the loop will be terminated, and the packet will time out.
   515    516   
   516    517   See also: <https://github.com/interledger/rfcs/issues/330#issuecomment-348750488>
   517    518   
   518    519   #### Built-in: rateLimit
   519    520   
   520         -* Pipelines: incomingData, incomingMoney, outgoingData, outgoingMoney
          521  +* Pipelines: `incomingData`, `incomingMoney`, `outgoingData`, `outgoingMoney`
   521    522   
   522    523   Reduces the maximum number of total requests incoming from or outgoing to any account.
   523    524   
   524    525   Used for basic rate limiting and to help with DoS.
   525    526   
   526    527   #### Built-in: maxPacketAmount
   527    528   
   528         -* Pipelines: incomingData, outgoingData
          529  +* Pipelines: `incomingData`, `outgoingData`
   529    530   
   530    531   Rejects packets with an amount greater than the specified value.
   531    532   
   532    533   #### Built-in: throughput
   533    534   
   534         -* Pipelines: incomingData, outgoingData
          535  +* Pipelines: `incomingData`, `outgoingData`
   535    536   
   536    537   Limits the throughput for a given account. Throughput is the amount of money transferred per time.
   537    538   
   538    539   #### Built-in: balance
   539    540   
   540         -* Pipelines: incomingData, incomingMoney, outgoingData, outgoingMoney
          541  +* Pipelines: `startup`, `incomingData`, `incomingMoney`, `outgoingData`, `outgoingMoney`
   541    542   
   542    543   Tracks the balance of a given account from the perspective of the connector. This is also the subsystem that triggers settlements.
   543    544   
   544    545   #### Built-in: validateFulfillment
   545    546   
   546         -* Pipelines: outgoingData
          547  +* Pipelines: `outgoingData`
   547    548   
   548    549   Validates fulfillments in incoming ILP fulfill responses. If the fulfillment is invalid, it converts the fulfillment into a rejection.
   549    550   
   550    551   #### Built-in: expire
   551    552   
   552         -* Pipelines: outgoingData
          553  +* Pipelines: `outgoingData`
   553    554   
   554    555   Expires outgoing ILP packets at their designated `expiresAt` time. Returns a rejection when this occurs.
   555    556   
          557  +#### Built-in: stats
          558  +
          559  +* Pipelines: `incomingData`, `incomingMoney`, `outgoingData`, `outgoingMoney`
          560  +
          561  +Tracks throughput by account. Results are accessible through the admin API.
          562  +
   556    563   ### Extensibility: Backends
   557    564   
   558    565   Backends provide fee policies and exchange rates. For a professionally run connector, just should create your own backend, using exchange rates that come directly from the exchange or broker where you plan to trade to re-balance your accounts.
   559    566   
   560    567   #### Built-in: one-to-one
   561    568   
   562    569   * Supported currencies: _any_
   563    570   
   564    571   The `one-to-one` backend applies the `CONNECTOR_SPREAD` setting, the `assetScale` settings, and otherwise uses a 1:1 exchange rate for all assets. This is the simplest backend, recommended for connectors that deal in only one currency.
   565    572   
   566         -#### Built-in: fixerio
          573  +#### Built-in: ecb
   567    574   
   568         -* Supported currencies: see [fixer.io](http://fixer.io/)
          575  +* Supported currencies: see [Euro foreign exchange reference rates](http://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html)
   569    576   
   570         -The `fixerio` backend loads fiat exchange rates from [fixer.io](http://fixer.io/). **Suitable for development and experimental use only.**
          577  +The `ecb` backend loads fiat exchange rates from [Euro foreign exchange reference rates](http://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html). **Suitable for development and experimental use only.**
          578  +
          579  +#### Built-in: ecb-plus-xrp
          580  +
          581  +* Supported currencies: see [Euro foreign exchange reference rates](http://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html), XRP
          582  +
          583  +The `ecb-plus-xrp` backend loads fiat exchange rates from [Euro foreign exchange reference rates](http://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html) and XRP exchange rates from the [Ripple Data API](https://ripple.com/build/data-api-v2/). **Suitable for development and experimental use only.**
          584  +
          585  +#### Built-in: ecb-plus-coinmarketcap
   571    586   
   572         -#### Built-in: fixerio-plus-xrp
   573         -
   574         -* Supported currencies: see [fixer.io](http://fixer.io/), XRP
          587  +* Supported currencies: see [Euro foreign exchange reference rates](http://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html), see [CoinMarketCap](https://coinmarketcap.com/)
   575    588   
   576         -The `fixerio-plus-xrp` backend loads fiat exchange rates from [fixer.io](http://fixer.io/) and XRP exchange rates from the [Ripple Data API](https://ripple.com/build/data-api-v2/). **Suitable for development and experimental use only.**
   577         -
   578         -#### Built-in: fixerio-plus-coinmarketcap
   579         -
   580         -* Supported currencies: see [fixer.io](http://fixer.io/), see [CoinMarketCap](https://coinmarketcap.com/)
   581         -
   582         -The `fixerio-plus-coinmarketcap` backend loads fiat exchange rates from [fixer.io](http://fixer.io/) and crypto-currency exchange rates from [CoinMarketCap](https://coinmarketcap.com/). **Suitable for development and experimental use only.**
          589  +The `ecb-plus-coinmarketcap` backend loads fiat exchange rates from [Euro foreign exchange reference rates](http://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html) and crypto-currency exchange rates from [CoinMarketCap](https://coinmarketcap.com/). **Suitable for development and experimental use only.**
   583    590   
   584    591   ## Development
   585    592   
   586    593   If you would like to contribute back to this project, please follow these steps:
   587    594   
   588    595   #### Step 1: Clone repo
   589    596   
................................................................................
   602    609   
   603    610   ```sh
   604    611   CONNECTOR_STORE_PATH=~/.connector-data CONNECTOR_ACCOUNTS='{}' CONNECTOR_ILP_ADDRESS=test.quickstart npm start
   605    612   ```
   606    613   
   607    614   #### Step 4: Read the contributor guidelines
   608    615   
   609         -See [CONTRIBUTE.md](/CONTRIBUTE.md).
          616  +See [CONTRIBUTING.md](/CONTRIBUTING.md).