saaap-server

REST server and library for the Saaap system

Usage no npm install needed!

<script type="module">
  import saaapServer from 'https://cdn.skypack.dev/saaap-server';
</script>

README

saaap-server

Github tag (latest by date) npm Github last commit Github issues NPM

saaap-server provides a REST service for handling transactions in the Saaap™ blockchain.

It provides services for the broker as well as any node in the system.

NB: Each new Rooot™ beneficiary should install it along with his "light" node to automate the purchase of the necessary tokens and fees.

Usage

$ git clone https://github.com/cyrildever/saaap-server.git && cd saaap-server && npm i
$ npm start

Check out the config/default.yml file to adjust/set the server's configuration to adapt to your own environment.

Environment variables

You may also set the following environment variables to make the corresponding ajdustment in the server's settings:

  • HTTP_PORT: the API's HTTP port number (default: 3130);
  • NODE_URL: the associated Saaap™ node URL;
  • NODE_ID: the associated node ID;
  • SERVER_ID: the unique ID of the current instance of saaap-server;
  • MONGO_USERNAME: the username for the MongoDB;
  • MONGO_PASSWORD: the password associated with this user;
  • MONGO_DOMAIN: the domain name (default: "localhost");
  • MONGO_PORT: the MongoDB port number (default: 27017);
  • MONGO_DB: the database name;
  • MONGO_COLLECTION_ACCOUNTS: the database collection for the accounts (default: "accounts");
  • MONGO_COLLECTION_SECRET: the collection for the access token and API secret credentials (default: "secret");
  • DEPOSITARY_ID: the depositary ID used when signing a transaction itself;
  • DEPOSITARY_URL: the URL of the depositary's gateway;
  • BROKER_ID: the broker ID;
  • BROKER_URL: the full broker service URL;
  • BROKER_KEY_PATH: the optional broker's key path (default: "m/0'/0/0");
  • BROKER_PUBLIC_KEY: the optional broker's public key (in hexadecimal string);
  • BROKER_PRIVATE_KEY: the optional broker's private key (in hexadecimal string).

The last two variables should only be set in case this is a broker's service.

API

All endpoints return either 400, 403, 404 or 500 status code on error (respectively for wrong arguments, access forbidden, item not found or internal server error).

The following end points are available at root:

  • GET /account

This endpoint returns an account object from its passed query argument accountId, eg. http://localhost:3130/account?accountId=1234567890[...]abcdef.

It expects two mandatory HTTP headers x-access-token and x-api-secret (which you should get from the service provider beforehand - see example in POST /account).

It returns a JSON object respecting the following format:

{
  "accountId": "1234567890[...]abcdef",
  "masterKey": "",
  "proof": {
    "type": "",
    "reference": "",
    "id": ""
  },
  "info": {
    "pseudo": "",
    "address": {
      "streetNumber": "",
      "streetName": "",
      "complement": "",
      "zipCode": "",
      "locality": "",
      "city": "",
      "state": "",
      "countryCode": ""
    },
    "corporate": {
      "name": "",
      "legalForm": ""
    },
    "individual": {
      "title": "",
      "firstName": "",
      "lastName": ""
    }
  }
}

NB: Not all fields will be filled.

  • GET /metadata

This endpoint returns the current metadata needed to build a transaction, eg. http://localhost:3130/metadata.

It returns a JSON object respecting the following format:

{
  "timestamp": 0,
  "currentPeriodId": 0,
  "lastBlockId": "",
  "genesisTimestamp": 0,
  "periodDuration": 10000
}
  • GET /transactions

This endpoint returns the transactions that exists according to the transactionIds query arguments being an array of transaction IDs, eg. http://localhost:3130/transactions?transactionIds=123456789abcdef[...]&transactionIds=9876543210fedcba[...]

Upon success, it returns an array of transactions respecting the following format:

