shelf_network_sdk.js

import urijs from 'urijs'
import { HorizonServer } from './horizon'
import { WalletServer, Wallet } from './wallets'
import { Token } from './auth/token'
import { CartServer } from './cart'
import { ParserServer } from './parser'
import { PaymentServer } from './payments'
import { FileServer } from './files'
import { TransportationServer } from './transportation'
import { FeeCalculatorServer } from './fee_calculator'
import { NotificationServer } from './notifications'
import { AuthServer } from './auth'
import { AzryLeasingServer } from './azry-leasing'

import { Network } from './base/network'

const services = [
  {
    name: 'horizon',
    configFieldName: 'horizonUrl',
    create: (sdk, url, opts) => new HorizonServer(sdk, url, opts)
  },
  {
    name: 'wallets',
    configFieldName: 'walletServerUrl',
    create: (sdk, url, opts) => new WalletServer(sdk, url, opts)
  },
  {
    name: 'parser',
    configFieldName: 'parserServerUrl',
    create: (sdk, url, opts) => new ParserServer(sdk, url, opts)
  },
  {
    name: 'transportation',
    configFieldName: 'transportationServerUrl',
    create: (sdk, url, opts) => new TransportationServer(sdk, url, opts)
  },
  {
    name: 'feeCalculator',
    configFieldName: 'feeCalculatorServerUrl',
    create: (sdk, url, opts) => new FeeCalculatorServer(sdk, url, opts)
  },
  {
    name: 'payments',
    configFieldName: 'paymentServerUrl',
    create: (sdk, url, opts) => new PaymentServer(sdk, url, opts)
  },
  {
    name: 'cart',
    configFieldName: 'cartServerUrl',
    create: (sdk, url, opts) => new CartServer(sdk, url, opts)
  },
  {
    name: 'files',
    configFieldName: 'fileServerUrl',
    create: (sdk, url, opts) => new FileServer(sdk, url, opts)
  },
  {
    name: 'notifications',
    configFieldName: 'notificationServerUrl',
    create: (sdk, url, opts) => new NotificationServer(sdk, url, opts)
  },
  {
    name: 'auth',
    configFieldName: 'authServerUrl',
    create: (sdk, url, opts) => new AuthServer(sdk, url, opts)
  },
  {
    name: 'azryLeasing',
    configFieldName: 'azryLeasingUrl',
    create: (sdk, url, opts) => new AzryLeasingServer(sdk, url, opts)
  }
]

/**
 * Shelf.Network Software Development Toolkit.
 *
 * @export
 */
export class ShelfNetwork {
  /**
   * Make a new ShelfNetwork SDK instance.
   *
   * @param {object} [opts]
   * @param {string} [opts.platformId] Shelf.Network platform ID.
   * @param {string} [opts.gatewayUrl] Gateway server url.
   * @param {string} [opts.horizonUrl] Horizon server url.
   * @param {string} [opts.walletServerUrl] Wallet server url.
   * @param {string} [opts.cartServerUrl] Cart server url.
   * @param {string} [opts.parserServerUrl] Parser server url.
   * @param {string} [opts.transportationServerUrl] Transportation server url.
   * @param {string} [opts.feeCalculatorServerUrl] Fee server url.
   * @param {string} [opts.paymentServerUrl] Payment server url.
   * @param {string} [opts.authServerUrl] Auth server url.
   * @param {string} [opts.azryLeasingUrl] AZRY leasing server url.
   * @param {boolean} [opts.allowHttp] Allow connecting to http servers, default: `false`. This must be set to false in production deployments!
   * @param {object} [opts.proxy] Proxy configuration. Look [axios docs](https://github.com/axios/axios#request-config) for more info
   * @param {object} [opts.httpBasicAuth] HTTP basic auth credentials. Look [axios docs](https://github.com/axios/axios#request-config) for more info.
   * @param {object} [opts.customHeaders] Custom headers for request.
   * @param {boolean} [opts.withCredentials] Indicates whether or not cross-site Access-Control requests should be made using credentials.
   *
   * @constructor
   */
  constructor (opts = {}) {
    if (opts.gatewayUrl) {
      const baseUrl = urijs(opts.gatewayUrl).toString()
      services.forEach(service => {
        opts[service.configFieldName] = baseUrl
      })
    }

    services.forEach(service => {
      this[`_${service.name}`] = service.create(
        this,
        opts[service.configFieldName],
        opts
      )
    })

    this._clockDiff = 0
    this._platformId = opts.platformId
  }

