Source

models/ERC721/ERC721Collectibles.js

import { erc721collectibles } from '../../interfaces';
import Numbers from '../../utils/Numbers';
import IContract from '../IContract';
import ERC20Contract from '../ERC20/ERC20Contract';

const baseFeeAddress = '0x6714d41094a264bb4b8fcb74713b42cfee6b4f74';

/**
 * @typedef {Object} ERC721Collectibles~Options
 * @property {Boolean} test
 * @property {Boolean} localtest ganache local blockchain
 * @property {Web3Connection} [web3Connection=Web3Connection] created from params: 'test', 'localtest' and optional 'web3Connection' string and 'privateKey'
 * @property {string} [contractAddress]
 */

/**
 * ERC721Collectibles Object
 * @class ERC721Collectibles
 * @param {ERC721Collectibles~Options} options
 */
class ERC721Collectibles extends IContract {
  constructor(params = {}) {
    super({ abi: erc721collectibles, ...params });
  }

  /**
   * Uses {@link erc721collectibles} on the current address and assigns a new {@link ERC20Contract} with
   * {@link ERC721Collectibles#purchaseToken} as its contract address
   * @function
   * @return {Promise<void>}
   * @throws {Error} Contract is not deployed, first deploy it and provide a contract address
   */
  __assert = async () => {
    if (!this.getAddress()) {
      throw new Error(
        'Contract is not deployed, first deploy it and provide a contract address',
      );
    }
    /* Use ABI */
    this.params.contract.use(erc721collectibles, this.getAddress());

    /* Set Token Address Contract for easy access */
    this.params.ERC20Contract = new ERC20Contract({
      web3Connection: this.web3Connection,
      contractAddress: await this.purchaseToken(),
    });

    /* Assert Token Contract */
    await this.params.ERC20Contract.start();
    await this.params.ERC20Contract.__assert();
  };

  /**
   * Get ERC20 Address of the Contract
   * @returns {Promise<Address>}
   */
  purchaseToken() {
    return this.getContract()
      .methods._purchaseToken()
      .call();
  }

  /**
   * Get Price Per Pack
   * @returns {Promise<number>}
   */
  async getPricePerPack() {
    return Numbers.fromDecimals(
      await this.getContract().methods._pricePerPack().call(),
      18,
    );
  }

  /**
   * Verify if token ID exists
   * @param {Object} params
   * @param {string} params.tokenID
   * @returns {Promise<number>} Token Id
   */
  exists({ tokenID }) {
    return this.getContract()
      .methods.exists(tokenID)
      .call();
  }

  /**
   * show balance of address
   * @param {Object} params
   * @param {Address} params.address
   * @return {Promise<TransactionObject>}
   */
  balanceOf({ address }) {
    return this.__sendTx(
      this.getContract().methods.balanceOf(address),
      { call: true },
    );
  }

  /**
   * Verify if it is limited
   * @returns {Promise<boolean>}
   */
  isLimited() {
    return this.getContract().methods._isLimited().call();
  }

  /**
   * Verify what is the currentTokenId
   * @returns {Promise<number>} Current Token Id
   */
  async currentTokenId() {
    return parseInt(
      await this.getContract().methods._currentTokenId().call(),
      10,
    );
  }

  /**
   * Verify what is the getURITokenID
   * @returns {Promise<string>} URI
   */
  getURITokenID({ tokenID }) {
    return this.getContract()
      .methods.tokenURI(tokenID)
      .call();
  }

  /**
   * Verify what is the baseURI
   * @returns {Promise<string>} URI
   */
  baseURI() {
    return this.getContract().methods.baseURI().call();
  }

  /**
   * Get Ids
   * @param {Object} params
   * @param {Address} params.address
   * @returns {number[]} ids
   */
  async getRegisteredIDs({ address }) {
    const res = await this.getContract()
      .methods.getRegisteredIDs(address)
      .call();

    return res.map(r => parseInt(r, 10));
  }

  /**
   * Verify if ID is registered
   * @returns {Promise<boolean>}
   */
  isIDRegistered({ address, tokenID }) {
    return this.getContract()
      .methods.registeredIDs(address, tokenID)
      .call();
  }

  /**
   * Verify what is the current price per Pack
   * @returns {Promise<number>} Price per pack in tokens
   */
  async pricePerPack() {
    return Numbers.fromDecimals(
      await this.getContract().methods._pricePerPack().call(),
      18,
    );
  }

  /**
   * Verify how much opened packs exist
   * @returns {Promise<number>} packs
   */
  async openedPacks() {
    return parseInt(
      await this.getContract().methods._openedPacks().call(),
      10,
    );
  }

