API written in nodejs to fetch information from the Winding Tree platform.
- Nodejs >=10
In order to install and run tests, we must:
git clone [email protected]:windingtree/wt-read-api.git
nvm install
npm install
npm run resolve-swagger-references
npm test
With all the dependencies installed, you can start the dev server. First step is starting Ganache (local Ethereum network node). You can skip this step if you have a different network already running.
npm run dev-net
If you need to interact (for example add some testing hotels) with the running dev-net
in any way, you can use the Winding Tree demo wallet protected by password windingtree
.
It is initialized with enough ether. For sample interaction scripts, check out our
Developer guides.
!!!NEVER USE THIS WALLET FOR ANYTHING IN PRODUCTION!!! Anyone has access to it.
{"version":3,"id":"7fe84016-4686-4622-97c9-dc7b47f5f5c6","address":"d037ab9025d43f60a31b32a82e10936f07484246","crypto":{"ciphertext":"ef9dcce915eeb0c4f7aa2bb16b9ae6ce5a4444b4ed8be45d94e6b7fe7f4f9b47","cipherparams":{"iv":"31b12ef1d308ea1edacc4ab00de80d55"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"d06ccd5d9c5d75e1a66a81d2076628f5716a3161ca204d92d04a42c057562541","n":8192,"r":8,"p":1},"mac":"2c30bc373c19c5b41385b85ffde14b9ea9f0f609c7812a10fdcb0a565034d9db"}};
Now we can run our dev server.
npm run dev
When using a dev
config, we internally run a script to deploy
contracts. It is not immediate, so you might experience some errors in a
first few seconds. And that's the reason why it is not used in the same
manner in tests.
You can then visit http://localhost:3000/docs/ to interact with the live server. An OAS description is published there.
You can tweak with the configuration in src/config/
.
You can run the whole API in a docker container, and you can control which config will be used by passing an appropriate value to WT_CONFIG variable at runtime.
$ docker build -t windingtree/wt-read-api .
$ docker run -p 8080:3000 -e ETH_NETWORK_PROVIDER=address_to_node -e WT_CONFIG=playground windingtree/wt-read-api
After that you can access the wt-read-api on local port 8080
. This deployment
is using a Ropsten configuration that can be found in src/config/playground.js
.
You can install and run this from NPM as well:
$ npm install -g @windingtree/wt-read-api
$ ETH_NETWORK_PROVIDER=address_to_node WT_CONFIG=playground wt-read-api
Probably the easiest way of getting an Ethereum Node API is to register with Infura.
You can customize the behaviour of the instance by many environment
variables which get applied if you run the API with WT_CONFIG=envvar
.
These are:
WT_CONFIG
- Which config will be used. Defaults todev
.WT_SEGMENTS
- Which segments will be enabled. Defaults tohotels,airlines
.ADAPTER_IN_MEMORY
- Enables in memory off-chain data adapter. Defaults tofalse
.ADAPTER_SWARM
- Enables Swarm off-chain data adapter. Defaults totrue
.ADAPTER_SWARM_GATEWAY
- Address of a Swarm HTTP Gateway, for examplehttps://swarm.windingtree.com
orhttps://swarm-gateways.net
ADAPTER_SWARM_READ_TIMEOUT
- Read timeout in milliseconds for Swarm, defaults to 1000ADAPTER_HTTPS
- Enables HTTP off-chain data adapter. Defaults totrue
.WT_HOTEL_DIRECTORY_ADDRESS
- On chain address of Segment DirectoryWT_AIRLINE_DIRECTORY_ADDRESS
- On chain address of Segment DirectoryWT_HOTEL_FACTORY_ADDRESS
- On chain address of Organization FactoryWT_AIRLINE_FACTORY_ADDRESS
- On chain address of Organization FactoryPORT
- HTTP Port where the API will listen, defaults to 3000.BASE_URL
- Base URL of this API instance, for examplehttps://playground-api.windingtree.com
ETH_NETWORK_NAME
- Name of Ethereum network for informational purposes, for exampleropsten
ormainnet
ETH_NETWORK_PROVIDER
- Address of Ethereum node, for examplehttps://ropsten.infura.io/v3/my-project-id
TRUST_CLUES_CHECK
- If trust clues should be evaluated for hotels. This may affect which data will be returned by the API. Defaults totrue
.TRUST_CLUES_CURATED_LIST_ADDRESS
- ETH Address of an instance of Curated List Trust clue if used as a trust clue.TRUST_CLUES_LIF_DEPOSIT_ADDRESS
- ETH Address of an instance of Líf Deposit Trust clue if used as a trust clue. A local instance is automatically deployed if adev
config is used.
For example the playground configuration can be emulated with the following command (the actual values will differ, check src/config/playground.js
for current ones):
docker run -p 8080:3000 \
-e WT_CONFIG=envvar \
-e WT_SEGMENTS=hotels,airlines \
-e WT_HOTEL_DIRECTORY_ADDRESS=0xfb562057d613175c850df65e435bb0824b65d319 \
-e WT_AIRLINE_DIRECTORY_ADDRESS=0xai562057d613175c850df65e435bb0824b65d333 \
-e ADAPTER_SWARM_GATEWAY=https://swarm.windingtree.com \
-e ADAPTER_SWARM=1 \
-e ADAPTER_HTTPS=1 \
-e ETH_NETWORK_NAME=ropsten \
-e ETH_NETWORK_PROVIDER=https://ropsten.infura.io/v3/my-project-id \
-e TRUST_CLUES_CHECK=0 \
windingtree/wt-read-api
See API definition for full details or in a more readable form here.
Calling GET /hotels
will retrieve an array of hotels. By default fields are id
, name
and location
, which
means that at least some off-chain stored data is retrieved.
You can use a query attribute fields
to specify which fields you want to be included in the response.
Hotel ID is included by default in every request. Ex. GET /hotels?fields=name
. You can also choose to include
only ids (e. g. GET /hotels?fields=id
) which will not fetch any off-chain data, so the response will be much faster.
items: [
...
{
id: '0x585c0771Fe960f99aBdba8dc77e5d31Be2Ada74d',
name: 'WT Hotel'
},
...
]
If an error is produced for a hotel, the response will look like this
items: [
{
id: '0x417C3DDae54aB2f5BCd8d5A1750487a1f765a94a',
name: 'WT Hotel'
}
],
warnings: [],
errors: [
{
error: 'Unsupported data storage type: ipfs',
originalError: 'Unsupported data storage type: ipfs',
data: { id: '0x585c0771Fe960f99aBdba8dc77e5d31Be2Ada74d' }
}
]
Request to /hotels/:address
can fetch off-chain data in a single request. By default, included fields are id
, location
,
name
, description
, contacts
, address
, currency
, images
, amenities
, updatedAt
.
id: "0x417C3DDae54aB2f5BCd8d5A1750487a1f765a94a",
location: { "latitude": 35.89421911, "longitude": 139.94637467 },
name: "Winding Tree Hotel",
dataFormatVersion: "0.6.0",
description: "string",
contacts:
{
general:
{
email: "[email protected]",
phone: 44123456789,
url: "string",
ethereum: "string",
additionalContacts: []
}
},
roomTypes: [
{
id: "room-type-1111",
name: "Room with windows",
description: "some fancy room type description",
totalQuantity: 0,
occupancy: {
min: 1,
max: 3
},
amenities: [
"tv"
],
images: [
"https://example.com/room-image.jpg"
],
updatedAt: "2018-06-19T13:19:58.190Z"
}
],
address:
{
road: "string",
houseNumber: "string",
postcode: "string",
city: "string",
countryCode: "US"
},
currency: "string",
images: [ "string" ],
amenities: [ "free wi-fi" ],
updatedAt: "2018-06-19T13:19:58.190Z"
The airline endpoints work basically the same way as hotels. The default fields for airline list (/airlines
) are id
, name
and code
.
You can use a query parameter fields
to specify fields to be included in the response. See the airline data specification and endpoint specification for full list.
A simple GET /airlines
may return:
items: [
{
name: 'Mazurka Airlines',
code: 'MA',
id: '0xa8c4cbB500da540D9fEd05BE7Bef0f0f5df3e2cc'
}, {
name: 'Falco Airlines',
code: 'FA',
id: '0x972422ce30AAC491Fa24a5287C40eAf85b0b9dC4'
},
],
...
Or in case an error occurs while fetching upstream data:
items: [
{
name: 'Mazurka Airlines',
code: 'MA',
id: '0xa8c4cbB500da540D9fEd05BE7Bef0f0f5df3e2cc'
}
],
warnings: [],
errors: [
{
error: 'Cannot access on-chain data, maybe the deployed smart contract is broken',
originalError: 'VM Exception while processing transaction: revert',
data: {
id: '0x972422ce30AAC491Fa24a5287C40eAf85b0b9dC4'
}
}
]
Request to /airlines/:address
can fetch off-chain data in a single request. By default, included fields are id
,
name
, description
, contacts
, currency
, updatedAt
.
name: 'Mazurka Airlines',
description: 'Small but flexible',
dataFormatVersion: "0.6.0",
contacts: {
general: {
email: '[email protected]',
phone: '004078965423',
url: 'https://www.airline-mazurka.com'
}
},
currency: 'EUR',
updatedAt: '2019-02-01 10:00:00',
id: '0x0f7aDd75c09E2F8F5e4444fcde917267257471bD'
Use GET at /airlines/:address/flights/:id
. Use fields
query param to get instances data as well.
id: "IeKeix6G",
origin: "PRG",
destination: "LAX",
segments: [
{
id: "segment1",
departureAirport: "PRG",
arrivalAirport: "CDG"
},
{
id: "segment2",
departureAirport: "CDG",
arrivalAirport: "LAX"
}
]
Use GET at /airlines/:address/flights/:flightId/instances/:instanceId
.
id: 'IeKeix6G-1',
departureDateTime: '2018-12-10 12:00:00',
bookingClasses: [
{ id: 'economy', availabilityCount: 100 },
{ id: 'business', availabilityCount: 20 }
]
segments: {
segment1: {
departureDateTime: "2018-12-10 12:00:00",
arrivalDateTime: "2018-12-10 15:00:00"
},
segment2: {
departureDateTime: "2018-12-10 20:00:00",
arrivalDateTime: "2018-12-11 02:00:00"
}
}
For currently available public instances of wt-read-api, please see this page.
This API serves upstream data and has no control over the content. To ensure basic semantic compatibility,
data is validated against model definition and returned as an error when validation fails.
(Detail endpoints will return 422 HTTP code, lists will contain the data in errors
array.)
In case the validation succeeds but the declared data format version is different than the version supported by the API,
it is returned with a warning. This usually means there was a non-breaking change in the data format but may have consequences
in case of a semantic change. (Warnings are returned in x-data-validation-warning
header for detail endpoints, warnings
array for a list.)