Skip to content

REST and Socket connections

yoxira edited this page Nov 10, 2024 · 9 revisions

ADAMANT Node provides RESTful API to process clients' requests. REST requests are reliable and fit for most of tasks.

In some cases client needs to get new transactions instantly, allowing users superior performance. It is most important for messaging applications to provide smooth experience for chatting. This way nodes provide socket connections.

To enable node for sockets, refer to wsClient section of config.json:

"wsClient": {
    "portWS": 36668,
    "enabled": true
}

To check if node offers socket connections, request status:

https://endless.adamant.im/api/node/status
{
  "success": true,
  "nodeTimestamp": 226901657,
  // ...
  "wsClient": {
    "enabled": true,
    "port": 36668
  }
}

Clients are able to listen socket to get notified about all of transactions, including unconfirmed yet. New unconfirmed transactions has no block_timestamp. Most of transactions fetched by socket are new and unconfirmed as they just appeared in the ADAMANT network, and not stored in blockchain yet. Important to understand this fact to process transfer (amount > 0) transaction correctly, check if transaction confirmed in the network, and confirmation count. Unconfirmed transaction can never become confirmed, it may be rejected by nodes' consensus.

Nodes emit transactions of all types with newTrans event, and client app should filter them according to its needs (f. e., which ADM address, recipient or sender, transaction type). For socket connections, nodes store pool of transactions for 60 seconds.

Socket should be not the only connection, but additional to REST requests. This is because socket connection can be lost for some time, and fetching transactions by REST from time to time makes an application much more reliable. Still socket allows to send REST requests less often. When a new transaction received by socket, it should be checked with REST request for its status.

To listen to new transactions by socket, subscribe to node's socket events. Here is an example:

connect (socketAddress) {
    // Note, connection type can be "ws" or "wss"
    this.connection = io(`ws://${socketAddress}:36668`, { reconnection: false, timeout: 5000 })

    this.connection.on('connect', () => {
        this.currentSocketAddress = socketAddress
        // Subscribe to transactions for specific ADM address
        this.connection.emit('address', this.adamantAddress)
    })

    this.connection.on('disconnect', reason => {
        if (reason === 'ping timeout' || reason === 'io server disconnect') {
            console.warn('[Socket] Disconnected. Reason:', reason)
        }
    })

    this.connection.on('connect_error', (err) => {
        console.warn('[Socket] connect_error', err)
    })

    // `newTrans` event emits when node finds new transaction for subscribed ADM address
    this.connection.on('newTrans', transaction => {
        // Filter necessary transaction types
        if ((transaction.recipientId === this.admAddress) && (transaction.type === 0 || transaction.type === 8)) {
            console.info(`[Socket] New incoming socket transaction received: ${transaction.id}`);
            this.onNewMessage(transaction);
        }
    });
}

CORS

By default, ADAMANT Node allows any origins to make requests. You can control CORS with the cors object option in config.json that accepts following properties:

  • origin: Configures the Access-Control-Allow-Origin CORS header. Possible values:
    • Boolean - set origin to true to reflect the request origin, as defined by req.header('Origin'), or set it to false to disable CORS.
    • String - set origin to a specific origin. For example if you set it to "http://example.com" only requests from "http://example.com" will be allowed.
    • Array - set origin to an array of valid origins. For example ["http://example1.com", "http://example2.com/"] will accept any request from "http://example1.com" or "example2.com".
  • methods: Configures the Access-Control-Allow-Methods CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: ['GET', 'PUT', 'POST']).

Example:

{
  "cors": {
    "origin": "http://example1.com",
    "methods": "GET,PUT,POST"
  }
}