horizon/resources/account.js

import omit from 'lodash/omit'
import { ResourceGroupBase } from '../../resource_group_base'
import {
  safeAccountId,
  safePlatformId
} from '../../utils/safe_account_id'

const accountTypes = Object.freeze({
  user: 'user',
  dealer: 'dealer'
})

/**
 * Account.
 *
 * @class
 */
export class Account extends ResourceGroupBase {
  /**
   * Account types.
   *
   * @enum {sting}
   */
  get types () {
    return accountTypes
  }

  /**
   * Create an account.
   *
   * @param {object} opts Account options.
   * @param {string} opts.type Account type.
   * @param {string} opts.platformId User's platform.
   * @param {string} [opts.facebookToken] Can override email, firstName, lastName and city.
   * @param {string} [opts.currency] Preferred currency.
   * @param {string} [opts.locale] Preferred user's locale.
   * @param {string} opts.email User's email.
   * @param {string} opts.firstName User's first name.
   * @param {string} opts.lastName User's last name.
   * @param {string} opts.phoneNumber User's phone number.
   * @param {string} [opts.city] User's city.
   * @param {string} [opts.company] User's company.
   * @param {string} opts.email Preferred user's locale.
   * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
   * @param {string} [password] Desired password.
   *
   * @return {JsonApiResponse}
   */
  create (opts, accountId, password) {
    return this._makeCallBuilder().post({
      data: {
        type: 'accounts',
        id: safeAccountId(accountId, this._sdk),
        attributes: Object.assign(
          {
            accountType: opts.type,
            password: password || undefined
          },
          omit(opts, ['type'])
        )
      }
    })
  }

  /**
   * Update account details.
   *
   * @param {object} opts Account options.
   * @param {string} [opts.facebookToken] Can override email, firstName, lastName and city.
   * @param {string} [opts.currency] Preferred currency.
   * @param {string} [opts.locale] Preferred user's locale.
   * @param {string} [opts.firstName] User's first name.
   * @param {string} [opts.lastName] User's last name.
   * @param {string} [opts.city] User's city.
   * @param {string} [opts.company] User's company.
   * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
   *
   * @return {JsonApiResponse}
   */
  update (opts, accountId) {
    accountId = safeAccountId(accountId, this._sdk)

    return this._makeAccountCallBuilder(accountId)
      .withCredentials()
      .patch({
        data: {
          type: 'accounts',
          id: safeAccountId(accountId, this._sdk),
          attributes: opts
        }
      })
  }

  /**
   * Verify user's phone number.
   *
   * @param {string} token 6-digit token from SMS.
   * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
   */
  verifyPhone (token, accountId) {
    return this._makeCallBuilder()
      .appendUrlSegment(['verification', 'phone'])
      .patch({
        data: {
          type: 'accounts',
          id: safeAccountId(accountId, this._sdk),
          attributes: { token }
        }
      })
  }

  /**
   * Verify user's phone number.
   *
   * @param {string} token 6-digit token from SMS.
   * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
   */
  verifyEmail (token, accountId) {
    return this._makeCallBuilder()
      .appendUrlSegment(['verification', 'email'])
      .patch({
        data: {
          type: 'accounts',
          id: safeAccountId(accountId, this._sdk),
          attributes: { token }
        }
      })
  }

  /**
   * Resend phone verification code.
   *
   * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
   */
  resendPhoneVerificationCode (accountId) {
    return this._makeCallBuilder()
      .appendUrlSegment(['verification', 'resend'])
      .get({
        accountId: safeAccountId(accountId, this._sdk),
        receiver: 'phone'
      })
  }

  /**
   * Resend phone verification code.
   *
   * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
   */
  resendEmailVerificationCode (accountId) {
    return this._makeCallBuilder()
      .appendUrlSegment(['verification', 'resend'])
      .get({
        accountId: safeAccountId(accountId, this._sdk),
        receiver: 'email'
      })
  }

  /**
   * Get user's account.
   *
   * @param {sting} [accountId] User's account ID. Use account ID of the attached wallet by default.
   * @return {JsonApiResponse}
   */
  get (accountId) {
    return this._makeAccountCallBuilder(accountId).get()
  }

  /**
   * Get multiple accounts.
   *
   * @param {object} query Request options.
   * @param {string} query.in List of account ids splitted by ','
   * @return {JsonApiResponse}
   */
  getAccounts (query) {
    return this._makeCallBuilder().get(query)
  }

  /**
   * Get account signers.
   *
   * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
   * @return {JsonApiResponse}
   */
  getSigners (accountId = null) {
    return this._makeAccountCallBuilder(accountId)
      .appendUrlSegment('signers')
      .get()
  }

