home-2/src/api.js

import * as vaultSecp256k1 from '@zippie/vault-api/src/secp256k1'
import vaultweb3 from '@zippie/vault-web3-provider'
import * as constants from './util/constants'
import { fetchDataFromPermaStore } from './util/zippieBackend'
import { initDatabase } from './util/zippieDatabase'
import { 
  updateSubWallet, 
  fetchBlankCheck, 
  claimBlankCheckNoPending,
  initZippieMultisigAccounts, 
  getTokenBalanceFromWeb3, 
  initZippieMultisigContract, 
  initErc20TokenContract,
  createBlankCheck,
  addNewMultisigAccount,
  getMultisigAccountForToken
} from './util/zippieWallet'

import Web3 from 'web3'

/** @module zippie-api/Wallet */

const WALLET_SERVICE_TAG = 'wallet'

var context

export async function init (vault) {
  context = vault

  var provider = vaultweb3.init(vault, vaultSecp256k1, constants.web3Parameters)
  window.web3 = new Web3(provider)

  const zippieMultisigContract = initZippieMultisigContract(vault)
  window.zippieMultisigContract = zippieMultisigContract

  const erc20TokenContract = initErc20TokenContract()
  window.erc20TokenContract = erc20TokenContract

  await initDatabase()

  const address = await vaultweb3.addAccount(constants.signerAccountDerive)
  window.zippieSignerAddress = address

  initZippieMultisigAccounts(vault)

  const ipc = vault.ipc.createService(WALLET_SERVICE_TAG)

  ipc.addReceiver(createAccountForToken, 'createAccountForToken')
  ipc.addReceiver(getAccountForToken, 'getAccountForToken')
  ipc.addReceiver(getTokenBalance, 'getTokenBalance')
  ipc.addReceiver(getPaymentInfo, 'getPaymentInfo')
  ipc.addReceiver(createPayment, 'createPayment')
  ipc.addReceiver(redeemPayment, 'redeemPayment')

  // DEPRECATED
  ipc.addReceiver(function (token, amount, message) {
    console.warn('[WAPI]: DEPRECATED API CALL USAGE')
    return createPayment(token, amount, message)
  }, 'createPaymentLink')

  // DEPRECATED
  ipc.addReceiver(function (payment) {
    console.warn('[WAPI]: DEPRECATED API CALL USAGE')
    return redeemPayment(payment)
  }, 'claimPayment')

  ipc.ready()
}

/**
 * Create a whitelisted multisig account for a particular ERC20 token
 * for use by this application.
 * 
 * @param {string} token ERC20 Token contract address
 * @returns {Promise} Resolves with WalletAccount on success
 */
async function createAccountForToken (token) {
  let account = await getMultisigAccountForToken(token)

  if(account === undefined) {
    account = await addNewMultisigAccount(context, token, this.origin)
    console.info('[WAPI createAccountForToken - [New Account] ', account)
  }

  console.info('[WAPI] createAccountForToken', account)
  return account
}

/**
 * Get a users' ERC20 multisig account associated with a specific token
 * contract address.
 * @param {*} address ERC20 Token contract address
 * @returns {Promise} Resolves with WalletAccount on success
 */
async function getAccountForToken (address) {
  console.info('[WAPI] getAccountForToken - ', address)

  let data = await fetchDataFromPermaStore(context, constants.permaStoreMultisigAccountsDerive)
  if(data !== undefined && address in data) {
    console.info('[WAPI] getAccountForToken', data)
    var tokenAccount = data[address][0].accountAddress
  }

  console.info('[WAPI] getAccountForToken - ', tokenAccount)
  return tokenAccount || null
}

/**
 * Get the users' balance for specified Token.
 * @param {*} token ERC20 Token contract address
 * @returns {Promise} Resolves with account balance in BN string format.
 */
async function getTokenBalance (token) {
  let walletInfo = await updateSubWallet(context, token)
  let data = await getTokenBalanceFromWeb3(token, walletInfo.accountAddress)

  console.info('[WAPI]: getTokenBalance - ', data)
  return data
}

/**
 * Downloads and decrypts payment object from IPFS and returns payment object.
 * @param {string} ipfshash IPFS content address and decryption key tuple.
 * @returns {Promise} Resolves PaymentObject on success.
 */
async function getPaymentInfo (ipfshash) {
  let data = await fetchBlankCheck(ipfshash)

  console.info('[WAPI] fetchBlankCheck ', data)
  return data
}

/**
 * Creates a new payment object and stores encrypted into IPFS.
 * @param {string} token ERC20 Token contract address
 * @param {string} amount Amount to send, in wei
 * @param {string} message Customisable user message
 * @returns {Promise} Resolves to IPFS hash and key tuple on success.
 */
async function createPayment (token, amount, message = '') {
  console.info('[WAPI] createPaymentLink ', token, amount, message)

  // TODO: check token
  // TODO: Any further validation?

  let multisig = await getMultisigAccountForToken(token)

  console.info('[WAPI] createPaymentLink ', multisig)

  if(this.origin !== multisig.dappUri) {
    console.warn('[WAPI]: Permission denied, origin has to be:', multisig.dappUri)
    return { error: 'Permission Denied' }
  }

  return await createBlankCheck(context, multisig, amount, message)
}

/**
 * Redeems a PaymentObject payment into the appropriate users' wallet account.
 * @param {PaymentObject} payment
 * @returns {Promise} Resolves on success.
 */
async function redeemPayment (payment) {
  let data = await claimBlankCheckNoPending(context, payment, this.origin)

  console.info('[WAPI]: claimBlankCheck - ', data)
  return data
}