[
  {
    "transactionId": "",
    "lastBlockId": "",
    "timestamp": 1,
    "type": "",
    "coins": {
      "token": {
        "index": 0,
        "order": "0",
        "id": ""
      },
      "fee": {
        "units": 0,
        "transactionId": "",
        "proof": ""
      },
      "formula": ""
    },
    "contract": {
      "oracles": [
        {
          "brokerId": "",
          "source": "consent",
          "object": "transaction",
          "reference": "",
        },
        [...]
      ],
      "deadline": 172800001,
      "signatures": {
        "input": "",
        "output": ""
      }
    },
    "scripts": {
      "locking": "",
      "unlocking": ""
    }
  },
  [...]
]

NB: Depending on the type of transaction (buy, stake, pay, consume), all fields might not be filled.

  • POST /account

This endpoint records a new account in the database.

It expects two mandatory HTTP headers x-access-token and x-api-secret (which you should get from the service provider beforehand), eg.

POST /account HTTP/1.1
x-access-token: ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789abcdef=
x-api-secret: 12345678-90ab-cdef-1234-567890abcdef
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: node.rooot.io
Accept-Language: fr-FR
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

It also expects as body the JSON account object in a format depending on the type of account.

  • For a corporation:
    {
      "accountId": "",
      "masterKey": "",
      "proof": {
        "type": "",
        "reference": "",
        "id": ""
      },
      "info": {
        "pseudo": "",
        "address": {
          "streetNumber": "",
          "streetName": "",
          "complement": "",
          "zipCode": "",
          "locality": "",
          "city": "",
          "state": "",
          "countryCode": ""
        },
        "corporate": {
          "name": "",
          "legalForm": ""
        }
      }
    }
    
  • For an individual:
    {
      "accountId": "",
      "masterKey": "",
      "proof": {
        "type": "",
        "reference": "",
        "id": ""
      },
      "info": {
        "pseudo": "",
        "address": {
          "streetNumber": "",
          "streetName": "",
          "complement": "",
          "zipCode": "",
          "locality": "",
          "city": "",
          "state": "",
          "countryCode": ""
        },
        "individual": {
          "title": "",
          "firstName": "",
          "lastName": ""
        }
      }
    }
    

It returns a 201 status code upon successful creation, a 206 status if the account was recorded but couldn't be spread to other nodes, or a 304 status if an account with same account ID already exists. In the latter case, you should use the PUT /account endpoint below instead.

  • POST /transactions/buy/create

This endpoint creates a response to help building a buy transaction.

It expects two mandatory HTTP headers:

  • x-output-public-key: the public key of the buyer;
  • x-payment-ref: the payment reference (provided by the broker). In case it is a transaction for an oblivion-ar, two extra headers are needed:
  • x-token-output-id: the ID of the pay transaction in Saaap™ that enforces the opt-out;
  • x-consent-oblivion-id: the transaction ID in the remote system (Rooot™) of the oblivion to acknowledge.

It also expects the following request information as the JSON body:

{
  "deadline": 172800001,
  "formula": "",
  "timestamp": 1,
  "units": ""
}

The formula and the units depend on the type of upcoming transactions this buy operation is made for. The deadline must be at least 48 hours after the timestamp gotten from the metadata, ie. deadline = timestamp + 172,800,000 milliseconds.

Upon success, it returns a 200 status code, two HTTP headers (x-input-id, x-input-public-key) and the following response in JSON format:

{
  "token": {
    "index": 0,
    "order": "0"
  },
  "oracles": [
    {
      "brokerId": "",
      "source": "token",
      "object": "broker",
      "reference": ""
    },
    [...]
  ],
  "rand": 12345678,
  "input": {
    "signature": "",
    "id": "",
    "checker": "",
    "depositary": {
      "id": "",
      "url": ""
    }
  }
}

Check the status code and the message in the body in case of failure.

  • POST /transactions/buy/send

This endpoint takes a transaction and sends it to the node and the depositary if it checks out.

It expects a valid buy transaction as JSON in the body (see above).

It returns a 201 status code upon success.

  • POST /transactions/stake/create

This endpoint creates a response to help building a stake transaction.

It expects one mandatory HTTP header:

  • x-input-public-key: the public key of the depositor.

It also expects the following request information as the JSON body:

{
  "buy": {
    "token": {
      "id": "",
      "index": 0
    },
    "transactionId": ""
  },
  "deadline": 172800001,
  "formula": "",
  "oracle": {
    "brokerId": "",
    "source": "",
    "object": "",
    "reference": ""
  },
  "timestamp": 1,
  "units": ""
}