  /**
  * Get account stars.
  *
  * @param {object} [query] Request options.
  * @param {Number} [query.page.number] Page number.
  * @param {Number} [query.page.size] Page size.
  * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
  *
  * @return {JsonApiResponse}
  */
  getStars (query, accountId = null) {
    return this._makeAccountCallBuilder(accountId)
      .appendUrlSegment('stars')
      .withCredentials()
      .get(query)
  }

  /**
  * Create star.
  *
  * @param {Number} lotId Lot ID.
  * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
  *
  * @return {JsonApiResponse}
  */
  createStar (lotId, accountId = null) {
    accountId = safeAccountId(accountId, this._sdk)

    return this._makeAccountCallBuilder(accountId)
      .appendUrlSegment('stars')
      .withCredentials()
      .post({
        data: {
          type: 'stars',
          id: lotId
        }
      })
  }

  /**
  * Delete star.
  *
  * @param {Number} lotId Lot ID.
  * @param {string} [accountId] User's account ID. Use account ID of the attached wallet by default.
  *
  * @return {JsonApiResponse}
  */
  deleteStar (lotId, accountId = null) {
    accountId = safeAccountId(accountId, this._sdk)

    return this._makeAccountCallBuilder(accountId)
      .appendUrlSegment(['stars', lotId])
      .withCredentials()
      .delete()
  }

  /**
   * Get account signers.
   *
   * @param {sting} signerId Signer ID.
   * @param {sting} [accountId] User's account ID. Use account ID of the attached wallet by default.
   * @return {JsonApiResponse}
   */
  getSigner (signerId, accountId) {
    return this._makeAccountCallBuilder(accountId)
      .appendUrlSegment(['signers', signerId])
      .get()
  }

  /**
   * Get account participation requests.
   *
   * @param {object} [query] Request options.
   * @param {Number} [query.page.number] Page number.
   * @param {Number} [query.page.size] Page size.
   * @param {string[]} [query.sort] Sorting params.
   * @param {string} [query.requestor] Requestor of the request.
   * @param {reviewer} [query.reviewer] Reviewer of th request.
   * @return {JsonApiResponse}
   */
  getParticipationRequests (query, accountId) {
    return this._makeAccountCallBuilder(accountId)
      .appendUrlSegment('participation_requests')
      .get(query)
  }

  /**
   * Get account bid requests.
   *
   * @param {object} [query] Request options.
   * @param {Number} [query.page.number] Page number.
   * @param {Number} [query.page.size] Page size.
   * @param {string[]} [query.sort] Sorting params.
   * @param {string} [query.requestor] Requestor of the request.
   * @param {reviewer} [query.reviewer] Reviewer of the request.
   * @return {JsonApiResponse}
   */
  getBidRequests (query, accountId) {
    return this._makeAccountCallBuilder(accountId)
      .appendUrlSegment('bid_requests')
      .get(query)
  }

  /**
   * Get account create lot requests.
   *
   * @param {object} [query] Request options.
   * @param {Number} [query.page.number] Page number.
   * @param {Number} [query.page.size] Page size.
   * @param {string[]} [query.sort] Sorting params.
   * @param {string} [query.requestor] Requestor of the request.
   * @param {reviewer} [query.reviewer] Reviewer of the request.
   * @return {JsonApiResponse}
   */
  getCreateLotRequests (query, accountId) {
    return this._makeAccountCallBuilder(accountId)
      .appendUrlSegment('create_lot_requests')
      .get(query)
  }

  /**
   * Request account recovery.
   *
   * @param {string} email User's email.
   */
  requestRecovery (email, platformId = null) {
    platformId = safePlatformId(platformId, this._sdk)

    return this._makeCallBuilder()
      .appendUrlSegment('recovery')
      .post({
        data: {
          type: 'recovery_requests',
          id: email,
          attributes: {
            platformId
          }
        }
      })
  }

  /**
   * Recover account.
   *
   * @param {string} email User's email.
   * @param {string} token Recovery token.
   * @param {string} newSigner Public key of the new signer.
   */
  recover (email, token, newSigner, platformId = null) {
    platformId = safePlatformId(platformId, this._sdk)

    return this._makeCallBuilder()
      .appendUrlSegment(['recovery', 'approve'])
      .post({
        data: {
          type: 'recovery_requests',
          id: email,
          attributes: {
            signer: newSigner,
            token,
            platformId
          }
        }
      })
  }

  _makeCallBuilder () {
    return this._server._makeCallBuilder().appendUrlSegment('accounts')
  }

  _makeAccountCallBuilder (accountId) {
    return this._server._makeCallBuilder()
      .appendUrlSegment('accounts')
      .appendAccountId(accountId)
  }
}