  /**
   * Approve ERC20 Allowance
   * @function
   * @return {Promise<Transaction>}
   */
  approveERC20 = async () => {
    const totalMaxAmount = await this.getERC20Contract().totalSupply();
    return this.getERC20Contract().approve({
      address: this.getAddress(),
      amount: totalMaxAmount,
    });
  };

  /**
   * Set Base Token URI
   * @function
   * @param {Object} params
   * @param {string} params.URI
   * @return {Promise<TransactionObject>}
   */
  setBaseTokenURI = ({ URI }, options) => this.__sendTx(
    this.getContract().methods.setBaseURI(URI),
    options,
  );

  /**
   * Approve ERC20 Allowance
   * @function
   * @param {Object} params
   * @param {Address} params.address
   * @param {number} params.amount
   * @return {Promise<boolean>}
   */
  isApproved = ({ address, amount }) => this.getERC20Contract().isApproved({
    address,
    amount,
    spenderAddress: this.getAddress(),
  });

  /**
   * open Pack of tokens
   * @param {Object} params
   * @param {number} params.amount Amount of packs to open
   * @return {Promise<TransactionObject>}
   */
  openPack({ amount }, options) {
    return this.__sendTx(
      this.getContract().methods.openPack(amount),
      options,
    );
  }

  /**
   * Mint created TokenID
   * @param {Object} params
   * @param {number} params.tokenID
   */
  mint({ tokenID }, options) {
    return this.__sendTx(
      this.getContract().methods.mint(tokenID),
      options,
    );
  }

  /**
   * set Purchase Token Address
   * @param {Object} params
   * @param {Address} params.purchaseToken
   * @return {Promise<TransactionObject>}
   */
  setPurchaseTokenAddress({ purchaseToken }, options) {
    return this.__sendTx(
      this.getContract()
        .methods.setPurchaseTokenAddress(purchaseToken),
      options,
    );
  }

  /**
   * Set Stake Address
   * @param {Object} params
   * @param {Address} params.purchaseToken
   * @return {Promise<TransactionObject>}
   */
  setStakeAddress({ purchaseToken }, options) {
    return this.__sendTx(
      this.getContract().methods.setStakeAddress(purchaseToken),
      options,
    );
  }

  /**
   * Set Fee Address
   * @param {Object} params
   * @param {Address} params.purchaseToken
   * @return {Promise<TransactionObject>}
   */
  setSwapBackAddress({ purchaseToken }, options) {
    return this.__sendTx(
      this.getContract()
        .methods.setSwapBackAddress(purchaseToken),
      options,
    );
  }

  /**
   * Set Fee Address
   * @param {Object} params
   * @param {Address} params.purchaseToken
   * @return {Promise<TransactionObject>}
   */
  setFeeAddress({ purchaseToken }, options) {
    return this.__sendTx(
      this.getContract().methods.setFeeAddress(purchaseToken),
      options,
    );
  }

  /**
   * Set Price per Pack
   * @param {Object} amount
   * @param {number} amount.newPrice
   * @return {Promise<TransactionObject>}
   */
  setPricePerPack({ newPrice }, options) {
    const newPriceWithDecimals = Numbers.toSmartContractDecimals(newPrice, 18);
    return this.__sendTx(
      this.getContract()
        .methods.setPricePerPack(newPriceWithDecimals),
      options,
    );
  }

  /**
   * @link ERC721Collectibles.__deploy
   * @function
   * @param {Object} params
   * @param {*} params.name
   * @param {*} params.symbol
   * @param {number} params.limitedAmount
   * @param {*} params.erc20Purchase
   * @param {string} params.feeAddress
   * @param {string} params.otherAddress
   * @param {IContract~TxOptions} options
   * @return {Promise<*|undefined>}
   * @throws {Error} Please provide an erc20 address for purchases
   * @throws {Error} Please provide a name
   * @throws {Error} Please provide a symbol
   */
  deploy = async (
    {
      name,
      symbol,
      limitedAmount = 0,
      erc20Purchase,
      feeAddress = '0x0000000000000000000000000000000000000001',
      otherAddress = '0x0000000000000000000000000000000000000001',
    },
    options,
  ) => {
    if (!erc20Purchase) {
      throw new Error('Please provide an erc20 address for purchases');
    }

    if (!name) {
      throw new Error('Please provide a name');
    }

    if (!symbol) {
      throw new Error('Please provide a symbol');
    }
    const params = [
      name,
      symbol,
      limitedAmount,
      erc20Purchase,
      baseFeeAddress,
      feeAddress,
      otherAddress,
    ];
    const res = await this.__deploy(params, options);
    this.params.contractAddress = res.contractAddress;
    /* Call to Backend API */
    await this.__assert();
    return res;
  };

  /**
   * @function
   * @return ERC20Contract|undefined
   */
  getERC20Contract = () => this.params.ERC20Contract;
}

export default ERC721Collectibles;