The buy fields depend on the corresponding operation for the used token (identified by its token.id) as well as the formula and units fields that rely on the values used in the related transaction.
The deadline must be at least 48 hours after the timestamp gotten from the metadata, ie. deadline = timestamp + 172,800,000 milliseconds.
The oracle fields are expected to make reference to the Consent Management blockchain, eg.

{
  "brokerId": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
  "source": "consent",
  "object": "transaction",
  "reference": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}

the reference field being the transaction ID in the remote blockchain.

Upon success, it returns a 200 status code, two HTTP headers (x-output-id, x-output-public-key) and the following response in JSON format:

{
  "token": {
    "id": "",
    "index": 0,
    "order": "0"
  },
  "oracles": [
    {
      "brokerId": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
      "source": "consent",
      "object": "transaction",
      "reference": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
    },
    {
      "brokerId": "",
      "source": "broker",
      "object": "transaction",
      "reference": ""
    },
    [...]
  ],
  "rand": 12345678,
  "output": {
    "signature": "",
    "id": "",
    "checker": "",
    "depositary": {
      "id": "",
      "url": ""
    }
  }
}

Check the status code and the message in the body in case of failure.

  • POST /transactions/stake/send

This endpoint takes a transaction and sends it to the node and the depositary if it checks out.

It expects a valid stake transaction as JSON in the body (see above).

It returns a 201 status code upon success.

  • POST /transactions/pay/create

This endpoint creates a response to help building a pay transaction.

It expects one mandatory HTTP header:

  • x-output-public-key: the public key of the emitter.

It also expects the following request information as the JSON body:

{
  "buy": {
    "token": {
      "id": "",
      "index": 0,
      "order": "0"
    },
    "transactionId": ""
  },
  "deadline": 172800001,
  "formula": "",
  "intendedPay": "",
  "oracle": {
    "brokerId": "",
    "source": "",
    "object": "",
    "reference": ""
  },
  "stake": {
    "token": {
      "id": "",
      "index": 0,
      "order": "0"
    },
    "transactionId": ""
  },
  "timestamp": 1,
  "units": ""
}

The buy and stake fields depend on the corresponding operation for the used token (identified by its token.id) as well as the formula and units fields that rely on the values used in the related transaction.
The deadline must be at least 48 hours after the timestamp gotten from the metadata, ie. deadline = timestamp + 172,800,000 milliseconds.
The intendedPay could one of the following: "opt-in", "state::spending", "state::feeding::with", "state::feeding::without", "opt-out", "oblivion::ar". The oracle fields are expected to make reference to the Consent Management blockchain, eg.

{
  "brokerId": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
  "source": "consent",
  "object": "transaction",
  "reference": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}

the reference field being the transaction ID in the remote blockchain.

Upon success, it returns a 200 status code, two HTTP headers (x-input-id, x-input-public-key) and the following response in JSON format:

{
  "token": {
    "id": "",
    "index": 0,
    "order": "0"
  },
  "oracles": [
    {
      "brokerId": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
      "source": "consent",
      "object": "transaction",
      "reference": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
    },
    [...]
  ],
  "rand": 12345678,
  "input": {
    "signature": "",
    "id": "",
    "checker": "",
    "depositary": {
      "id": "",
      "url": ""
    }
  }
}

Check the status code and the message in the body in case of failure.

  • POST /transactions/pay/send

This endpoint takes a transaction and sends it to the node and the depositary if it checks out.

It expects a valid pay transaction as JSON in the body (see above).

It returns a 201 status code upon success.

  • PUT /account

This endpoint updates an existing account in the database.

It expects two mandatory HTTP headers x-access-token and x-api-secret (which you should get from the service provider beforehand - see above).

It also expects as body the full updated JSON account object (see formats above).

It returns a 200 status code upon success, or a 206 status if the account was updated but the changes couldn't be spread to other nodes.

License

The use of the Saaap™ libraries and executables are subject to fees for commercial purpose and to the respect of the BSD-2-Clause-Patent license. Please contact me to get further information.


© 2021 Cyril Dever. All rights reserved.