ixo Message Relayer

Ixo Message Relayer

The Ixo Message Relayer is a server that facilitates a meticulously coordinated sequence of operations ensuring mobile-to-web authentication and transaction signing on the IXO blockchain. The process kicks off with the Login module, where the SDK generates a random hash and a secureHash (which is a SHA-256 hash of the hash and a secureNonce). A QR code, containing this hash, is then displayed for the mobile app to scan. Once scanned, the mobile app uploads the user data to the server using this hash as an identifier of the login request, which the SDK is polling for. This endpoint is secured with an AUTHORIZATION environment variable, ensuring only the mobile app with the correct authorization can upload this data. Subsequently, the SDK polls the server to fetch the login data, providing a secureNonce in the process. The server validates the request by hashing the provided hash and secureNonce to ensure it matches the secureHash, thereby affirming the authenticity of the user making the request. Upon validation, the server returns the login data to the SDK and purges the data from the server to maintain data cleanliness.

Transitioning to the Transactions module, the SDK creates a transaction request by uploading all the necessary transaction data along with an identifier hash, which is derived from the hash of the transaction data. This hash acts as a unique identifier for the transaction. Upon scanning a QR code generated by the SDK, the mobile app fetches the transaction data from the server using this hash. This endpoint is also protected to ensure only the mobile app can access the transaction data. The mobile app then validates the integrity of the data received from the server by hashing the data and ensuring the hash matches the hash it obtained from the QR code, thereby ensuring data authenticity and thwarting any potential middleman attacks. Following this, the mobile app signs the transaction, broadcasts it to the IXO blockchain, and updates the transaction status on the server, either as success or failure. This update endpoint is also protected to ensure only the mobile app can update the transaction data. Concurrently, the SDK polls the server to fetch the transaction response for the provided hash, allowing it to retrieve the response only for the transaction that was updated by the mobile app.

The server's response to all endpoints is structured in a consistent format, encapsulated in an object. This object always contains a success field indicating the success or failure of the intended operation. Additionally, there's a data field which generally houses a message field explaining the reason for the success or failure of the request. If there's data to be provided, it is encapsulated within this data field. For the polling endpoints like login fetch and transaction response, there's an additional code field in the response. A code value of 418 signifies that even if the success field is false, the SDK should continue polling and not throw an error, ensuring a robust and resilient flow of operations.

The server is designed to work seamlessly with a complementary SDK which facilitates the management of various authentication and transaction flows between web clients, mobile applications, and the server itself. For more comprehensive insights and utilization of the server's capabilities, you may explore the SDK source code hosted on this repository or directly integrate the SDK into your projects via the published NPM package.

Environment Variables

Ensuring the secure and efficient operation of the Ixo Message Relayer Nest.js server, various environment variables are configured to govern aspects like authorization, and database management. The .env.example file illustrates a templated structure of these variables, providing a guideline for environment setup.

Here's an overview of each environment variable and its utility within the application:

  • PORT: Specifies the port number on which the Nest.js server will run.

  • AUTHORIZATION: Utilized for authorizing API requests, ensuring they originate from authenticated sources. The Authorization header in API requests must precisely match this value (example: Bearer u4D81XDt4YsbXo6KSynYFChk).

  • DATABASE_URL: The full PostgresQL database uri as provided in example.

  • SENTRY_DSN: Sentry DNS for Sentry error logging to catch production issues.

Security Note

It is paramount that sensitive variables such as AUTHORIZATION and DATABASE_URL are secured and not exposed to unauthorized personnel or systems. Employ stringent security practices like utilizing secrets management tools, employing strict access controls, and conducting periodic security audits to ensure the confidentiality and integrity of these critical data points.

Usage Note

To implement these configurations, developers need to create an .env file, using .env.example as a template, and supply the appropriate values for each variable, ensuring the secure and tailored operation of the server based on the specific deployment environment and use case.

This environment configuration section can serve as a guide to developers, system administrators, and other stakeholders involved in the deployment and maintenance of the server, providing a structured view of the configurable elements that dictate the server’s functionality and security.

Running the app

# Clone the repository
$ git clone https://github.com/ixofoundation/ixo-message-relayer.git
# Navigate to the project directory
$ cd ixo-message-relayer

# Install dependancies
$ yarn install

# development
$ yarn run start

# watch mode
$ yarn run start:dev

# production mode
$ yarn run start:prod

Docker Usage