  /**
   * Make a new ShelfNetwork SDK instance.
   * Deprecated. Use constructor instead.
   *
   * @deprecated
   * @param {object} [opts]
   * @param {string} [opts.platformId] Shelf.Network platform ID.
   * @param {string} [opts.gatewayUrl] Gateway server url.
   * @param {string} [opts.horizonUrl] Horizon server url.
   * @param {string} [opts.walletServerUrl] Wallet server url.
   * @param {string} [opts.cartServerUrl] Cart server url.
   * @param {string} [opts.parserServerUrl] Parser server url.
   * @param {string} [opts.transportationServerUrl] Transportation server url.
   * @param {string} [opts.feeCalculatorServerUrl] Fee server url.
   * @param {string} [opts.paymentServerUrl] Payment server url.
   * @param {string} [opts.authServerUrl] Auth server url.
   * @param {string} [opts.azryLeasingUrl] AZRY leasing server url.
   * @param {boolean} [opts.allowHttp] Allow connecting to http servers, default: `false`. This must be set to false in production deployments!
   * @param {object} [opts.proxy] Proxy configuration. Look [axios docs](https://github.com/axios/axios#request-config) for more info
   * @param {object} [opts.httpBasicAuth] HTTP basic auth credentials. Look [axios docs](https://github.com/axios/axios#request-config) for more info.
   * @param {object} [opts.customHeaders] Custom headers for request.
   * @param {boolean} [opts.withCredentials] Indicates whether or not cross-site Access-Control requests should be made using credentials.
   *
   * @return {Promise.<ShelfNetwork>}
   */
  static async create (opts) {
    console.warn('`.create()` method is deprecated. Use ShelfNetwork constructor instead.')
    let sdk = new ShelfNetwork(opts)
    await sdk.fetchNetworkDetails()

    return sdk
  }

  /**
   * Shelf.Network platform ID.
   *
   * @type {string}
   */
  get platformId () {
    return this._platformId
  }

  /**
   * Horizon server instance.
   *
   * @type {HorizonServer}
   */
  get horizon () {
    return this._horizon
  }

  /**
   * Wallet server instance.
   *
   * @type {WalletServer}
   */
  get wallets () {
    return this._wallets
  }

  /**
   * Cart server instance.
   *
   * @type {CartServer}
   */
  get cart () {
    return this._cart
  }

  /**
   * Parser server instance.
   *
   * @type {ParserServer}
   */
  get parser () {
    return this._parser
  }

  /**
   * Transportation server instance.
   *
   * @type {TransportationServer}
   */
  get transportation () {
    return this._transportation
  }

  /**
   * Fee server instance.
   *
   * @type {FeeCalculatorServer}
   */
  get feeCalculator () {
    return this._feeCalculator
  }

  /**
   * Payment server instance.
   *
   * @type {PaymentServer}
   */
  get payments () {
    return this._payments
  }

  /**
   * File server instance.
   *
   * @type {FileServer}
   */
  get files () {
    return this._files
  }

  /**
   * Notification server instance.
   *
   * @type {NotificationServer}
   */
  get notifications () {
    return this._notifications
  }

  /**
   * Notification server instance.
   *
   * @type {AuthServer}
   */
  get auth () {
    return this._auth
  }

  /**
   * AZRY leasing server url.
   *
   * @type {AuthServer}
   */
  get azryLeasing () {
    return this._azryLeasing
  }

  /**
   * User's wallet.
   *
   * @type {Wallet}
   */
  get wallet () {
    return this._wallet
  }

  /**
   * User's token.
   *
   * @type {Token}
   */
  get token () {
    return this._token
  }

  /**
   * Clock difference with the backend.
   *
   * @type {Number}
   */
  get clockDiff () {
    return this._clockDiff
  }

  /**
   * Use a wallet to sign transactions.
   *
   * @param {Wallet} wallet User's wallet.
   */
  useWallet (wallet) {
    if (!(wallet instanceof Wallet)) {
      throw new TypeError('A wallet instance expected.')
    }

    this._wallet = wallet
  }

  /**
   * Use user's token to authenticate requests.
   *
   * @param {Token} token User's token.
   */
  useToken (token) {
    if (!(token instanceof Token)) {
      throw new TypeError('A Token instance expected.')
    }

    this._token = token
  }

  /**
   * Eject current wallet.
   */
  ejectWallet () {
    this._wallet = null
  }

  /**
   * Eject current JWT token.
   */
  ejectToken () {
    this._token = null
  }

  /**
   * Fetch network details.
   * Use it if you are going to use wallets or manually sign transactions.
   *
   * @return {Promise}
   */
  async fetchNetworkDetails () {
    let networkDetails = await this.horizon.getNetworkDetails()

    this._useNetworkPassphrase(networkDetails.meta.networkPassphrase)
    this._calculateClockDiff(networkDetails.meta.currentTime)
  }

  _useNetworkPassphrase (networkPassphrase) {
    Network.use(new Network(networkPassphrase))
  }

  _calculateClockDiff (timestamp) {
    this._clockDiff = (Date.now() / 1000) - timestamp
  }
}