If you prefer to run the application inside a Docker container, we've provided a Docker image for convenience. The image is available at ghcr.io/ixofoundation/ixo-message-relayer:v0.0.1 and an example docker-compose file is below for reference:

docker-compose.yaml

version: '3.7'
services:
  ixo-message-relayer:
    container_name: ixo-message-relayer
    image: ghcr.io/ixofoundation/ixo-message-relayer:v0.0.1
    build:
      context: .
      dockerfile: Dockerfile
      # Can use a .env file
    env_file: .env
    restart: always
    ports:
      - 3000:3000
    logging:
      driver: 'json-file'
      options:
        max-size: '1m'
        max-file: '1'
    depends_on:
      - ixo-message-relayer-db

  ixo-message-relayer-db:
    container_name: ixo-message-relayer-db
    image: postgres:15.1
    restart: always
    environment:
      - POSTGRES_DB=message-relayer
      - POSTGRES_PASSWORD=pass
    ports:
      - 5432:5432
    volumes:
      - ./data/db:/var/lib/postgresql/data
      - ./prisma/migrations/20230301091449_init/:/docker-entrypoint-initdb.d/

API Documentation

POST /login/create

This endpoint is utilized by the mobile app to store login request data on the server. Upon scanning a QR code generated by the SDK, the mobile app initiates a login request by sending the relevant data to this endpoint. The login data is stored on the server under a unique hash identifier generated by the SDK, which facilitates subsequent polling by the SDK to retrieve this data for user login. The endpoint is protected by an authorization mechanism to ensure that only the mobile app can upload login data.

Parameters

  • hash: A unique identifier for the login request.

  • secureHash: A secure hash generated by hashing the hash and a secureNonce.

  • data: The login request data.

  • success: A boolean indicating the success status of the login request.

Request Body

{
  "hash": "string",
  "secureHash": "string",
  "data": "object",
  "success": "boolean"
}

Response Body

{
  "success": "boolean",
  "data": {
    "message": "string"
  }
}

Response Properties

  • success: Indicates whether the request to server was successful.

  • data:

    • message: A message explaining the success or failure of the request.

Usage

curl -X POST https://[server-address]/login/create \
-H "Content-Type: application/json" \
-d '{"hash": "uniqueHash", "secureHash": "secureHashValue", "data": { ... }, "success": true}'

POST /login/fetch

This endpoint facilitates the retrieval of login request data that was previously stored on the server by the mobile app. The SDK polls this endpoint to fetch the login data for a user based on a unique hash identifier. The server validates the request by hashing the provided hash and a secureNonce to ensure it matches the stored secureHash, thereby affirming the authenticity of the user making the request. Upon validation, the server returns the login data to the SDK and deletes the data from the server to maintain data cleanliness.

Parameters

  • hash: A unique identifier for the login request.

  • secureNonce: A secure nonce generated by the SDK.

Request Body

{
  "hash": "string",
  "secureNonce": "string"
}

Response Body

{
  "success": "boolean",
  "data": {
    "message": "string",
    "data": "object",
    "success": "boolean"
  },
  "code": "number"
}

Response Properties

  • success: Indicates whether the request to server was successful.

  • code: A code indicating whether the SDK should continue polling (418 if it should continue).

  • data:

    • message: A message explaining the success or failure of the request.

    • data: The login data

    • success: Wether the login was a sucess or fail due to rejection on mobile for example

Usage

curl -X POST https://[server-address]/login/fetch \
-H "Content-Type: application/json" \
-d '{"hash": "uniqueHash", "secureNonce": "secureNonceValue"}'

POST /transaction/create

This endpoint is utilized by the SDK to store transaction request data on the server. The SDK initiates a transaction request by sending the relevant data, along with a unique hash identifier (which is also the hash of the transaction data), to this endpoint. This hash facilitates subsequent retrieval of this data by the mobile app for signing and broadcasting the transaction. The endpoint validates the request by hashing the provided transaction data and ensuring it matches the provided hash, thereby affirming the authenticity of the transaction data.

Parameters

  • hash: A unique identifier for the transaction request which is also the hash of the transaction data.

  • address: The address involved in the transaction.

  • did: The decentralized identifier involved in the transaction.

  • pubkey: The public key of the user initiating the transaction.

  • txBodyHex: The hexadecimal encoded raw txBodyBytes which can be encoded from the registry exported from @ixo/impactxclient-sdk npm package (eg registry.encodeTxBody({ messages, memo }))

  • timestamp: The stringified utc DateTime, add uniqueness for tx hash to prevent duplicates (eg new Date().toISOString())

Request Body

{
  "hash": "string",
  "address": "string",
  "did": "string",
  "pubkey": "string",
  "txBodyHex": "string",
  "timestamp": "string"
}

Response Body

{
  "success": "boolean",
  "data": {
    "message": "string",
    "validUntil": "string"
  }
}

Response Properties

  • success: Indicates whether the request to server was successful.

  • data:

    • message: A message explaining the success or failure of the request.

    • validUntil: The ISO 8601 formatted datetime string indicating the expiry time of the transaction request

Usage

curl -X POST https://[server-address]/transaction/create \
-H "Content-Type: application/json" \
-d '{"hash": "uniqueHash", "address": "userAddress", "did": "userDid", "pubkey": "userPubKey", "txBodyHex": "transactionBodyHex", "timestamp": "transactionTimestamp"}'

POST /transaction/fetch

This endpoint allows the mobile app to fetch the data of a specific transaction request based on a unique hash identifier. After scanning the QR code displayed by the SDK, the mobile app uses the hash to retrieve the transaction data from this endpoint for signing and broadcasting the transaction. The endpoint is protected to ensure only the mobile app can access the transaction data, and it validates the request by checking the hash against the stored transaction data to ensure data authenticity.

Parameters

  • hash: A unique identifier for the transaction request.

Request Body

{
  "hash": "string"
}

Response Body

{
  "success": "boolean",
  "data": {
    "message": "string",
    "address": "string",
    "did": "string",
    "pubkey": "string",
    "txBodyHex": "string",
    "timestamp": "string"
  }
}

Response Properties

  • success: Indicates whether the request to server was successful.

  • data:

    • message: A message explaining the success or failure of the request.

    • address: The address involved in the transaction.

    • did: The decentralized identifier involved in the transaction.

    • pubkey: The public key of the user initiating the transaction.

    • txBodyHex: The hexadecimal representation of the raw encoded transaction body.

    • timestamp: The The ISO 8601 formatted timestamp when the transaction request was created.

Usage

curl -X POST https://[server-address]/transaction/fetch \
-H "Content-Type: application/json" \
-d '{"hash": "uniqueHash"}'

POST /transaction/update

This endpoint is leveraged by the mobile app to update a transaction request's data on the server following the signing and broadcasting of the transaction. The mobile app sends the transaction response data to this endpoint, which then updates the corresponding transaction request record on the server. The endpoint is protected to ensure only the mobile app can update the transaction data.

Parameters

  • hash: A unique identifier for the transaction request.

  • data: The response data of the transaction.

  • success: A boolean indicating whether the transaction was successful or failed.

Request Body

{
  "hash": "string",
  "data": "string",
  "success": "boolean"
}

Response Body

{
  "success": "boolean",
  "data": {
    "message": "string"
  }
}

Response Properties

  • success: Indicates whether the request to server was successful.

  • data:

    • message: A message explaining the success or failure of the request.

Usage

curl -X POST https://[server-address]/transaction/update \
-H "Content-Type: application/json" \
-d '{"hash": "uniqueHash", "data": "transactionResponseData", "success": true}'

POST /transaction/response

This endpoint is utilized by the SDK to poll the server for a response to a specific transaction request. By providing the unique hash identifier for the transaction, the SDK can retrieve the response data updated by the mobile app. This endpoint facilitates the flow where after the mobile app signs and broadcasts the transaction, and updates the server with the response data, the SDK polls this endpoint to obtain the response.

Parameters

  • hash: A unique identifier for the transaction request.

Request Body

{
  "hash": "string"
}

Response Body

{
  "success": "boolean",
  "code": "number",
  "data": {
    "message": "string",
    "data": "string",
    "success": "boolean"
  }
}

Response Properties

  • success: Indicates whether the request to server was successful.

  • code: A code indicating whether the SDK should continue polling (418 if it should continue).

  • data:

    • message: A message explaining the success or failure of the request.

    • data: The response data of the transaction.

    • success: Whether the transaction was a success or fail due to rejection on mobile for example.

Usage

curl -X POST https://[server-address]/transaction/response \
-H "Content-Type: application/json" \
-d '{"hash": "uniqueHash"}'

📃 License

This SDK is licensed under the Apache 2 License. See the LICENSE file for more information.

Last updated