@oceanprotocol/lib 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/CodeExamples.md +19 -8
- package/dist/lib.js +1 -1
- package/dist/lib.js.map +1 -1
- package/dist/lib.modern.js +1 -1
- package/dist/lib.modern.js.map +1 -1
- package/dist/lib.module.js +1 -1
- package/dist/lib.module.js.map +1 -1
- package/dist/lib.umd.js +1 -1
- package/dist/lib.umd.js.map +1 -1
- package/dist/src/@types/File.d.ts +23 -0
- package/dist/src/@types/{FileMetadata.d.ts → FileInfo.d.ts} +1 -1
- package/dist/src/@types/index.d.ts +2 -1
- package/dist/src/provider/Provider.d.ts +5 -5
- package/dist/src/utils/TokenUtils.d.ts +17 -0
- package/package.json +8 -8
package/dist/lib.modern.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.modern.js","sources":["../src/utils/Logger.ts","../src/utils/DatatokenName.ts","../src/utils/minAbi.ts","../src/utils/Constants.ts","../src/utils/ContractUtils.ts","../src/utils/FetchHelper.ts","../src/utils/ConfigHelper.ts","../src/utils/DdoHelpers.ts","../src/utils/SignatureUtils.ts","../src/utils/TokenUtils.ts","../src/utils/General.ts","../src/utils/PoolHelpers.ts","../src/aquarius/Aquarius.ts","../src/pools/balancer/Pool.ts","../src/pools/dispenser/Dispenser.ts","../src/pools/fixedRate/FixedRateExchange.ts","../src/pools/ssContracts/SideStaking.ts","../src/pools/Router.ts","../src/tokens/NFT.ts","../src/tokens/Datatoken.ts","../src/factories/NFTFactory.ts","../src/models/Config.ts","../src/utils/ConversionTypeHelper.ts","../src/provider/Provider.ts"],"sourcesContent":["/* eslint-disable no-unused-vars */\nexport enum LogLevel {\n None = -1,\n Error = 0,\n Warn = 1,\n Log = 2,\n Verbose = 3\n}\n/* eslint-enable no-unused-vars */\n\nexport class Logger {\n constructor(private logLevel: LogLevel = LogLevel.Error) {}\n\n public setLevel(logLevel: LogLevel): void {\n this.logLevel = logLevel\n }\n\n public bypass(...args: any[]): void {\n this.dispatch('log', -Infinity as any, ...args)\n }\n\n public debug(...args: any[]): void {\n this.dispatch('debug', LogLevel.Verbose, ...args)\n }\n\n public log(...args: any[]): void {\n this.dispatch('log', LogLevel.Log, ...args)\n }\n\n public warn(...args: any[]): void {\n this.dispatch('warn', LogLevel.Warn, ...args)\n }\n\n public error(...args: any[]): void {\n this.dispatch('error', LogLevel.Error, ...args)\n }\n\n private dispatch(verb: string, level: LogLevel, ...args: any[]) {\n if (this.logLevel >= level) {\n console[verb](...args)\n }\n }\n}\n\nexport const LoggerInstance = new Logger()\nexport default LoggerInstance\n","import wordListDefault from '../data/words.json'\n\n/**\n * Generate new datatoken name & symbol from a word list\n * @return {<{ name: String; symbol: String }>} datatoken name & symbol. Produces e.g. \"Endemic Jellyfish Token\" & \"ENDJEL-45\"\n */\nexport function generateDtName(wordList?: { nouns: string[]; adjectives: string[] }): {\n name: string\n symbol: string\n} {\n const list = wordList || wordListDefault\n const random1 = Math.floor(Math.random() * list.adjectives.length)\n const random2 = Math.floor(Math.random() * list.nouns.length)\n const indexNumber = Math.floor(Math.random() * 100)\n\n // Capitalized adjective & noun\n const adjective = list.adjectives[random1].replace(/^\\w/, (c) => c.toUpperCase())\n const noun = list.nouns[random2].replace(/^\\w/, (c) => c.toUpperCase())\n\n const name = `${adjective} ${noun} Token`\n // use first 3 letters of name, uppercase it, and add random number\n const symbol = `${(\n adjective.substring(0, 3) + noun.substring(0, 3)\n ).toUpperCase()}-${indexNumber}`\n\n return { name, symbol }\n}\n","import { AbiItem } from 'web3-utils/types'\n\nexport const minAbi = [\n {\n constant: true,\n inputs: [],\n name: 'name',\n outputs: [\n {\n name: '',\n type: 'string'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: false,\n inputs: [\n {\n name: '_spender',\n type: 'address'\n },\n {\n name: '_value',\n type: 'uint256'\n }\n ],\n name: 'approve',\n outputs: [\n {\n name: '',\n type: 'bool'\n }\n ],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function'\n },\n {\n constant: true,\n inputs: [],\n name: 'totalSupply',\n outputs: [\n {\n name: '',\n type: 'uint256'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: false,\n inputs: [\n {\n name: '_from',\n type: 'address'\n },\n {\n name: '_to',\n type: 'address'\n },\n {\n name: '_value',\n type: 'uint256'\n }\n ],\n name: 'transferFrom',\n outputs: [\n {\n name: '',\n type: 'bool'\n }\n ],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function'\n },\n {\n constant: true,\n inputs: [],\n name: 'decimals',\n outputs: [\n {\n name: '',\n type: 'uint8'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: true,\n inputs: [\n {\n name: '_owner',\n type: 'address'\n }\n ],\n name: 'balanceOf',\n outputs: [\n {\n name: 'balance',\n type: 'uint256'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: true,\n inputs: [],\n name: 'symbol',\n outputs: [\n {\n name: '',\n type: 'string'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: false,\n inputs: [\n {\n name: '_to',\n type: 'address'\n },\n {\n name: '_value',\n type: 'uint256'\n }\n ],\n name: 'transfer',\n outputs: [\n {\n name: '',\n type: 'bool'\n }\n ],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function'\n },\n {\n constant: true,\n inputs: [\n {\n name: '_owner',\n type: 'address'\n },\n {\n name: '_spender',\n type: 'address'\n }\n ],\n name: 'allowance',\n outputs: [\n {\n name: '',\n type: 'uint256'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n payable: true,\n stateMutability: 'payable',\n type: 'fallback'\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: true,\n name: 'owner',\n type: 'address'\n },\n {\n indexed: true,\n name: 'spender',\n type: 'address'\n },\n {\n indexed: false,\n name: 'value',\n type: 'uint256'\n }\n ],\n name: 'Approval',\n type: 'event'\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: true,\n name: 'from',\n type: 'address'\n },\n {\n indexed: true,\n name: 'to',\n type: 'address'\n },\n {\n indexed: false,\n name: 'value',\n type: 'uint256'\n }\n ],\n name: 'Transfer',\n type: 'event'\n }\n] as AbiItem[]\n","export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'\nexport const GASLIMIT_DEFAULT = 1000000\n","import Web3 from 'web3'\nimport BigNumber from 'bignumber.js'\nimport { Contract } from 'web3-eth-contract'\nimport { generateDtName } from './DatatokenName'\nimport {\n Erc20CreateParams,\n FreCreationParams,\n FreOrderParams,\n PoolCreationParams\n} from '../@types'\nimport { Config } from '../models'\nimport { minAbi } from './minAbi'\nimport LoggerInstance from './Logger'\nimport { GASLIMIT_DEFAULT, ZERO_ADDRESS } from './Constants'\n\nexport function setContractDefaults(contract: Contract, config: Config): Contract {\n if (config) {\n if (config.transactionBlockTimeout)\n contract.transactionBlockTimeout = config.transactionBlockTimeout\n if (config.transactionConfirmationBlocks)\n contract.transactionConfirmationBlocks = config.transactionConfirmationBlocks\n if (config.transactionPollingTimeout)\n contract.transactionPollingTimeout = config.transactionPollingTimeout\n }\n return contract\n}\n\nexport async function getFairGasPrice(web3: Web3, config: Config): Promise<string> {\n const x = new BigNumber(await web3.eth.getGasPrice())\n if (config && config.gasFeeMultiplier)\n return x\n .multipliedBy(config.gasFeeMultiplier)\n .integerValue(BigNumber.ROUND_DOWN)\n .toString(10)\n else return x.toString(10)\n}\n\nexport function getErcCreationParams(ercParams: Erc20CreateParams): any {\n let name: string, symbol: string\n // Generate name & symbol if not present\n if (!ercParams.name || !ercParams.symbol) {\n ;({ name, symbol } = generateDtName())\n }\n return {\n templateIndex: ercParams.templateIndex,\n strings: [ercParams.name || name, ercParams.symbol || symbol],\n addresses: [\n ercParams.minter,\n ercParams.paymentCollector,\n ercParams.mpFeeAddress,\n ercParams.feeToken\n ],\n uints: [Web3.utils.toWei(ercParams.cap), Web3.utils.toWei(ercParams.feeAmount)],\n bytess: []\n }\n}\n\nexport function getFreOrderParams(freParams: FreOrderParams): any {\n return {\n exchangeContract: freParams.exchangeContract,\n exchangeId: freParams.exchangeId,\n maxBaseTokenAmount: Web3.utils.toWei(freParams.maxBaseTokenAmount),\n swapMarketFee: Web3.utils.toWei(freParams.swapMarketFee),\n marketFeeAddress: freParams.marketFeeAddress\n }\n}\n\nexport function getFreCreationParams(freParams: FreCreationParams): any {\n if (!freParams.allowedConsumer) freParams.allowedConsumer = ZERO_ADDRESS\n const withMint = freParams.withMint ? 1 : 0\n\n return {\n fixedPriceAddress: freParams.fixedRateAddress,\n addresses: [\n freParams.baseTokenAddress,\n freParams.owner,\n freParams.marketFeeCollector,\n freParams.allowedConsumer\n ],\n uints: [\n freParams.baseTokenDecimals,\n freParams.datatokenDecimals,\n Web3.utils.toWei(freParams.fixedRate),\n Web3.utils.toWei(freParams.marketFee),\n withMint\n ]\n }\n}\n\nexport async function getPoolCreationParams(\n web3: Web3,\n poolParams: PoolCreationParams\n): Promise<any> {\n return {\n addresses: [\n poolParams.ssContract,\n poolParams.baseTokenAddress,\n poolParams.baseTokenSender,\n poolParams.publisherAddress,\n poolParams.marketFeeCollector,\n poolParams.poolTemplateAddress\n ],\n ssParams: [\n Web3.utils.toWei(poolParams.rate),\n poolParams.baseTokenDecimals,\n Web3.utils.toWei(poolParams.vestingAmount),\n poolParams.vestedBlocks,\n await amountToUnits(\n web3,\n poolParams.baseTokenAddress,\n poolParams.initialBaseTokenLiquidity\n )\n ],\n swapFees: [\n Web3.utils.toWei(poolParams.swapFeeLiquidityProvider),\n Web3.utils.toWei(poolParams.swapFeeMarketRunner)\n ]\n }\n}\n\nexport async function unitsToAmount(\n web3: Web3,\n token: string,\n amount: string,\n tokenDecimals?: number\n): Promise<string> {\n try {\n const tokenContract = new web3.eth.Contract(minAbi, token)\n let decimals = tokenDecimals || (await tokenContract.methods.decimals().call())\n if (decimals === '0') {\n decimals = 18\n }\n\n const amountFormatted = new BigNumber(amount).div(\n new BigNumber(10).exponentiatedBy(decimals)\n )\n\n BigNumber.config({ EXPONENTIAL_AT: 50 })\n return amountFormatted.toString()\n } catch (e) {\n LoggerInstance.error(`ERROR: FAILED TO CALL DECIMALS(), USING 18' : ${e.message}`)\n }\n}\n\nexport async function amountToUnits(\n web3: Web3,\n token: string,\n amount: string,\n tokenDecimals?: number\n): Promise<string> {\n try {\n const tokenContract = new web3.eth.Contract(minAbi, token)\n let decimals = tokenDecimals || (await tokenContract.methods.decimals().call())\n if (decimals === '0') {\n decimals = 18\n }\n BigNumber.config({ EXPONENTIAL_AT: 50 })\n\n const amountFormatted = new BigNumber(amount).times(\n new BigNumber(10).exponentiatedBy(decimals)\n )\n\n return amountFormatted.toString()\n } catch (e) {\n LoggerInstance.error(`ERROR: FAILED TO CALL DECIMALS(), USING 18', ${e.message}`)\n }\n}\n\n/**\n * Estimates the gas used when a function would be executed on chain\n * @param {string} from account that calls the function\n * @param {Function} functionToEstimateGas function that we need to estimate the gas\n * @param {...any[]} args arguments of the function\n * @return {Promise<number>} gas cost of the function\n */\nexport async function estimateGas(\n from: string,\n functionToEstimateGas: Function,\n ...args: any[]\n): Promise<any> {\n let estimatedGas = GASLIMIT_DEFAULT\n try {\n estimatedGas = await functionToEstimateGas.apply(null, args).estimateGas(\n {\n from: from\n },\n (err, estGas) => (err ? GASLIMIT_DEFAULT : estGas)\n )\n } catch (e) {\n LoggerInstance.error(`ERROR: Estimate gas failed!`, e)\n }\n return estimatedGas\n}\n","import fetch from 'cross-fetch'\nimport LoggerInstance from './Logger'\nimport { DownloadResponse } from '../@types/DownloadResponse'\n\nexport async function fetchData(url: string, opts: RequestInit): Promise<Response> {\n const result = await fetch(url, opts)\n if (!result.ok) {\n LoggerInstance.error(`Error requesting [${opts.method}] ${url}`)\n LoggerInstance.error(`Response message: \\n${await result.text()}`)\n throw result\n }\n return result\n}\n\nexport async function downloadFileBrowser(url: string): Promise<void> {\n const anchor = document.createElement('a')\n anchor.download = ''\n anchor.href = url\n anchor.click()\n}\n\nexport async function downloadFile(\n url: string,\n index?: number\n): Promise<DownloadResponse> {\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error('Response error.')\n }\n let filename: string\n try {\n filename = response.headers\n .get('content-disposition')\n .match(/attachment;filename=(.+)/)[1]\n } catch {\n try {\n filename = url.split('/').pop()\n } catch {\n filename = `file${index}`\n }\n }\n\n return { data: await response.arrayBuffer(), filename }\n}\n\nexport async function getData(url: string): Promise<Response> {\n return fetch(url, {\n method: 'GET',\n headers: {\n 'Content-type': 'application/json'\n }\n })\n}\n\nasync function postWithHeaders(\n url: string,\n payload: BodyInit,\n headers: any\n): Promise<Response> {\n if (payload != null) {\n return fetch(url, {\n method: 'POST',\n body: payload,\n headers\n })\n } else {\n return fetch(url, {\n method: 'POST'\n })\n }\n}\n\nexport async function postData(url: string, payload: BodyInit): Promise<Response> {\n const headers = {\n 'Content-type': 'application/json'\n }\n return postWithHeaders(url, payload, headers)\n}\n","import Config from '../models/Config'\n// eslint-disable-next-line import/no-named-default\nimport { default as DefaultContractsAddresses } from '@oceanprotocol/contracts/addresses/address.json'\nimport LoggerInstance from './Logger'\n\nconst configHelperNetworksBase: Config = {\n chainId: null,\n network: 'unknown',\n metadataCacheUri: 'https://v4.aquarius.oceanprotocol.com',\n nodeUri: 'http://127.0.0.1:8545',\n providerUri: 'http://127.0.0.1:8030',\n subgraphUri: null,\n explorerUri: null,\n oceanTokenAddress: null,\n oceanTokenSymbol: 'OCEAN',\n poolTemplateAddress: null,\n fixedRateExchangeAddress: null,\n dispenserAddress: null,\n startBlock: 0,\n transactionBlockTimeout: 50,\n transactionConfirmationBlocks: 1,\n transactionPollingTimeout: 750,\n gasFeeMultiplier: 1\n}\n\nexport const configHelperNetworks: Config[] = [\n {\n ...configHelperNetworksBase\n },\n {\n // barge\n ...configHelperNetworksBase,\n chainId: 8996,\n network: 'development',\n metadataCacheUri: 'http://127.0.0.1:5000',\n providerUri: 'http://172.15.0.4:8030'\n },\n {\n ...configHelperNetworksBase,\n chainId: 3,\n network: 'ropsten',\n nodeUri: 'https://ropsten.infura.io/v3',\n providerUri: 'https://v4.provider.ropsten.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.ropsten.oceanprotocol.com',\n explorerUri: 'https://ropsten.etherscan.io',\n gasFeeMultiplier: 1.1\n },\n {\n ...configHelperNetworksBase,\n chainId: 4,\n network: 'rinkeby',\n nodeUri: 'https://rinkeby.infura.io/v3',\n providerUri: 'https://v4.provider.rinkeby.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.rinkeby.oceanprotocol.com',\n explorerUri: 'https://rinkeby.etherscan.io',\n gasFeeMultiplier: 1.1\n },\n {\n ...configHelperNetworksBase,\n chainId: 1,\n network: 'mainnet',\n nodeUri: 'https://mainnet.infura.io/v3',\n providerUri: 'https://v4.provider.mainnet.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.mainnet.oceanprotocol.com',\n explorerUri: 'https://etherscan.io',\n startBlock: 11105459,\n transactionBlockTimeout: 150,\n transactionConfirmationBlocks: 5,\n transactionPollingTimeout: 1750,\n gasFeeMultiplier: 1.05\n },\n {\n ...configHelperNetworksBase,\n chainId: 137,\n network: 'polygon',\n nodeUri: 'https://polygon-mainnet.infura.io/v3',\n providerUri: 'https://v4.provider.polygon.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.polygon.oceanprotocol.com',\n explorerUri: 'https://polygonscan.com',\n oceanTokenSymbol: 'mOCEAN'\n },\n {\n ...configHelperNetworksBase,\n chainId: 1287,\n network: 'moonbase',\n nodeUri: 'https://rpc.api.moonbase.moonbeam.network',\n providerUri: 'https://v4.provider.moonbase.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.moonbase.oceanprotocol.com',\n explorerUri: 'https://moonbase.moonscan.io/',\n gasFeeMultiplier: 1.1\n },\n {\n ...configHelperNetworksBase,\n chainId: 2021000,\n network: 'gaiaxtestnet',\n nodeUri: 'https://rpc.gaiaxtestnet.oceanprotocol.com',\n providerUri: 'https://v4.provider.gaiaxtestnet.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.gaiaxtestnet.oceanprotocol.com',\n explorerUri: 'https://blockscout.gaiaxtestnet.oceanprotocol.com'\n },\n {\n ...configHelperNetworksBase,\n chainId: 80001,\n network: 'mumbai',\n nodeUri: 'https://polygon-mumbai.infura.io/v3',\n providerUri: 'https://v4.provider.mumbai.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.mumbai.oceanprotocol.com',\n explorerUri: 'https://mumbai.polygonscan.com',\n gasFeeMultiplier: 1.1\n },\n {\n ...configHelperNetworksBase,\n chainId: 56,\n network: 'bsc',\n nodeUri: 'https://bsc-dataseed.binance.org',\n providerUri: 'https://v4.provider.bsc.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.bsc.oceanprotocol.com',\n explorerUri: 'https://bscscan.com/',\n gasFeeMultiplier: 1.05\n },\n {\n ...configHelperNetworksBase,\n chainId: 246,\n network: 'energyweb',\n nodeUri: 'https://rpc.energyweb.org',\n providerUri: 'https://v4.provider.energyweb.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.energyweb.oceanprotocol.com',\n explorerUri: 'https://explorer.energyweb.org',\n gasFeeMultiplier: 1.05\n },\n {\n ...configHelperNetworksBase,\n chainId: 1285,\n network: 'moonriver',\n nodeUri: 'https://moonriver.api.onfinality.io/public',\n providerUri: 'https://v4.provider.moonriver.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.moonriver.oceanprotocol.com',\n explorerUri: 'https://moonriver.moonscan.io/',\n gasFeeMultiplier: 1.05\n }\n]\n\nexport class ConfigHelper {\n /* Load contract addresses from env ADDRESS_FILE (generated by ocean-contracts) */\n public getAddressesFromEnv(network: string, customAddresses?: any): Partial<Config> {\n // use the defaults first\n let configAddresses: Partial<Config>\n\n // load from custom addresses structure\n if (customAddresses) {\n try {\n const {\n FixedPrice,\n Dispenser,\n Staking,\n poolTemplate,\n ERC721Factory,\n OPFCommunityFeeCollector,\n Ocean,\n chainId,\n startBlock\n } = customAddresses[network]\n configAddresses = {\n erc721FactoryAddress: ERC721Factory,\n sideStakingAddress: Staking,\n opfCommunityFeeCollector: OPFCommunityFeeCollector,\n poolTemplateAddress: poolTemplate,\n fixedRateExchangeAddress: FixedPrice,\n dispenserAddress: Dispenser,\n oceanTokenAddress: Ocean,\n chainId: chainId,\n startBlock: startBlock,\n ...(process.env.AQUARIUS_URI && { metadataCacheUri: process.env.AQUARIUS_URI })\n }\n } catch (e) {\n // console.error(`ERROR: Could not load local contract address file: ${e.message}`)\n // return null\n }\n } else {\n // no custom addresses structure was passed, trying to load default\n if (DefaultContractsAddresses[network]) {\n const {\n FixedPrice,\n Dispenser,\n Staking,\n poolTemplate,\n OPFCommunityFeeCollector,\n ERC721Factory,\n Ocean,\n chainId,\n startBlock\n } = DefaultContractsAddresses[network]\n configAddresses = {\n erc721FactoryAddress: ERC721Factory,\n sideStakingAddress: Staking,\n opfCommunityFeeCollector: OPFCommunityFeeCollector,\n poolTemplateAddress: poolTemplate,\n fixedRateExchangeAddress: FixedPrice,\n dispenserAddress: Dispenser,\n oceanTokenAddress: Ocean,\n chainId: chainId,\n startBlock: startBlock,\n ...(process.env.AQUARIUS_URI && { metadataCacheUri: process.env.AQUARIUS_URI })\n }\n }\n }\n return configAddresses\n }\n\n public getConfig(network: string | number, infuraProjectId?: string): Config {\n const filterBy = typeof network === 'string' ? 'network' : 'chainId'\n let config = configHelperNetworks.find((c) => c[filterBy] === network)\n\n if (!config) {\n LoggerInstance.error(`No config found for given network '${network}'`)\n return null\n }\n\n const contractAddressesConfig = this.getAddressesFromEnv(config.network)\n config = { ...config, ...contractAddressesConfig }\n\n const nodeUri = infuraProjectId\n ? `${config.nodeUri}/${infuraProjectId}`\n : config.nodeUri\n\n return { ...config, nodeUri }\n }\n}\n","import sha256 from 'crypto-js/sha256'\nimport Web3 from 'web3'\nimport LoggerInstance from './Logger'\n\nexport function generateDid(erc721Address: string, chainId: number): string {\n erc721Address = Web3.utils.toChecksumAddress(erc721Address)\n const checksum = sha256(erc721Address + chainId.toString(10))\n return `did:op:${checksum.toString()}`\n}\n\nexport function getHash(data: any): string {\n try {\n return sha256(data).toString()\n } catch (e) {\n LoggerInstance.error('getHash error: ', e.message)\n }\n}\n","import Web3 from 'web3'\nimport { LoggerInstance } from './Logger'\n\nexport async function signHash(web3: Web3, message: string, address: string) {\n let signedMessage = await web3.eth.sign(message, address)\n signedMessage = signedMessage.substr(2) // remove 0x\n const r = '0x' + signedMessage.slice(0, 64)\n const s = '0x' + signedMessage.slice(64, 128)\n let v = '0x' + signedMessage.slice(128, 130)\n // make sure we obey 27 and 28 standards\n if (v === '0x00') v = '0x1b'\n if (v === '0x01') v = '0x1c'\n return { v, r, s }\n}\n","import Decimal from 'decimal.js'\nimport { Contract } from 'web3-eth-contract'\nimport {\n amountToUnits,\n estimateGas,\n getFairGasPrice,\n unitsToAmount\n} from './ContractUtils'\nimport { minAbi } from './minAbi'\nimport LoggerInstance from './Logger'\nimport { TransactionReceipt } from 'web3-core'\nimport Web3 from 'web3'\n\n/**\n * Estimate gas cost for approval function\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} spender\n * @param {String} amount\n * @param {String} force\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\nexport async function estApprove(\n web3: Web3,\n account: string,\n tokenAddress: string,\n spender: string,\n amount: string,\n contractInstance?: Contract\n): Promise<number> {\n const tokenContract = contractInstance || new web3.eth.Contract(minAbi, tokenAddress)\n\n return estimateGas(account, tokenContract.methods.approve, spender, amount)\n}\n\n/**\n * Approve spender to spent amount tokens\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} spender\n * @param {String} amount amount of ERC20 tokens (always expressed as wei)\n * @param {boolean} force if true, will overwrite any previous allowence. Else, will check if allowence is enough and will not send a transaction if it's not needed\n * @param {number} tokenDecimals optional number of decimals of the token\n */\nexport async function approve(\n web3: Web3,\n account: string,\n tokenAddress: string,\n spender: string,\n amount: string,\n force = false,\n tokenDecimals?: number\n): Promise<TransactionReceipt | string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n if (!force) {\n const currentAllowence = await allowance(web3, tokenAddress, account, spender)\n if (new Decimal(currentAllowence).greaterThanOrEqualTo(new Decimal(amount))) {\n return currentAllowence\n }\n }\n let result = null\n const amountFormatted = await amountToUnits(web3, tokenAddress, amount, tokenDecimals)\n const estGas = await estimateGas(\n account,\n tokenContract.methods.approve,\n spender,\n amountFormatted\n )\n\n try {\n result = await tokenContract.methods.approve(spender, amountFormatted).send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(web3, null)\n })\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to approve spender to spend tokens : ${e.message}`\n )\n }\n return result\n}\n\n/**\n * Estimate gas cost for transfer function\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} recipient\n * @param {String} amount\n * @param {String} force\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\nexport async function estTransfer(\n web3: Web3,\n account: string,\n tokenAddress: string,\n recipient: string,\n amount: string,\n contractInstance?: Contract\n): Promise<number> {\n const tokenContract = contractInstance || new web3.eth.Contract(minAbi, tokenAddress)\n\n return estimateGas(account, tokenContract.methods.transfer, recipient, amount)\n}\n\n/**\n * Moves amount tokens from the caller’s account to recipient.\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} recipient\n * @param {String} amount amount of ERC20 tokens (not as wei)\n * @param {String} force if true, will overwrite any previous allowence. Else, will check if allowence is enough and will not send a transaction if it's not needed\n */\nexport async function transfer(\n web3: Web3,\n account: string,\n tokenAddress: string,\n recipient: string,\n amount: string\n): Promise<TransactionReceipt | string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n\n let result = null\n const amountFormatted = await amountToUnits(web3, tokenAddress, amount)\n const estGas = await estimateGas(\n account,\n tokenContract.methods.transfer,\n recipient,\n amountFormatted\n )\n\n try {\n result = await tokenContract.methods.transfer(recipient, amountFormatted).send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(web3, null)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to transfer tokens : ${e.message}`)\n }\n return result\n}\n\n/**\n * Get Allowance for any erc20\n * @param {Web3} web3\n * @param {String } tokenAdress\n * @param {String} account\n * @param {String} spender\n * @param {number} tokenDecimals optional number of decimals of the token\n */\nexport async function allowance(\n web3: Web3,\n tokenAddress: string,\n account: string,\n spender: string,\n tokenDecimals?: number\n): Promise<string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n const trxReceipt = await tokenContract.methods.allowance(account, spender).call()\n\n return await unitsToAmount(web3, tokenAddress, trxReceipt, tokenDecimals)\n}\n\n/**\n * Get balance for any erc20\n * @param {Web3} web3\n * @param {String} tokenAdress\n * @param {String} owner\n * @param {String} spender\n * @param {number} tokenDecimals optional number of decimals of the token\n */\nexport async function balance(\n web3: Web3,\n tokenAddress: string,\n account: string,\n tokenDecimals?: number\n): Promise<string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n const trxReceipt = await tokenContract.methods.balanceOf(account).call()\n\n return await unitsToAmount(web3, tokenAddress, trxReceipt, tokenDecimals)\n}\n\n/**\n * Get decimals for any erc20\n * @param {Web3} web3\n * @param {String} tokenAdress\n * @return {Promise<number>} Number of decimals of the token\n */\nexport async function decimals(web3: Web3, tokenAddress: string): Promise<number> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n return await tokenContract.methods.decimals().call()\n}\n","/**\n * Simple blocking sleep function\n */\nexport async function sleep(ms: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, ms)\n })\n}\n","import Decimal from 'decimal.js'\nimport { Pool } from '..'\n\nexport function calcMaxExactOut(balance: string): Decimal {\n return new Decimal(balance).div(2)\n}\n\nexport function calcMaxExactIn(balance: string): Decimal {\n return new Decimal(balance).div(2)\n}\nexport async function getMaxSwapExactOut(\n poolInstance: Pool,\n poolAddress: string,\n tokenAddress: string\n): Promise<Decimal> {\n const reserve = await poolInstance.getReserve(poolAddress, tokenAddress)\n return calcMaxExactOut(reserve)\n}\n\nexport async function getMaxSwapExactIn(\n poolInstance: Pool,\n poolAddress: string,\n tokenAddress: string\n): Promise<Decimal> {\n const reserve = await poolInstance.getReserve(poolAddress, tokenAddress)\n return calcMaxExactIn(reserve)\n}\n\nexport async function getMaxAddLiquidity(\n poolInstance: Pool,\n poolAddress: string,\n tokenAddress: string\n): Promise<Decimal> {\n const reserve = await poolInstance.getReserve(poolAddress, tokenAddress)\n\n return calcMaxExactIn(reserve)\n}\n\nexport async function getMaxRemoveLiquidity(\n poolInstance: Pool,\n poolAddress: string,\n tokenAddress: string\n): Promise<Decimal> {\n const reserve = await poolInstance.getReserve(poolAddress, tokenAddress)\n\n return calcMaxExactIn(reserve)\n}\n","import { LoggerInstance, sleep } from '../utils'\nimport { Asset, DDO, ValidateMetadata } from '../@types/'\nimport fetch from 'cross-fetch'\nexport class Aquarius {\n public aquariusURL\n /**\n * Instantiate Aquarius\n * @param {String} aquariusURL\n */\n constructor(aquariusURL: string) {\n this.aquariusURL = aquariusURL\n }\n\n /** Resolves a DID\n * @param {string} did\n * @param {AbortSignal} signal abort signal\n * @return {Promise<Asset>} Asset\n */\n public async resolve(did: string, signal?: AbortSignal): Promise<Asset> {\n const path = this.aquariusURL + '/api/aquarius/assets/ddo/' + did\n try {\n const response = await fetch(path, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n\n if (response.ok) {\n const raw = await response.json()\n return raw as Asset\n } else {\n throw new Error('HTTP request failed with status ' + response.status)\n }\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('HTTP request failed')\n }\n }\n\n /**\n * Blocks until Aqua will cache the did (or the update for that did) or timeouts\n \n * @param {string} did DID of the asset.\n * @param {string} txid used when the did exists and we expect an update with that txid.\n * @param {AbortSignal} signal abort signal\n * @return {Promise<DDO>} DDO of the asset.\n */\n public async waitForAqua(\n did: string,\n txid?: string,\n signal?: AbortSignal\n ): Promise<Asset> {\n let tries = 0\n do {\n try {\n const path = this.aquariusURL + '/api/aquarius/assets/ddo/' + did\n const response = await fetch(path, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n if (response.ok) {\n const ddo = await response.json()\n if (txid) {\n // check tx\n if (ddo.event && ddo.event.txid === txid) return ddo as Asset\n } else return ddo as Asset\n }\n } catch (e) {\n // do nothing\n }\n await sleep(1500)\n tries++\n } while (tries < 100)\n return null\n }\n\n /**\n * Validate DDO content\n * @param {DDO} ddo DID Descriptor Object content.\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ValidateMetadata>}.\n */\n public async validate(ddo: DDO, signal?: AbortSignal): Promise<ValidateMetadata> {\n const status: ValidateMetadata = {\n valid: false\n }\n let jsonResponse\n try {\n const path = this.aquariusURL + '/api/aquarius/assets/ddo/validate'\n\n const response = await fetch(path, {\n method: 'POST',\n body: JSON.stringify(ddo),\n headers: {\n 'Content-Type': 'application/octet-stream'\n },\n signal: signal\n })\n\n jsonResponse = await response.json()\n if (response.status === 200) {\n status.valid = true\n status.hash = jsonResponse.hash\n status.proof = {\n validatorAddress: jsonResponse.publicKey,\n r: jsonResponse.r[0],\n s: jsonResponse.s[0],\n v: jsonResponse.v\n }\n } else {\n status.errors = jsonResponse\n LoggerInstance.error('validate Metadata failed:', response.status, status.errors)\n }\n } catch (error) {\n LoggerInstance.error('Error validating metadata: ', error)\n }\n return status\n }\n}\n\nexport default Aquarius\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils/types'\nimport { TransactionReceipt } from 'web3-core'\nimport { Contract } from 'web3-eth-contract'\nimport {\n getFairGasPrice,\n setContractDefaults,\n unitsToAmount,\n amountToUnits,\n LoggerInstance,\n estimateGas,\n ConfigHelper\n} from '../../utils'\nimport BigNumber from 'bignumber.js'\nimport PoolTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/balancer/BPool.sol/BPool.json'\nimport defaultErc20Abi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json'\nimport {\n CurrentFees,\n TokenInOutMarket,\n AmountsInMaxFee,\n AmountsOutMaxFee,\n PoolPriceAndFees\n} from '../../@types'\nimport { Config } from '../../models'\nimport {\n getMaxAddLiquidity,\n getMaxRemoveLiquidity,\n getMaxSwapExactIn,\n getMaxSwapExactOut\n} from '../../utils/PoolHelpers'\nimport Decimal from 'decimal.js'\nconst MaxUint256 =\n '115792089237316195423570985008687907853269984665640564039457584007913129639934'\n\n/**\n * Provides an interface to Ocean friendly fork from Balancer BPool\n */\nexport class Pool {\n public poolAbi: AbiItem | AbiItem[]\n public web3: Web3\n private config: Config\n\n constructor(\n web3: Web3,\n network?: string | number,\n poolAbi: AbiItem | AbiItem[] = null,\n config?: Config\n ) {\n if (poolAbi) this.poolAbi = poolAbi\n else this.poolAbi = PoolTemplate.abi as AbiItem[]\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n }\n\n async amountToUnits(\n token: string,\n amount: string,\n tokenDecimals?: number\n ): Promise<string> {\n return amountToUnits(this.web3, token, amount, tokenDecimals)\n }\n\n async unitsToAmount(\n token: string,\n amount: string,\n tokenDecimals?: number\n ): Promise<string> {\n return unitsToAmount(this.web3, token, amount, tokenDecimals)\n }\n\n /**\n * Get user shares of pool tokens\n * @param {String} account\n * @param {String} poolAddress\n * @return {String}\n */\n async sharesBalance(account: string, poolAddress: string): Promise<string> {\n let result = null\n try {\n const token = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n const balance = await token.methods.balanceOf(account).call()\n result = this.web3.utils.fromWei(balance)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get shares of pool : ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for setSwapFee\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} spender\n * @param {String} amount\n * @param {String} force\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSetSwapFee(\n account: string,\n poolAddress: string,\n fee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(defaultErc20Abi.abi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(account, poolContract.methods.setSwapFee, fee)\n }\n\n /**\n * Allows controller to change the swapFee\n * @param {String} account\n * @param {String} poolAddress\n * @param {String} fee swap fee (1e17 = 10 % , 1e16 = 1% , 1e15 = 0.1%, 1e14 = 0.01%)\n */\n async setSwapFee(\n account: string,\n poolAddress: string,\n fee: string\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress, {\n from: account\n }),\n this.config\n )\n let result = null\n const estGas = await estimateGas(account, pool.methods.setSwapFee, fee)\n\n try {\n result = await pool.methods.setSwapFee(this.web3.utils.toWei(fee)).send({\n from: account,\n gas: estGas,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to set pool swap fee: ${e.message}`)\n }\n return result\n }\n\n /**\n * Returns number of tokens bounded to pool\n * @param {String} poolAddress\n * @return {String}\n */\n async getNumTokens(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getNumTokens().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get number of tokens: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get total supply of pool shares\n * @param {String} poolAddress\n * @return {String}\n */\n async getPoolSharesTotalSupply(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n try {\n const result = await pool.methods.totalSupply().call()\n amount = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get total supply of pool shares: ${e.message}`\n )\n }\n return amount\n }\n\n /**\n * Get tokens composing this poo\n * Returns tokens bounded to pool, before the pool is finalizedl\n * @param {String} poolAddress\n * @return {String[]}\n */\n async getCurrentTokens(poolAddress: string): Promise<string[]> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getCurrentTokens().call()\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get tokens composing this pool: ${e.message}`\n )\n }\n return result\n }\n\n /**\n * Get the final tokens composing this pool\n * Returns tokens bounded to pool, after the pool was finalized\n * @param {String} poolAddress\n * @return {String[]}\n */\n async getFinalTokens(poolAddress: string): Promise<string[]> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getFinalTokens().call()\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get the final tokens composing this pool ${e.message}`\n )\n }\n return result\n }\n\n /**\n * Returns the current controller address (ssBot)\n * @param {String} poolAddress\n * @return {String}\n */\n async getController(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getController().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get pool controller address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Returns the current baseToken address of the pool\n * @param {String} poolAddress\n * @return {String}\n */\n async getBaseToken(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getBaseTokenAddress().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get baseToken address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Returns the current datatoken address\n * @param {String} poolAddress\n * @return {String}\n */\n async getDatatoken(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getDatatokenAddress().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get datatoken address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get getMarketFee\n * @param {String} poolAddress\n * @return {String}\n */\n async getMarketFee(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getMarketFee().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get getMarketFee: ${e.message}`)\n }\n return this.web3.utils.fromWei(result).toString()\n }\n\n /**\n * Get marketFeeCollector of this pool\n * @param {String} poolAddress\n * @return {String}\n */\n async getMarketFeeCollector(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods._publishMarketCollector().call()\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get marketFeeCollector address: ${e.message}`\n )\n }\n return result\n }\n\n /**\n * Get if a token is bounded to a pool\n * Returns true if token is bound\n * @param {String} poolAddress\n * @param {String} token Address of the token to be checked\n * @return {Boolean}\n */\n async isBound(poolAddress: string, token: string): Promise<boolean> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.isBound(token).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to check whether a token \\\n bounded to a pool. ${e.message}`)\n }\n return result\n }\n\n /**\n * Returns the current token reserve amount\n * @param {String} poolAddress\n * @param {String} token Address of the token to be checked\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getReserve(\n poolAddress: string,\n token: string,\n tokenDecimals?: number\n ): Promise<string> {\n let amount = null\n try {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n const result = await pool.methods.getBalance(token).call()\n amount = await this.unitsToAmount(token, result, tokenDecimals)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get how many tokens \\\n are in the pool: ${e.message}`)\n }\n return amount.toString()\n }\n\n /**\n * Get if a pool is finalized\n * Returns true if pool is finalized\n * @param {String} poolAddress\n * @return {Boolean}\n */\n async isFinalized(poolAddress: string): Promise<boolean> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.isFinalized().call()\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to check whether pool is finalized: ${e.message}`\n )\n }\n return result\n }\n\n /**\n * Returns the current Liquidity Providers swap fee\n * @param {String} poolAddress\n * @return {String} Swap fee. To get the percentage value, substract by 100. E.g. `0.1` represents a 10% swap fee.\n */\n async getSwapFee(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let fee = null\n try {\n const result = await pool.methods.getSwapFee().call()\n fee = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get pool fee: ${e.message}`)\n }\n return fee\n }\n\n /**\n * Returns normalized weight of a token.\n * The combined normalized weights of all tokens will sum up to 1.\n * (Note: the actual sum may be 1 plus or minus a few wei due to division precision loss)\n * @param {String} poolAddress\n * @param {String} token token to be checked\n * @return {String}\n */\n async getNormalizedWeight(poolAddress: string, token: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.getNormalizedWeight(token).call()\n weight = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get normalized weight of a token: ${e.message}`\n )\n }\n return weight\n }\n\n /**\n * Returns denormalized weight of a token\n * @param {String} poolAddress\n * @param {String} token token to be checked\n * @return {String}\n */\n async getDenormalizedWeight(poolAddress: string, token: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.getDenormalizedWeight(token).call()\n weight = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get denormalized weight of a token in pool ${e.message}`\n )\n }\n return weight\n }\n\n /**\n * getTotalDenormalizedWeight\n * Returns total denormalized weught of the pool\n * @param {String} poolAddress\n * @return {String}\n */\n async getTotalDenormalizedWeight(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.getTotalDenormalizedWeight().call()\n weight = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get total denormalized weight in pool ${e.message}`\n )\n }\n return weight\n }\n\n /**\n * Returns the current fee of publishingMarket\n * Get Market Fees available to be collected for a specific token\n * @param {String} poolAddress\n * @param {String} token token we want to check fees\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getMarketFees(\n poolAddress: string,\n token: string,\n tokenDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.publishMarketFees(token).call()\n weight = await this.unitsToAmount(token, result, tokenDecimals)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get market fees for a token: ${e.message}`)\n }\n return weight\n }\n\n /**\n * Get Community Get the current amount of fees which can be withdrawned by the Market\n * @return {CurrentFees}\n */\n async getCurrentMarketFees(poolAddress: string): Promise<CurrentFees> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n try {\n const currentMarketFees = await pool.methods.getCurrentOPCFees().call()\n return currentMarketFees\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get community fees for a token: ${e.message}`\n )\n }\n }\n\n /**\n * Get getCurrentOPFFees Get the current amount of fees which can be withdrawned by OPF\n * @return {CurrentFees}\n */\n async getCurrentOPCFees(poolAddress: string): Promise<CurrentFees> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n try {\n const currentMarketFees = await pool.methods.getCurrentOPCFees().call()\n return currentMarketFees\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get community fees for a token: ${e.message}`\n )\n }\n }\n\n /**\n * Get Community Fees available to be collected for a specific token\n * @param {String} poolAddress\n * @param {String} token token we want to check fees\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getCommunityFees(\n poolAddress: string,\n token: string,\n tokenDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.communityFees(token).call()\n weight = await this.unitsToAmount(token, result, tokenDecimals)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get community fees for a token: ${e.message}`\n )\n }\n return weight\n }\n\n /**\n * Estimate gas cost for collectOPF\n * @param {String} address\n * @param {String} poolAddress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectOPC(\n address: string,\n poolAddress: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(address, poolContract.methods.collectOPC)\n }\n\n /**\n * collectOPF - collect opf fee - can be called by anyone\n * @param {String} address\n * @param {String} poolAddress\n * @return {TransactionReceipt}\n */\n async collectOPC(address: string, poolAddress: string): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n const estGas = await estimateGas(address, pool.methods.collectOPC)\n\n try {\n result = await pool.methods.collectOPC().send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to swap exact amount in : ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for collectMarketFee\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} to address that will receive fees\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectMarketFee(\n address: string,\n poolAddress: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(address, poolContract.methods.collectMarketFee)\n }\n\n /**\n * collectOPF - collect market fees - can be called by the publishMarketCollector\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} to address that will receive fees\n * @return {TransactionReceipt}\n */\n async collectMarketFee(\n address: string,\n poolAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getMarketFeeCollector(poolAddress)) !== address) {\n throw new Error(`Caller is not MarketFeeCollector`)\n }\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n const estGas = await estimateGas(address, pool.methods.collectMarketFee)\n\n try {\n result = await pool.methods.collectMarketFee().send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to swap exact amount in : ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for updatePublishMarketFee\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} newPublishMarketAddress new market address\n * @param {String} newPublishMarketSwapFee new market swap fee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estUpdatePublishMarketFee(\n address: string,\n poolAddress: string,\n newPublishMarketAddress: string,\n newPublishMarketSwapFee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(\n address,\n poolContract.methods.updatePublishMarketFee,\n newPublishMarketAddress,\n this.web3.utils.toWei(newPublishMarketSwapFee)\n )\n }\n\n /**\n * updatePublishMarketFee - sets a new newPublishMarketAddress and new newPublishMarketSwapFee- can be called only by the marketFeeCollector\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} newPublishMarketAddress new market fee collector address\n * @param {String} newPublishMarketSwapFee fee recieved by the publisher market when a dt is swaped from a pool, percent\n * @return {TransactionReceipt}\n */\n async updatePublishMarketFee(\n address: string,\n poolAddress: string,\n newPublishMarketAddress: string,\n newPublishMarketSwapFee: string\n ): Promise<TransactionReceipt> {\n if ((await this.getMarketFeeCollector(poolAddress)) !== address) {\n throw new Error(`Caller is not MarketFeeCollector`)\n }\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n\n const estGas = await estimateGas(\n address,\n pool.methods.updatePublishMarketFee,\n newPublishMarketAddress,\n this.web3.utils.toWei(newPublishMarketSwapFee)\n )\n try {\n result = await pool.methods\n .updatePublishMarketFee(\n newPublishMarketAddress,\n this.web3.utils.toWei(newPublishMarketSwapFee)\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to updatePublishMarketFee : ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for swapExactAmountIn\n * @param {String} address\n * @param {String} poolAddress\n * @param {TokenInOutMarket} tokenInOutMarket object contianing addresses like tokenIn, tokenOut, consumeMarketFeeAddress\n * @param {AmountsInMaxFee} amountsInOutMaxFee object contianing tokenAmountIn, minAmountOut, maxPrice, consumeMarketSwapFee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSwapExactAmountIn(\n address: string,\n poolAddress: string,\n tokenInOutMarket: TokenInOutMarket,\n amountsInOutMaxFee: AmountsInMaxFee,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n const tokenAmountIn = await this.amountToUnits(\n tokenInOutMarket.tokenIn,\n amountsInOutMaxFee.tokenAmountIn,\n tokenInOutMarket.tokenInDecimals\n )\n\n const minAmountOut = await this.amountToUnits(\n tokenInOutMarket.tokenOut,\n amountsInOutMaxFee.minAmountOut,\n tokenInOutMarket.tokenOutDecimals\n )\n\n const maxPrice = amountsInOutMaxFee.maxPrice\n ? this.amountToUnits(\n await this.getBaseToken(poolAddress),\n amountsInOutMaxFee.maxPrice\n )\n : MaxUint256\n\n return estimateGas(\n address,\n poolContract.methods.swapExactAmountIn,\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n tokenAmountIn,\n minAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n }\n\n /**\n * Swaps an exact amount of tokensIn to get a mimum amount of tokenOut\n * Trades an exact tokenAmountIn of tokenIn taken from the caller by the pool,\n * in exchange for at least minAmountOut of tokenOut given to the caller from the pool, with a maximum marginal price of maxPrice.\n * Returns (tokenAmountOut, spotPriceAfter), where tokenAmountOut is the amount of token that came out of the pool,\n * and spotPriceAfter is the new marginal spot price, ie, the result of getSpotPrice after the call.\n * (These values are what are limited by the arguments; you are guaranteed tokenAmountOut >= minAmountOut and spotPriceAfter <= maxPrice).\n * @param {String} address\n * @param {String} poolAddress\n * @param {TokenInOutMarket} tokenInOutMarket object contianing addresses like tokenIn, tokenOut, consumeMarketFeeAddress\n * @param {AmountsInMaxFee} amountsInOutMaxFee object contianing tokenAmountIn, minAmountOut, maxPrice, consumeMarketSwapFee\n * @return {TransactionReceipt}\n */\n async swapExactAmountIn(\n address: string,\n poolAddress: string,\n tokenInOutMarket: TokenInOutMarket,\n amountsInOutMaxFee: AmountsInMaxFee\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n\n const maxSwap = await getMaxSwapExactIn(this, poolAddress, tokenInOutMarket.tokenIn)\n if (new Decimal(amountsInOutMaxFee.tokenAmountIn).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountIn is greater than ${maxSwap.toString()}`)\n }\n\n const tokenAmountIn = await this.amountToUnits(\n tokenInOutMarket.tokenIn,\n amountsInOutMaxFee.tokenAmountIn,\n tokenInOutMarket.tokenInDecimals\n )\n\n const minAmountOut = await this.amountToUnits(\n tokenInOutMarket.tokenOut,\n amountsInOutMaxFee.minAmountOut,\n tokenInOutMarket.tokenOutDecimals\n )\n\n const maxPrice = amountsInOutMaxFee.maxPrice\n ? await this.amountToUnits(\n await this.getBaseToken(poolAddress),\n amountsInOutMaxFee.maxPrice\n )\n : MaxUint256\n\n const estGas = await estimateGas(\n address,\n pool.methods.swapExactAmountIn,\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n tokenAmountIn,\n minAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n\n let result = null\n try {\n result = await pool.methods\n .swapExactAmountIn(\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n tokenAmountIn,\n minAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to swap exact amount in : ${e.message}`)\n }\n\n return result\n }\n\n /**\n * Estimate gas cost for swapExactAmountOut\n * @param {String} address\n * @param {String} poolAddress\n * @param {TokenInOutMarket} tokenInOutMarket\n * @param {AmountsOutMaxFee} amountsInOutMaxFee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSwapExactAmountOut(\n address: string,\n poolAddress: string,\n tokenInOutMarket: TokenInOutMarket,\n amountsInOutMaxFee: AmountsOutMaxFee,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n const maxAmountIn = await this.amountToUnits(\n tokenInOutMarket.tokenIn,\n amountsInOutMaxFee.maxAmountIn,\n tokenInOutMarket.tokenInDecimals\n )\n\n const tokenAmountOut = await this.amountToUnits(\n tokenInOutMarket.tokenOut,\n amountsInOutMaxFee.tokenAmountOut,\n tokenInOutMarket.tokenOutDecimals\n )\n\n const maxPrice = amountsInOutMaxFee.maxPrice\n ? await this.amountToUnits(\n await this.getBaseToken(poolAddress),\n amountsInOutMaxFee.maxPrice\n )\n : MaxUint256\n\n return estimateGas(\n address,\n poolContract.methods.swapExactAmountOut,\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n maxAmountIn,\n tokenAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n }\n\n /**\n * Swaps a maximum maxAmountIn of tokensIn to get an exact amount of tokenOut\n * @param {String} account\n * @param {String} poolAddress\n * @param {TokenInOutMarket} tokenInOutMarket Object containing addresses like tokenIn, tokenOut, consumeMarketFeeAddress\n * @param {AmountsOutMaxFee} amountsInOutMaxFee Object containging maxAmountIn,tokenAmountOut,maxPrice, consumeMarketSwapFee]\n * @return {TransactionReceipt}\n */\n async swapExactAmountOut(\n account: string,\n poolAddress: string,\n tokenInOutMarket: TokenInOutMarket,\n amountsInOutMaxFee: AmountsOutMaxFee\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n\n const maxSwap = await getMaxSwapExactOut(this, poolAddress, tokenInOutMarket.tokenOut)\n if (new Decimal(amountsInOutMaxFee.tokenAmountOut).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`)\n }\n\n const maxAmountIn = await this.amountToUnits(\n tokenInOutMarket.tokenIn,\n amountsInOutMaxFee.maxAmountIn,\n tokenInOutMarket.tokenInDecimals\n )\n\n const tokenAmountOut = await this.amountToUnits(\n tokenInOutMarket.tokenOut,\n amountsInOutMaxFee.tokenAmountOut,\n tokenInOutMarket.tokenOutDecimals\n )\n\n const maxPrice = amountsInOutMaxFee.maxPrice\n ? this.amountToUnits(\n await this.getBaseToken(poolAddress),\n amountsInOutMaxFee.maxPrice\n )\n : MaxUint256\n\n const estGas = await estimateGas(\n account,\n pool.methods.swapExactAmountOut,\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n maxAmountIn,\n tokenAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n\n try {\n result = await pool.methods\n .swapExactAmountOut(\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n maxAmountIn,\n tokenAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n .send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to swap exact amount out: ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for joinswapExternAmountIn\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} tokenIn\n * @param {String} tokenAmountIn exact number of base tokens to spend\n * @param {String} minPoolAmountOut minimum of pool shares expectex\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estJoinswapExternAmountIn(\n address: string,\n poolAddress: string,\n tokenAmountIn: string,\n minPoolAmountOut: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(\n address,\n poolContract.methods.joinswapExternAmountIn,\n tokenAmountIn,\n minPoolAmountOut\n )\n }\n\n /**\n * Single side add liquidity to the pool,\n * expecting a minPoolAmountOut of shares for spending tokenAmountIn basetokens.\n * Pay tokenAmountIn of baseToken to join the pool, getting poolAmountOut of the pool shares.\n * @param {String} account\n * @param {String} poolAddress\n * @param {String} tokenAmountIn exact number of base tokens to spend\n * @param {String} minPoolAmountOut minimum of pool shares expectex\n * @param {number} tokenInDecimals optional number of decimals of the token\n * @return {TransactionReceipt}\n */\n async joinswapExternAmountIn(\n account: string,\n poolAddress: string,\n tokenAmountIn: string,\n minPoolAmountOut: string,\n tokenInDecimals?: number\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n const tokenIn = await this.getBaseToken(poolAddress)\n const maxSwap = await getMaxAddLiquidity(this, poolAddress, tokenIn)\n if (new Decimal(tokenAmountIn).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`)\n }\n\n const amountInFormatted = await this.amountToUnits(\n tokenIn,\n tokenAmountIn,\n tokenInDecimals\n )\n const estGas = await estimateGas(\n account,\n pool.methods.joinswapExternAmountIn,\n amountInFormatted,\n this.web3.utils.toWei(minPoolAmountOut)\n )\n\n try {\n result = await pool.methods\n .joinswapExternAmountIn(\n amountInFormatted,\n this.web3.utils.toWei(minPoolAmountOut)\n )\n .send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to pay tokens in order to \\\n join the pool: ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for exitswapPoolAmountIn\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} poolAmountIn exact number of pool shares to spend\n * @param {String} minTokenAmountOut minimum amount of basetokens expected\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estExitswapPoolAmountIn(\n address: string,\n poolAddress: string,\n poolAmountIn: string,\n minTokenAmountOut: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(\n address,\n poolContract.methods.exitswapPoolAmountIn,\n poolAmountIn,\n minTokenAmountOut\n )\n }\n\n /**\n * Single side remove liquidity from the pool,\n * expecting a minAmountOut of basetokens for spending poolAmountIn pool shares\n * Pay poolAmountIn pool shares into the pool, getting minTokenAmountOut of the baseToken\n * @param {String} account\n * @param {String} poolAddress\n * @param {String} poolAmountIn exact number of pool shares to spend\n * @param {String} minTokenAmountOut minimum amount of basetokens expected\n * @param {number} poolDecimals optional number of decimals of the poool\n * @return {TransactionReceipt}\n */\n async exitswapPoolAmountIn(\n account: string,\n poolAddress: string,\n poolAmountIn: string,\n minTokenAmountOut: string,\n poolDecimals?: number\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n const tokenOut = await this.getBaseToken(poolAddress)\n\n const tokenAmountOut = await this.calcSingleOutGivenPoolIn(\n poolAddress,\n tokenOut,\n poolAmountIn\n )\n\n const maxSwap = await getMaxRemoveLiquidity(this, poolAddress, tokenOut)\n if (new Decimal(tokenAmountOut).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`)\n }\n\n const minTokenOutFormatted = await this.amountToUnits(\n await this.getBaseToken(poolAddress),\n minTokenAmountOut,\n poolDecimals\n )\n const estGas = await estimateGas(\n account,\n pool.methods.exitswapPoolAmountIn,\n this.web3.utils.toWei(poolAmountIn),\n minTokenOutFormatted\n )\n\n try {\n result = await pool.methods\n .exitswapPoolAmountIn(this.web3.utils.toWei(poolAmountIn), minTokenOutFormatted)\n .send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to pay pool shares into the pool: ${e.message}`)\n }\n return result\n }\n\n /**\n * Return the spot price of swapping tokenIn to tokenOut\n * @param {String} poolAddress\n * @param {String} tokenIn in token\n * @param {String} tokenOut out token\n * @param {String} swapMarketFe consume market swap fee\n * @return {String}\n */\n async getSpotPrice(\n poolAddress: string,\n tokenIn: string,\n tokenOut: string,\n swapMarketFee: string\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let decimalsTokenIn = 18\n let decimalsTokenOut = 18\n\n const tokenInContract = setContractDefaults(\n new this.web3.eth.Contract(defaultErc20Abi.abi as AbiItem[], tokenIn),\n this.config\n )\n const tokenOutContract = setContractDefaults(\n new this.web3.eth.Contract(defaultErc20Abi.abi as AbiItem[], tokenOut),\n this.config\n )\n try {\n decimalsTokenIn = await tokenInContract.methods.decimals().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: FAILED TO CALL DECIMALS(), USING 18 ${e.message}`)\n }\n try {\n decimalsTokenOut = await tokenOutContract.methods.decimals().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: FAILED TO CALL DECIMALS(), USING 18 ${e.message}`)\n }\n\n let price = null\n try {\n price = await pool.methods\n .getSpotPrice(tokenIn, tokenOut, this.web3.utils.toWei(swapMarketFee))\n .call()\n price = new BigNumber(price.toString())\n } catch (e) {\n LoggerInstance.error(\n 'ERROR: Failed to get spot price of swapping tokenIn to tokenOut'\n )\n }\n\n let decimalsDiff\n if (decimalsTokenIn > decimalsTokenOut) {\n decimalsDiff = decimalsTokenIn - decimalsTokenOut\n price = new BigNumber(price / 10 ** decimalsDiff)\n price = price / 10 ** decimalsTokenOut\n } else {\n decimalsDiff = decimalsTokenOut - decimalsTokenIn\n price = new BigNumber(price * 10 ** (2 * decimalsDiff))\n price = price / 10 ** decimalsTokenOut\n }\n\n return price.toString()\n }\n\n /**\n * How many tokensIn do you need in order to get exact tokenAmountOut.\n * Returns: tokenAmountIn, swapFee, opcFee , consumeMarketSwapFee, publishMarketSwapFee\n * Returns: tokenAmountIn, LPFee, opcFee , publishMarketSwapFee, consumeMarketSwapFee\n * @param tokenIn token to be swaped\n * @param tokenOut token to get\n * @param tokenAmountOut exact amount of tokenOut\n * @param swapMarketFee consume market swap fee\n * @param {number} tokenInDecimals optional number of decimals of the token to be swaped\n * @param {number} tokenOutDecimals optional number of decimals of the token to get\n */\n public async getAmountInExactOut(\n poolAddress: string,\n tokenIn: string,\n tokenOut: string,\n tokenAmountOut: string,\n swapMarketFee: string,\n tokenInDecimals?: number,\n tokenOutDecimals?: number\n ): Promise<PoolPriceAndFees> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n\n const maxSwap = await getMaxSwapExactOut(this, poolAddress, tokenOut)\n\n if (new Decimal(tokenAmountOut).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`)\n }\n\n const amountOutFormatted = await this.amountToUnits(\n tokenOut,\n tokenAmountOut,\n tokenOutDecimals\n )\n\n let amount = null\n\n try {\n const result = await pool.methods\n .getAmountInExactOut(\n tokenIn,\n tokenOut,\n amountOutFormatted,\n this.web3.utils.toWei(swapMarketFee)\n )\n .call()\n amount = {\n tokenAmount: await this.unitsToAmount(\n tokenOut,\n result.tokenAmountIn,\n tokenOutDecimals\n ),\n liquidityProviderSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.lpFeeAmount,\n tokenInDecimals\n ),\n oceanFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.oceanFeeAmount,\n tokenInDecimals\n ),\n publishMarketSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.publishMarketSwapFeeAmount,\n tokenInDecimals\n ),\n consumeMarketSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.consumeMarketSwapFeeAmount,\n tokenInDecimals\n )\n }\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to calcInGivenOut ${e.message}`)\n }\n return amount\n }\n\n /**\n * How many tokensOut you will get for a exact tokenAmountIn\n * Returns: tokenAmountOut, LPFee, opcFee , publishMarketSwapFee, consumeMarketSwapFee\n * @param tokenIn token to be swaped\n * @param tokenOut token to get\n * @param tokenAmountIn exact amount of tokenIn\n * @param swapMarketFee\n * @param {number} tokenInDecimals optional number of decimals of the token to be swaped\n * @param {number} tokenOutDecimals optional number of decimals of the token to get\n */\n public async getAmountOutExactIn(\n poolAddress: string,\n tokenIn: string,\n tokenOut: string,\n tokenAmountIn: string,\n swapMarketFee: string,\n tokenInDecimals?: number,\n tokenOutDecimals?: number\n ): Promise<PoolPriceAndFees> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n\n const maxSwap = await getMaxSwapExactIn(this, poolAddress, tokenIn)\n if (new Decimal(tokenAmountIn).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountIn is greater than ${maxSwap.toString()}`)\n }\n\n const amountInFormatted = await this.amountToUnits(\n tokenIn,\n tokenAmountIn,\n tokenInDecimals\n )\n\n let amount = null\n\n try {\n const result = await pool.methods\n .getAmountOutExactIn(\n tokenIn,\n tokenOut,\n amountInFormatted,\n this.web3.utils.toWei(swapMarketFee)\n )\n .call()\n\n amount = {\n tokenAmount: await this.unitsToAmount(\n tokenOut,\n result.tokenAmountOut,\n tokenOutDecimals\n ),\n liquidityProviderSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.lpFeeAmount,\n tokenInDecimals\n ),\n oceanFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.oceanFeeAmount,\n tokenInDecimals\n ),\n publishMarketSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.publishMarketSwapFeeAmount,\n tokenInDecimals\n ),\n consumeMarketSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.consumeMarketSwapFeeAmount,\n tokenInDecimals\n )\n }\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to calcOutGivenIn ${e.message}`)\n }\n return amount\n }\n\n /**\n * Returns number of poolshares obtain by staking exact tokenAmountIn tokens\n * @param tokenIn tokenIn\n * @param tokenAmountIn exact number of tokens staked\n * @param {number} poolDecimals optional number of decimals of the poool\n * @param {number} tokenInDecimals optional number of decimals of the token\n */\n public async calcPoolOutGivenSingleIn(\n poolAddress: string,\n tokenIn: string,\n tokenAmountIn: string,\n poolDecimals?: number,\n tokenInDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n\n try {\n const result = await pool.methods\n .calcPoolOutSingleIn(\n tokenIn,\n await this.amountToUnits(tokenIn, tokenAmountIn, tokenInDecimals)\n )\n .call()\n\n amount = await this.unitsToAmount(poolAddress, result, poolDecimals)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to calculate PoolOutGivenSingleIn : ${e.message}`\n )\n }\n return amount\n }\n\n /**\n * Returns number of tokens to be staked to the pool in order to get an exact number of poolshares\n * @param tokenIn tokenIn\n * @param poolAmountOut expected amount of pool shares\n * @param {number} poolDecimals optional number of decimals of the pool\n * @param {number} tokenInDecimals optional number of decimals of the token\n */\n public async calcSingleInGivenPoolOut(\n poolAddress: string,\n tokenIn: string,\n poolAmountOut: string,\n poolDecimals?: number,\n tokenInDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n const amountFormatted = await this.amountToUnits(\n poolAddress,\n poolAmountOut,\n poolDecimals\n )\n try {\n const result = await pool.methods\n .calcSingleInPoolOut(tokenIn, amountFormatted)\n .call()\n\n amount = await this.unitsToAmount(tokenIn, result, tokenInDecimals)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to calculate SingleInGivenPoolOut : ${e.message}`\n )\n }\n return amount\n }\n\n /**\n * Returns expected amount of tokenOut for removing exact poolAmountIn pool shares from the pool\n * @param tokenOut tokenOut\n * @param poolAmountIn amount of shares spent\n * @param {number} poolDecimals optional number of decimals of the pool\n * @param {number} tokenOutDecimals optional number of decimals of the token\n */\n public async calcSingleOutGivenPoolIn(\n poolAddress: string,\n tokenOut: string,\n poolAmountIn: string,\n poolDecimals?: number,\n tokenOutDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n\n try {\n const result = await pool.methods\n .calcSingleOutPoolIn(\n tokenOut,\n await this.amountToUnits(poolAddress, poolAmountIn, poolDecimals)\n )\n .call()\n amount = await this.unitsToAmount(tokenOut, result, tokenOutDecimals)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to calculate SingleOutGivenPoolIn : ${e}`)\n }\n return amount\n }\n\n /**\n * Returns number of poolshares needed to withdraw exact tokenAmountOut tokens\n * @param tokenOut tokenOut\n * @param tokenAmountOut expected amount of tokensOut\n * @param {number} poolDecimals optional number of decimals of the pool\n * @param {number} tokenOutDecimals optional number of decimals of the token\n */\n public async calcPoolInGivenSingleOut(\n poolAddress: string,\n tokenOut: string,\n tokenAmountOut: string,\n poolDecimals?: number,\n tokenOutDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n\n try {\n const result = await pool.methods\n .calcPoolInSingleOut(\n tokenOut,\n await this.amountToUnits(tokenOut, tokenAmountOut, tokenOutDecimals)\n )\n .call()\n\n amount = await this.unitsToAmount(poolAddress, result, poolDecimals)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to calculate PoolInGivenSingleOut : ${e.message}`\n )\n }\n return amount\n }\n\n /**\n * Get LOG_SWAP encoded topic\n * @return {String}\n */\n public getSwapEventSignature(): string {\n const abi = this.poolAbi as AbiItem[]\n const eventdata = abi.find(function (o) {\n if (o.name === 'LOG_SWAP' && o.type === 'event') return o\n })\n const topic = this.web3.eth.abi.encodeEventSignature(eventdata as any)\n return topic\n }\n\n /**\n * Get LOG_JOIN encoded topic\n * @return {String}\n */\n public getJoinEventSignature(): string {\n const abi = this.poolAbi as AbiItem[]\n const eventdata = abi.find(function (o) {\n if (o.name === 'LOG_JOIN' && o.type === 'event') return o\n })\n const topic = this.web3.eth.abi.encodeEventSignature(eventdata as any)\n return topic\n }\n\n /**\n * Get LOG_EXIT encoded topic\n * @return {String}\n */\n public getExitEventSignature(): string {\n const abi = this.poolAbi as AbiItem[]\n const eventdata = abi.find(function (o) {\n if (o.name === 'LOG_EXIT' && o.type === 'event') return o\n })\n const topic = this.web3.eth.abi.encodeEventSignature(eventdata as any)\n return topic\n }\n}\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils'\nimport { Contract } from 'web3-eth-contract'\nimport { TransactionReceipt } from 'web3-eth'\nimport Decimal from 'decimal.js'\nimport defaultDispenserAbi from '@oceanprotocol/contracts/artifacts/contracts/pools/dispenser/Dispenser.sol/Dispenser.json'\nimport {\n LoggerInstance as logger,\n getFairGasPrice,\n setContractDefaults,\n estimateGas,\n ConfigHelper\n} from '../../utils/'\nimport { Datatoken } from '../../tokens'\nimport { Config } from '../../models/index.js'\n\nexport interface DispenserToken {\n active: boolean\n owner: string\n maxTokens: string\n maxBalance: string\n balance: string\n isMinter: boolean\n allowedSwapper: string\n}\n\nexport class Dispenser {\n public web3: Web3 = null\n public dispenserAddress: string\n public config: Config\n public dispenserAbi: AbiItem | AbiItem[]\n public dispenserContract: Contract\n\n /**\n * Instantiate Dispenser\n * @param {any} web3\n * @param {String} dispenserAddress\n * @param {any} dispenserABI\n */\n constructor(\n web3: Web3,\n network?: string | number,\n dispenserAddress: string = null,\n dispenserAbi: AbiItem | AbiItem[] = null,\n config?: Config\n ) {\n this.web3 = web3\n this.dispenserAddress = dispenserAddress\n this.dispenserAbi = dispenserAbi || (defaultDispenserAbi.abi as AbiItem[])\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n if (web3)\n this.dispenserContract = setContractDefaults(\n new this.web3.eth.Contract(this.dispenserAbi, this.dispenserAddress),\n this.config\n )\n }\n\n /**\n * Get information about a datatoken dispenser\n * @param {String} dtAddress\n * @return {Promise<FixedPricedExchange>} Exchange details\n */\n public async status(dtAdress: string): Promise<DispenserToken> {\n try {\n const result: DispenserToken = await this.dispenserContract.methods\n .status(dtAdress)\n .call()\n result.maxTokens = this.web3.utils.fromWei(result.maxTokens)\n result.maxBalance = this.web3.utils.fromWei(result.maxBalance)\n result.balance = this.web3.utils.fromWei(result.balance)\n return result\n } catch (e) {\n logger.warn(`No dispenser available for datatoken: ${dtAdress}`)\n }\n return null\n }\n\n /**\n * Estimate gas cost for create method\n * @param {String} dtAddress Datatoken address\n * @param {String} address Owner address\n * @param {String} maxTokens max tokens to dispense\n * @param {String} maxBalance max balance of requester\n * @param {String} allowedSwapper if !=0, only this address can request DTs\n * @return {Promise<any>}\n */\n public async estGasCreate(\n dtAddress: string,\n address: string,\n maxTokens: string,\n maxBalance: string,\n allowedSwapper: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.dispenserContract.methods.create,\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance),\n address,\n allowedSwapper\n )\n }\n\n /**\n * Creates a new Dispenser\n * @param {String} dtAddress Datatoken address\n * @param {String} address Owner address\n * @param {String} maxTokens max tokens to dispense\n * @param {String} maxBalance max balance of requester\n * @param {String} allowedSwapper only account that can ask tokens. set address(0) if not required\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async create(\n dtAddress: string,\n address: string,\n maxTokens: string,\n maxBalance: string,\n allowedSwapper: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.create,\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance),\n address,\n allowedSwapper\n )\n\n // Call createFixedRate contract method\n const trxReceipt = await this.dispenserContract.methods\n .create(\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance),\n address,\n allowedSwapper\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas for activate method\n * @param {String} dtAddress\n * @param {Number} maxTokens max amount of tokens to dispense\n * @param {Number} maxBalance max balance of user. If user balance is >, then dispense will be rejected\n * @param {String} address User address (must be owner of the datatoken)\n * @return {Promise<any>}\n */\n public async estGasActivate(\n dtAddress: string,\n maxTokens: string,\n maxBalance: string,\n address: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.dispenserContract.methods.activate,\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance)\n )\n }\n\n /**\n * Activates a new dispener.\n * @param {String} dtAddress refers to datatoken address.\n * @param {Number} maxTokens max amount of tokens to dispense\n * @param {Number} maxBalance max balance of user. If user balance is >, then dispense will be rejected\n * @param {String} address User address (must be owner of the datatoken)\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async activate(\n dtAddress: string,\n maxTokens: string,\n maxBalance: string,\n address: string\n ): Promise<TransactionReceipt> {\n try {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.activate,\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance)\n )\n\n const trxReceipt = await this.dispenserContract.methods\n .activate(\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance)\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to activate dispenser: ${e.message}`)\n }\n return null\n }\n\n /**\n * Estimate gas for deactivate method\n * @param {String} dtAddress\n * @param {String} address User address (must be owner of the datatoken)\n * @return {Promise<any>}\n */\n public async estGasDeactivate(dtAddress: string, address: string): Promise<any> {\n return estimateGas(address, this.dispenserContract.methods.deactivate, dtAddress)\n }\n\n /**\n * Deactivate an existing dispenser.\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async deactivate(\n dtAddress: string,\n address: string\n ): Promise<TransactionReceipt> {\n try {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.deactivate,\n dtAddress\n )\n\n const trxReceipt = await this.dispenserContract.methods.deactivate(dtAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to activate dispenser: ${e.message}`)\n }\n return null\n }\n\n /**\n * Estimate gas for setAllowedSwapper method\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @param {String} newAllowedSwapper refers to the new allowedSwapper\n * @return {Promise<any>}\n */\n public async estGasSetAllowedSwapper(\n dtAddress: string,\n address: string,\n newAllowedSwapper: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.dispenserContract.methods.setAllowedSwapper,\n dtAddress,\n newAllowedSwapper\n )\n }\n\n /**\n * Sets a new allowedSwapper.\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @param {String} newAllowedSwapper refers to the new allowedSwapper\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async setAllowedSwapper(\n dtAddress: string,\n address: string,\n newAllowedSwapper: string\n ): Promise<TransactionReceipt> {\n try {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.setAllowedSwapper,\n dtAddress,\n newAllowedSwapper\n )\n\n const trxReceipt = await this.dispenserContract.methods\n .setAllowedSwapper(dtAddress, newAllowedSwapper)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to activate dispenser: ${e.message}`)\n }\n return null\n }\n\n /**\n * Estimate gas for dispense method\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @param {String} newAllowedSwapper refers to the new allowedSwapper\n * @return {Promise<any>}\n */\n public async estGasDispense(\n dtAddress: string,\n address: string,\n amount: string = '1',\n destination: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.dispenserContract.methods.dispense,\n dtAddress,\n this.web3.utils.toWei(amount),\n destination\n )\n }\n\n /**\n * Dispense datatokens to caller.\n * The dispenser must be active, hold enough DT (or be able to mint more)\n * and respect maxTokens/maxBalance requirements\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address\n * @param {String} amount amount of datatokens required.\n * @param {String} destination who will receive the tokens\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async dispense(\n dtAddress: string,\n address: string,\n amount: string = '1',\n destination: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.dispense,\n dtAddress,\n this.web3.utils.toWei(amount),\n destination\n )\n\n try {\n const trxReceipt = await this.dispenserContract.methods\n .dispense(dtAddress, this.web3.utils.toWei(amount), destination)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to dispense tokens: ${e.message}`)\n }\n return null\n }\n\n /**\n * Estimate gas for ownerWithdraw method\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @param {String} newAllowedSwapper refers to the new allowedSwapper\n * @return {Promise<any>}\n */\n public async estGasOwnerWithdraw(dtAddress: string, address: string): Promise<any> {\n return estimateGas(address, this.dispenserContract.methods.ownerWithdraw, dtAddress)\n }\n\n /**\n * Withdraw all tokens from the dispenser\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the dispenser)\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async ownerWithdraw(\n dtAddress: string,\n address: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.ownerWithdraw,\n dtAddress\n )\n\n try {\n const trxReceipt = await this.dispenserContract.methods\n .ownerWithdraw(dtAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to withdraw tokens: ${e.message}`)\n }\n return null\n }\n\n /**\n * Check if tokens can be dispensed\n * @param {String} dtAddress\n * @param {String} address User address that will receive datatokens\n * @param {String} amount amount of datatokens required.\n * @return {Promise<Boolean>}\n */\n public async isDispensable(\n dtAddress: string,\n datatoken: Datatoken,\n address: string,\n amount: string = '1'\n ): Promise<Boolean> {\n const status = await this.status(dtAddress)\n if (!status) return false\n // check active\n if (status.active === false) return false\n // check maxBalance\n const userBalance = new Decimal(await datatoken.balance(dtAddress, address))\n if (userBalance.greaterThanOrEqualTo(status.maxBalance)) return false\n // check maxAmount\n if (new Decimal(String(amount)).greaterThan(status.maxTokens)) return false\n // check dispenser balance\n const contractBalance = new Decimal(status.balance)\n if (contractBalance.greaterThanOrEqualTo(amount) || status.isMinter === true)\n return true\n return false\n }\n}\n","import defaultFixedRateExchangeAbi from '@oceanprotocol/contracts/artifacts/contracts/pools/fixedRate/FixedRateExchange.sol/FixedRateExchange.json'\nimport { TransactionReceipt } from 'web3-core'\nimport { Contract } from 'web3-eth-contract'\nimport { AbiItem } from 'web3-utils/types'\nimport Web3 from 'web3'\nimport {\n LoggerInstance,\n getFairGasPrice,\n setContractDefaults,\n amountToUnits,\n unitsToAmount,\n estimateGas,\n ZERO_ADDRESS,\n ConfigHelper\n} from '../../utils'\nimport { Config } from '../../models/index.js'\nimport { PriceAndFees } from '../..'\n\nexport interface FixedPriceExchange {\n active: boolean\n exchangeOwner: string\n datatoken: string\n baseToken: string\n fixedRate: string\n dtDecimals: string\n btDecimals: string\n dtBalance: string\n btBalance: string\n dtSupply: string\n btSupply: string\n withMint: boolean\n allowedSwapper: string\n exchangeId?: string\n}\n\nexport interface FeesInfo {\n opcFee: string\n marketFee: string\n marketFeeCollector: string\n marketFeeAvailable: string\n oceanFeeAvailable: string\n exchangeId: string\n}\nexport interface FixedPriceSwap {\n exchangeId: string\n caller: string\n baseTokenAmount: string\n datatokenAmount: string\n}\n\n/* eslint-disable no-unused-vars */\nexport enum FixedRateCreateProgressStep {\n CreatingExchange,\n ApprovingDatatoken\n}\n/* eslint-enable no-unused-vars */\n\nexport class FixedRateExchange {\n /** Ocean related functions */\n public oceanAddress: string = null\n public fixedRateAddress: string\n public fixedRateExchangeAbi: AbiItem | AbiItem[]\n public web3: Web3\n public fixedRateContract: Contract = null\n\n public config: Config\n public ssAbi: AbiItem | AbiItem[]\n\n /**\n * Instantiate FixedRateExchange\n * @param {any} web3\n * @param {any} fixedRateExchangeAbi\n */\n constructor(\n web3: Web3,\n fixedRateAddress: string,\n network?: string | number,\n fixedRateExchangeAbi: AbiItem | AbiItem[] = null,\n oceanAddress: string = null,\n config?: Config\n ) {\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n this.fixedRateExchangeAbi =\n fixedRateExchangeAbi || (defaultFixedRateExchangeAbi.abi as AbiItem[])\n this.oceanAddress = oceanAddress\n this.fixedRateAddress = fixedRateAddress\n this.fixedRateContract = setContractDefaults(\n new this.web3.eth.Contract(this.fixedRateExchangeAbi, this.fixedRateAddress),\n this.config\n )\n }\n\n async amountToUnits(\n token: string,\n amount: string,\n tokenDecimals: number\n ): Promise<string> {\n return amountToUnits(this.web3, token, amount, tokenDecimals)\n }\n\n async unitsToAmount(\n token: string,\n amount: string,\n tokenDecimals: number\n ): Promise<string> {\n return unitsToAmount(this.web3, token, amount, tokenDecimals)\n }\n\n /**\n * Creates unique exchange identifier.\n * @param {String} baseToken baseToken contract address\n * @param {String} datatoken Datatoken contract address\n * @return {Promise<string>} exchangeId\n */\n public async generateExchangeId(baseToken: string, datatoken: string): Promise<string> {\n const exchangeId = await this.fixedRateContract.methods\n .generateExchangeId(baseToken, datatoken)\n .call()\n return exchangeId\n }\n\n /**\n * Estimate gas cost for buyDT\n * @param {String} account\n * @param {String} dtAmount datatoken amount we want to buy\n * @param {String} datatokenAddress datatokenAddress\n * @param {String} consumeMarketAddress consumeMarketAddress\n * @param {String} consumeMarketFee fee recieved by the consume market when a dt is bought from a fixed rate exchange, percent\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estBuyDT(\n account: string,\n datatokenAddress: string,\n dtAmount: string,\n maxBaseTokenAmount: string,\n consumeMarketAddress: string,\n consumeMarketFee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.buyDT,\n datatokenAddress,\n dtAmount,\n maxBaseTokenAmount,\n consumeMarketAddress,\n consumeMarketFee\n )\n }\n\n /**\n * Atomic swap\n * @param {String} exchangeId ExchangeId\n * @param {String} datatokenAmount Amount of datatokens\n * @param {String} maxBaseTokenAmount max amount of baseToken we want to pay for datatokenAmount\n * @param {String} address User address\n * @param {String} consumeMarketAddress consumeMarketAddress\n * @param {String} consumeMarketFee consumeMarketFee in fraction\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async buyDT(\n address: string,\n exchangeId: string,\n datatokenAmount: string,\n maxBaseTokenAmount: string,\n consumeMarketAddress: string = ZERO_ADDRESS,\n consumeMarketFee: string = '0'\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n const consumeMarketFeeFormatted = this.web3.utils.toWei(consumeMarketFee)\n const dtAmountFormatted = await this.amountToUnits(\n exchange.datatoken,\n datatokenAmount,\n +exchange.dtDecimals\n )\n const maxBtFormatted = await this.amountToUnits(\n exchange.baseToken,\n maxBaseTokenAmount,\n +exchange.btDecimals\n )\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.buyDT,\n exchangeId,\n dtAmountFormatted,\n maxBtFormatted,\n consumeMarketAddress,\n consumeMarketFeeFormatted\n )\n try {\n const trxReceipt = await this.fixedRateContract.methods\n .buyDT(\n exchangeId,\n dtAmountFormatted,\n maxBtFormatted,\n consumeMarketAddress,\n consumeMarketFeeFormatted\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to buy datatokens: ${e.message}`)\n return null\n }\n }\n\n /**\n * Estimate gas cost for sellDT\n * @param {String} account\n * @param {String} dtAmount datatoken amount we want to sell\n * @param {String} datatokenAddress datatokenAddress\n * @param {String} consumeMarketAddress consumeMarketAddress\n * @param {String} consumeMarketFee consumeMarketFee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSellDT(\n account: string,\n datatokenAddress: string,\n dtAmount: string,\n maxBaseTokenAmount: string,\n consumeMarketAddress: string,\n consumeMarketFee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.sellDT,\n datatokenAddress,\n dtAmount,\n maxBaseTokenAmount,\n consumeMarketAddress,\n consumeMarketFee\n )\n }\n\n /**\n * Atomic swap\n * @param {String} exchangeId ExchangeId\n * @param {String} datatokenAmount Amount of datatokens\n * @param {String} minBaseTokenAmount min amount of baseToken we want to receive back\n * @param {String} address User address\n * @param {String} consumeMarketAddress consumeMarketAddress\n * @param {String} consumeMarketFee consumeMarketFee in fraction\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async sellDT(\n address: string,\n exchangeId: string,\n datatokenAmount: string,\n minBaseTokenAmount: string,\n consumeMarketAddress: string = ZERO_ADDRESS,\n consumeMarketFee: string = '0'\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n const consumeMarketFeeFormatted = this.web3.utils.toWei(consumeMarketFee)\n const dtAmountFormatted = await this.amountToUnits(\n exchange.datatoken,\n datatokenAmount,\n +exchange.dtDecimals\n )\n const minBtFormatted = await this.amountToUnits(\n exchange.baseToken,\n minBaseTokenAmount,\n +exchange.btDecimals\n )\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.sellDT,\n exchangeId,\n dtAmountFormatted,\n minBtFormatted,\n consumeMarketAddress,\n consumeMarketFeeFormatted\n )\n try {\n const trxReceipt = await this.fixedRateContract.methods\n .sellDT(\n exchangeId,\n dtAmountFormatted,\n minBtFormatted,\n consumeMarketAddress,\n consumeMarketFeeFormatted\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to sell datatokens: ${e.message}`)\n return null\n }\n }\n\n /**\n * Gets total number of exchanges\n * @param {String} exchangeId ExchangeId\n * @param {Number} datatokenAmount Amount of datatokens\n * @return {Promise<Number>} no of available exchanges\n */\n public async getNumberOfExchanges(): Promise<number> {\n const numExchanges = await this.fixedRateContract.methods\n .getNumberOfExchanges()\n .call()\n return numExchanges\n }\n\n /**\n * Estimate gas cost for setRate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} newRate New rate\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSetRate(\n account: string,\n exchangeId: string,\n newRate: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.setRate,\n exchangeId,\n await this.web3.utils.toWei(newRate)\n )\n }\n\n /**\n * Set new rate\n * @param {String} exchangeId ExchangeId\n * @param {String} newRate New rate\n * @param {String} address User account\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async setRate(\n address: string,\n exchangeId: string,\n newRate: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.setRate,\n exchangeId,\n this.web3.utils.toWei(newRate)\n )\n const trxReceipt = await this.fixedRateContract.methods\n .setRate(exchangeId, this.web3.utils.toWei(newRate))\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for setRate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} newAllowedSwapper new allowed swapper address\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSetAllowedSwapper(\n account: string,\n exchangeId: string,\n newAllowedSwapper: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.setAllowedSwapper,\n exchangeId,\n newAllowedSwapper\n )\n }\n\n /**\n * Set new rate\n * @param {String} exchangeId ExchangeId\n * @param {String} newAllowedSwapper newAllowedSwapper (set address zero if we want to remove allowed swapper)\n * @param {String} address User account\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async setAllowedSwapper(\n address: string,\n exchangeId: string,\n newAllowedSwapper: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.setAllowedSwapper,\n exchangeId,\n newAllowedSwapper\n )\n const trxReceipt = await this.fixedRateContract.methods\n .setAllowedSwapper(exchangeId, newAllowedSwapper)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for activate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estActivate(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.toggleExchangeState, exchangeId)\n }\n\n /**\n * Activate an exchange\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async activate(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n if (exchange.active === true) return null\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.toggleExchangeState,\n exchangeId\n )\n const trxReceipt = await this.fixedRateContract.methods\n .toggleExchangeState(exchangeId)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for deactivate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estDeactivate(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.toggleExchangeState, exchangeId)\n }\n\n /**\n * Deactivate an exchange\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async deactivate(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n if (exchange.active === false) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.toggleExchangeState,\n exchangeId\n )\n\n const trxReceipt = await this.fixedRateContract.methods\n .toggleExchangeState(exchangeId)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Get Rate\n * @param {String} exchangeId ExchangeId\n * @return {Promise<string>} Rate (converted from wei)\n */\n public async getRate(exchangeId: string): Promise<string> {\n const weiRate = await this.fixedRateContract.methods.getRate(exchangeId).call()\n const rate = await this.web3.utils.fromWei(weiRate)\n return rate\n }\n\n /**\n * Get Datatoken Supply in the exchange\n * @param {String} exchangeId ExchangeId\n * @return {Promise<string>} dt supply formatted\n */\n public async getDTSupply(exchangeId: string): Promise<string> {\n const dtSupply = await this.fixedRateContract.methods.getDTSupply(exchangeId).call()\n const exchange = await this.getExchange(exchangeId)\n return await this.unitsToAmount(exchange.datatoken, dtSupply, +exchange.dtDecimals)\n }\n\n /**\n * Get BaseToken Supply in the exchange\n * @param {String} exchangeId ExchangeId\n * @return {Promise<string>} dt supply formatted\n */\n public async getBTSupply(exchangeId: string): Promise<string> {\n const btSupply = await this.fixedRateContract.methods.getBTSupply(exchangeId).call()\n const exchange = await this.getExchange(exchangeId)\n return await this.unitsToAmount(exchange.baseToken, btSupply, +exchange.btDecimals)\n }\n\n /**\n * Get Allower Swapper (if set this is the only account which can use this exchange, else is set at address(0))\n * @param {String} exchangeId ExchangeId\n * @return {Promise<string>} address of allowedSwapper\n */\n public async getAllowedSwapper(exchangeId: string): Promise<string> {\n return await this.fixedRateContract.methods.getAllowedSwapper(exchangeId).call()\n }\n\n /**\n * calcBaseInGivenOutDT - Calculates how many base tokens are needed to get specified amount of datatokens\n * @param {String} exchangeId ExchangeId\n * @param {string} datatokenAmount Amount of datatokens user wants to buy\n * @param {String} consumeMarketFee consumeMarketFee in fraction\n * @return {Promise<PriceAndFees>} how many base tokens are needed and fees\n */\n public async calcBaseInGivenOutDT(\n exchangeId: string,\n datatokenAmount: string,\n consumeMarketFee: string = '0'\n ): Promise<PriceAndFees> {\n const fixedRateExchange = await this.getExchange(exchangeId)\n const result = await this.fixedRateContract.methods\n .calcBaseInGivenOutDT(\n exchangeId,\n await this.amountToUnits(\n fixedRateExchange.datatoken,\n datatokenAmount,\n +fixedRateExchange.dtDecimals\n ),\n this.web3.utils.toWei(consumeMarketFee)\n )\n .call()\n\n const priceAndFees = {\n baseTokenAmount: await this.unitsToAmount(\n fixedRateExchange.baseToken,\n result.baseTokenAmount,\n +fixedRateExchange.btDecimals\n ),\n marketFeeAmount: await this.unitsToAmount(\n fixedRateExchange.baseToken,\n result.marketFeeAmount,\n +fixedRateExchange.btDecimals\n ),\n oceanFeeAmount: await this.unitsToAmount(\n fixedRateExchange.baseToken,\n result.oceanFeeAmount,\n +fixedRateExchange.btDecimals\n ),\n consumeMarketFeeAmount: await this.unitsToAmount(\n fixedRateExchange.baseToken,\n result.consumeMarketFeeAmount,\n +fixedRateExchange.btDecimals\n )\n } as PriceAndFees\n return priceAndFees\n }\n\n /**\n * getBTOut - returns amount in baseToken that user will receive for datatokenAmount sold\n * @param {String} exchangeId ExchangeId\n * @param {Number} datatokenAmount Amount of datatokens\n * @param {String} consumeMarketFee consumeMarketFee in fraction\n * @return {Promise<string>} Amount of baseTokens user will receive\n */\n public async getAmountBTOut(\n exchangeId: string,\n datatokenAmount: string,\n consumeMarketFee: string = '0'\n ): Promise<string> {\n const exchange = await this.getExchange(exchangeId)\n const result = await this.fixedRateContract.methods\n .calcBaseOutGivenInDT(\n exchangeId,\n await this.amountToUnits(\n exchange.datatoken,\n datatokenAmount,\n +exchange.dtDecimals\n ),\n this.web3.utils.toWei(consumeMarketFee)\n )\n .call()\n\n return await this.unitsToAmount(exchange.baseToken, result[0], +exchange.btDecimals)\n }\n\n /**\n * Get exchange details\n * @param {String} exchangeId ExchangeId\n * @return {Promise<FixedPricedExchange>} Exchange details\n */\n public async getExchange(exchangeId: string): Promise<FixedPriceExchange> {\n const result: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n result.dtDecimals = result.dtDecimals.toString()\n result.btDecimals = result.btDecimals.toString()\n result.dtBalance = await this.unitsToAmount(\n result.datatoken,\n result.dtBalance,\n +result.dtDecimals\n )\n result.btBalance = await this.unitsToAmount(\n result.baseToken,\n result.btBalance,\n +result.btDecimals\n )\n result.dtSupply = await this.unitsToAmount(\n result.datatoken,\n result.dtSupply,\n +result.dtDecimals\n )\n result.btSupply = await this.unitsToAmount(\n result.baseToken,\n result.btSupply,\n +result.btDecimals\n )\n result.fixedRate = this.web3.utils.fromWei(result.fixedRate)\n result.exchangeId = exchangeId\n return result\n }\n\n /**\n * Get fee details for an exchange\n * @param {String} exchangeId ExchangeId\n * @return {Promise<FixedPricedExchange>} Exchange details\n */\n public async getFeesInfo(exchangeId: string): Promise<FeesInfo> {\n const result: FeesInfo = await this.fixedRateContract.methods\n .getFeesInfo(exchangeId)\n .call()\n result.opcFee = this.web3.utils.fromWei(result.opcFee.toString())\n result.marketFee = this.web3.utils.fromWei(result.marketFee.toString())\n\n const exchange = await this.getExchange(exchangeId)\n result.marketFeeAvailable = await this.unitsToAmount(\n exchange.baseToken,\n result.marketFeeAvailable,\n +exchange.btDecimals\n )\n result.oceanFeeAvailable = await this.unitsToAmount(\n exchange.baseToken,\n result.oceanFeeAvailable,\n +exchange.btDecimals\n )\n\n result.exchangeId = exchangeId\n return result\n }\n\n /**\n * Get all exchanges\n * @param {String} exchangeId ExchangeId\n * @return {Promise<String[]>} Exchanges list\n */\n public async getExchanges(): Promise<string[]> {\n return await this.fixedRateContract.methods.getExchanges().call()\n }\n\n /**\n * Check if an exchange is active\n * @param {String} exchangeId ExchangeId\n * @return {Promise<Boolean>} Result\n */\n public async isActive(exchangeId: string): Promise<boolean> {\n const result = await this.fixedRateContract.methods.isActive(exchangeId).call()\n return result\n }\n\n /**\n * Estimate gas cost for activate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estActivateMint(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.toggleMintState, exchangeId, true)\n }\n\n /**\n * Activate minting option for fixed rate contract\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async activateMint(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n if (exchange.withMint === true) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.toggleMintState,\n exchangeId,\n true\n )\n const trxReceipt = await this.fixedRateContract.methods\n .toggleMintState(exchangeId, true)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for deactivate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estDeactivateMint(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.toggleMintState(exchangeId, false),\n exchangeId,\n false\n )\n }\n\n /**\n * Deactivate minting for fixed rate\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async deactivateMint(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n if (exchange.withMint === false) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.toggleMintState,\n exchangeId,\n false\n )\n\n const trxReceipt = await this.fixedRateContract.methods\n .toggleMintState(exchangeId, false)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for collectBT\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} amount amount to be collected\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectBT(\n account: string,\n exchangeId: string,\n amount: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n const amountWei = await this.amountToUnits(\n fixedrate.baseToken,\n amount,\n +fixedrate.btDecimals\n )\n return estimateGas(account, fixedRate.methods.collectBT, exchangeId, amountWei)\n }\n\n /**\n * Collect BaseTokens in the contract (anyone can call this, funds are sent to erc20.paymentCollector)\n * @param {String} address User address\n * @param {String} exchangeId ExchangeId\n * @param {String} amount amount to be collected\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async collectBT(\n address: string,\n exchangeId: string,\n amount: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n\n const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n const amountWei = await this.amountToUnits(\n fixedrate.baseToken,\n amount,\n +fixedrate.btDecimals\n )\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.collectBT,\n exchangeId,\n amountWei\n )\n\n const trxReceipt = await this.fixedRateContract.methods\n .collectBT(exchangeId, amountWei)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for collecDT\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} amount amount to be collected\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectDT(\n account: string,\n exchangeId: string,\n amount: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n\n const amountWei = await this.amountToUnits(\n fixedrate.datatoken,\n amount,\n +fixedrate.dtDecimals\n )\n return estimateGas(account, fixedRate.methods.collectDT, exchangeId, amountWei)\n }\n\n /**\n * Collect datatokens in the contract (anyone can call this, funds are sent to erc20.paymentCollector)\n * @param {String} address User address\n * @param {String} exchangeId ExchangeId\n * @param {String} amount amount to be collected\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async collectDT(\n address: string,\n exchangeId: string,\n amount: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n\n const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n const amountWei = await this.amountToUnits(\n fixedrate.datatoken,\n amount,\n +fixedrate.dtDecimals\n )\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.collectDT,\n exchangeId,\n amountWei\n )\n\n const trxReceipt = await this.fixedRateContract.methods\n .collectDT(exchangeId, amountWei)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for collecMarketFee\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectMarketFee(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.collectMarketFee, exchangeId)\n }\n\n /**\n * Collect market fee and send it to marketFeeCollector (anyone can call it)\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async collectMarketFee(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.collectMarketFee,\n exchangeId\n )\n const trxReceipt = await this.fixedRateContract.methods\n .collectMarketFee(exchangeId)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for collectOceanFee\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectOceanFee(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.collectMarketFee, exchangeId)\n }\n\n /**\n * Collect ocean fee and send it to OPF collector (anyone can call it)\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async collectOceanFee(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.collectOceanFee,\n exchangeId\n )\n const trxReceipt = await this.fixedRateContract.methods\n .collectOceanFee(exchangeId)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Get OPF Collector of fixed rate contract\n * @return {String}\n */\n async getOPCCollector(): Promise<string> {\n let result = null\n try {\n result = await this.fixedRateContract.methods.opcCollector().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get OPC Collector address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get Router address set in fixed rate contract\n * @return {String}\n */\n async getRouter(): Promise<string> {\n let result = null\n try {\n result = await this.fixedRateContract.methods.router().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get Router address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get Exchange Owner given an exchangeId\n * @param {String} exchangeId ExchangeId\n * @return {String} return exchange owner\n */\n async getExchangeOwner(exchangeId: string): Promise<string> {\n let result = null\n try {\n result = await (await this.getExchange(exchangeId)).exchangeOwner\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get OPF Collector address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for updateMarketFee\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} newMarketFee New market fee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estUpdateMarketFee(\n account: string,\n exchangeId: string,\n newMarketFee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.updateMarketFee,\n exchangeId,\n newMarketFee\n )\n }\n\n /**\n * Set new market fee, only market fee collector can update it\n * @param {String} address user address\n * @param {String} exchangeId ExchangeId\n * @param {String} newMarketFee New market fee\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async updateMarketFee(\n address: string,\n exchangeId: string,\n newMarketFee: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.updateMarketFee,\n exchangeId,\n this.web3.utils.toWei(newMarketFee)\n )\n const trxReceipt = await this.fixedRateContract.methods\n .updateMarketFee(exchangeId, this.web3.utils.toWei(newMarketFee))\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for updateMarketFeeCollector\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} newMarketFee New market fee collector\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estUpdateMarketFeeCollector(\n account: string,\n exchangeId: string,\n newMarketFeeCollector: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.updateMarketFeeCollector,\n exchangeId,\n newMarketFeeCollector\n )\n }\n\n /**\n * Set new market fee collector, only market fee collector can update it\n * @param {String} address user address\n * @param {String} exchangeId ExchangeId\n * @param {String} newMarketFeeCollector New market fee collector\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async updateMarketFeeCollector(\n address: string,\n exchangeId: string,\n newMarketFeeCollector: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.updateMarketFeeCollector,\n exchangeId,\n newMarketFeeCollector\n )\n const trxReceipt = await this.fixedRateContract.methods\n .updateMarketFeeCollector(exchangeId, newMarketFeeCollector)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n}\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils/types'\nimport { TransactionReceipt } from 'web3-core'\nimport { Contract } from 'web3-eth-contract'\nimport {\n LoggerInstance,\n getFairGasPrice,\n ConfigHelper,\n estimateGas,\n unitsToAmount\n} from '../../utils'\nimport SideStakingTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/ssContracts/SideStaking.sol/SideStaking.json'\nimport { Config } from '../../models'\n\nexport class SideStaking {\n public ssAbi: AbiItem | AbiItem[]\n public web3: Web3\n public config: Config\n\n constructor(\n web3: Web3,\n network?: string | number,\n ssAbi: AbiItem | AbiItem[] = null,\n config?: Config\n ) {\n if (ssAbi) this.ssAbi = ssAbi\n else this.ssAbi = SideStakingTemplate.abi as AbiItem[]\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n }\n\n async unitsToAmount(\n token: string,\n amount: string,\n tokenDecimals?: number\n ): Promise<string> {\n return unitsToAmount(this.web3, token, amount, tokenDecimals)\n }\n\n /**\n * Get (total vesting amount + token released from the contract when adding liquidity)\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatoken address\n * @return {String}\n */\n async getDatatokenCirculatingSupply(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods\n .getDatatokenCirculatingSupply(datatokenAddress)\n .call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result.toString()\n }\n\n /**\n * Get actual dts in circulation (vested token withdrawn from the contract +\n token released from the contract when adding liquidity)\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatoken address\n * @return {String}\n */\n async getDatatokenCurrentCirculatingSupply(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n try {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n result = await sideStaking.methods\n .getDatatokenCurrentCirculatingSupply(datatokenAddress)\n .call()\n return result.toString()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n }\n\n /**\n * Get Publisher address\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatoken address\n * @return {String}\n */\n async getPublisherAddress(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getPublisherAddress(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String}\n */\n async getBaseToken(ssAddress: string, datatokenAddress: string): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getBaseTokenAddress(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get Pool Address\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String}\n */\n async getPoolAddress(ssAddress: string, datatokenAddress: string): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getPoolAddress(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get baseToken balance in the contract\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String}\n */\n async getBaseTokenBalance(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getBaseTokenBalance(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get dt balance in the staking contract available for being added as liquidity\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getDatatokenBalance(\n ssAddress: string,\n datatokenAddress: string,\n tokenDecimals?: number\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getDatatokenBalance(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals)\n return result\n }\n\n /**\n * Get block when vesting ends\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String} end block for vesting amount\n */\n async getvestingEndBlock(ssAddress: string, datatokenAddress: string): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getvestingEndBlock(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get total amount vesting\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getvestingAmount(\n ssAddress: string,\n datatokenAddress: string,\n tokenDecimals?: number\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getvestingAmount(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals)\n return result\n }\n\n /**\n * Get last block publisher got some vested tokens\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String}\n */\n async getvestingLastBlock(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getvestingLastBlock(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get how much has been taken from the vesting amount\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getvestingAmountSoFar(\n ssAddress: string,\n datatokenAddress: string,\n tokenDecimals?: number\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getvestingAmountSoFar(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals)\n return result\n }\n\n /**\n * Estimate gas cost for getVesting\n * @param {String} account\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estGetVesting(\n account: string,\n ssAddress: string,\n datatokenAddress: string,\n contractInstance?: Contract\n ): Promise<number> {\n const sideStaking =\n contractInstance || new this.web3.eth.Contract(this.ssAbi as AbiItem[], ssAddress)\n\n return estimateGas(account, sideStaking.methods.getVesting, datatokenAddress)\n }\n\n /** Send vested tokens available to the publisher address, can be called by anyone\n *\n * @param {String} account\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {TransactionReceipt}\n */\n async getVesting(\n account: string,\n ssAddress: string,\n datatokenAddress: string\n ): Promise<TransactionReceipt> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n\n const estGas = await estimateGas(\n account,\n sideStaking.methods.getVesting,\n datatokenAddress\n )\n\n try {\n result = await sideStaking.methods.getVesting(datatokenAddress).send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error('ERROR: Failed to join swap pool amount out')\n }\n return result\n }\n\n /**\n * Estimate gas cost for getVesting\n * @param {String} account\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSetPoolSwapFee(\n account: string,\n ssAddress: string,\n datatokenAddress: string,\n poolAddress: string,\n swapFee: number,\n contractInstance?: Contract\n ): Promise<number> {\n const sideStaking =\n contractInstance || new this.web3.eth.Contract(this.ssAbi as AbiItem[], ssAddress)\n\n return estimateGas(\n account,\n sideStaking.methods.setPoolSwapFee,\n datatokenAddress,\n poolAddress,\n swapFee\n )\n }\n\n /** Send vested tokens available to the publisher address, can be called by anyone\n *\n * @param {String} account\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {TransactionReceipt}\n */\n async setPoolSwapFee(\n account: string,\n ssAddress: string,\n datatokenAddress: string,\n poolAddress: string,\n swapFee: number\n ): Promise<TransactionReceipt> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n\n const estGas = await estimateGas(\n account,\n sideStaking.methods.setPoolSwapFee,\n datatokenAddress,\n poolAddress,\n swapFee\n )\n\n try {\n result = await sideStaking.methods\n .setPoolSwapFee(datatokenAddress, poolAddress, swapFee)\n .send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error('ERROR: Failed to join swap pool amount out')\n }\n return result\n }\n\n /**\n * Get Router address set in side staking contract\n * @param {String} ssAddress side staking contract address\n * @return {String}\n */\n async getRouter(ssAddress: string): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.router().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get Router address: ${e.message}`)\n }\n return result\n }\n}\n","import { Contract } from 'web3-eth-contract'\nimport Web3 from 'web3'\nimport { TransactionReceipt } from 'web3-core'\nimport { AbiItem } from 'web3-utils'\nimport defaultRouter from '@oceanprotocol/contracts/artifacts/contracts/pools/FactoryRouter.sol/FactoryRouter.json'\nimport { getFairGasPrice, setContractDefaults, ConfigHelper, estimateGas } from '../utils'\nimport { Operation } from '../@types/Router'\nimport { Config } from '../models/index.js'\n\n/**\n * Provides an interface for FactoryRouter contract\n */\nexport class Router {\n public routerAddress: string\n public RouterAbi: AbiItem | AbiItem[]\n public web3: Web3\n public config: Config\n public router: Contract\n\n /**\n * Instantiate Router.\n * @param {String} routerAddress\n * @param {AbiItem | AbiItem[]} Router\n * @param {Web3} web3\n */\n constructor(\n routerAddress: string,\n web3: Web3,\n network?: string | number,\n RouterAbi?: AbiItem | AbiItem[],\n config?: Config\n ) {\n this.routerAddress = routerAddress\n this.RouterAbi = RouterAbi || (defaultRouter.abi as AbiItem[])\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n this.router = setContractDefaults(\n new this.web3.eth.Contract(this.RouterAbi, this.routerAddress),\n this.config\n )\n }\n\n /**\n * Estimate gas cost for buyDTBatch method\n * @param {String} address\n * @param {Operation} operations Operations objects array\n * @return {Promise<TransactionReceipt>} Transaction receipt\n */\n public async estGasBuyDTBatch(address: string, operations: Operation[]): Promise<any> {\n return estimateGas(address, this.router.methods.buyDTBatch, operations)\n }\n\n /**\n * BuyDTBatch\n * @param {String} address\n * @param {Operation} operations Operations objects array\n * @return {Promise<TransactionReceipt>} Transaction receipt\n */\n public async buyDTBatch(\n address: string,\n operations: Operation[]\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(address, this.router.methods.buyDTBatch, operations)\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.buyDTBatch(operations).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Check if a token is on approved tokens list, if true opfFee is lower in pools with that token/DT\n * @return {Promise<boolean>} true if is on the list.\n */\n public async isApprovedToken(address: string): Promise<boolean> {\n return await this.router.methods.isApprovedToken(address).call()\n }\n\n /** Check if an address is a side staking contract.\n * @return {Promise<boolean>} true if is a SS contract\n */\n public async isSideStaking(address: string): Promise<boolean> {\n return await this.router.methods.isSSContract(address).call()\n }\n\n /** Check if an address is a Fixed Rate contract.\n * @return {Promise<boolean>} true if is a Fixed Rate contract\n */\n public async isFixedPrice(address: string): Promise<boolean> {\n return await this.router.methods.isFixedRateContract(address).call()\n }\n\n /** Get Router Owner\n * @return {Promise<string>} Router Owner address\n */\n public async getOwner(): Promise<string> {\n return await this.router.methods.routerOwner().call()\n }\n\n /** Get NFT Factory address\n * @return {Promise<string>} NFT Factory address\n */\n public async getNFTFactory(): Promise<string> {\n return await this.router.methods.factory().call()\n }\n\n /** Check if an address is a pool template contract.\n * @return {Promise<boolean>} true if is a Template\n */\n public async isPoolTemplate(address: string): Promise<boolean> {\n return await this.router.methods.isPoolTemplate(address).call()\n }\n\n /**\n * Estimate gas cost for addApprovedToken\n * @param {String} address\n * @param {String} tokenAddress token address we want to add\n * @param {Contract} routerContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddApprovedToken(\n address: string,\n tokenAddress: string,\n contractInstance?: Contract\n ): Promise<any> {\n return estimateGas(address, this.router.methods.addApprovedToken, tokenAddress)\n }\n\n /**\n * Add a new token to oceanTokens list, pools with baseToken in this list have NO opf Fee\n * @param {String} address caller address\n * @param {String} tokenAddress token address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addApprovedToken(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addApprovedToken,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addApprovedToken(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeApprovedToken\n * @param {String} address caller address\n * @param {String} tokenAddress token address we want to add\n * @param {Contract} routerContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveApprovedToken(\n address: string,\n tokenAddress: string,\n contractInstance?: Contract\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removeApprovedToken, tokenAddress)\n }\n\n /**\n * Remove a token from oceanTokens list, pools without baseToken in this list have a opf Fee\n * @param {String} address\n * @param {String} tokenAddress address to remove\n * @return {Promise<TransactionReceipt>}\n */\n public async removeApprovedToken(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removeApprovedToken,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.removeApprovedToken(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addSSContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddSSContract(address: string, tokenAddress: string): Promise<any> {\n return estimateGas(address, this.router.methods.addSSContract, tokenAddress)\n }\n\n /**\n * Add a new contract to ssContract list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addSSContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addSSContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addSSContract(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeSSContract method\n * @param {String} address caller address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasRemoveSSContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removeSSContract, tokenAddress)\n }\n\n /**\n * Removes a new contract from ssContract list\n * @param {String} address caller address\n * @param {String} tokenAddress contract address to removed\n * @return {Promise<TransactionReceipt>}\n */\n public async removeSSContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removeSSContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.removeSSContract(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addFixedRateContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddFixedRateContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.addFixedRateContract, tokenAddress)\n }\n\n /**\n * Add a new contract to fixedRate list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addFixedRateContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addFixedRateContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addFixedRateContract(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addFixedRateContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasRemoveFixedRateContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removeFixedRateContract, tokenAddress)\n }\n\n /**\n * Removes a contract from fixedRate list\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async removeFixedRateContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removeFixedRateContract,\n tokenAddress\n )\n\n // Invoke removeFixedRateContract function of the contract\n const trxReceipt = await this.router.methods\n .removeFixedRateContract(tokenAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addDispenserContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddDispenserContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.addDispenserContract, tokenAddress)\n }\n\n /**\n * Add a new contract to dispenser list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addDispenserContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addDispenserContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addDispenserContract(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addDispenserContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasRemoveDispenserContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removeDispenserContract, tokenAddress)\n }\n\n /**\n * Add a new contract to dispenser list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async removeDispenserContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removeDispenserContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods\n .removeDispenserContract(tokenAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Get OPF Fee per token\n * @return {Promise<number>} OPC fee for a specific baseToken\n */\n public async getOPCFee(baseToken: string): Promise<number> {\n return await this.router.methods.getOPCFee(baseToken).call()\n }\n\n /** Get Current OPF Fee\n * @return {Promise<number>} OPF fee\n */\n public async getCurrentOPCFee(): Promise<number> {\n return await this.router.methods.swapOceanFee().call()\n }\n\n /**\n * Estimate gas cost for updateOPFFee method\n * @param {String} address\n * @param {String} newFee new OPF Fee\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasUpdateOPCFee(\n address: string,\n newSwapOceanFee: number,\n newSwapNonOceanFee: number,\n newConsumeFee: number,\n newProviderFee: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.router.methods.updateOPCFee,\n newSwapOceanFee,\n newSwapNonOceanFee,\n newConsumeFee,\n newProviderFee\n )\n }\n\n /**\n * Add a new contract to fixedRate list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {number} newSwapOceanFee Amount charged for swapping with ocean approved tokens\n * @param {number} newSwapNonOceanFee Amount charged for swapping with non ocean approved tokens\n * @param {number} newConsumeFee Amount charged from consumeFees\n * @param {number} newProviderFee Amount charged for providerFees\n * @return {Promise<TransactionReceipt>}\n */\n public async updateOPCFee(\n address: string,\n newSwapOceanFee: number,\n newSwapNonOceanFee: number,\n newConsumeFee: number,\n newProviderFee: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.updateOPCFee,\n newSwapOceanFee,\n newSwapNonOceanFee,\n newConsumeFee,\n newProviderFee\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods\n .updateOPCFee(newSwapOceanFee, newSwapNonOceanFee, newConsumeFee, newProviderFee)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addPoolTemplate method\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddPoolTemplate(\n address: string,\n templateAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.addPoolTemplate, templateAddress)\n }\n\n /**\n * Add a new template to poolTemplates mapping, after template is added,it can be used\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addPoolTemplate(\n address: string,\n templateAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addPoolTemplate,\n templateAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addPoolTemplate(templateAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removePoolTemplate method\n * @param {String} address\n * @param {String} templateAddress template address to remove\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasRemovePoolTemplate(\n address: string,\n templateAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removePoolTemplate, templateAddress)\n }\n\n /**\n * Remove template from poolTemplates mapping, after template is removed,it can be used anymore\n * @param {String} address\n * @param {String} templateAddress template address to remove\n * @return {Promise<TransactionReceipt>}\n */\n public async removePoolTemplate(\n address: string,\n templateAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removePoolTemplate,\n templateAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods\n .removePoolTemplate(templateAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n}\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils'\nimport { TransactionReceipt } from 'web3-eth'\nimport defaultNftAbi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json'\nimport {\n LoggerInstance,\n getFairGasPrice,\n generateDtName,\n setContractDefaults,\n estimateGas,\n ConfigHelper\n} from '../utils'\nimport { Contract } from 'web3-eth-contract'\nimport { MetadataProof } from '../../src/@types'\nimport { Config } from '../models/index.js'\nimport { MetadataAndTokenURI } from '../@types'\n\n/**\n * ERC721 ROLES\n */\ninterface Roles {\n manager: boolean\n deployERC20: boolean\n updateMetadata: boolean\n store: boolean\n}\n\nexport class Nft {\n public factory721Address: string\n public factory721Abi: AbiItem | AbiItem[]\n public nftAbi: AbiItem | AbiItem[]\n public web3: Web3\n public startBlock: number\n public config: Config\n\n constructor(\n web3: Web3,\n network?: string | number,\n nftAbi?: AbiItem | AbiItem[],\n config?: Config\n ) {\n this.nftAbi = nftAbi || (defaultNftAbi.abi as AbiItem[])\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n }\n\n /**\n * Estimate gas cost for createERC20 token creation\n * @param {String} nftAddress ERC721 addreess\n * @param {String} address User address\n * @param {String} minter User set as initial minter for the ERC20\n * @param {String} paymentCollector initial paymentCollector for this DT\n * @param {String} mpFeeAddress Consume marketplace fee address\n * @param {String} feeToken address of the token marketplace wants to add fee on top\n * @param {String} feeAmount amount of feeToken to be transferred to mpFeeAddress on top, will be converted to WEI\n * @param {String} cap Maximum cap (Number) - will be converted to wei\n * @param {String} name Token name\n * @param {String} symbol Token symbol\n * @param {Number} templateIndex NFT template index\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCreateErc20(\n nftAddress: string,\n address: string,\n minter: string,\n paymentCollector: string,\n mpFeeAddress: string,\n feeToken: string,\n feeAmount: string,\n cap: string,\n name?: string,\n symbol?: string,\n templateIndex?: number,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n return estimateGas(\n address,\n nftContract.methods.createERC20,\n templateIndex,\n [name, symbol],\n [minter, paymentCollector, mpFeeAddress, feeToken],\n [this.web3.utils.toWei(cap), this.web3.utils.toWei(feeAmount)],\n []\n )\n }\n\n /**\n * Create new ERC20 datatoken - only user with ERC20Deployer permission can succeed\n * @param {String} nftAddress ERC721 addreess\n * @param {String} address User address\n * @param {String} minter User set as initial minter for the ERC20\n * @param {String} paymentCollector initial paymentCollector for this DT\n * @param {String} mpFeeAddress Consume marketplace fee address\n * @param {String} feeToken address of the token marketplace wants to add fee on top\n * @param {String} feeAmount amount of feeToken to be transferred to mpFeeAddress on top, will be converted to WEI\n * @param {String} cap Maximum cap (Number) - will be converted to wei\n * @param {String} name Token name\n * @param {String} symbol Token symbol\n * @param {Number} templateIndex NFT template index\n * @return {Promise<string>} ERC20 datatoken address\n */\n public async createErc20(\n nftAddress: string,\n address: string,\n minter: string,\n paymentCollector: string,\n mpFeeAddress: string,\n feeToken: string,\n feeAmount: string,\n cap: string,\n name?: string,\n symbol?: string,\n templateIndex?: number\n ): Promise<string> {\n if ((await this.getNftPermissions(nftAddress, address)).deployERC20 !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n if (!templateIndex) templateIndex = 1\n\n // Generate name & symbol if not present\n if (!name || !symbol) {\n ;({ name, symbol } = generateDtName())\n }\n\n // Create 721contract object\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.createERC20,\n templateIndex,\n [name, symbol],\n [minter, paymentCollector, mpFeeAddress, feeToken],\n [this.web3.utils.toWei(cap), this.web3.utils.toWei(feeAmount)],\n []\n )\n\n // Call createERC20 token function of the contract\n const trxReceipt = await nftContract.methods\n .createERC20(\n templateIndex,\n [name, symbol],\n [minter, paymentCollector, mpFeeAddress, feeToken],\n [this.web3.utils.toWei(cap), this.web3.utils.toWei(feeAmount)],\n []\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n let tokenAddress = null\n try {\n tokenAddress = trxReceipt.events.TokenCreated.returnValues[0]\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to create datatoken : ${e.message}`)\n }\n return tokenAddress\n }\n\n /**\n * Estimate gas cost for add manager call\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {String} manager User adress which is going to be assing manager\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddManager(\n nftAddress: string,\n address: string,\n manager: string,\n contractInstance?: Contract\n ) {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.addManager, manager)\n }\n\n /**\n * Add Manager for NFT Contract (only NFT Owner can succeed)\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {String} manager User adress which is going to be assing manager\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async addManager(nftAddress: string, address: string, manager: string) {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== address) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const estGas = await estimateGas(address, nftContract.methods.addManager, manager)\n\n // Invoke addManager function of the contract\n const trxReceipt = await nftContract.methods.addManager(manager).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeManager method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {String} manager User adress which is going to be removed as manager\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveManager(\n nftAddress: string,\n address: string,\n manager: string,\n contractInstance?: Contract\n ) {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n return estimateGas(address, nftContract.methods.removeManager, manager)\n }\n\n /**\n * Removes a specific manager for NFT Contract (only NFT Owner can succeed)\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {String} manager User adress which is going to be removed as manager\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removeManager(nftAddress: string, address: string, manager: string) {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== address) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const estGas = await estimateGas(address, nftContract.methods.removeManager, manager)\n\n // Invoke removeManager function of the contract\n const trxReceipt = await nftContract.methods.removeManager(manager).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addToCreateERC20List method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} erc20Deployer User adress which is going to have erc20Deployer permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddErc20Deployer(\n nftAddress: string,\n address: string,\n erc20Deployer: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n return estimateGas(address, nftContract.methods.addToCreateERC20List, erc20Deployer)\n }\n\n /**\n * Add ERC20Deployer permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} erc20Deployer User adress which is going to have erc20Deployer permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async addErc20Deployer(\n nftAddress: string,\n address: string,\n erc20Deployer: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftPermissions(nftAddress, address)).manager !== true) {\n throw new Error(`Caller is not Manager`)\n }\n\n // Estimate gas for addToCreateERC20List method\n const estGas = await estimateGas(\n address,\n nftContract.methods.addToCreateERC20List,\n erc20Deployer\n )\n\n // Invoke addToCreateERC20List function of the contract\n const trxReceipt = await nftContract.methods\n .addToCreateERC20List(erc20Deployer)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeFromCreateERC20List method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} erc20Deployer Address of the user to be revoked ERC20Deployer Permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveErc20Deployer(\n nftAddress: string,\n address: string,\n erc20Deployer: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n address,\n nftContract.methods.removeFromCreateERC20List,\n erc20Deployer\n )\n }\n\n /**\n * Remove ERC20Deployer permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} erc20Deployer Address of the user to be revoked ERC20Deployer Permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removeErc20Deployer(\n nftAddress: string,\n address: string,\n erc20Deployer: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if (\n (await this.getNftPermissions(nftAddress, address)).manager !== true ||\n (address === erc20Deployer &&\n (await this.getNftPermissions(nftAddress, address)).deployERC20 !== true)\n ) {\n throw new Error(`Caller is not Manager nor ERC20Deployer`)\n }\n const estGas = await estimateGas(\n address,\n nftContract.methods.removeFromCreateERC20List,\n erc20Deployer\n )\n\n // Call removeFromCreateERC20List function of the contract\n const trxReceipt = await nftContract.methods\n .removeFromCreateERC20List(erc20Deployer)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addToMetadataList method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} metadataUpdater User adress which is going to have Metadata Updater permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddMetadataUpdater(\n nftAddress: string,\n address: string,\n metadataUpdater: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.addToMetadataList, metadataUpdater)\n }\n\n /**\n * Add Metadata Updater permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} metadataUpdater User adress which is going to have Metadata Updater permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async addMetadataUpdater(\n nftAddress: string,\n address: string,\n metadataUpdater: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftPermissions(nftAddress, address)).manager !== true) {\n throw new Error(`Caller is not Manager`)\n }\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.addToMetadataList,\n metadataUpdater\n )\n\n // Call addToMetadataList function of the contract\n const trxReceipt = await nftContract.methods.addToMetadataList(metadataUpdater).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeFromMetadataList method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} metadataUpdater Address of the user to be revoked Metadata updater Permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async esGasRemoveMetadataUpdater(\n nftAddress: string,\n address: string,\n metadataUpdater: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n address,\n nftContract.methods.removeFromMetadataList,\n metadataUpdater\n )\n }\n\n /**\n * Remove Metadata Updater permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} metadataUpdater Address of the user to be revoked Metadata updater Permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removeMetadataUpdater(\n nftAddress: string,\n address: string,\n metadataUpdater: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if (\n (await this.getNftPermissions(nftAddress, address)).manager !== true ||\n (address !== metadataUpdater &&\n (await this.getNftPermissions(nftAddress, address)).updateMetadata !== true)\n ) {\n throw new Error(`Caller is not Manager nor Metadata Updater`)\n }\n\n const estGas = await this.esGasRemoveMetadataUpdater(\n nftAddress,\n address,\n metadataUpdater,\n nftContract\n )\n\n // Call removeFromMetadataList function of the contract\n const trxReceipt = await nftContract.methods\n .removeFromMetadataList(metadataUpdater)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addTo725StoreList method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} storeUpdater User adress which is going to have Store Updater permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddStoreUpdater(\n nftAddress: string,\n address: string,\n storeUpdater: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.addTo725StoreList, storeUpdater)\n }\n\n /**\n * Add Store Updater permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} storeUpdater User adress which is going to have Store Updater permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async addStoreUpdater(\n nftAddress: string,\n address: string,\n storeUpdater: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftPermissions(nftAddress, address)).manager !== true) {\n throw new Error(`Caller is not Manager`)\n }\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.addTo725StoreList,\n storeUpdater\n )\n\n // Call addTo725StoreList function of the contract\n const trxReceipt = await nftContract.methods.addTo725StoreList(storeUpdater).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeFrom725StoreList method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} storeUpdater Address of the user to be revoked Store Updater Permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveStoreUpdater(\n nftAddress: string,\n address: string,\n storeUpdater: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.removeFrom725StoreList, storeUpdater)\n }\n\n /**\n * Remove Store Updater permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} storeUpdater Address of the user to be revoked Store Updater Permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removeStoreUpdater(\n nftAddress: string,\n address: string,\n storeUpdater: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if (\n (await this.getNftPermissions(nftAddress, address)).manager !== true ||\n (address !== storeUpdater &&\n (await this.getNftPermissions(nftAddress, address)).store !== true)\n ) {\n throw new Error(`Caller is not Manager nor storeUpdater`)\n }\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.removeFrom725StoreList,\n storeUpdater\n )\n\n // Call removeFrom725StoreList function of the contract\n const trxReceipt = await nftContract.methods\n .removeFrom725StoreList(storeUpdater)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for cleanPermissions method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCleanPermissions(\n nftAddress: string,\n address: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.cleanPermissions)\n }\n\n /**\n * This function allows to remove all ROLES at erc721 level: Managers, ERC20Deployer, MetadataUpdater, StoreUpdater\n * Even NFT Owner has to readd himself as Manager\n * Permissions at erc20 level stay.\n * Only NFT Owner can call it.\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n\n public async cleanPermissions(\n nftAddress: string,\n address: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== address) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const estGas = await estimateGas(address, nftContract.methods.cleanPermissions)\n\n // Call cleanPermissions function of the contract\n const trxReceipt = await nftContract.methods.cleanPermissions().send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for transfer NFT method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {String} nftReceiver User which will receive the NFT, will also be set as Manager\n * @param {Number} tokenId The id of the token to be transfered\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasTransferNft(\n nftAddress: string,\n nftOwner: string,\n nftReceiver: string,\n tokenId: number,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n nftOwner,\n nftContract.methods.transferFrom,\n nftOwner,\n nftReceiver,\n tokenId\n )\n }\n\n /**\n * Transfers the NFT\n * will clean all permissions both on erc721 and erc20 level.\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {String} nftReceiver User which will receive the NFT, will also be set as Manager\n * @param {Number} tokenId The id of the token to be transfered\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async transferNft(\n nftAddress: string,\n nftOwner: string,\n nftReceiver: string,\n tokenId?: number\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== nftOwner) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const tokenIdentifier = tokenId || 1\n\n const estGas = await estimateGas(\n nftOwner,\n nftContract.methods.transferFrom,\n nftOwner,\n nftReceiver,\n tokenIdentifier\n )\n\n // Call transferFrom function of the contract\n const trxReceipt = await nftContract.methods\n .transferFrom(nftOwner, nftReceiver, tokenIdentifier)\n .send({\n from: nftOwner,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for safeTransfer NFT method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {String} nftReceiver User which will receive the NFT, will also be set as Manager\n * @param {Number} tokenId The id of the token to be transfered\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSafeTransferNft(\n nftAddress: string,\n nftOwner: string,\n nftReceiver: string,\n tokenId: number,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n nftOwner,\n nftContract.methods.safeTransferFrom,\n nftOwner,\n nftReceiver,\n tokenId\n )\n }\n\n /**\n * safeTransferNFT Used for transferring the NFT, can be used by an approved relayer\n * will clean all permissions both on erc721 and erc20 level.\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {String} nftReceiver User which will receive the NFT, will also be set as Manager\n * @param {Number} tokenId The id of the token to be transfered\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async safeTransferNft(\n nftAddress: string,\n nftOwner: string,\n nftReceiver: string,\n tokenId?: number\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== nftOwner) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const tokenIdentifier = tokenId || 1\n\n const estGas = await estimateGas(\n nftOwner,\n nftContract.methods.safeTransferFrom,\n nftOwner,\n nftReceiver,\n tokenIdentifier\n )\n\n // Call transferFrom function of the contract\n const trxReceipt = await nftContract.methods\n .safeTransferFrom(nftOwner, nftReceiver, tokenIdentifier)\n .send({\n from: nftOwner,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n // TODO: Finish this description\n /**\n * Estimate gas cost for setMetadata method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} metadataUpdater metadataUpdater address\n * @param {Number} metadataState User which will receive the NFT, will also be set as Manager\n * @param {String} metadataDecryptorUrl\n * @param {Number} tokenId The id of the token to be transfered\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetMetadata(\n nftAddress: string,\n metadataUpdater: string,\n metadataState: number,\n metadataDecryptorUrl: string,\n metadataDecryptorAddress: string,\n flags: string,\n data: string,\n metadataHash: string,\n metadataProofs?: MetadataProof[],\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n if (!metadataProofs) metadataProofs = []\n return estimateGas(\n metadataUpdater,\n nftContract.methods.setMetaData,\n metadataState,\n metadataDecryptorUrl,\n metadataDecryptorAddress,\n flags,\n data,\n metadataHash,\n metadataProofs\n )\n }\n\n /**\n * safeTransferNFT Used for transferring the NFT, can be used by an approved relayer\n * will clean all permissions both on erc721 and erc20 level.\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address Caller address NFT Owner adress\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async setMetadata(\n nftAddress: string,\n address: string,\n metadataState: number,\n metadataDecryptorUrl: string,\n metadataDecryptorAddress: string,\n flags: string,\n data: string,\n metadataHash: string,\n metadataProofs?: MetadataProof[]\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n if (!metadataProofs) metadataProofs = []\n if (!(await this.getNftPermissions(nftAddress, address)).updateMetadata) {\n throw new Error(`Caller is not Metadata updater`)\n }\n const estGas = await estimateGas(\n address,\n nftContract.methods.setMetaData,\n metadataState,\n metadataDecryptorUrl,\n metadataDecryptorAddress,\n flags,\n data,\n metadataHash,\n metadataProofs\n )\n const trxReceipt = await nftContract.methods\n .setMetaData(\n metadataState,\n metadataDecryptorUrl,\n metadataDecryptorAddress,\n flags,\n data,\n metadataHash,\n metadataProofs\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for setMetadata method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} metadataUpdater metadataUpdater address\n * @param {MetaDataAndTokenURI} metadataAndTokenURI metaDataAndTokenURI object\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetMetadataAndTokenURI(\n nftAddress: string,\n metadataUpdater: string,\n metadataAndTokenURI: MetadataAndTokenURI,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const sanitizedMetadataAndTokenURI = {\n ...metadataAndTokenURI,\n metadataProofs: metadataAndTokenURI.metadataProofs || []\n }\n return estimateGas(\n metadataUpdater,\n nftContract.methods.setMetaDataAndTokenURI,\n sanitizedMetadataAndTokenURI\n )\n }\n\n /**\n * Helper function to improve UX sets both MetaData & TokenURI in one tx\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address Caller address\n * @param {MetadataAndTokenURI} metadataAndTokenURI metaDataAndTokenURI object\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async setMetadataAndTokenURI(\n nftAddress: string,\n metadataUpdater: string,\n metadataAndTokenURI: MetadataAndTokenURI\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n if (!(await this.getNftPermissions(nftAddress, metadataUpdater)).updateMetadata) {\n throw new Error(`Caller is not Metadata updater`)\n }\n const sanitizedMetadataAndTokenURI = {\n ...metadataAndTokenURI,\n metadataProofs: metadataAndTokenURI.metadataProofs || []\n }\n const estGas = await estimateGas(\n metadataUpdater,\n nftContract.methods.setMetaDataAndTokenURI,\n sanitizedMetadataAndTokenURI\n )\n const trxReceipt = await nftContract.methods\n .setMetaDataAndTokenURI(sanitizedMetadataAndTokenURI)\n .send({\n from: metadataUpdater,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for setMetadataState method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {Number} metadataState new metadata state\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetMetadataState(\n nftAddress: string,\n metadataUpdater: string,\n metadataState: number,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n metadataUpdater,\n nftContract.methods.setMetaDataState,\n metadataState\n )\n }\n\n /**\n * setMetadataState Used for updating the metadata State\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address Caller address => metadata updater\n * @param {Number} metadataState new metadata state\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async setMetadataState(\n nftAddress: string,\n address: string,\n metadataState: number\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if (!(await this.getNftPermissions(nftAddress, address)).updateMetadata) {\n throw new Error(`Caller is not Metadata updater`)\n }\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.setMetaDataState,\n metadataState\n )\n\n // Call transferFrom function of the contract\n const trxReceipt = await nftContract.methods.setMetaDataState(metadataState).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas cost for setTokenURI method\n * @param nftAddress erc721 contract adress\n * @param address user adress\n * @param data input data for TokenURI\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estSetTokenURI(\n nftAddress: string,\n address: string,\n data: string\n ): Promise<any> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.setTokenURI, '1', data)\n }\n\n /** set TokenURI on an nft\n * @param nftAddress erc721 contract adress\n * @param address user adress\n * @param data input data for TokenURI\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async setTokenURI(\n nftAddress: string,\n address: string,\n data: string\n ): Promise<any> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n const estGas = await estimateGas(address, nftContract.methods.setTokenURI, '1', data)\n const trxReceipt = await nftContract.methods.setTokenURI('1', data).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /** Get Owner\n * @param {String} nftAddress erc721 contract adress\n * @return {Promise<string>} string\n */\n public async getNftOwner(nftAddress: string): Promise<string> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const trxReceipt = await nftContract.methods.ownerOf(1).call()\n return trxReceipt\n }\n\n /** Get users NFT Permissions\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address user adress\n * @return {Promise<Roles>}\n */\n public async getNftPermissions(nftAddress: string, address: string): Promise<Roles> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const roles = await nftContract.methods.getPermissions(address).call()\n return roles\n }\n\n /** Get users Metadata, return Metadata details\n * @param {String} nftAddress erc721 contract adress\n * @return {Promise<Objecta>}\n */\n public async getMetadata(nftAddress: string): Promise<Object> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n return await nftContract.methods.getMetaData().call()\n }\n\n /** Get users ERC20Deployer role\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address user adress\n * @return {Promise<Roles>}\n */\n public async isErc20Deployer(nftAddress: string, address: string): Promise<boolean> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const isERC20Deployer = await nftContract.methods.isERC20Deployer(address).call()\n return isERC20Deployer\n }\n\n /** Gets data at a given `key`\n * @param {String} nftAddress erc721 contract adress\n * @param {String} key the key which value to retrieve\n * @return {Promise<string>} The data stored at the key\n */\n public async getData(nftAddress: string, key: string): Promise<string> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const data = await nftContract.methods.getData(key).call()\n return data\n }\n\n /** Gets data at a given `key`\n * @param {String} nftAddress erc721 contract adress\n * @param {String} id\n * @return {Promise<string>} The data stored at the key\n */\n public async getTokenURI(nftAddress: string, id: number): Promise<string> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const data = await nftContract.methods.tokenURI(id).call()\n return data\n }\n}\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils'\nimport { TransactionReceipt } from 'web3-eth'\nimport { Contract } from 'web3-eth-contract'\nimport Decimal from 'decimal.js'\nimport defaultDatatokensAbi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json'\nimport defaultDatatokensEnterpriseAbi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20TemplateEnterprise.sol/ERC20TemplateEnterprise.json'\nimport {\n LoggerInstance,\n getFairGasPrice,\n setContractDefaults,\n getFreOrderParams,\n estimateGas,\n ZERO_ADDRESS,\n ConfigHelper\n} from '../utils'\nimport {\n ConsumeMarketFee,\n FreOrderParams,\n FreCreationParams,\n ProviderFees,\n PublishingMarketFee\n} from '../@types'\nimport { Nft } from './NFT'\nimport { Config } from '../models/index.js'\n\n/**\n * ERC20 ROLES\n */\ninterface Roles {\n minter: boolean\n paymentManager: boolean\n}\n\nexport interface OrderParams {\n consumer: string\n serviceIndex: number\n _providerFee: ProviderFees\n _consumeMarketFee: ConsumeMarketFee\n}\n\nexport interface DispenserParams {\n maxTokens: string\n maxBalance: string\n withMint?: boolean // true if we want to allow the dispenser to be a minter\n allowedSwapper?: string // only account that can ask tokens. set address(0) if not required\n}\n\nexport class Datatoken {\n public factoryAddress: string\n public factoryABI: AbiItem | AbiItem[]\n public datatokensAbi: AbiItem | AbiItem[]\n public datatokensEnterpriseAbi: AbiItem | AbiItem[]\n public web3: Web3\n public config: Config\n public nft: Nft\n\n /**\n * Instantiate ERC20 Datatokens\n * @param {AbiItem | AbiItem[]} datatokensAbi\n * @param {Web3} web3\n */\n constructor(\n web3: Web3,\n network?: string | number,\n datatokensAbi?: AbiItem | AbiItem[],\n datatokensEnterpriseAbi?: AbiItem | AbiItem[],\n config?: Config\n ) {\n this.web3 = web3\n this.datatokensAbi = datatokensAbi || (defaultDatatokensAbi.abi as AbiItem[])\n this.datatokensEnterpriseAbi =\n datatokensEnterpriseAbi || (defaultDatatokensEnterpriseAbi.abi as AbiItem[])\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n this.nft = new Nft(this.web3)\n }\n\n /**\n * Estimate gas cost for mint method\n * @param {String} dtAddress Datatoken address\n * @param {String} spender Spender address\n * @param {string} amount Number of datatokens, as number. Will be converted to wei\n * @param {String} address User adress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasApprove(\n dtAddress: string,\n spender: string,\n amount: string,\n address: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(\n address,\n dtContract.methods.approve,\n spender,\n this.web3.utils.toWei(amount)\n )\n }\n\n /**\n * Approve\n * @param {String} dtAddress Datatoken address\n * @param {String} spender Spender address\n * @param {string} amount Number of datatokens, as number. Will be converted to wei\n * @param {String} address User adress\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async approve(\n dtAddress: string,\n spender: string,\n amount: string,\n address: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.approve,\n spender,\n this.web3.utils.toWei(amount)\n )\n\n // Call mint contract method\n const trxReceipt = await dtContract.methods\n .approve(spender, this.web3.utils.toWei(amount))\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for mint method\n * @param {String} dtAddress Datatoken address\n * @param {String} address Minter address\n * @param {String} amount Number of datatokens, as number. Will be converted to wei\n * @param {String} toAddress only if toAddress is different from the minter\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasMint(\n dtAddress: string,\n address: string,\n amount: string,\n toAddress?: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(\n address,\n dtContract.methods.mint,\n toAddress || address,\n this.web3.utils.toWei(amount)\n )\n }\n\n /**\n * Estimate gas cost for createFixedRate method\n * @param {String} dtAddress Datatoken address\n * @param {String} address Caller address\n * @param {String} fixedPriceAddress\n * @param {FixedRateParams} fixedRateParams\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCreateFixedRate(\n dtAddress: string,\n address: string,\n fixedRateParams: FreCreationParams,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if (!fixedRateParams.allowedConsumer) fixedRateParams.allowedConsumer = ZERO_ADDRESS\n const withMint = fixedRateParams.withMint ? 1 : 0\n\n return estimateGas(\n address,\n dtContract.methods.createFixedRate,\n fixedRateParams.fixedRateAddress,\n [\n fixedRateParams.baseTokenAddress,\n address,\n fixedRateParams.marketFeeCollector,\n fixedRateParams.allowedConsumer\n ],\n [\n fixedRateParams.baseTokenDecimals,\n fixedRateParams.datatokenDecimals,\n fixedRateParams.fixedRate,\n fixedRateParams.marketFee,\n withMint\n ]\n )\n }\n\n /**\n * Creates a new FixedRateExchange setup.\n * @param {String} dtAddress Datatoken address\n * @param {String} address Caller address\n * @param {String} fixedPriceAddress\n * @param {FixedRateParams} fixedRateParams\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async createFixedRate(\n dtAddress: string,\n address: string,\n fixedRateParams: FreCreationParams\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n if (!(await this.isERC20Deployer(dtAddress, address))) {\n throw new Error(`User is not ERC20 Deployer`)\n }\n if (!fixedRateParams.allowedConsumer) fixedRateParams.allowedConsumer = ZERO_ADDRESS\n\n const withMint = fixedRateParams.withMint ? 1 : 0\n\n // should check ERC20Deployer role using erc721 level ..\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.createFixedRate,\n fixedRateParams.fixedRateAddress,\n [\n fixedRateParams.baseTokenAddress,\n fixedRateParams.owner,\n fixedRateParams.marketFeeCollector,\n fixedRateParams.allowedConsumer\n ],\n [\n fixedRateParams.baseTokenDecimals,\n fixedRateParams.datatokenDecimals,\n fixedRateParams.fixedRate,\n fixedRateParams.marketFee,\n withMint\n ]\n )\n\n // Call createFixedRate contract method\n const trxReceipt = await dtContract.methods\n .createFixedRate(\n fixedRateParams.fixedRateAddress,\n [\n fixedRateParams.baseTokenAddress,\n fixedRateParams.owner,\n fixedRateParams.marketFeeCollector,\n fixedRateParams.allowedConsumer\n ],\n [\n fixedRateParams.baseTokenDecimals,\n fixedRateParams.datatokenDecimals,\n fixedRateParams.fixedRate,\n fixedRateParams.marketFee,\n withMint\n ]\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for createDispenser method\n * @param {String} dtAddress Datatoken address\n * @param {String} address Caller address\n * @param {String} dispenserAddress ispenser contract address\n * @param {String} dispenserParams\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCreateDispenser(\n dtAddress: string,\n address: string,\n dispenserAddress: string,\n dispenserParams: DispenserParams,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if (!dispenserParams.allowedSwapper) dispenserParams.allowedSwapper = ZERO_ADDRESS\n\n if (!dispenserParams.withMint) dispenserParams.withMint = false\n\n return estimateGas(\n address,\n dtContract.methods.createDispenser,\n dispenserAddress,\n dispenserParams.maxTokens,\n dispenserParams.maxBalance,\n dispenserParams.withMint,\n dispenserParams.allowedSwapper\n )\n }\n\n /**\n * Creates a new Dispenser\n * @param {String} dtAddress Datatoken address\n * @param {String} address Caller address\n * @param {String} dispenserAddress ispenser contract address\n * @param {String} dispenserParams\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async createDispenser(\n dtAddress: string,\n address: string,\n dispenserAddress: string,\n dispenserParams: DispenserParams\n ): Promise<TransactionReceipt> {\n if (!(await this.isERC20Deployer(dtAddress, address))) {\n throw new Error(`User is not ERC20 Deployer`)\n }\n\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if (!dispenserParams.allowedSwapper) dispenserParams.allowedSwapper = ZERO_ADDRESS\n\n if (!dispenserParams.withMint) dispenserParams.withMint = false\n\n // should check ERC20Deployer role using erc721 level ..\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.createDispenser,\n dispenserAddress,\n dispenserParams.maxTokens,\n dispenserParams.maxBalance,\n dispenserParams.withMint,\n dispenserParams.allowedSwapper\n )\n\n // Call createFixedRate contract method\n const trxReceipt = await dtContract.methods\n .createDispenser(\n dispenserAddress,\n dispenserParams.maxTokens,\n dispenserParams.maxBalance,\n dispenserParams.withMint,\n dispenserParams.allowedSwapper\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Mint\n * @param {String} dtAddress Datatoken address\n * @param {String} address Minter address\n * @param {String} amount Number of datatokens, as number. Will be converted to wei\n * @param {String} toAddress only if toAddress is different from the minter\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async mint(\n dtAddress: string,\n address: string,\n amount: string,\n toAddress?: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.getDTPermissions(dtAddress, address)).minter !== true) {\n throw new Error(`Caller is not Minter`)\n }\n\n const capAvailble = await this.getCap(dtAddress)\n if (new Decimal(capAvailble).gte(amount)) {\n const estGas = await estimateGas(\n address,\n dtContract.methods.mint,\n toAddress || address,\n this.web3.utils.toWei(amount)\n )\n\n // Call mint contract method\n const trxReceipt = await dtContract.methods\n .mint(toAddress || address, this.web3.utils.toWei(amount))\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } else {\n throw new Error(`Mint amount exceeds cap available`)\n }\n }\n\n /**\n * Estimate gas cost for addMinter method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} minter User which is going to be a Minter\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddMinter(\n dtAddress: string,\n address: string,\n minter: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.addMinter, minter)\n }\n\n /**\n * Add Minter for an ERC20 datatoken\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} minter User which is going to be a Minter\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async addMinter(\n dtAddress: string,\n address: string,\n minter: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.isERC20Deployer(dtAddress, address)) !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n // Estimate gas cost for addMinter method\n const estGas = await estimateGas(address, dtContract.methods.addMinter, minter)\n\n // Call addMinter function of the contract\n const trxReceipt = await dtContract.methods.addMinter(minter).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas for removeMinter method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} minter User which will be removed from Minter permission\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveMinter(\n dtAddress: string,\n address: string,\n minter: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n // should check ERC20Deployer role using erc721 level ..\n\n return estimateGas(address, dtContract.methods.removeMinter, minter)\n }\n\n /**\n * Revoke Minter permission for an ERC20 datatoken\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} minter User which will be removed from Minter permission\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async removeMinter(\n dtAddress: string,\n address: string,\n minter: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.isERC20Deployer(dtAddress, address)) !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n\n const estGas = await estimateGas(address, dtContract.methods.removeMinter, minter)\n\n // Call dtContract function of the contract\n const trxReceipt = await dtContract.methods.removeMinter(minter).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas for addPaymentManager method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} paymentManager User which is going to be a Minter\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddPaymentManager(\n dtAddress: string,\n address: string,\n paymentManager: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.addPaymentManager, paymentManager)\n }\n\n /**\n * Add addPaymentManager (can set who's going to collect fee when consuming orders)\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} paymentManager User which is going to be a Minter\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async addPaymentManager(\n dtAddress: string,\n address: string,\n paymentManager: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.isERC20Deployer(dtAddress, address)) !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.addPaymentManager,\n paymentManager\n )\n\n // Call addPaymentManager function of the contract\n const trxReceipt = await dtContract.methods.addPaymentManager(paymentManager).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas for removePaymentManager method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} paymentManager User which will be removed from paymentManager permission\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemovePaymentManager(\n dtAddress: string,\n address: string,\n paymentManager: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.removePaymentManager, paymentManager)\n }\n\n /**\n * Revoke paymentManager permission for an ERC20 datatoken\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} paymentManager User which will be removed from paymentManager permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removePaymentManager(\n dtAddress: string,\n address: string,\n paymentManager: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.isERC20Deployer(dtAddress, address)) !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.removePaymentManager,\n paymentManager\n )\n\n // Call removeFeeManager function of the contract\n const trxReceipt = await dtContract.methods\n .removePaymentManager(paymentManager)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas for setPaymentCollector method\n * @param dtAddress datatoken address\n * @param address Caller address\n * @param paymentCollector User to be set as new payment collector\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetPaymentCollector(\n dtAddress: string,\n address: string,\n paymentCollector: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.setPaymentCollector, paymentCollector)\n }\n\n /**\n * This function allows to set a new PaymentCollector (receives DT when consuming)\n * If not set the paymentCollector is the NFT Owner\n * only NFT owner can call\n * @param dtAddress datatoken address\n * @param address Caller address\n * @param paymentCollector User to be set as new payment collector\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async setPaymentCollector(\n dtAddress: string,\n address: string,\n paymentCollector: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const isPaymentManager = (await this.getDTPermissions(dtAddress, address))\n .paymentManager\n const nftAddress = !isPaymentManager && (await this.getNFTAddress(dtAddress))\n const isNftOwner = nftAddress && (await this.nft.getNftOwner(nftAddress)) === address\n const nftPermissions =\n nftAddress && !isNftOwner && (await this.nft.getNftPermissions(nftAddress, address))\n const isErc20Deployer = nftPermissions?.deployERC20\n if (!isPaymentManager && !isNftOwner && !isErc20Deployer) {\n throw new Error(`Caller is not Fee Manager, owner or erc20 Deployer`)\n }\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.setPaymentCollector,\n paymentCollector\n )\n\n // Call setFeeCollector method of the contract\n const trxReceipt = await dtContract.methods\n .setPaymentCollector(paymentCollector)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** getPaymentCollector - It returns the current paymentCollector\n * @param dtAddress datatoken address\n * @return {Promise<string>}\n */\n public async getPaymentCollector(dtAddress: string): Promise<string> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const paymentCollector = await dtContract.methods.getPaymentCollector().call()\n return paymentCollector\n }\n\n /**\n * Transfer as number from address to toAddress\n * @param {String} dtAddress Datatoken address\n * @param {String} toAddress Receiver address\n * @param {String} amount Number of datatokens, as number. To be converted to wei.\n * @param {String} address User adress\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async transfer(\n dtAddress: string,\n toAddress: string,\n amount: string,\n address: string\n ): Promise<TransactionReceipt> {\n const weiAmount = this.web3.utils.toWei(amount)\n return this.transferWei(dtAddress, toAddress, weiAmount, address)\n }\n\n /**\n * Estimate gas for transfer method\n * @param {String} dtAddress Datatoken address\n * @param {String} toAddress Receiver address\n * @param {String} amount Number of datatokens, as number. Expressed as wei\n * @param {String} address User adress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasTransfer(\n dtAddress: string,\n toAddress: string,\n amount: string,\n address: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.transfer, toAddress, amount)\n }\n\n /**\n * Transfer in wei from address to toAddress\n * @param {String} dtAddress Datatoken address\n * @param {String} toAddress Receiver address\n * @param {String} amount Number of datatokens, as number. Expressed as wei\n * @param {String} address User adress\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async transferWei(\n dtAddress: string,\n toAddress: string,\n amount: string,\n address: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n try {\n const estGas = await estimateGas(\n address,\n dtContract.methods.transfer,\n toAddress,\n amount\n )\n // Call transfer function of the contract\n const trxReceipt = await dtContract.methods.transfer(toAddress, amount).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to transfer tokens: ${e.message}`)\n throw new Error(`Failed Failed to transfer tokens: ${e.message}`)\n }\n }\n\n /** Estimate gas cost for startOrder method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {String} consumer Consumer Address\n * @param {Number} serviceIndex Service index in the metadata\n * @param {providerFees} providerFees provider fees\n * @param {consumeMarketFee} ConsumeMarketFee consume market fees\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasStartOrder(\n dtAddress: string,\n address: string,\n consumer: string,\n serviceIndex: number,\n providerFees: ProviderFees,\n consumeMarketFee?: ConsumeMarketFee,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(\n address,\n dtContract.methods.startOrder,\n consumer,\n serviceIndex,\n providerFees,\n consumeMarketFee\n )\n }\n\n /** Start Order: called by payer or consumer prior ordering a service consume on a marketplace.\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {String} consumer Consumer Address\n * @param {Number} serviceIndex Service index in the metadata\n * @param {providerFees} providerFees provider fees\n * @param {consumeMarketFee} ConsumeMarketFee consume market fees\n * @return {Promise<TransactionReceipt>} string\n */\n public async startOrder(\n dtAddress: string,\n address: string,\n consumer: string,\n serviceIndex: number,\n providerFees: ProviderFees,\n consumeMarketFee?: ConsumeMarketFee\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n if (!consumeMarketFee) {\n consumeMarketFee = {\n consumeMarketFeeAddress: ZERO_ADDRESS,\n consumeMarketFeeToken: ZERO_ADDRESS,\n consumeMarketFeeAmount: '0'\n }\n }\n try {\n const estGas = await estimateGas(\n address,\n dtContract.methods.startOrder,\n consumer,\n serviceIndex,\n providerFees,\n consumeMarketFee\n )\n\n const trxReceipt = await dtContract.methods\n .startOrder(consumer, serviceIndex, providerFees, consumeMarketFee)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to start order : ${e.message}`)\n throw new Error(`Failed to start order: ${e.message}`)\n }\n }\n\n /** Estimate gas cost for reuseOrder method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {String} orderTxId previous valid order\n * @param {providerFees} providerFees provider fees\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasReuseOrder(\n dtAddress: string,\n address: string,\n orderTxId: string,\n providerFees: ProviderFees,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.reuseOrder, orderTxId, providerFees)\n }\n\n /** Reuse Order: called by payer or consumer having a valid order, but with expired provider access.\n * Pays the provider fee again, but it will not require a new datatoken payment\n * Requires previous approval of provider fee.\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {String} orderTxId previous valid order\n * @param {providerFees} providerFees provider fees\n * @return {Promise<TransactionReceipt>} string\n */\n public async reuseOrder(\n dtAddress: string,\n address: string,\n orderTxId: string,\n providerFees: ProviderFees\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n try {\n const estGas = await estimateGas(\n address,\n dtContract.methods.reuseOrder,\n orderTxId,\n providerFees\n )\n\n const trxReceipt = await dtContract.methods\n .reuseOrder(orderTxId, providerFees)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to call reuse order order : ${e.message}`)\n throw new Error(`Failed to start order: ${e.message}`)\n }\n }\n\n /** Estimate gas cost for buyFromFreAndOrder method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {OrderParams} orderParams Consumer Address\n * @param {FreParams} freParams Amount of tokens that is going to be transfered\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasBuyFromFreAndOrder(\n dtAddress: string,\n address: string,\n orderParams: OrderParams,\n freParams: FreOrderParams,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n new this.web3.eth.Contract(this.datatokensEnterpriseAbi, dtAddress)\n\n return estimateGas(\n address,\n dtContract.methods.buyFromFreAndOrder,\n orderParams,\n freParams\n )\n }\n\n /** Buys 1 DT from the FRE and then startsOrder, while burning that DT\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {OrderParams} orderParams Consumer Address\n * @param {FreParams} freParams Amount of tokens that is going to be transfered\n * @return {Promise<TransactionReceipt>}\n */\n public async buyFromFreAndOrder(\n dtAddress: string,\n address: string,\n orderParams: OrderParams,\n freParams: FreOrderParams\n ): Promise<TransactionReceipt> {\n const dtContract = new this.web3.eth.Contract(this.datatokensEnterpriseAbi, dtAddress)\n try {\n const freContractParams = getFreOrderParams(freParams)\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.buyFromFreAndOrder,\n orderParams,\n freContractParams\n )\n\n const trxReceipt = await dtContract.methods\n .buyFromFreAndOrder(orderParams, freContractParams)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to buy DT From Fre And Order : ${e.message}`)\n throw new Error(`Failed to buy DT From Fre And Order: ${e.message}`)\n }\n }\n\n /** Estimate gas cost for buyFromFreAndOrder method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {OrderParams} orderParams\n * @param {String} dispenserContract\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasBuyFromDispenserAndOrder(\n dtAddress: string,\n address: string,\n orderParams: OrderParams,\n dispenserContract: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n new this.web3.eth.Contract(this.datatokensEnterpriseAbi, dtAddress)\n\n return estimateGas(\n address,\n dtContract.methods.buyFromDispenserAndOrder,\n orderParams,\n dispenserContract\n )\n }\n\n /** Gets DT from dispenser and then startsOrder, while burning that DT\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {OrderParams} orderParams\n * @param {String} dispenserContract\n * @return {Promise<TransactionReceipt>}\n */\n public async buyFromDispenserAndOrder(\n dtAddress: string,\n address: string,\n orderParams: OrderParams,\n dispenserContract: string\n ): Promise<TransactionReceipt> {\n const dtContract = new this.web3.eth.Contract(this.datatokensEnterpriseAbi, dtAddress)\n try {\n const estGas = await estimateGas(\n address,\n dtContract.methods.buyFromDispenserAndOrder,\n orderParams,\n dispenserContract\n )\n\n const trxReceipt = await dtContract.methods\n .buyFromDispenserAndOrder(orderParams, dispenserContract)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to buy DT From Fre And Order : ${e.message}`)\n throw new Error(`Failed to buy DT From Fre And Order: ${e.message}`)\n }\n }\n\n /** Estimate gas for setData method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} value Data to be stored into 725Y standard\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetData(\n dtAddress: string,\n address: string,\n value: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.setData, value)\n }\n\n /** setData\n * This function allows to store data with a preset key (keccak256(ERC20Address)) into NFT 725 Store\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} value Data to be stored into 725Y standard\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async setData(\n dtAddress: string,\n address: string,\n value: string\n ): Promise<TransactionReceipt> {\n if (!(await this.isERC20Deployer(dtAddress, address))) {\n throw new Error(`User is not ERC20 Deployer`)\n }\n\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n const estGas = await estimateGas(address, dtContract.methods.setData, value)\n\n // Call setData function of the contract\n const trxReceipt = await dtContract.methods.setData(value).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas for cleanPermissions method\n * @param dtAddress Datatoken address where we want to clean permissions\n * @param address User adress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCleanPermissions(\n dtAddress: string,\n address: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.cleanPermissions)\n }\n\n /**\n * Clean erc20level Permissions (minters, paymentManager and reset the paymentCollector) for an ERC20 datatoken\n * Only NFT Owner (at 721 level) can call it.\n * @param dtAddress Datatoken address where we want to clean permissions\n * @param address User adress\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async cleanPermissions(\n dtAddress: string,\n address: string\n ): Promise<TransactionReceipt> {\n if ((await this.nft.getNftOwner(await this.getNFTAddress(dtAddress))) !== address) {\n throw new Error('Caller is NOT Nft Owner')\n }\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n const estGas = await estimateGas(address, dtContract.methods.cleanPermissions)\n\n // Call cleanPermissions function of the contract\n const trxReceipt = await dtContract.methods.cleanPermissions().send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Returns ERC20 user's permissions for a datatoken\n * @param {String} dtAddress Datatoken adress\n * @param {String} address user adress\n * @return {Promise<Roles>}\n */\n public async getDTPermissions(dtAddress: string, address: string): Promise<Roles> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const roles = await dtContract.methods.permissions(address).call()\n return roles\n }\n\n /** Returns the Datatoken capital\n * @param {String} dtAddress Datatoken adress\n * @return {Promise<string>}\n */\n public async getCap(dtAddress: string): Promise<string> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const cap = await dtContract.methods.cap().call()\n return this.web3.utils.fromWei(cap)\n }\n\n /** It returns the token decimals, how many supported decimal points\n * @param {String} dtAddress Datatoken adress\n * @return {Promise<number>}\n */\n public async getDecimals(dtAddress: string): Promise<string> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const decimals = await dtContract.methods.decimals().call()\n return decimals\n }\n\n /** It returns the token decimals, how many supported decimal points\n * @param {String} dtAddress Datatoken adress\n * @return {Promise<number>}\n */\n public async getNFTAddress(dtAddress: string): Promise<string> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const nftAddress = await dtContract.methods.getERC721Address().call()\n return nftAddress\n }\n\n /** Returns true if address has deployERC20 role\n * @param {String} dtAddress Datatoken adress\n * @param {String} dtAddress Datatoken adress\n * @return {Promise<boolean>}\n */\n public async isERC20Deployer(dtAddress: string, address: string): Promise<boolean> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const isERC20Deployer = await dtContract.methods.isERC20Deployer(address).call()\n return isERC20Deployer\n }\n\n /**\n * Get Address Balance for datatoken\n * @param {String} dtAddress Datatoken adress\n * @param {String} address user adress\n * @return {Promise<String>} balance Number of datatokens. Will be converted from wei\n */\n public async balance(datatokenAddress: string, address: string): Promise<string> {\n const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, {\n from: address\n })\n const balance = await dtContract.methods.balanceOf(address).call()\n return this.web3.utils.fromWei(balance)\n }\n\n /**\n * @dev estGasSetPublishingMarketFee\n * Estimating gas for publishMarketFeeAddress method\n * @param {string} datatokenAddress Datatoken adress\n * @param {string} publishMarketFeeAddress new publish Market Fee Address\n * @param {string} publishMarketFeeToken new publish Market Fee Token\n * @param {string} publishMarketFeeAmount new fee amount\n * @param {String} address user adress\n */\n public async estGasSetPublishingMarketFee(\n datatokenAddress: string,\n publishMarketFeeAddress: string,\n publishMarketFeeToken: string,\n publishMarketFeeAmount: string,\n address: string\n ): Promise<number> {\n // Estimate gas cost for publishMarketFeeAddress method\n const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, {\n from: address\n })\n return estimateGas(\n address,\n dtContract.methods.setPublishingMarketFee,\n publishMarketFeeAddress,\n publishMarketFeeToken,\n publishMarketFeeAmount\n )\n }\n\n /**\n * @dev setPublishingMarketFee\n * Only publishMarketFeeAddress can call it\n * This function allows to set the fee required by the publisherMarket\n * @param {string} datatokenAddress Datatoken adress\n * @param {string} publishMarketFeeAddress new publish Market Fee Address\n * @param {string} publishMarketFeeToken new publish Market Fee Token\n * @param {string} publishMarketFeeAmount new fee amount\n * @param {String} address user adress\n */\n public async setPublishingMarketFee(\n datatokenAddress: string,\n publishMarketFeeAddress: string,\n publishMarketFeeToken: string,\n publishMarketFeeAmount: string,\n address: string\n ) {\n const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, {\n from: address\n })\n const mktFeeAddress = (await dtContract.methods.getPublishingMarketFee().call())[0]\n if (mktFeeAddress !== address) {\n throw new Error(`Caller is not the Publishing Market Fee Address`)\n }\n const estGas = await this.estGasSetPublishingMarketFee(\n datatokenAddress,\n publishMarketFeeAddress,\n publishMarketFeeToken,\n publishMarketFeeAmount,\n address\n )\n await dtContract.methods\n .setPublishingMarketFee(\n publishMarketFeeAddress,\n publishMarketFeeToken,\n publishMarketFeeAmount\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n }\n\n /**\n * @dev getPublishingMarketFee\n * Get publishingMarket Fee\n * This function allows to get the current fee set by the publishing market\n * @param {String} datatokenAddress Datatoken adress\n * @param {String} address user adress\n * @return {Promise<PublishingMarketFee>} Current fee set by the publishing market\n */\n public async getPublishingMarketFee(\n datatokenAddress: string,\n address: string\n ): Promise<PublishingMarketFee> {\n const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, {\n from: address\n })\n\n const publishingMarketFee = await dtContract.methods.getPublishingMarketFee().call()\n const returnValues = {\n publishMarketFeeAddress: publishingMarketFee[0],\n publishMarketFeeToken: publishingMarketFee[1],\n publishMarketFeeAmount: publishingMarketFee[2]\n }\n return returnValues\n }\n}\n","import { Contract } from 'web3-eth-contract'\nimport Web3 from 'web3'\nimport { TransactionReceipt } from 'web3-core'\nimport { AbiItem } from 'web3-utils'\nimport defaultFactory721Abi from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json'\nimport {\n LoggerInstance,\n getFairGasPrice,\n generateDtName,\n getFreCreationParams,\n getErcCreationParams,\n getPoolCreationParams,\n setContractDefaults,\n estimateGas,\n ZERO_ADDRESS,\n ConfigHelper\n} from '../utils'\nimport { Config } from '../models/index.js'\nimport {\n ProviderFees,\n FreCreationParams,\n Erc20CreateParams,\n PoolCreationParams,\n DispenserCreationParams,\n ConsumeMarketFee\n} from '../@types/index.js'\n\ninterface Template {\n templateAddress: string\n isActive: boolean\n}\n\nexport interface TokenOrder {\n tokenAddress: string\n consumer: string\n serviceIndex: number\n _providerFee: ProviderFees\n _consumeMarketFee: ConsumeMarketFee\n}\n\nexport interface NftCreateData {\n name: string\n symbol: string\n templateIndex: number\n tokenURI: string\n transferable: boolean\n owner: string\n}\n\n/**\n * Provides an interface for NFT Factory contract\n */\nexport class NftFactory {\n public factory721Address: string\n public factory721Abi: AbiItem | AbiItem[]\n public web3: Web3\n public config: Config\n public factory721: Contract\n\n /**\n * Instantiate Datatokens.\n * @param {String} factory721Address\n * @param {AbiItem | AbiItem[]} factory721ABI\n * @param {Web3} web3\n */\n constructor(\n factory721Address: string,\n web3: Web3,\n network?: string | number,\n factory721Abi?: AbiItem | AbiItem[],\n config?: Config\n ) {\n this.factory721Address = factory721Address\n this.factory721Abi = factory721Abi || (defaultFactory721Abi.abi as AbiItem[])\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n this.factory721 = setContractDefaults(\n new this.web3.eth.Contract(this.factory721Abi, this.factory721Address),\n this.config\n )\n }\n\n /**\n * Get estimated gas cost for deployERC721Contract value\n * @param {String} address\n * @param {String} nftData\n * @return {Promise<string>} NFT datatoken address\n */\n public async estGasCreateNFT(address: string, nftData: NftCreateData): Promise<string> {\n return estimateGas(\n address,\n this.factory721.methods.deployERC721Contract,\n nftData.name,\n nftData.symbol,\n nftData.templateIndex,\n ZERO_ADDRESS,\n ZERO_ADDRESS,\n nftData.tokenURI,\n nftData.transferable,\n nftData.owner\n )\n }\n\n /**\n * Create new NFT\n * @param {String} address\n * @param {NFTCreateData} nftData\n * @return {Promise<string>} NFT datatoken address\n */\n public async createNFT(address: string, nftData: NftCreateData): Promise<string> {\n if (!nftData.templateIndex) nftData.templateIndex = 1\n\n if (!nftData.name || !nftData.symbol) {\n const { name, symbol } = generateDtName()\n nftData.name = name\n nftData.symbol = symbol\n }\n if (nftData.templateIndex > (await this.getCurrentNFTTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (nftData.templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n if ((await this.getNFTTemplate(nftData.templateIndex)).isActive === false) {\n throw new Error(`Template is not active`)\n }\n const estGas = await estimateGas(\n address,\n this.factory721.methods.deployERC721Contract,\n nftData.name,\n nftData.symbol,\n nftData.templateIndex,\n ZERO_ADDRESS,\n ZERO_ADDRESS,\n nftData.tokenURI,\n nftData.transferable,\n nftData.owner\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .deployERC721Contract(\n nftData.name,\n nftData.symbol,\n nftData.templateIndex,\n ZERO_ADDRESS,\n ZERO_ADDRESS,\n nftData.tokenURI,\n nftData.transferable,\n nftData.owner\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n let tokenAddress = null\n try {\n tokenAddress = trxReceipt.events.NFTCreated.returnValues[0]\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to create datatoken : ${e.message}`)\n }\n return tokenAddress\n }\n\n /** Get Current NFT Count (NFT created)\n * @return {Promise<number>} Number of NFT created from this factory\n */\n public async getCurrentNFTCount(): Promise<number> {\n const trxReceipt = await this.factory721.methods.getCurrentNFTCount().call()\n return trxReceipt\n }\n\n /** Get Current Datatoken Count\n * @return {Promise<number>} Number of DTs created from this factory\n */\n public async getCurrentTokenCount(): Promise<number> {\n const trxReceipt = await this.factory721.methods.getCurrentTokenCount().call()\n return trxReceipt\n }\n\n /** Get Factory Owner\n * @return {Promise<string>} Factory Owner address\n */\n public async getOwner(): Promise<string> {\n const trxReceipt = await this.factory721.methods.owner().call()\n return trxReceipt\n }\n\n /** Get Current NFT Template Count\n * @return {Promise<number>} Number of NFT Template added to this factory\n */\n public async getCurrentNFTTemplateCount(): Promise<number> {\n const count = await this.factory721.methods.getCurrentNFTTemplateCount().call()\n return count\n }\n\n /** Get Current Template Datatoken (ERC20) Count\n * @return {Promise<number>} Number of ERC20 Template added to this factory\n */\n public async getCurrentTokenTemplateCount(): Promise<number> {\n const count = await this.factory721.methods.getCurrentTemplateCount().call()\n return count\n }\n\n /** Get NFT Template\n * @param {Number} index Template index\n * @return {Promise<Template>} Number of Template added to this factory\n */\n public async getNFTTemplate(index: number): Promise<Template> {\n if (index > (await this.getCurrentNFTTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (index === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n const template = await this.factory721.methods.getNFTTemplate(index).call()\n return template\n }\n\n /** Get Datatoken(erc20) Template\n * @param {Number} index Template index\n * @return {Promise<Template>} DT Template info\n */\n public async getTokenTemplate(index: number): Promise<Template> {\n const template = await this.factory721.methods.getTokenTemplate(index).call()\n return template\n }\n\n /** Check if ERC20 is deployed from the factory\n * @param {String} datatoken Datatoken address we want to check\n * @return {Promise<Boolean>} return true if deployed from this factory\n */\n public async checkDatatoken(datatoken: string): Promise<Boolean> {\n const isDeployed = await this.factory721.methods.erc20List(datatoken).call()\n return isDeployed\n }\n\n /** Check if NFT is deployed from the factory\n * @param {String} nftAddress nftAddress address we want to check\n * @return {Promise<String>} return address(0) if it's not, or the nftAddress if true\n */\n public async checkNFT(nftAddress: string): Promise<String> {\n const confirmAddress = await this.factory721.methods.erc721List(nftAddress).call()\n return confirmAddress\n }\n\n /**\n * Estimate gas cost for add721TokenTemplate method\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddNFTTemplate(\n address: string,\n templateAddress: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.add721TokenTemplate,\n templateAddress\n )\n }\n\n /**\n * Add a new erc721 token template - only factory Owner\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addNFTTemplate(\n address: string,\n templateAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateAddress === ZERO_ADDRESS) {\n throw new Error(`Template cannot be ZERO address`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.add721TokenTemplate,\n templateAddress\n )\n\n // Invoke add721TokenTemplate function of the contract\n const trxReceipt = await this.factory721.methods\n .add721TokenTemplate(templateAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for disable721TokenTemplate method\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to disable\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async estGasDisableNFTTemplate(\n address: string,\n templateIndex: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.disable721TokenTemplate,\n templateIndex\n )\n }\n\n /**\n * Disable token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to disable\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async disableNFTTemplate(\n address: string,\n templateIndex: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateIndex > (await this.getCurrentNFTTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n const estGas = await estimateGas(\n address,\n this.factory721.methods.disable721TokenTemplate,\n templateIndex\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .disable721TokenTemplate(templateIndex)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Reactivate a previously disabled token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to reactivate\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async estGasReactivateNFTTemplate(\n address: string,\n templateIndex: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.reactivate721TokenTemplate,\n templateIndex\n )\n }\n\n /**\n * Reactivate a previously disabled token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to reactivate\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async reactivateNFTTemplate(\n address: string,\n templateIndex: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateIndex > (await this.getCurrentNFTTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.reactivate721TokenTemplate,\n templateIndex\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .reactivate721TokenTemplate(templateIndex)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addTokenTemplate method\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddTokenTemplate(\n address: string,\n templateAddress: string\n ): Promise<any> {\n return estimateGas(address, this.factory721.methods.addTokenTemplate, templateAddress)\n }\n\n /**\n * Add a new erc721 token template - only factory Owner\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addTokenTemplate(\n address: string,\n templateAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateAddress === ZERO_ADDRESS) {\n throw new Error(`Template cannot be address ZERO`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.addTokenTemplate,\n templateAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .addTokenTemplate(templateAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for disableTokenTemplate method\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to disable\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async estGasDisableTokenTemplate(\n address: string,\n templateIndex: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.disableTokenTemplate,\n templateIndex\n )\n }\n\n /**\n * Disable token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to disable\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async disableTokenTemplate(\n address: string,\n templateIndex: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateIndex > (await this.getCurrentTokenTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n if ((await this.getTokenTemplate(templateIndex)).isActive === false) {\n throw new Error(`Template is already disabled`)\n }\n const estGas = await estimateGas(\n address,\n this.factory721.methods.disableTokenTemplate,\n templateIndex\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .disableTokenTemplate(templateIndex)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for reactivateTokenTemplate method\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to reactivate\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async estGasReactivateTokenTemplate(\n address: string,\n templateIndex: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.reactivateTokenTemplate,\n templateIndex\n )\n }\n\n /**\n * Reactivate a previously disabled token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to reactivate\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async reactivateTokenTemplate(\n address: string,\n templateIndex: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateIndex > (await this.getCurrentTokenTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n if ((await this.getTokenTemplate(templateIndex)).isActive === true) {\n throw new Error(`Template is already active`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.reactivateTokenTemplate,\n templateIndex\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .reactivateTokenTemplate(templateIndex)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas cost for startMultipleTokenOrder method\n * @param address Caller address\n * @param orders an array of struct tokenOrder\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estGasStartMultipleTokenOrder(\n address: string,\n orders: TokenOrder[]\n ): Promise<any> {\n return estimateGas(address, this.factory721.methods.startMultipleTokenOrder, orders)\n }\n\n /**\n * @dev startMultipleTokenOrder\n * Used as a proxy to order multiple services\n * Users can have inifinite approvals for fees for factory instead of having one approval/ erc20 contract\n * Requires previous approval of all :\n * - consumeFeeTokens\n * - publishMarketFeeTokens\n * - erc20 datatokens\n * @param address Caller address\n * @param orders an array of struct tokenOrder\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async startMultipleTokenOrder(\n address: string,\n orders: TokenOrder[]\n ): Promise<TransactionReceipt> {\n if (orders.length > 50) {\n throw new Error(`Too many orders`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.startMultipleTokenOrder,\n orders\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .startMultipleTokenOrder(orders)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for createNftWithErc20 method\n * @param address Caller address\n * @param _NftCreateData input data for nft creation\n * @param _ErcCreateData input data for erc20 creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n\n public async estGasCreateNftWithErc20(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams\n ): Promise<any> {\n const ercCreateData = getErcCreationParams(ercParams)\n return estimateGas(\n address,\n this.factory721.methods.createNftWithErc20,\n nftCreateData,\n ercCreateData\n )\n }\n\n /**\n * @dev createNftWithErc20\n * Creates a new NFT, then a ERC20,all in one call\n * @param address Caller address\n * @param _NftCreateData input data for nft creation\n * @param _ErcCreateData input data for erc20 creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n\n public async createNftWithErc20(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams\n ): Promise<TransactionReceipt> {\n const ercCreateData = getErcCreationParams(ercParams)\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.createNftWithErc20,\n nftCreateData,\n ercCreateData\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .createNftWithErc20(nftCreateData, ercCreateData)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for createNftErc20WithPool method\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param poolParams input data for Pool Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estGasCreateNftErc20WithPool(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n poolParams: PoolCreationParams\n ): Promise<any> {\n const ercCreateData = getErcCreationParams(ercParams)\n const poolData = await getPoolCreationParams(this.web3, poolParams)\n return estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithPool,\n nftCreateData,\n ercCreateData,\n poolData\n )\n }\n\n /**\n * @dev createNftErc20WithPool\n * Creates a new NFT, then a ERC20, then a Pool, all in one call\n * Use this carefully, because if Pool creation fails, you are still going to pay a lot of gas\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param poolParams input data for Pool Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async createNftErc20WithPool(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n poolParams: PoolCreationParams\n ): Promise<TransactionReceipt> {\n const ercCreateData = getErcCreationParams(ercParams)\n const poolData = await getPoolCreationParams(this.web3, poolParams)\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithPool,\n nftCreateData,\n ercCreateData,\n poolData\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .createNftWithErc20WithPool(nftCreateData, ercCreateData, poolData)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas cost for createNftErc20WithFixedRate method\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param freParams input data for FixedRate Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estGasCreateNftErc20WithFixedRate(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n freParams: FreCreationParams\n ): Promise<any> {\n const ercCreateData = getErcCreationParams(ercParams)\n const fixedData = await getFreCreationParams(freParams)\n return estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithFixedRate,\n nftCreateData,\n ercCreateData,\n fixedData\n )\n }\n\n /**\n * @dev createNftErc20WithFixedRate\n * Creates a new NFT, then a ERC20, then a FixedRateExchange, all in one call\n * Use this carefully, because if Fixed Rate creation fails, you are still going to pay a lot of gas\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param freParams input data for FixedRate Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async createNftErc20WithFixedRate(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n freParams: FreCreationParams\n ): Promise<TransactionReceipt> {\n const ercCreateData = getErcCreationParams(ercParams)\n const fixedData = getFreCreationParams(freParams)\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithFixedRate,\n nftCreateData,\n ercCreateData,\n fixedData\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .createNftWithErc20WithFixedRate(nftCreateData, ercCreateData, fixedData)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas cost for createNftErc20WithFixedRate method\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param dispenserParams input data for Dispenser Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estGasCreateNftErc20WithDispenser(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n dispenserParams: DispenserCreationParams\n ): Promise<any> {\n const ercCreateData = getErcCreationParams(ercParams)\n return estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithDispenser,\n nftCreateData,\n ercCreateData,\n dispenserParams\n )\n }\n\n /**\n * @dev createNftErc20WithDispenser\n * Creates a new NFT, then a ERC20, then a Dispenser, all in one call\n * Use this carefully, because if Dispenser creation fails, you are still going to pay a lot of gas\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param dispenserParams input data for Dispenser Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async createNftErc20WithDispenser(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n dispenserParams: DispenserCreationParams\n ): Promise<TransactionReceipt> {\n const ercCreateData = getErcCreationParams(ercParams)\n\n dispenserParams.maxBalance = Web3.utils.toWei(dispenserParams.maxBalance)\n dispenserParams.maxTokens = Web3.utils.toWei(dispenserParams.maxTokens)\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithDispenser,\n nftCreateData,\n ercCreateData,\n dispenserParams\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .createNftWithErc20WithDispenser(nftCreateData, ercCreateData, dispenserParams)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n}\n","import { LogLevel } from '../utils/Logger'\nimport { AbiItem } from 'web3-utils/types'\n\nexport class Config {\n /**\n * Ethereum node URL.\n * @type {string}\n */\n public nodeUri?: string\n\n /**\n * Address of Provider.\n * @type {string}\n */\n public providerAddress?: string\n\n /**\n * Metadata Store URL.\n * @type {string}\n */\n public metadataCacheUri?: string\n\n /**\n * Provider URL.\n * @type {string}\n */\n public providerUri?: string\n\n /**\n * Web3 Provider.\n * @type {any}\n */\n public web3Provider?: any\n\n /**\n * Ocean Token address\n * @type {string}\n */\n public oceanTokenAddress?: string\n\n /**\n * Factory address\n * @type {string}\n */\n public erc721FactoryAddress?: string\n\n /**\n * Factory ABI\n * @type {string}\n */\n public erc721FFactoryABI?: AbiItem | AbiItem[]\n\n /**\n * datatokens ABI\n * @type {string}\n */\n public datatokensABI?: AbiItem | AbiItem[]\n\n /**\n * Pool Template address\n * @type {string}\n */\n public poolTemplateAddress?: string\n\n /**\n * Pool Factory ABI\n * @type {string}\n */\n public poolFactoryABI?: AbiItem | AbiItem[]\n\n /**\n * Pool ABI\n * @type {string}\n */\n public poolABI?: AbiItem | AbiItem[]\n\n /**\n * FixedRateExchangeAddress\n * @type {string}\n */\n public fixedRateExchangeAddress?: string\n\n /**\n * FixedRateExchangeAddressABI\n * @type {any}\n */\n public fixedRateExchangeAddressABI?: AbiItem | AbiItem[]\n\n /**\n * DispenserAddress\n * @type {string}\n */\n public dispenserAddress?: string\n\n /**\n * DispenserABI\n * @type {any}\n */\n public dispenserABI?: AbiItem | AbiItem[]\n\n /**\n * OPFCommunityFeeCollector\n * @type {string}\n */\n public opfCommunityFeeCollector?: string\n\n /**\n * SideStaking address\n * @type {string}\n */\n public sideStakingAddress?: string\n\n /**\n * block number of the deployment\n * @type {number}\n */\n public startBlock?: number\n /**\n * Log level.\n * @type {boolean | LogLevel}\n */\n public verbose?: boolean | LogLevel\n\n /**\n * Message shown when the user creates its own token.\n * @type {string}\n */\n public authMessage?: string\n\n /**\n * Token expiration time in ms.\n * @type {number}\n */\n public authTokenExpiration?: number\n\n /**\n * Parity config\n * @type {string}\n */\n public parityUri?: string\n\n public threshold?: number\n\n /**\n * Chain ID\n * @type {number}\n */\n chainId: number\n\n /**\n * Network name ex: mainnet, rinkeby, polygon\n * @type {string}\n */\n network: string\n\n /**\n * Url of the relevant subgraph instance ex: https://subgraph.mainnet.oceanprotocol.com\n * @type {string}\n */\n subgraphUri: string\n\n /**\n * Url of the blockchain exporer ex: https://etherscan.io\n * @type {string}\n */\n explorerUri: string\n\n /**\n * Ocean toke symbol on the chain, it's used just for convenience to reduce number of calls\n * @type {string}\n */\n oceanTokenSymbol: string\n\n /**\n * Specify the transaction Block Timeout\n * @type {number}\n */\n transactionBlockTimeout: number\n\n /**\n * Specify the transaction Confirmation Blocks\n * @type {number}\n */\n transactionConfirmationBlocks: number\n\n /**\n * Specify the transaction Polling Blocks Timeout\n * @type {number}\n */\n transactionPollingTimeout: number\n\n /**\n * Specify the multiplier for the gas fee\n * @type {number}\n */\n gasFeeMultiplier: number\n}\n\nexport default Config\n","import { LoggerInstance } from './Logger'\n\nexport const zeroX = (input: string): string => zeroXTransformer(input, true)\nexport const noZeroX = (input: string): string => zeroXTransformer(input, false)\nexport function zeroXTransformer(input = '', zeroOutput: boolean): string {\n const { valid, output } = inputMatch(input, /^(?:0x)*([a-f0-9]+)$/i, 'zeroXTransformer')\n return (zeroOutput && valid ? '0x' : '') + output\n}\n\n// Shared functions\nfunction inputMatch(\n input: string,\n regexp: RegExp,\n conversorName: string\n): { valid: boolean; output: string } {\n if (typeof input !== 'string') {\n LoggerInstance.debug('Not input string:')\n LoggerInstance.debug(input)\n throw new Error(`[${conversorName}] Expected string, input type: ${typeof input}`)\n }\n const match = input.match(regexp)\n if (!match) {\n LoggerInstance.warn(`[${conversorName}] Input transformation failed.`)\n return { valid: false, output: input }\n }\n return { valid: true, output: match[1] }\n}\n","import Web3 from 'web3'\nimport { LoggerInstance, getData } from '../utils'\nimport {\n FileMetadata,\n ComputeJob,\n ComputeOutput,\n ComputeAlgorithm,\n ComputeAsset,\n ComputeEnvironment,\n ProviderInitialize,\n ProviderComputeInitializeResults\n} from '../@types/'\nimport { noZeroX } from '../utils/ConversionTypeHelper'\nimport fetch from 'cross-fetch'\nexport interface HttpCallback {\n (httpMethod: string, url: string, body: string, header: any): Promise<any>\n}\n\nexport interface ServiceEndpoint {\n serviceName: string\n method: string\n urlPath: string\n}\nexport interface UserCustomParameters {\n [key: string]: any\n}\n\nexport class Provider {\n /**\n * Returns the provider endpoints\n * @return {Promise<ServiceEndpoint[]>}\n */\n async getEndpoints(providerUri: string): Promise<any> {\n try {\n const endpoints = await getData(providerUri)\n return await endpoints.json()\n } catch (e) {\n LoggerInstance.error('Finding the service endpoints failed:', e)\n return null\n }\n }\n\n getEndpointURL(\n servicesEndpoints: ServiceEndpoint[],\n serviceName: string\n ): ServiceEndpoint {\n if (!servicesEndpoints) return null\n return servicesEndpoints.find((s) => s.serviceName === serviceName) as ServiceEndpoint\n }\n\n /**\n * Returns the service endpoints that exist in provider.\n * @param {any} endpoints\n * @return {Promise<ServiceEndpoint[]>}\n */\n public async getServiceEndpoints(providerEndpoint: string, endpoints: any) {\n const serviceEndpoints: ServiceEndpoint[] = []\n for (const i in endpoints.serviceEndpoints) {\n const endpoint: ServiceEndpoint = {\n serviceName: i,\n method: endpoints.serviceEndpoints[i][0],\n urlPath: providerEndpoint + endpoints.serviceEndpoints[i][1]\n }\n serviceEndpoints.push(endpoint)\n }\n return serviceEndpoints\n }\n\n /** Gets current nonce\n * @param {string} providerUri provider uri address\n * @param {string} consumerAddress Publisher address\n * @param {AbortSignal} signal abort signal\n * @param {string} providerEndpoints Identifier of the asset to be registered in ocean\n * @param {string} serviceEndpoints document description object (DDO)=\n * @return {Promise<string>} urlDetails\n */\n public async getNonce(\n providerUri: string,\n consumerAddress: string,\n signal?: AbortSignal,\n providerEndpoints?: any,\n serviceEndpoints?: ServiceEndpoint[]\n ): Promise<string> {\n if (!providerEndpoints) {\n providerEndpoints = await this.getEndpoints(providerUri)\n }\n if (!serviceEndpoints) {\n serviceEndpoints = await this.getServiceEndpoints(providerUri, providerEndpoints)\n }\n const path = this.getEndpointURL(serviceEndpoints, 'nonce')\n ? this.getEndpointURL(serviceEndpoints, 'nonce').urlPath\n : null\n if (!path) return null\n try {\n const response = await fetch(path + `?userAddress=${consumerAddress}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n return (await response.json()).nonce.toString()\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('HTTP request failed')\n }\n }\n\n public async signProviderRequest(\n web3: Web3,\n accountId: string,\n message: string,\n password?: string\n ): Promise<string> {\n const consumerMessage = web3.utils.soliditySha3({\n t: 'bytes',\n v: web3.utils.utf8ToHex(message)\n })\n const isMetaMask =\n web3 && web3.currentProvider && (web3.currentProvider as any).isMetaMask\n if (isMetaMask)\n return await web3.eth.personal.sign(consumerMessage, accountId, password)\n else return await web3.eth.sign(consumerMessage, accountId)\n }\n\n /** Encrypt data using the Provider's own symmetric key\n * @param {string} data data in json format that needs to be sent , it can either be a DDO or a File array\n * @param {string} providerUri provider uri address\n * @param {AbortSignal} signal abort signal\n * @return {Promise<string>} urlDetails\n */\n public async encrypt(\n data: any,\n providerUri: string,\n signal?: AbortSignal\n ): Promise<string> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const path = this.getEndpointURL(serviceEndpoints, 'encrypt')\n ? this.getEndpointURL(serviceEndpoints, 'encrypt').urlPath\n : null\n if (!path) return null\n try {\n const response = await fetch(path, {\n method: 'POST',\n body: JSON.stringify(data),\n headers: {\n 'Content-Type': 'application/octet-stream'\n },\n signal: signal\n })\n return await response.text()\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('HTTP request failed')\n }\n }\n\n /** Get DDO File details (if possible)\n * @param {string} did did\n * @param {number} serviceId the id of the service for which to check the files\n * @param {string} providerUri uri of the provider that will be used to check the file\n * @param {AbortSignal} signal abort signal\n * @return {Promise<FileMetadata[]>} urlDetails\n */\n public async checkDidFiles(\n did: string,\n serviceId: number,\n providerUri: string,\n signal?: AbortSignal\n ): Promise<FileMetadata[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const args = { did: did, serviceId: serviceId }\n const files: FileMetadata[] = []\n const path = this.getEndpointURL(serviceEndpoints, 'fileinfo')\n ? this.getEndpointURL(serviceEndpoints, 'fileinfo').urlPath\n : null\n if (!path) return null\n try {\n const response = await fetch(path, {\n method: 'POST',\n body: JSON.stringify(args),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const results: FileMetadata[] = await response.json()\n for (const result of results) {\n files.push(result)\n }\n return files\n } catch (e) {\n return null\n }\n }\n\n /** Get URL details (if possible)\n * @param {string} url or did\n * @param {string} providerUri uri of the provider that will be used to check the file\n * @param {AbortSignal} signal abort signal\n * @return {Promise<FileMetadata[]>} urlDetails\n */\n public async checkFileUrl(\n url: string,\n providerUri: string,\n signal?: AbortSignal\n ): Promise<FileMetadata[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const args = { url: url, type: 'url' }\n const files: FileMetadata[] = []\n const path = this.getEndpointURL(serviceEndpoints, 'fileinfo')\n ? this.getEndpointURL(serviceEndpoints, 'fileinfo').urlPath\n : null\n if (!path) return null\n try {\n const response = await fetch(path, {\n method: 'POST',\n body: JSON.stringify(args),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const results: FileMetadata[] = await response.json()\n for (const result of results) {\n files.push(result)\n }\n return files\n } catch (e) {\n return null\n }\n }\n\n /** Get Compute Environments\n * @return {Promise<ComputeEnvironment[]>} urlDetails\n */\n public async getComputeEnvironments(\n providerUri: string,\n signal?: AbortSignal\n ): Promise<ComputeEnvironment[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const path = this.getEndpointURL(serviceEndpoints, 'computeEnvironments')?.urlPath\n if (!path) return null\n try {\n const response = await fetch(path, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const envs: ComputeEnvironment[] = await response.json()\n return envs\n } catch (e) {\n LoggerInstance.error(e.message)\n return null\n }\n }\n\n /** Initialize a service request.\n * @param {DDO | string} asset\n * @param {number} serviceIndex\n * @param {string} serviceType\n * @param {string} consumerAddress\n * @param {UserCustomParameters} userCustomParameters\n * @param {string} providerUri Identifier of the asset to be registered in ocean\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ProviderInitialize>} ProviderInitialize data\n */\n public async initialize(\n did: string,\n serviceId: string,\n fileIndex: number,\n consumerAddress: string,\n providerUri: string,\n signal?: AbortSignal,\n userCustomParameters?: UserCustomParameters,\n computeEnv?: string,\n validUntil?: number\n ): Promise<ProviderInitialize> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n let initializeUrl = this.getEndpointURL(serviceEndpoints, 'initialize')\n ? this.getEndpointURL(serviceEndpoints, 'initialize').urlPath\n : null\n\n if (!initializeUrl) return null\n initializeUrl += `?documentId=${did}`\n initializeUrl += `&serviceId=${serviceId}`\n initializeUrl += `&fileIndex=${fileIndex}`\n initializeUrl += `&consumerAddress=${consumerAddress}`\n if (userCustomParameters)\n initializeUrl += '&userdata=' + encodeURI(JSON.stringify(userCustomParameters))\n if (computeEnv) initializeUrl += '&environment=' + encodeURI(computeEnv)\n if (validUntil) initializeUrl += '&validUntil=' + validUntil\n try {\n const response = await fetch(initializeUrl, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const results: ProviderInitialize = await response.json()\n return results\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('Asset URL not found or not available.')\n }\n }\n\n /** Initialize a compute request.\n * @param {ComputeAsset} assets\n * @param {ComputeAlgorithmber} algorithm\n * @param {string} computeEnv\n * @param {number} validUntil\n * @param {string} providerUri Identifier of the asset to be registered in ocean\n * @param {string} accountId\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ProviderComputeInitialize>} ProviderComputeInitialize data\n */\n public async initializeCompute(\n assets: ComputeAsset[],\n algorithm: ComputeAlgorithm,\n computeEnv: string,\n validUntil: number,\n providerUri: string,\n accountId: string,\n signal?: AbortSignal\n ): Promise<ProviderComputeInitializeResults> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const providerData = {\n datasets: assets,\n algorithm: algorithm,\n compute: {\n env: computeEnv,\n validUntil: validUntil\n },\n consumerAddress: accountId\n }\n const initializeUrl = this.getEndpointURL(serviceEndpoints, 'initializeCompute')\n ? this.getEndpointURL(serviceEndpoints, 'initializeCompute').urlPath\n : null\n if (!initializeUrl) return null\n try {\n const response = await fetch(initializeUrl, {\n method: 'POST',\n body: JSON.stringify(providerData),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const results = await response.json()\n return results\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('ComputeJob cannot be initialized')\n }\n }\n\n /** Gets fully signed URL for download\n * @param {string} did\n * @param {string} accountId\n * @param {string} serviceId\n * @param {number} fileIndex\n * @param {string} providerUri\n * @param {Web3} web3\n * @param {UserCustomParameters} userCustomParameters\n * @return {Promise<string>}\n */\n public async getDownloadUrl(\n did: string,\n accountId: string,\n serviceId: string,\n fileIndex: number,\n transferTxId: string,\n providerUri: string,\n web3: Web3,\n userCustomParameters?: UserCustomParameters\n ): Promise<any> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const downloadUrl = this.getEndpointURL(serviceEndpoints, 'download')\n ? this.getEndpointURL(serviceEndpoints, 'download').urlPath\n : null\n if (!downloadUrl) return null\n const nonce = Date.now()\n const signature = await this.signProviderRequest(web3, accountId, did + nonce)\n let consumeUrl = downloadUrl\n consumeUrl += `?fileIndex=${fileIndex}`\n consumeUrl += `&documentId=${did}`\n consumeUrl += `&transferTxId=${transferTxId}`\n consumeUrl += `&serviceId=${serviceId}`\n consumeUrl += `&consumerAddress=${accountId}`\n consumeUrl += `&nonce=${nonce}`\n consumeUrl += `&signature=${signature}`\n if (userCustomParameters)\n consumeUrl += '&userdata=' + encodeURI(JSON.stringify(userCustomParameters))\n return consumeUrl\n }\n\n /** Instruct the provider to start a compute job\n * @param {string} did\n * @param {string} consumerAddress\n * @param {string} computeEnv\n * @param {ComputeAlgorithm} algorithm\n * @param {string} providerUri\n * @param {Web3} web3\n * @param {AbortSignal} signal abort signal\n * @param {ComputeOutput} output\n * @return {Promise<ComputeJob | ComputeJob[]>}\n */\n public async computeStart(\n providerUri: string,\n web3: Web3,\n consumerAddress: string,\n computeEnv: string,\n dataset: ComputeAsset,\n algorithm: ComputeAlgorithm,\n signal?: AbortSignal,\n additionalDatasets?: ComputeAsset[],\n output?: ComputeOutput\n ): Promise<ComputeJob | ComputeJob[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeStartUrl = this.getEndpointURL(serviceEndpoints, 'computeStart')\n ? this.getEndpointURL(serviceEndpoints, 'computeStart').urlPath\n : null\n\n const nonce = Date.now()\n let signatureMessage = consumerAddress\n signatureMessage += dataset.documentId\n signatureMessage += nonce\n const signature = await this.signProviderRequest(\n web3,\n consumerAddress,\n signatureMessage\n )\n const payload = Object()\n payload.consumerAddress = consumerAddress\n payload.signature = signature\n payload.nonce = nonce\n payload.environment = computeEnv\n payload.dataset = dataset\n payload.algorithm = algorithm\n if (payload.additionalDatasets) payload.additionalDatasets = additionalDatasets\n if (output) payload.output = output\n if (!computeStartUrl) return null\n try {\n const response = await fetch(computeStartUrl, {\n method: 'POST',\n body: JSON.stringify(payload),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n\n if (response?.ok) {\n const params = await response.json()\n return params\n }\n LoggerInstance.error('Compute start failed: ', response.status, response.statusText)\n LoggerInstance.error('Payload was:', payload)\n return null\n } catch (e) {\n LoggerInstance.error('Compute start failed:')\n LoggerInstance.error(e)\n LoggerInstance.error('Payload was:', payload)\n return null\n }\n }\n\n /** Instruct the provider to Stop the execution of a to stop a compute job.\n * @param {string} did\n * @param {string} consumerAddress\n * @param {string} jobId\n * @param {string} providerUri\n * @param {Web3} web3\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ComputeJob | ComputeJob[]>}\n */\n public async computeStop(\n did: string,\n consumerAddress: string,\n jobId: string,\n providerUri: string,\n web3: Web3,\n signal?: AbortSignal\n ): Promise<ComputeJob | ComputeJob[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeStopUrl = this.getEndpointURL(serviceEndpoints, 'computeStop')\n ? this.getEndpointURL(serviceEndpoints, 'computeStop').urlPath\n : null\n\n const nonce = await this.getNonce(\n providerUri,\n consumerAddress,\n signal,\n providerEndpoints,\n serviceEndpoints\n )\n\n let signatureMessage = consumerAddress\n signatureMessage += jobId || ''\n signatureMessage += (did && `${noZeroX(did)}`) || ''\n signatureMessage += nonce\n const signature = await this.signProviderRequest(\n web3,\n consumerAddress,\n signatureMessage\n )\n const payload = Object()\n payload.signature = signature\n payload.documentId = noZeroX(did)\n payload.consumerAddress = consumerAddress\n if (jobId) payload.jobId = jobId\n\n if (!computeStopUrl) return null\n try {\n const response = await fetch(computeStopUrl, {\n method: 'PUT',\n body: JSON.stringify(payload),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n\n if (response?.ok) {\n const params = await response.json()\n return params\n }\n LoggerInstance.error('Compute stop failed:', response.status, response.statusText)\n LoggerInstance.error('Payload was:', payload)\n return null\n } catch (e) {\n LoggerInstance.error('Compute stop failed:')\n LoggerInstance.error(e)\n LoggerInstance.error('Payload was:', payload)\n return null\n }\n }\n\n /** Get compute status for a specific jobId/documentId/owner.\n * @param {string} providerUri The URI of the provider we want to query\n * @param {string} consumerAddress The consumer ethereum address\n * @param {string} jobId The ID of a compute job.\n * @param {string} did The ID of the asset\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ComputeJob | ComputeJob[]>}\n */\n public async computeStatus(\n providerUri: string,\n consumerAddress: string,\n jobId?: string,\n did?: string,\n signal?: AbortSignal\n ): Promise<ComputeJob | ComputeJob[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeStatusUrl = this.getEndpointURL(serviceEndpoints, 'computeStatus')\n ? this.getEndpointURL(serviceEndpoints, 'computeStatus').urlPath\n : null\n\n let url = `?consumerAddress=${consumerAddress}`\n url += (did && `&documentId=${noZeroX(did)}`) || ''\n url += (jobId && `&jobId=${jobId}`) || ''\n\n if (!computeStatusUrl) return null\n try {\n const response = await fetch(computeStatusUrl + url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n if (response?.ok) {\n const params = await response.json()\n return params\n }\n LoggerInstance.error(\n 'Get compute status failed:',\n response.status,\n response.statusText\n )\n return null\n } catch (e) {\n LoggerInstance.error('Get compute status failed')\n LoggerInstance.error(e)\n return null\n }\n }\n\n /** Get compute result url\n * @param {string} providerUri The URI of the provider we want to query\n * @param {Web3} web3 Web3 instance\n * @param {string} consumerAddress The consumer ethereum address\n * @param {string} jobId The ID of a compute job.\n * @param {number} index Result index\n * @return {Promise<string>}\n */\n public async getComputeResultUrl(\n providerUri: string,\n web3: Web3,\n consumerAddress: string,\n jobId: string,\n index: number\n ): Promise<string> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeResultUrl = this.getEndpointURL(serviceEndpoints, 'computeResult')\n ? this.getEndpointURL(serviceEndpoints, 'computeResult').urlPath\n : null\n\n const nonce = Date.now()\n let signatureMessage = consumerAddress\n signatureMessage += jobId\n signatureMessage += index.toString()\n signatureMessage += nonce\n const signature = await this.signProviderRequest(\n web3,\n consumerAddress,\n signatureMessage\n )\n if (!computeResultUrl) return null\n let resultUrl = computeResultUrl\n resultUrl += `?consumerAddress=${consumerAddress}`\n resultUrl += `&jobId=${jobId}`\n resultUrl += `&index=${index.toString()}`\n resultUrl += `&nonce=${nonce}`\n resultUrl += (signature && `&signature=${signature}`) || ''\n return resultUrl\n }\n\n /** Deletes a compute job.\n * @param {string} did\n * @param {string} consumerAddress\n * @param {string} jobId\n * @param {string} providerUri\n * @param {Web3} web3\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ComputeJob | ComputeJob[]>}\n */\n public async computeDelete(\n did: string,\n consumerAddress: string,\n jobId: string,\n providerUri: string,\n web3: Web3,\n signal?: AbortSignal\n ): Promise<ComputeJob | ComputeJob[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeDeleteUrl = this.getEndpointURL(serviceEndpoints, 'computeDelete')\n ? this.getEndpointURL(serviceEndpoints, 'computeDelete').urlPath\n : null\n\n const nonce = await this.getNonce(\n providerUri,\n consumerAddress,\n signal,\n providerEndpoints,\n serviceEndpoints\n )\n\n let signatureMessage = consumerAddress\n signatureMessage += jobId || ''\n signatureMessage += (did && `${noZeroX(did)}`) || ''\n signatureMessage += nonce\n const signature = await this.signProviderRequest(\n web3,\n consumerAddress,\n signatureMessage\n )\n const payload = Object()\n payload.documentId = noZeroX(did)\n payload.consumerAddress = consumerAddress\n payload.jobId = jobId\n if (signature) payload.signature = signature\n\n if (!computeDeleteUrl) return null\n try {\n const response = await fetch(computeDeleteUrl, {\n method: 'DELETE',\n body: JSON.stringify(payload),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n\n if (response?.ok) {\n const params = await response.json()\n return params\n }\n LoggerInstance.error(\n 'Delete compute job failed:',\n response.status,\n response.statusText\n )\n LoggerInstance.error('Payload was:', payload)\n return null\n } catch (e) {\n LoggerInstance.error('Delete compute job failed:')\n LoggerInstance.error(e)\n LoggerInstance.error('Payload was:', payload)\n return null\n }\n }\n\n /** Check for a valid provider at URL\n * @param {String} url provider uri address\n * @param {AbortSignal} signal abort signal\n * @return {Promise<boolean>} string\n */\n public async isValidProvider(url: string, signal?: AbortSignal): Promise<boolean> {\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n if (response?.ok) {\n const params = await response.json()\n if (params && params.providerAddress) return true\n }\n return false\n } catch (error) {\n LoggerInstance.error(`Error validating provider: ${error.message}`)\n return false\n }\n }\n}\n\nexport const ProviderInstance = new Provider()\nexport default ProviderInstance\n"],"names":["LogLevel","Logger","constructor","logLevel","Error","this","setLevel","bypass","args","dispatch","Infinity","debug","Verbose","log","Log","warn","Warn","error","verb","level","console","LoggerInstance","generateDtName","wordList","list","wordListDefault","random1","Math","floor","random","adjectives","length","random2","nouns","indexNumber","adjective","replace","c","toUpperCase","noun","name","symbol","substring","minAbi","constant","inputs","outputs","type","payable","stateMutability","anonymous","indexed","ZERO_ADDRESS","GASLIMIT_DEFAULT","setContractDefaults","contract","config","transactionBlockTimeout","transactionConfirmationBlocks","transactionPollingTimeout","getFairGasPrice","web3","x","BigNumber","eth","getGasPrice","gasFeeMultiplier","multipliedBy","integerValue","ROUND_DOWN","toString","getErcCreationParams","ercParams","templateIndex","strings","addresses","minter","paymentCollector","mpFeeAddress","feeToken","uints","Web3","utils","toWei","cap","feeAmount","bytess","getFreOrderParams","freParams","exchangeContract","exchangeId","maxBaseTokenAmount","swapMarketFee","marketFeeAddress","getFreCreationParams","allowedConsumer","withMint","fixedPriceAddress","fixedRateAddress","baseTokenAddress","owner","marketFeeCollector","baseTokenDecimals","datatokenDecimals","fixedRate","marketFee","getPoolCreationParams","poolParams","ssContract","baseTokenSender","publisherAddress","poolTemplateAddress","ssParams","rate","vestingAmount","vestedBlocks","amountToUnits","initialBaseTokenLiquidity","swapFees","swapFeeLiquidityProvider","swapFeeMarketRunner","unitsToAmount","token","amount","tokenDecimals","tokenContract","Contract","decimals","methods","call","amountFormatted","div","exponentiatedBy","EXPONENTIAL_AT","e","message","times","estimateGas","from","functionToEstimateGas","estimatedGas","apply","err","estGas","fetchData","url","opts","result","fetch","ok","method","text","downloadFileBrowser","anchor","document","createElement","download","href","click","downloadFile","index","response","filename","headers","get","match","split","pop","data","arrayBuffer","getData","postData","payload","async","body","postWithHeaders","configHelperNetworksBase","chainId","network","metadataCacheUri","nodeUri","providerUri","subgraphUri","explorerUri","oceanTokenAddress","oceanTokenSymbol","fixedRateExchangeAddress","dispenserAddress","startBlock","configHelperNetworks","ConfigHelper","getAddressesFromEnv","customAddresses","configAddresses","FixedPrice","Dispenser","Staking","poolTemplate","ERC721Factory","OPFCommunityFeeCollector","Ocean","erc721FactoryAddress","sideStakingAddress","opfCommunityFeeCollector","process","env","AQUARIUS_URI","DefaultContractsAddresses","getConfig","infuraProjectId","filterBy","find","generateDid","erc721Address","toChecksumAddress","sha256","getHash","signHash","address","signedMessage","sign","substr","r","slice","s","v","estApprove","account","tokenAddress","spender","contractInstance","approve","force","currentAllowence","allowance","Decimal","greaterThanOrEqualTo","send","gas","gasPrice","estTransfer","recipient","transfer","trxReceipt","balance","balanceOf","sleep","ms","Promise","resolve","setTimeout","calcMaxExactOut","calcMaxExactIn","getMaxSwapExactOut","poolInstance","poolAddress","getReserve","getMaxSwapExactIn","getMaxAddLiquidity","getMaxRemoveLiquidity","Aquarius","aquariusURL","did","signal","path","json","status","txid","tries","ddo","event","valid","jsonResponse","JSON","stringify","hash","proof","validatorAddress","publicKey","errors","MaxUint256","Pool","poolAbi","PoolTemplate","abi","fromWei","fee","defaultErc20Abi","setSwapFee","pool","getNumTokens","totalSupply","getCurrentTokens","getFinalTokens","getController","getBaseTokenAddress","getDatatokenAddress","getMarketFee","_publishMarketCollector","isBound","getBalance","isFinalized","getSwapFee","weight","getNormalizedWeight","getDenormalizedWeight","getTotalDenormalizedWeight","publishMarketFees","getCurrentOPCFees","communityFees","collectOPC","collectMarketFee","getMarketFeeCollector","newPublishMarketAddress","newPublishMarketSwapFee","updatePublishMarketFee","tokenInOutMarket","amountsInOutMaxFee","poolContract","tokenAmountIn","tokenIn","tokenInDecimals","minAmountOut","tokenOut","tokenOutDecimals","maxPrice","getBaseToken","swapExactAmountIn","maxSwap","greaterThan","maxAmountIn","tokenAmountOut","swapExactAmountOut","minPoolAmountOut","joinswapExternAmountIn","amountInFormatted","poolAmountIn","minTokenAmountOut","exitswapPoolAmountIn","poolDecimals","calcSingleOutGivenPoolIn","minTokenOutFormatted","decimalsTokenIn","decimalsTokenOut","tokenInContract","tokenOutContract","decimalsDiff","price","getSpotPrice","amountOutFormatted","getAmountInExactOut","tokenAmount","liquidityProviderSwapFeeAmount","lpFeeAmount","oceanFeeAmount","publishMarketSwapFeeAmount","consumeMarketSwapFeeAmount","getAmountOutExactIn","calcPoolOutSingleIn","poolAmountOut","calcSingleInPoolOut","calcSingleOutPoolIn","calcPoolInSingleOut","getSwapEventSignature","eventdata","o","encodeEventSignature","getJoinEventSignature","getExitEventSignature","dispenserAbi","dispenserContract","defaultDispenserAbi","dtAdress","maxTokens","maxBalance","logger","dtAddress","allowedSwapper","create","activate","deactivate","newAllowedSwapper","setAllowedSwapper","destination","dispense","ownerWithdraw","datatoken","active","String","isMinter","FixedRateCreateProgressStep","FixedRateExchange","fixedRateExchangeAbi","oceanAddress","fixedRateContract","ssAbi","defaultFixedRateExchangeAbi","baseToken","generateExchangeId","datatokenAddress","dtAmount","consumeMarketAddress","consumeMarketFee","buyDT","datatokenAmount","exchange","getExchange","consumeMarketFeeFormatted","dtAmountFormatted","dtDecimals","maxBtFormatted","btDecimals","sellDT","minBaseTokenAmount","minBtFormatted","getNumberOfExchanges","newRate","setRate","toggleExchangeState","weiRate","getRate","dtSupply","getDTSupply","btSupply","getBTSupply","getAllowedSwapper","fixedRateExchange","calcBaseInGivenOutDT","baseTokenAmount","marketFeeAmount","consumeMarketFeeAmount","calcBaseOutGivenInDT","dtBalance","btBalance","getFeesInfo","opcFee","marketFeeAvailable","oceanFeeAvailable","getExchanges","isActive","toggleMintState","fixedrate","amountWei","collectBT","collectDT","collectOceanFee","opcCollector","router","exchangeOwner","newMarketFee","updateMarketFee","newMarketFeeCollector","updateMarketFeeCollector","SideStaking","SideStakingTemplate","ssAddress","sideStaking","getDatatokenCirculatingSupply","getDatatokenCurrentCirculatingSupply","getPublisherAddress","getPoolAddress","getBaseTokenBalance","getDatatokenBalance","getvestingEndBlock","getvestingAmount","getvestingLastBlock","getvestingAmountSoFar","getVesting","swapFee","setPoolSwapFee","Router","routerAddress","RouterAbi","defaultRouter","operations","buyDTBatch","isApprovedToken","isSSContract","isFixedRateContract","routerOwner","factory","isPoolTemplate","addApprovedToken","getOwner","removeApprovedToken","addSSContract","removeSSContract","addFixedRateContract","removeFixedRateContract","addDispenserContract","removeDispenserContract","getOPCFee","swapOceanFee","newSwapOceanFee","newSwapNonOceanFee","newConsumeFee","newProviderFee","updateOPCFee","templateAddress","addPoolTemplate","removePoolTemplate","Nft","nftAbi","factory721Address","factory721Abi","defaultNftAbi","nftAddress","createERC20","getNftPermissions","deployERC20","nftContract","events","TokenCreated","returnValues","manager","addManager","getNftOwner","removeManager","erc20Deployer","addToCreateERC20List","removeFromCreateERC20List","metadataUpdater","addToMetadataList","removeFromMetadataList","updateMetadata","esGasRemoveMetadataUpdater","storeUpdater","addTo725StoreList","removeFrom725StoreList","store","cleanPermissions","nftOwner","nftReceiver","tokenId","transferFrom","tokenIdentifier","safeTransferFrom","metadataState","metadataDecryptorUrl","metadataDecryptorAddress","flags","metadataHash","metadataProofs","setMetaData","metadataAndTokenURI","sanitizedMetadataAndTokenURI","setMetaDataAndTokenURI","setMetaDataState","setTokenURI","ownerOf","getPermissions","getMetaData","isERC20Deployer","key","id","tokenURI","Datatoken","datatokensAbi","datatokensEnterpriseAbi","factoryAddress","factoryABI","nft","defaultDatatokensAbi","defaultDatatokensEnterpriseAbi","dtContract","toAddress","mint","fixedRateParams","createFixedRate","dispenserParams","createDispenser","getDTPermissions","capAvailble","getCap","gte","addMinter","removeMinter","paymentManager","addPaymentManager","removePaymentManager","setPaymentCollector","isPaymentManager","getNFTAddress","isNftOwner","nftPermissions","getPaymentCollector","weiAmount","transferWei","consumer","serviceIndex","providerFees","startOrder","consumeMarketFeeAddress","consumeMarketFeeToken","orderTxId","reuseOrder","orderParams","buyFromFreAndOrder","freContractParams","buyFromDispenserAndOrder","value","setData","permissions","getERC721Address","publishMarketFeeAddress","publishMarketFeeToken","publishMarketFeeAmount","setPublishingMarketFee","getPublishingMarketFee","estGasSetPublishingMarketFee","publishingMarketFee","NftFactory","factory721","defaultFactory721Abi","nftData","deployERC721Contract","transferable","getCurrentNFTTemplateCount","getNFTTemplate","NFTCreated","getCurrentNFTCount","getCurrentTokenCount","getCurrentTemplateCount","getTokenTemplate","erc20List","erc721List","add721TokenTemplate","disable721TokenTemplate","reactivate721TokenTemplate","addTokenTemplate","disableTokenTemplate","getCurrentTokenTemplateCount","reactivateTokenTemplate","orders","startMultipleTokenOrder","nftCreateData","ercCreateData","createNftWithErc20","poolData","createNftWithErc20WithPool","fixedData","createNftWithErc20WithFixedRate","createNftWithErc20WithDispenser","Config","providerAddress","web3Provider","erc721FFactoryABI","datatokensABI","poolFactoryABI","poolABI","fixedRateExchangeAddressABI","dispenserABI","verbose","authMessage","authTokenExpiration","parityUri","threshold","noZeroX","input","zeroOutput","output","regexp","conversorName","inputMatch","zeroXTransformer","Provider","endpoints","getEndpointURL","servicesEndpoints","serviceName","providerEndpoint","serviceEndpoints","i","push","urlPath","consumerAddress","providerEndpoints","getEndpoints","getServiceEndpoints","nonce","accountId","password","consumerMessage","soliditySha3","t","utf8ToHex","currentProvider","isMetaMask","personal","serviceId","files","results","_this$getEndpointURL","fileIndex","userCustomParameters","computeEnv","validUntil","initializeUrl","encodeURI","assets","algorithm","providerData","datasets","compute","transferTxId","downloadUrl","Date","now","consumeUrl","signProviderRequest","dataset","additionalDatasets","computeStartUrl","signatureMessage","documentId","signature","Object","environment","statusText","jobId","computeStopUrl","getNonce","computeStatusUrl","computeResultUrl","resultUrl","computeDeleteUrl","params","ProviderInstance"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lib.modern.js","sources":["../src/utils/Logger.ts","../src/utils/DatatokenName.ts","../src/utils/minAbi.ts","../src/utils/Constants.ts","../src/utils/ContractUtils.ts","../src/utils/FetchHelper.ts","../src/utils/ConfigHelper.ts","../src/utils/DdoHelpers.ts","../src/utils/SignatureUtils.ts","../src/utils/TokenUtils.ts","../src/utils/General.ts","../src/utils/PoolHelpers.ts","../src/aquarius/Aquarius.ts","../src/pools/balancer/Pool.ts","../src/pools/dispenser/Dispenser.ts","../src/pools/fixedRate/FixedRateExchange.ts","../src/pools/ssContracts/SideStaking.ts","../src/pools/Router.ts","../src/tokens/NFT.ts","../src/tokens/Datatoken.ts","../src/factories/NFTFactory.ts","../src/models/Config.ts","../src/utils/ConversionTypeHelper.ts","../src/provider/Provider.ts"],"sourcesContent":["/* eslint-disable no-unused-vars */\nexport enum LogLevel {\n None = -1,\n Error = 0,\n Warn = 1,\n Log = 2,\n Verbose = 3\n}\n/* eslint-enable no-unused-vars */\n\nexport class Logger {\n constructor(private logLevel: LogLevel = LogLevel.Error) {}\n\n public setLevel(logLevel: LogLevel): void {\n this.logLevel = logLevel\n }\n\n public bypass(...args: any[]): void {\n this.dispatch('log', -Infinity as any, ...args)\n }\n\n public debug(...args: any[]): void {\n this.dispatch('debug', LogLevel.Verbose, ...args)\n }\n\n public log(...args: any[]): void {\n this.dispatch('log', LogLevel.Log, ...args)\n }\n\n public warn(...args: any[]): void {\n this.dispatch('warn', LogLevel.Warn, ...args)\n }\n\n public error(...args: any[]): void {\n this.dispatch('error', LogLevel.Error, ...args)\n }\n\n private dispatch(verb: string, level: LogLevel, ...args: any[]) {\n if (this.logLevel >= level) {\n console[verb](...args)\n }\n }\n}\n\nexport const LoggerInstance = new Logger()\nexport default LoggerInstance\n","import wordListDefault from '../data/words.json'\n\n/**\n * Generate new datatoken name & symbol from a word list\n * @return {<{ name: String; symbol: String }>} datatoken name & symbol. Produces e.g. \"Endemic Jellyfish Token\" & \"ENDJEL-45\"\n */\nexport function generateDtName(wordList?: { nouns: string[]; adjectives: string[] }): {\n name: string\n symbol: string\n} {\n const list = wordList || wordListDefault\n const random1 = Math.floor(Math.random() * list.adjectives.length)\n const random2 = Math.floor(Math.random() * list.nouns.length)\n const indexNumber = Math.floor(Math.random() * 100)\n\n // Capitalized adjective & noun\n const adjective = list.adjectives[random1].replace(/^\\w/, (c) => c.toUpperCase())\n const noun = list.nouns[random2].replace(/^\\w/, (c) => c.toUpperCase())\n\n const name = `${adjective} ${noun} Token`\n // use first 3 letters of name, uppercase it, and add random number\n const symbol = `${(\n adjective.substring(0, 3) + noun.substring(0, 3)\n ).toUpperCase()}-${indexNumber}`\n\n return { name, symbol }\n}\n","import { AbiItem } from 'web3-utils/types'\n\nexport const minAbi = [\n {\n constant: true,\n inputs: [],\n name: 'name',\n outputs: [\n {\n name: '',\n type: 'string'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: false,\n inputs: [\n {\n name: '_spender',\n type: 'address'\n },\n {\n name: '_value',\n type: 'uint256'\n }\n ],\n name: 'approve',\n outputs: [\n {\n name: '',\n type: 'bool'\n }\n ],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function'\n },\n {\n constant: true,\n inputs: [],\n name: 'totalSupply',\n outputs: [\n {\n name: '',\n type: 'uint256'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: false,\n inputs: [\n {\n name: '_from',\n type: 'address'\n },\n {\n name: '_to',\n type: 'address'\n },\n {\n name: '_value',\n type: 'uint256'\n }\n ],\n name: 'transferFrom',\n outputs: [\n {\n name: '',\n type: 'bool'\n }\n ],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function'\n },\n {\n constant: true,\n inputs: [],\n name: 'decimals',\n outputs: [\n {\n name: '',\n type: 'uint8'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: true,\n inputs: [\n {\n name: '_owner',\n type: 'address'\n }\n ],\n name: 'balanceOf',\n outputs: [\n {\n name: 'balance',\n type: 'uint256'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: true,\n inputs: [],\n name: 'symbol',\n outputs: [\n {\n name: '',\n type: 'string'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n constant: false,\n inputs: [\n {\n name: '_to',\n type: 'address'\n },\n {\n name: '_value',\n type: 'uint256'\n }\n ],\n name: 'transfer',\n outputs: [\n {\n name: '',\n type: 'bool'\n }\n ],\n payable: false,\n stateMutability: 'nonpayable',\n type: 'function'\n },\n {\n constant: true,\n inputs: [\n {\n name: '_owner',\n type: 'address'\n },\n {\n name: '_spender',\n type: 'address'\n }\n ],\n name: 'allowance',\n outputs: [\n {\n name: '',\n type: 'uint256'\n }\n ],\n payable: false,\n stateMutability: 'view',\n type: 'function'\n },\n {\n payable: true,\n stateMutability: 'payable',\n type: 'fallback'\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: true,\n name: 'owner',\n type: 'address'\n },\n {\n indexed: true,\n name: 'spender',\n type: 'address'\n },\n {\n indexed: false,\n name: 'value',\n type: 'uint256'\n }\n ],\n name: 'Approval',\n type: 'event'\n },\n {\n anonymous: false,\n inputs: [\n {\n indexed: true,\n name: 'from',\n type: 'address'\n },\n {\n indexed: true,\n name: 'to',\n type: 'address'\n },\n {\n indexed: false,\n name: 'value',\n type: 'uint256'\n }\n ],\n name: 'Transfer',\n type: 'event'\n }\n] as AbiItem[]\n","export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'\nexport const GASLIMIT_DEFAULT = 1000000\n","import Web3 from 'web3'\nimport BigNumber from 'bignumber.js'\nimport { Contract } from 'web3-eth-contract'\nimport { generateDtName } from './DatatokenName'\nimport {\n Erc20CreateParams,\n FreCreationParams,\n FreOrderParams,\n PoolCreationParams\n} from '../@types'\nimport { Config } from '../models'\nimport { minAbi } from './minAbi'\nimport LoggerInstance from './Logger'\nimport { GASLIMIT_DEFAULT, ZERO_ADDRESS } from './Constants'\n\nexport function setContractDefaults(contract: Contract, config: Config): Contract {\n if (config) {\n if (config.transactionBlockTimeout)\n contract.transactionBlockTimeout = config.transactionBlockTimeout\n if (config.transactionConfirmationBlocks)\n contract.transactionConfirmationBlocks = config.transactionConfirmationBlocks\n if (config.transactionPollingTimeout)\n contract.transactionPollingTimeout = config.transactionPollingTimeout\n }\n return contract\n}\n\nexport async function getFairGasPrice(web3: Web3, config: Config): Promise<string> {\n const x = new BigNumber(await web3.eth.getGasPrice())\n if (config && config.gasFeeMultiplier)\n return x\n .multipliedBy(config.gasFeeMultiplier)\n .integerValue(BigNumber.ROUND_DOWN)\n .toString(10)\n else return x.toString(10)\n}\n\nexport function getErcCreationParams(ercParams: Erc20CreateParams): any {\n let name: string, symbol: string\n // Generate name & symbol if not present\n if (!ercParams.name || !ercParams.symbol) {\n ;({ name, symbol } = generateDtName())\n }\n return {\n templateIndex: ercParams.templateIndex,\n strings: [ercParams.name || name, ercParams.symbol || symbol],\n addresses: [\n ercParams.minter,\n ercParams.paymentCollector,\n ercParams.mpFeeAddress,\n ercParams.feeToken\n ],\n uints: [Web3.utils.toWei(ercParams.cap), Web3.utils.toWei(ercParams.feeAmount)],\n bytess: []\n }\n}\n\nexport function getFreOrderParams(freParams: FreOrderParams): any {\n return {\n exchangeContract: freParams.exchangeContract,\n exchangeId: freParams.exchangeId,\n maxBaseTokenAmount: Web3.utils.toWei(freParams.maxBaseTokenAmount),\n swapMarketFee: Web3.utils.toWei(freParams.swapMarketFee),\n marketFeeAddress: freParams.marketFeeAddress\n }\n}\n\nexport function getFreCreationParams(freParams: FreCreationParams): any {\n if (!freParams.allowedConsumer) freParams.allowedConsumer = ZERO_ADDRESS\n const withMint = freParams.withMint ? 1 : 0\n\n return {\n fixedPriceAddress: freParams.fixedRateAddress,\n addresses: [\n freParams.baseTokenAddress,\n freParams.owner,\n freParams.marketFeeCollector,\n freParams.allowedConsumer\n ],\n uints: [\n freParams.baseTokenDecimals,\n freParams.datatokenDecimals,\n Web3.utils.toWei(freParams.fixedRate),\n Web3.utils.toWei(freParams.marketFee),\n withMint\n ]\n }\n}\n\nexport async function getPoolCreationParams(\n web3: Web3,\n poolParams: PoolCreationParams\n): Promise<any> {\n return {\n addresses: [\n poolParams.ssContract,\n poolParams.baseTokenAddress,\n poolParams.baseTokenSender,\n poolParams.publisherAddress,\n poolParams.marketFeeCollector,\n poolParams.poolTemplateAddress\n ],\n ssParams: [\n Web3.utils.toWei(poolParams.rate),\n poolParams.baseTokenDecimals,\n Web3.utils.toWei(poolParams.vestingAmount),\n poolParams.vestedBlocks,\n await amountToUnits(\n web3,\n poolParams.baseTokenAddress,\n poolParams.initialBaseTokenLiquidity\n )\n ],\n swapFees: [\n Web3.utils.toWei(poolParams.swapFeeLiquidityProvider),\n Web3.utils.toWei(poolParams.swapFeeMarketRunner)\n ]\n }\n}\n\nexport async function unitsToAmount(\n web3: Web3,\n token: string,\n amount: string,\n tokenDecimals?: number\n): Promise<string> {\n try {\n const tokenContract = new web3.eth.Contract(minAbi, token)\n let decimals = tokenDecimals || (await tokenContract.methods.decimals().call())\n if (decimals === '0') {\n decimals = 18\n }\n\n const amountFormatted = new BigNumber(amount).div(\n new BigNumber(10).exponentiatedBy(decimals)\n )\n\n BigNumber.config({ EXPONENTIAL_AT: 50 })\n return amountFormatted.toString()\n } catch (e) {\n LoggerInstance.error(`ERROR: FAILED TO CALL DECIMALS(), USING 18' : ${e.message}`)\n }\n}\n\nexport async function amountToUnits(\n web3: Web3,\n token: string,\n amount: string,\n tokenDecimals?: number\n): Promise<string> {\n try {\n const tokenContract = new web3.eth.Contract(minAbi, token)\n let decimals = tokenDecimals || (await tokenContract.methods.decimals().call())\n if (decimals === '0') {\n decimals = 18\n }\n BigNumber.config({ EXPONENTIAL_AT: 50 })\n\n const amountFormatted = new BigNumber(amount).times(\n new BigNumber(10).exponentiatedBy(decimals)\n )\n\n return amountFormatted.toString()\n } catch (e) {\n LoggerInstance.error(`ERROR: FAILED TO CALL DECIMALS(), USING 18', ${e.message}`)\n }\n}\n\n/**\n * Estimates the gas used when a function would be executed on chain\n * @param {string} from account that calls the function\n * @param {Function} functionToEstimateGas function that we need to estimate the gas\n * @param {...any[]} args arguments of the function\n * @return {Promise<number>} gas cost of the function\n */\nexport async function estimateGas(\n from: string,\n functionToEstimateGas: Function,\n ...args: any[]\n): Promise<any> {\n let estimatedGas = GASLIMIT_DEFAULT\n try {\n estimatedGas = await functionToEstimateGas.apply(null, args).estimateGas(\n {\n from: from\n },\n (err, estGas) => (err ? GASLIMIT_DEFAULT : estGas)\n )\n } catch (e) {\n LoggerInstance.error(`ERROR: Estimate gas failed!`, e)\n }\n return estimatedGas\n}\n","import fetch from 'cross-fetch'\nimport LoggerInstance from './Logger'\nimport { DownloadResponse } from '../@types/DownloadResponse'\n\nexport async function fetchData(url: string, opts: RequestInit): Promise<Response> {\n const result = await fetch(url, opts)\n if (!result.ok) {\n LoggerInstance.error(`Error requesting [${opts.method}] ${url}`)\n LoggerInstance.error(`Response message: \\n${await result.text()}`)\n throw result\n }\n return result\n}\n\nexport async function downloadFileBrowser(url: string): Promise<void> {\n const anchor = document.createElement('a')\n anchor.download = ''\n anchor.href = url\n anchor.click()\n}\n\nexport async function downloadFile(\n url: string,\n index?: number\n): Promise<DownloadResponse> {\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error('Response error.')\n }\n let filename: string\n try {\n filename = response.headers\n .get('content-disposition')\n .match(/attachment;filename=(.+)/)[1]\n } catch {\n try {\n filename = url.split('/').pop()\n } catch {\n filename = `file${index}`\n }\n }\n\n return { data: await response.arrayBuffer(), filename }\n}\n\nexport async function getData(url: string): Promise<Response> {\n return fetch(url, {\n method: 'GET',\n headers: {\n 'Content-type': 'application/json'\n }\n })\n}\n\nasync function postWithHeaders(\n url: string,\n payload: BodyInit,\n headers: any\n): Promise<Response> {\n if (payload != null) {\n return fetch(url, {\n method: 'POST',\n body: payload,\n headers\n })\n } else {\n return fetch(url, {\n method: 'POST'\n })\n }\n}\n\nexport async function postData(url: string, payload: BodyInit): Promise<Response> {\n const headers = {\n 'Content-type': 'application/json'\n }\n return postWithHeaders(url, payload, headers)\n}\n","import Config from '../models/Config'\n// eslint-disable-next-line import/no-named-default\nimport { default as DefaultContractsAddresses } from '@oceanprotocol/contracts/addresses/address.json'\nimport LoggerInstance from './Logger'\n\nconst configHelperNetworksBase: Config = {\n chainId: null,\n network: 'unknown',\n metadataCacheUri: 'https://v4.aquarius.oceanprotocol.com',\n nodeUri: 'http://127.0.0.1:8545',\n providerUri: 'http://127.0.0.1:8030',\n subgraphUri: null,\n explorerUri: null,\n oceanTokenAddress: null,\n oceanTokenSymbol: 'OCEAN',\n poolTemplateAddress: null,\n fixedRateExchangeAddress: null,\n dispenserAddress: null,\n startBlock: 0,\n transactionBlockTimeout: 50,\n transactionConfirmationBlocks: 1,\n transactionPollingTimeout: 750,\n gasFeeMultiplier: 1\n}\n\nexport const configHelperNetworks: Config[] = [\n {\n ...configHelperNetworksBase\n },\n {\n // barge\n ...configHelperNetworksBase,\n chainId: 8996,\n network: 'development',\n metadataCacheUri: 'http://127.0.0.1:5000',\n providerUri: 'http://172.15.0.4:8030'\n },\n {\n ...configHelperNetworksBase,\n chainId: 3,\n network: 'ropsten',\n nodeUri: 'https://ropsten.infura.io/v3',\n providerUri: 'https://v4.provider.ropsten.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.ropsten.oceanprotocol.com',\n explorerUri: 'https://ropsten.etherscan.io',\n gasFeeMultiplier: 1.1\n },\n {\n ...configHelperNetworksBase,\n chainId: 4,\n network: 'rinkeby',\n nodeUri: 'https://rinkeby.infura.io/v3',\n providerUri: 'https://v4.provider.rinkeby.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.rinkeby.oceanprotocol.com',\n explorerUri: 'https://rinkeby.etherscan.io',\n gasFeeMultiplier: 1.1\n },\n {\n ...configHelperNetworksBase,\n chainId: 1,\n network: 'mainnet',\n nodeUri: 'https://mainnet.infura.io/v3',\n providerUri: 'https://v4.provider.mainnet.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.mainnet.oceanprotocol.com',\n explorerUri: 'https://etherscan.io',\n startBlock: 11105459,\n transactionBlockTimeout: 150,\n transactionConfirmationBlocks: 5,\n transactionPollingTimeout: 1750,\n gasFeeMultiplier: 1.05\n },\n {\n ...configHelperNetworksBase,\n chainId: 137,\n network: 'polygon',\n nodeUri: 'https://polygon-mainnet.infura.io/v3',\n providerUri: 'https://v4.provider.polygon.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.polygon.oceanprotocol.com',\n explorerUri: 'https://polygonscan.com',\n oceanTokenSymbol: 'mOCEAN'\n },\n {\n ...configHelperNetworksBase,\n chainId: 1287,\n network: 'moonbase',\n nodeUri: 'https://rpc.api.moonbase.moonbeam.network',\n providerUri: 'https://v4.provider.moonbase.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.moonbase.oceanprotocol.com',\n explorerUri: 'https://moonbase.moonscan.io/',\n gasFeeMultiplier: 1.1\n },\n {\n ...configHelperNetworksBase,\n chainId: 2021000,\n network: 'gaiaxtestnet',\n nodeUri: 'https://rpc.gaiaxtestnet.oceanprotocol.com',\n providerUri: 'https://v4.provider.gaiaxtestnet.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.gaiaxtestnet.oceanprotocol.com',\n explorerUri: 'https://blockscout.gaiaxtestnet.oceanprotocol.com'\n },\n {\n ...configHelperNetworksBase,\n chainId: 80001,\n network: 'mumbai',\n nodeUri: 'https://polygon-mumbai.infura.io/v3',\n providerUri: 'https://v4.provider.mumbai.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.mumbai.oceanprotocol.com',\n explorerUri: 'https://mumbai.polygonscan.com',\n gasFeeMultiplier: 1.1\n },\n {\n ...configHelperNetworksBase,\n chainId: 56,\n network: 'bsc',\n nodeUri: 'https://bsc-dataseed.binance.org',\n providerUri: 'https://v4.provider.bsc.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.bsc.oceanprotocol.com',\n explorerUri: 'https://bscscan.com/',\n gasFeeMultiplier: 1.05\n },\n {\n ...configHelperNetworksBase,\n chainId: 246,\n network: 'energyweb',\n nodeUri: 'https://rpc.energyweb.org',\n providerUri: 'https://v4.provider.energyweb.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.energyweb.oceanprotocol.com',\n explorerUri: 'https://explorer.energyweb.org',\n gasFeeMultiplier: 1.05\n },\n {\n ...configHelperNetworksBase,\n chainId: 1285,\n network: 'moonriver',\n nodeUri: 'https://moonriver.api.onfinality.io/public',\n providerUri: 'https://v4.provider.moonriver.oceanprotocol.com',\n subgraphUri: 'https://v4.subgraph.moonriver.oceanprotocol.com',\n explorerUri: 'https://moonriver.moonscan.io/',\n gasFeeMultiplier: 1.05\n }\n]\n\nexport class ConfigHelper {\n /* Load contract addresses from env ADDRESS_FILE (generated by ocean-contracts) */\n public getAddressesFromEnv(network: string, customAddresses?: any): Partial<Config> {\n // use the defaults first\n let configAddresses: Partial<Config>\n\n // load from custom addresses structure\n if (customAddresses) {\n try {\n const {\n FixedPrice,\n Dispenser,\n Staking,\n poolTemplate,\n ERC721Factory,\n OPFCommunityFeeCollector,\n Ocean,\n chainId,\n startBlock\n } = customAddresses[network]\n configAddresses = {\n erc721FactoryAddress: ERC721Factory,\n sideStakingAddress: Staking,\n opfCommunityFeeCollector: OPFCommunityFeeCollector,\n poolTemplateAddress: poolTemplate,\n fixedRateExchangeAddress: FixedPrice,\n dispenserAddress: Dispenser,\n oceanTokenAddress: Ocean,\n chainId: chainId,\n startBlock: startBlock,\n ...(process.env.AQUARIUS_URI && { metadataCacheUri: process.env.AQUARIUS_URI })\n }\n } catch (e) {\n // console.error(`ERROR: Could not load local contract address file: ${e.message}`)\n // return null\n }\n } else {\n // no custom addresses structure was passed, trying to load default\n if (DefaultContractsAddresses[network]) {\n const {\n FixedPrice,\n Dispenser,\n Staking,\n poolTemplate,\n OPFCommunityFeeCollector,\n ERC721Factory,\n Ocean,\n chainId,\n startBlock\n } = DefaultContractsAddresses[network]\n configAddresses = {\n erc721FactoryAddress: ERC721Factory,\n sideStakingAddress: Staking,\n opfCommunityFeeCollector: OPFCommunityFeeCollector,\n poolTemplateAddress: poolTemplate,\n fixedRateExchangeAddress: FixedPrice,\n dispenserAddress: Dispenser,\n oceanTokenAddress: Ocean,\n chainId: chainId,\n startBlock: startBlock,\n ...(process.env.AQUARIUS_URI && { metadataCacheUri: process.env.AQUARIUS_URI })\n }\n }\n }\n return configAddresses\n }\n\n public getConfig(network: string | number, infuraProjectId?: string): Config {\n const filterBy = typeof network === 'string' ? 'network' : 'chainId'\n let config = configHelperNetworks.find((c) => c[filterBy] === network)\n\n if (!config) {\n LoggerInstance.error(`No config found for given network '${network}'`)\n return null\n }\n\n const contractAddressesConfig = this.getAddressesFromEnv(config.network)\n config = { ...config, ...contractAddressesConfig }\n\n const nodeUri = infuraProjectId\n ? `${config.nodeUri}/${infuraProjectId}`\n : config.nodeUri\n\n return { ...config, nodeUri }\n }\n}\n","import sha256 from 'crypto-js/sha256'\nimport Web3 from 'web3'\nimport LoggerInstance from './Logger'\n\nexport function generateDid(erc721Address: string, chainId: number): string {\n erc721Address = Web3.utils.toChecksumAddress(erc721Address)\n const checksum = sha256(erc721Address + chainId.toString(10))\n return `did:op:${checksum.toString()}`\n}\n\nexport function getHash(data: any): string {\n try {\n return sha256(data).toString()\n } catch (e) {\n LoggerInstance.error('getHash error: ', e.message)\n }\n}\n","import Web3 from 'web3'\nimport { LoggerInstance } from './Logger'\n\nexport async function signHash(web3: Web3, message: string, address: string) {\n let signedMessage = await web3.eth.sign(message, address)\n signedMessage = signedMessage.substr(2) // remove 0x\n const r = '0x' + signedMessage.slice(0, 64)\n const s = '0x' + signedMessage.slice(64, 128)\n let v = '0x' + signedMessage.slice(128, 130)\n // make sure we obey 27 and 28 standards\n if (v === '0x00') v = '0x1b'\n if (v === '0x01') v = '0x1c'\n return { v, r, s }\n}\n","import Decimal from 'decimal.js'\nimport { Contract } from 'web3-eth-contract'\nimport {\n amountToUnits,\n estimateGas,\n getFairGasPrice,\n unitsToAmount\n} from './ContractUtils'\nimport { minAbi } from './minAbi'\nimport LoggerInstance from './Logger'\nimport { TransactionReceipt } from 'web3-core'\nimport Web3 from 'web3'\nimport BigNumber from 'bignumber.js'\n\n/**\n * Estimate gas cost for approval function\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} spender\n * @param {String} amount\n * @param {String} force\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\nexport async function estApprove(\n web3: Web3,\n account: string,\n tokenAddress: string,\n spender: string,\n amount: string,\n contractInstance?: Contract\n): Promise<number> {\n const tokenContract = contractInstance || new web3.eth.Contract(minAbi, tokenAddress)\n\n return estimateGas(account, tokenContract.methods.approve, spender, amount)\n}\n\n/**\n * Approve spender to spent amount tokens\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} spender\n * @param {String} amount amount of ERC20 tokens (always expressed as wei)\n * @param {boolean} force if true, will overwrite any previous allowence. Else, will check if allowence is enough and will not send a transaction if it's not needed\n * @param {number} tokenDecimals optional number of decimals of the token\n */\nexport async function approve(\n web3: Web3,\n account: string,\n tokenAddress: string,\n spender: string,\n amount: string,\n force = false,\n tokenDecimals?: number\n): Promise<TransactionReceipt | string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n if (!force) {\n const currentAllowence = await allowance(web3, tokenAddress, account, spender)\n if (new Decimal(currentAllowence).greaterThanOrEqualTo(new Decimal(amount))) {\n return currentAllowence\n }\n }\n let result = null\n const amountFormatted = await amountToUnits(web3, tokenAddress, amount, tokenDecimals)\n const estGas = await estimateGas(\n account,\n tokenContract.methods.approve,\n spender,\n amountFormatted\n )\n\n try {\n result = await tokenContract.methods.approve(spender, amountFormatted).send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(web3, null)\n })\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to approve spender to spend tokens : ${e.message}`\n )\n }\n return result\n}\n\n/**\n * Approve spender to spent amount tokens\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} spender\n * @param {String} amount amount of ERC20 tokens (always expressed as wei)\n * @param {boolean} force if true, will overwrite any previous allowence. Else, will check if allowence is enough and will not send a transaction if it's not needed\n */\nexport async function approveWei(\n web3: Web3,\n account: string,\n tokenAddress: string,\n spender: string,\n amount: string,\n force = false\n): Promise<TransactionReceipt | string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n if (!force) {\n const currentAllowence = await allowanceWei(web3, tokenAddress, account, spender)\n if (new BigNumber(currentAllowence).gt(new BigNumber(amount))) {\n return currentAllowence\n }\n }\n let result = null\n const estGas = await estimateGas(\n account,\n tokenContract.methods.approve,\n spender,\n amount\n )\n\n try {\n result = await tokenContract.methods.approve(spender, amount).send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(web3, null)\n })\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to approve spender to spend tokens : ${e.message}`\n )\n }\n return result\n}\n/**\n * Estimate gas cost for transfer function\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} recipient\n * @param {String} amount\n * @param {String} force\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\nexport async function estTransfer(\n web3: Web3,\n account: string,\n tokenAddress: string,\n recipient: string,\n amount: string,\n contractInstance?: Contract\n): Promise<number> {\n const tokenContract = contractInstance || new web3.eth.Contract(minAbi, tokenAddress)\n\n return estimateGas(account, tokenContract.methods.transfer, recipient, amount)\n}\n\n/**\n * Moves amount tokens from the caller’s account to recipient.\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} recipient\n * @param {String} amount amount of ERC20 tokens (not as wei)\n * @param {String} force if true, will overwrite any previous allowence. Else, will check if allowence is enough and will not send a transaction if it's not needed\n */\nexport async function transfer(\n web3: Web3,\n account: string,\n tokenAddress: string,\n recipient: string,\n amount: string\n): Promise<TransactionReceipt | string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n\n let result = null\n const amountFormatted = await amountToUnits(web3, tokenAddress, amount)\n const estGas = await estimateGas(\n account,\n tokenContract.methods.transfer,\n recipient,\n amountFormatted\n )\n\n try {\n result = await tokenContract.methods.transfer(recipient, amountFormatted).send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(web3, null)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to transfer tokens : ${e.message}`)\n }\n return result\n}\n\n/**\n * Get Allowance for any erc20\n * @param {Web3} web3\n * @param {String } tokenAdress\n * @param {String} account\n * @param {String} spender\n * @param {number} tokenDecimals optional number of decimals of the token\n */\nexport async function allowance(\n web3: Web3,\n tokenAddress: string,\n account: string,\n spender: string,\n tokenDecimals?: number\n): Promise<string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n const trxReceipt = await tokenContract.methods.allowance(account, spender).call()\n\n return await unitsToAmount(web3, tokenAddress, trxReceipt, tokenDecimals)\n}\n\n/**\n * Get Allowance for any erc20\n * @param {Web3} web3\n * @param {String } tokenAdress\n * @param {String} account\n * @param {String} spender\n */\nexport async function allowanceWei(\n web3: Web3,\n tokenAddress: string,\n account: string,\n spender: string,\n tokenDecimals?: number\n): Promise<string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n return await tokenContract.methods.allowance(account, spender).call()\n}\n\n/**\n * Get balance for any erc20\n * @param {Web3} web3\n * @param {String} tokenAdress\n * @param {String} owner\n * @param {String} spender\n * @param {number} tokenDecimals optional number of decimals of the token\n */\nexport async function balance(\n web3: Web3,\n tokenAddress: string,\n account: string,\n tokenDecimals?: number\n): Promise<string> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n const trxReceipt = await tokenContract.methods.balanceOf(account).call()\n\n return await unitsToAmount(web3, tokenAddress, trxReceipt, tokenDecimals)\n}\n\n/**\n * Get decimals for any erc20\n * @param {Web3} web3\n * @param {String} tokenAdress\n * @return {Promise<number>} Number of decimals of the token\n */\nexport async function decimals(web3: Web3, tokenAddress: string): Promise<number> {\n const tokenContract = new web3.eth.Contract(minAbi, tokenAddress)\n return await tokenContract.methods.decimals().call()\n}\n","/**\n * Simple blocking sleep function\n */\nexport async function sleep(ms: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, ms)\n })\n}\n","import Decimal from 'decimal.js'\nimport { Pool } from '..'\n\nexport function calcMaxExactOut(balance: string): Decimal {\n return new Decimal(balance).div(2)\n}\n\nexport function calcMaxExactIn(balance: string): Decimal {\n return new Decimal(balance).div(2)\n}\nexport async function getMaxSwapExactOut(\n poolInstance: Pool,\n poolAddress: string,\n tokenAddress: string\n): Promise<Decimal> {\n const reserve = await poolInstance.getReserve(poolAddress, tokenAddress)\n return calcMaxExactOut(reserve)\n}\n\nexport async function getMaxSwapExactIn(\n poolInstance: Pool,\n poolAddress: string,\n tokenAddress: string\n): Promise<Decimal> {\n const reserve = await poolInstance.getReserve(poolAddress, tokenAddress)\n return calcMaxExactIn(reserve)\n}\n\nexport async function getMaxAddLiquidity(\n poolInstance: Pool,\n poolAddress: string,\n tokenAddress: string\n): Promise<Decimal> {\n const reserve = await poolInstance.getReserve(poolAddress, tokenAddress)\n\n return calcMaxExactIn(reserve)\n}\n\nexport async function getMaxRemoveLiquidity(\n poolInstance: Pool,\n poolAddress: string,\n tokenAddress: string\n): Promise<Decimal> {\n const reserve = await poolInstance.getReserve(poolAddress, tokenAddress)\n\n return calcMaxExactIn(reserve)\n}\n","import { LoggerInstance, sleep } from '../utils'\nimport { Asset, DDO, ValidateMetadata } from '../@types/'\nimport fetch from 'cross-fetch'\nexport class Aquarius {\n public aquariusURL\n /**\n * Instantiate Aquarius\n * @param {String} aquariusURL\n */\n constructor(aquariusURL: string) {\n this.aquariusURL = aquariusURL\n }\n\n /** Resolves a DID\n * @param {string} did\n * @param {AbortSignal} signal abort signal\n * @return {Promise<Asset>} Asset\n */\n public async resolve(did: string, signal?: AbortSignal): Promise<Asset> {\n const path = this.aquariusURL + '/api/aquarius/assets/ddo/' + did\n try {\n const response = await fetch(path, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n\n if (response.ok) {\n const raw = await response.json()\n return raw as Asset\n } else {\n throw new Error('HTTP request failed with status ' + response.status)\n }\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('HTTP request failed')\n }\n }\n\n /**\n * Blocks until Aqua will cache the did (or the update for that did) or timeouts\n \n * @param {string} did DID of the asset.\n * @param {string} txid used when the did exists and we expect an update with that txid.\n * @param {AbortSignal} signal abort signal\n * @return {Promise<DDO>} DDO of the asset.\n */\n public async waitForAqua(\n did: string,\n txid?: string,\n signal?: AbortSignal\n ): Promise<Asset> {\n let tries = 0\n do {\n try {\n const path = this.aquariusURL + '/api/aquarius/assets/ddo/' + did\n const response = await fetch(path, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n if (response.ok) {\n const ddo = await response.json()\n if (txid) {\n // check tx\n if (ddo.event && ddo.event.txid === txid) return ddo as Asset\n } else return ddo as Asset\n }\n } catch (e) {\n // do nothing\n }\n await sleep(1500)\n tries++\n } while (tries < 100)\n return null\n }\n\n /**\n * Validate DDO content\n * @param {DDO} ddo DID Descriptor Object content.\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ValidateMetadata>}.\n */\n public async validate(ddo: DDO, signal?: AbortSignal): Promise<ValidateMetadata> {\n const status: ValidateMetadata = {\n valid: false\n }\n let jsonResponse\n try {\n const path = this.aquariusURL + '/api/aquarius/assets/ddo/validate'\n\n const response = await fetch(path, {\n method: 'POST',\n body: JSON.stringify(ddo),\n headers: {\n 'Content-Type': 'application/octet-stream'\n },\n signal: signal\n })\n\n jsonResponse = await response.json()\n if (response.status === 200) {\n status.valid = true\n status.hash = jsonResponse.hash\n status.proof = {\n validatorAddress: jsonResponse.publicKey,\n r: jsonResponse.r[0],\n s: jsonResponse.s[0],\n v: jsonResponse.v\n }\n } else {\n status.errors = jsonResponse\n LoggerInstance.error('validate Metadata failed:', response.status, status.errors)\n }\n } catch (error) {\n LoggerInstance.error('Error validating metadata: ', error)\n }\n return status\n }\n}\n\nexport default Aquarius\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils/types'\nimport { TransactionReceipt } from 'web3-core'\nimport { Contract } from 'web3-eth-contract'\nimport {\n getFairGasPrice,\n setContractDefaults,\n unitsToAmount,\n amountToUnits,\n LoggerInstance,\n estimateGas,\n ConfigHelper\n} from '../../utils'\nimport BigNumber from 'bignumber.js'\nimport PoolTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/balancer/BPool.sol/BPool.json'\nimport defaultErc20Abi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json'\nimport {\n CurrentFees,\n TokenInOutMarket,\n AmountsInMaxFee,\n AmountsOutMaxFee,\n PoolPriceAndFees\n} from '../../@types'\nimport { Config } from '../../models'\nimport {\n getMaxAddLiquidity,\n getMaxRemoveLiquidity,\n getMaxSwapExactIn,\n getMaxSwapExactOut\n} from '../../utils/PoolHelpers'\nimport Decimal from 'decimal.js'\nconst MaxUint256 =\n '115792089237316195423570985008687907853269984665640564039457584007913129639934'\n\n/**\n * Provides an interface to Ocean friendly fork from Balancer BPool\n */\nexport class Pool {\n public poolAbi: AbiItem | AbiItem[]\n public web3: Web3\n private config: Config\n\n constructor(\n web3: Web3,\n network?: string | number,\n poolAbi: AbiItem | AbiItem[] = null,\n config?: Config\n ) {\n if (poolAbi) this.poolAbi = poolAbi\n else this.poolAbi = PoolTemplate.abi as AbiItem[]\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n }\n\n async amountToUnits(\n token: string,\n amount: string,\n tokenDecimals?: number\n ): Promise<string> {\n return amountToUnits(this.web3, token, amount, tokenDecimals)\n }\n\n async unitsToAmount(\n token: string,\n amount: string,\n tokenDecimals?: number\n ): Promise<string> {\n return unitsToAmount(this.web3, token, amount, tokenDecimals)\n }\n\n /**\n * Get user shares of pool tokens\n * @param {String} account\n * @param {String} poolAddress\n * @return {String}\n */\n async sharesBalance(account: string, poolAddress: string): Promise<string> {\n let result = null\n try {\n const token = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n const balance = await token.methods.balanceOf(account).call()\n result = this.web3.utils.fromWei(balance)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get shares of pool : ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for setSwapFee\n * @param {String} account\n * @param {String} tokenAddress\n * @param {String} spender\n * @param {String} amount\n * @param {String} force\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSetSwapFee(\n account: string,\n poolAddress: string,\n fee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(defaultErc20Abi.abi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(account, poolContract.methods.setSwapFee, fee)\n }\n\n /**\n * Allows controller to change the swapFee\n * @param {String} account\n * @param {String} poolAddress\n * @param {String} fee swap fee (1e17 = 10 % , 1e16 = 1% , 1e15 = 0.1%, 1e14 = 0.01%)\n */\n async setSwapFee(\n account: string,\n poolAddress: string,\n fee: string\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress, {\n from: account\n }),\n this.config\n )\n let result = null\n const estGas = await estimateGas(account, pool.methods.setSwapFee, fee)\n\n try {\n result = await pool.methods.setSwapFee(this.web3.utils.toWei(fee)).send({\n from: account,\n gas: estGas,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to set pool swap fee: ${e.message}`)\n }\n return result\n }\n\n /**\n * Returns number of tokens bounded to pool\n * @param {String} poolAddress\n * @return {String}\n */\n async getNumTokens(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getNumTokens().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get number of tokens: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get total supply of pool shares\n * @param {String} poolAddress\n * @return {String}\n */\n async getPoolSharesTotalSupply(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n try {\n const result = await pool.methods.totalSupply().call()\n amount = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get total supply of pool shares: ${e.message}`\n )\n }\n return amount\n }\n\n /**\n * Get tokens composing this poo\n * Returns tokens bounded to pool, before the pool is finalizedl\n * @param {String} poolAddress\n * @return {String[]}\n */\n async getCurrentTokens(poolAddress: string): Promise<string[]> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getCurrentTokens().call()\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get tokens composing this pool: ${e.message}`\n )\n }\n return result\n }\n\n /**\n * Get the final tokens composing this pool\n * Returns tokens bounded to pool, after the pool was finalized\n * @param {String} poolAddress\n * @return {String[]}\n */\n async getFinalTokens(poolAddress: string): Promise<string[]> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getFinalTokens().call()\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get the final tokens composing this pool ${e.message}`\n )\n }\n return result\n }\n\n /**\n * Returns the current controller address (ssBot)\n * @param {String} poolAddress\n * @return {String}\n */\n async getController(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getController().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get pool controller address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Returns the current baseToken address of the pool\n * @param {String} poolAddress\n * @return {String}\n */\n async getBaseToken(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getBaseTokenAddress().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get baseToken address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Returns the current datatoken address\n * @param {String} poolAddress\n * @return {String}\n */\n async getDatatoken(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getDatatokenAddress().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get datatoken address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get getMarketFee\n * @param {String} poolAddress\n * @return {String}\n */\n async getMarketFee(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.getMarketFee().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get getMarketFee: ${e.message}`)\n }\n return this.web3.utils.fromWei(result).toString()\n }\n\n /**\n * Get marketFeeCollector of this pool\n * @param {String} poolAddress\n * @return {String}\n */\n async getMarketFeeCollector(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods._publishMarketCollector().call()\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get marketFeeCollector address: ${e.message}`\n )\n }\n return result\n }\n\n /**\n * Get if a token is bounded to a pool\n * Returns true if token is bound\n * @param {String} poolAddress\n * @param {String} token Address of the token to be checked\n * @return {Boolean}\n */\n async isBound(poolAddress: string, token: string): Promise<boolean> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.isBound(token).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to check whether a token \\\n bounded to a pool. ${e.message}`)\n }\n return result\n }\n\n /**\n * Returns the current token reserve amount\n * @param {String} poolAddress\n * @param {String} token Address of the token to be checked\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getReserve(\n poolAddress: string,\n token: string,\n tokenDecimals?: number\n ): Promise<string> {\n let amount = null\n try {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n const result = await pool.methods.getBalance(token).call()\n amount = await this.unitsToAmount(token, result, tokenDecimals)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get how many tokens \\\n are in the pool: ${e.message}`)\n }\n return amount.toString()\n }\n\n /**\n * Get if a pool is finalized\n * Returns true if pool is finalized\n * @param {String} poolAddress\n * @return {Boolean}\n */\n async isFinalized(poolAddress: string): Promise<boolean> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n try {\n result = await pool.methods.isFinalized().call()\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to check whether pool is finalized: ${e.message}`\n )\n }\n return result\n }\n\n /**\n * Returns the current Liquidity Providers swap fee\n * @param {String} poolAddress\n * @return {String} Swap fee. To get the percentage value, substract by 100. E.g. `0.1` represents a 10% swap fee.\n */\n async getSwapFee(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let fee = null\n try {\n const result = await pool.methods.getSwapFee().call()\n fee = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get pool fee: ${e.message}`)\n }\n return fee\n }\n\n /**\n * Returns normalized weight of a token.\n * The combined normalized weights of all tokens will sum up to 1.\n * (Note: the actual sum may be 1 plus or minus a few wei due to division precision loss)\n * @param {String} poolAddress\n * @param {String} token token to be checked\n * @return {String}\n */\n async getNormalizedWeight(poolAddress: string, token: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.getNormalizedWeight(token).call()\n weight = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get normalized weight of a token: ${e.message}`\n )\n }\n return weight\n }\n\n /**\n * Returns denormalized weight of a token\n * @param {String} poolAddress\n * @param {String} token token to be checked\n * @return {String}\n */\n async getDenormalizedWeight(poolAddress: string, token: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.getDenormalizedWeight(token).call()\n weight = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get denormalized weight of a token in pool ${e.message}`\n )\n }\n return weight\n }\n\n /**\n * getTotalDenormalizedWeight\n * Returns total denormalized weught of the pool\n * @param {String} poolAddress\n * @return {String}\n */\n async getTotalDenormalizedWeight(poolAddress: string): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.getTotalDenormalizedWeight().call()\n weight = this.web3.utils.fromWei(result)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get total denormalized weight in pool ${e.message}`\n )\n }\n return weight\n }\n\n /**\n * Returns the current fee of publishingMarket\n * Get Market Fees available to be collected for a specific token\n * @param {String} poolAddress\n * @param {String} token token we want to check fees\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getMarketFees(\n poolAddress: string,\n token: string,\n tokenDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.publishMarketFees(token).call()\n weight = await this.unitsToAmount(token, result, tokenDecimals)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get market fees for a token: ${e.message}`)\n }\n return weight\n }\n\n /**\n * Get Community Get the current amount of fees which can be withdrawned by the Market\n * @return {CurrentFees}\n */\n async getCurrentMarketFees(poolAddress: string): Promise<CurrentFees> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n try {\n const currentMarketFees = await pool.methods.getCurrentOPCFees().call()\n return currentMarketFees\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get community fees for a token: ${e.message}`\n )\n }\n }\n\n /**\n * Get getCurrentOPFFees Get the current amount of fees which can be withdrawned by OPF\n * @return {CurrentFees}\n */\n async getCurrentOPCFees(poolAddress: string): Promise<CurrentFees> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n try {\n const currentMarketFees = await pool.methods.getCurrentOPCFees().call()\n return currentMarketFees\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get community fees for a token: ${e.message}`\n )\n }\n }\n\n /**\n * Get Community Fees available to be collected for a specific token\n * @param {String} poolAddress\n * @param {String} token token we want to check fees\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getCommunityFees(\n poolAddress: string,\n token: string,\n tokenDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let weight = null\n try {\n const result = await pool.methods.communityFees(token).call()\n weight = await this.unitsToAmount(token, result, tokenDecimals)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to get community fees for a token: ${e.message}`\n )\n }\n return weight\n }\n\n /**\n * Estimate gas cost for collectOPF\n * @param {String} address\n * @param {String} poolAddress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectOPC(\n address: string,\n poolAddress: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(address, poolContract.methods.collectOPC)\n }\n\n /**\n * collectOPF - collect opf fee - can be called by anyone\n * @param {String} address\n * @param {String} poolAddress\n * @return {TransactionReceipt}\n */\n async collectOPC(address: string, poolAddress: string): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n const estGas = await estimateGas(address, pool.methods.collectOPC)\n\n try {\n result = await pool.methods.collectOPC().send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to swap exact amount in : ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for collectMarketFee\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} to address that will receive fees\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectMarketFee(\n address: string,\n poolAddress: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(address, poolContract.methods.collectMarketFee)\n }\n\n /**\n * collectOPF - collect market fees - can be called by the publishMarketCollector\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} to address that will receive fees\n * @return {TransactionReceipt}\n */\n async collectMarketFee(\n address: string,\n poolAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getMarketFeeCollector(poolAddress)) !== address) {\n throw new Error(`Caller is not MarketFeeCollector`)\n }\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n const estGas = await estimateGas(address, pool.methods.collectMarketFee)\n\n try {\n result = await pool.methods.collectMarketFee().send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to swap exact amount in : ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for updatePublishMarketFee\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} newPublishMarketAddress new market address\n * @param {String} newPublishMarketSwapFee new market swap fee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estUpdatePublishMarketFee(\n address: string,\n poolAddress: string,\n newPublishMarketAddress: string,\n newPublishMarketSwapFee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(\n address,\n poolContract.methods.updatePublishMarketFee,\n newPublishMarketAddress,\n this.web3.utils.toWei(newPublishMarketSwapFee)\n )\n }\n\n /**\n * updatePublishMarketFee - sets a new newPublishMarketAddress and new newPublishMarketSwapFee- can be called only by the marketFeeCollector\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} newPublishMarketAddress new market fee collector address\n * @param {String} newPublishMarketSwapFee fee recieved by the publisher market when a dt is swaped from a pool, percent\n * @return {TransactionReceipt}\n */\n async updatePublishMarketFee(\n address: string,\n poolAddress: string,\n newPublishMarketAddress: string,\n newPublishMarketSwapFee: string\n ): Promise<TransactionReceipt> {\n if ((await this.getMarketFeeCollector(poolAddress)) !== address) {\n throw new Error(`Caller is not MarketFeeCollector`)\n }\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n\n const estGas = await estimateGas(\n address,\n pool.methods.updatePublishMarketFee,\n newPublishMarketAddress,\n this.web3.utils.toWei(newPublishMarketSwapFee)\n )\n try {\n result = await pool.methods\n .updatePublishMarketFee(\n newPublishMarketAddress,\n this.web3.utils.toWei(newPublishMarketSwapFee)\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to updatePublishMarketFee : ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for swapExactAmountIn\n * @param {String} address\n * @param {String} poolAddress\n * @param {TokenInOutMarket} tokenInOutMarket object contianing addresses like tokenIn, tokenOut, consumeMarketFeeAddress\n * @param {AmountsInMaxFee} amountsInOutMaxFee object contianing tokenAmountIn, minAmountOut, maxPrice, consumeMarketSwapFee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSwapExactAmountIn(\n address: string,\n poolAddress: string,\n tokenInOutMarket: TokenInOutMarket,\n amountsInOutMaxFee: AmountsInMaxFee,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n const tokenAmountIn = await this.amountToUnits(\n tokenInOutMarket.tokenIn,\n amountsInOutMaxFee.tokenAmountIn,\n tokenInOutMarket.tokenInDecimals\n )\n\n const minAmountOut = await this.amountToUnits(\n tokenInOutMarket.tokenOut,\n amountsInOutMaxFee.minAmountOut,\n tokenInOutMarket.tokenOutDecimals\n )\n\n const maxPrice = amountsInOutMaxFee.maxPrice\n ? this.amountToUnits(\n await this.getBaseToken(poolAddress),\n amountsInOutMaxFee.maxPrice\n )\n : MaxUint256\n\n return estimateGas(\n address,\n poolContract.methods.swapExactAmountIn,\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n tokenAmountIn,\n minAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n }\n\n /**\n * Swaps an exact amount of tokensIn to get a mimum amount of tokenOut\n * Trades an exact tokenAmountIn of tokenIn taken from the caller by the pool,\n * in exchange for at least minAmountOut of tokenOut given to the caller from the pool, with a maximum marginal price of maxPrice.\n * Returns (tokenAmountOut, spotPriceAfter), where tokenAmountOut is the amount of token that came out of the pool,\n * and spotPriceAfter is the new marginal spot price, ie, the result of getSpotPrice after the call.\n * (These values are what are limited by the arguments; you are guaranteed tokenAmountOut >= minAmountOut and spotPriceAfter <= maxPrice).\n * @param {String} address\n * @param {String} poolAddress\n * @param {TokenInOutMarket} tokenInOutMarket object contianing addresses like tokenIn, tokenOut, consumeMarketFeeAddress\n * @param {AmountsInMaxFee} amountsInOutMaxFee object contianing tokenAmountIn, minAmountOut, maxPrice, consumeMarketSwapFee\n * @return {TransactionReceipt}\n */\n async swapExactAmountIn(\n address: string,\n poolAddress: string,\n tokenInOutMarket: TokenInOutMarket,\n amountsInOutMaxFee: AmountsInMaxFee\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n\n const maxSwap = await getMaxSwapExactIn(this, poolAddress, tokenInOutMarket.tokenIn)\n if (new Decimal(amountsInOutMaxFee.tokenAmountIn).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountIn is greater than ${maxSwap.toString()}`)\n }\n\n const tokenAmountIn = await this.amountToUnits(\n tokenInOutMarket.tokenIn,\n amountsInOutMaxFee.tokenAmountIn,\n tokenInOutMarket.tokenInDecimals\n )\n\n const minAmountOut = await this.amountToUnits(\n tokenInOutMarket.tokenOut,\n amountsInOutMaxFee.minAmountOut,\n tokenInOutMarket.tokenOutDecimals\n )\n\n const maxPrice = amountsInOutMaxFee.maxPrice\n ? await this.amountToUnits(\n await this.getBaseToken(poolAddress),\n amountsInOutMaxFee.maxPrice\n )\n : MaxUint256\n\n const estGas = await estimateGas(\n address,\n pool.methods.swapExactAmountIn,\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n tokenAmountIn,\n minAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n\n let result = null\n try {\n result = await pool.methods\n .swapExactAmountIn(\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n tokenAmountIn,\n minAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to swap exact amount in : ${e.message}`)\n }\n\n return result\n }\n\n /**\n * Estimate gas cost for swapExactAmountOut\n * @param {String} address\n * @param {String} poolAddress\n * @param {TokenInOutMarket} tokenInOutMarket\n * @param {AmountsOutMaxFee} amountsInOutMaxFee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSwapExactAmountOut(\n address: string,\n poolAddress: string,\n tokenInOutMarket: TokenInOutMarket,\n amountsInOutMaxFee: AmountsOutMaxFee,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n const maxAmountIn = await this.amountToUnits(\n tokenInOutMarket.tokenIn,\n amountsInOutMaxFee.maxAmountIn,\n tokenInOutMarket.tokenInDecimals\n )\n\n const tokenAmountOut = await this.amountToUnits(\n tokenInOutMarket.tokenOut,\n amountsInOutMaxFee.tokenAmountOut,\n tokenInOutMarket.tokenOutDecimals\n )\n\n const maxPrice = amountsInOutMaxFee.maxPrice\n ? await this.amountToUnits(\n await this.getBaseToken(poolAddress),\n amountsInOutMaxFee.maxPrice\n )\n : MaxUint256\n\n return estimateGas(\n address,\n poolContract.methods.swapExactAmountOut,\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n maxAmountIn,\n tokenAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n }\n\n /**\n * Swaps a maximum maxAmountIn of tokensIn to get an exact amount of tokenOut\n * @param {String} account\n * @param {String} poolAddress\n * @param {TokenInOutMarket} tokenInOutMarket Object containing addresses like tokenIn, tokenOut, consumeMarketFeeAddress\n * @param {AmountsOutMaxFee} amountsInOutMaxFee Object containging maxAmountIn,tokenAmountOut,maxPrice, consumeMarketSwapFee]\n * @return {TransactionReceipt}\n */\n async swapExactAmountOut(\n account: string,\n poolAddress: string,\n tokenInOutMarket: TokenInOutMarket,\n amountsInOutMaxFee: AmountsOutMaxFee\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n\n const maxSwap = await getMaxSwapExactOut(this, poolAddress, tokenInOutMarket.tokenOut)\n if (new Decimal(amountsInOutMaxFee.tokenAmountOut).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`)\n }\n\n const maxAmountIn = await this.amountToUnits(\n tokenInOutMarket.tokenIn,\n amountsInOutMaxFee.maxAmountIn,\n tokenInOutMarket.tokenInDecimals\n )\n\n const tokenAmountOut = await this.amountToUnits(\n tokenInOutMarket.tokenOut,\n amountsInOutMaxFee.tokenAmountOut,\n tokenInOutMarket.tokenOutDecimals\n )\n\n const maxPrice = amountsInOutMaxFee.maxPrice\n ? this.amountToUnits(\n await this.getBaseToken(poolAddress),\n amountsInOutMaxFee.maxPrice\n )\n : MaxUint256\n\n const estGas = await estimateGas(\n account,\n pool.methods.swapExactAmountOut,\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n maxAmountIn,\n tokenAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n\n try {\n result = await pool.methods\n .swapExactAmountOut(\n [\n tokenInOutMarket.tokenIn,\n tokenInOutMarket.tokenOut,\n tokenInOutMarket.marketFeeAddress\n ],\n [\n maxAmountIn,\n tokenAmountOut,\n maxPrice,\n this.web3.utils.toWei(amountsInOutMaxFee.swapMarketFee)\n ]\n )\n .send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to swap exact amount out: ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for joinswapExternAmountIn\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} tokenIn\n * @param {String} tokenAmountIn exact number of base tokens to spend\n * @param {String} minPoolAmountOut minimum of pool shares expectex\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estJoinswapExternAmountIn(\n address: string,\n poolAddress: string,\n tokenAmountIn: string,\n minPoolAmountOut: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(\n address,\n poolContract.methods.joinswapExternAmountIn,\n tokenAmountIn,\n minPoolAmountOut\n )\n }\n\n /**\n * Single side add liquidity to the pool,\n * expecting a minPoolAmountOut of shares for spending tokenAmountIn basetokens.\n * Pay tokenAmountIn of baseToken to join the pool, getting poolAmountOut of the pool shares.\n * @param {String} account\n * @param {String} poolAddress\n * @param {String} tokenAmountIn exact number of base tokens to spend\n * @param {String} minPoolAmountOut minimum of pool shares expectex\n * @param {number} tokenInDecimals optional number of decimals of the token\n * @return {TransactionReceipt}\n */\n async joinswapExternAmountIn(\n account: string,\n poolAddress: string,\n tokenAmountIn: string,\n minPoolAmountOut: string,\n tokenInDecimals?: number\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n const tokenIn = await this.getBaseToken(poolAddress)\n const maxSwap = await getMaxAddLiquidity(this, poolAddress, tokenIn)\n if (new Decimal(tokenAmountIn).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`)\n }\n\n const amountInFormatted = await this.amountToUnits(\n tokenIn,\n tokenAmountIn,\n tokenInDecimals\n )\n const estGas = await estimateGas(\n account,\n pool.methods.joinswapExternAmountIn,\n amountInFormatted,\n this.web3.utils.toWei(minPoolAmountOut)\n )\n\n try {\n result = await pool.methods\n .joinswapExternAmountIn(\n amountInFormatted,\n this.web3.utils.toWei(minPoolAmountOut)\n )\n .send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to pay tokens in order to \\\n join the pool: ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for exitswapPoolAmountIn\n * @param {String} address\n * @param {String} poolAddress\n * @param {String} poolAmountIn exact number of pool shares to spend\n * @param {String} minTokenAmountOut minimum amount of basetokens expected\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estExitswapPoolAmountIn(\n address: string,\n poolAddress: string,\n poolAmountIn: string,\n minTokenAmountOut: string,\n contractInstance?: Contract\n ): Promise<number> {\n const poolContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi as AbiItem[], poolAddress),\n this.config\n )\n\n return estimateGas(\n address,\n poolContract.methods.exitswapPoolAmountIn,\n poolAmountIn,\n minTokenAmountOut\n )\n }\n\n /**\n * Single side remove liquidity from the pool,\n * expecting a minAmountOut of basetokens for spending poolAmountIn pool shares\n * Pay poolAmountIn pool shares into the pool, getting minTokenAmountOut of the baseToken\n * @param {String} account\n * @param {String} poolAddress\n * @param {String} poolAmountIn exact number of pool shares to spend\n * @param {String} minTokenAmountOut minimum amount of basetokens expected\n * @param {number} poolDecimals optional number of decimals of the poool\n * @return {TransactionReceipt}\n */\n async exitswapPoolAmountIn(\n account: string,\n poolAddress: string,\n poolAmountIn: string,\n minTokenAmountOut: string,\n poolDecimals?: number\n ): Promise<TransactionReceipt> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let result = null\n const tokenOut = await this.getBaseToken(poolAddress)\n\n const tokenAmountOut = await this.calcSingleOutGivenPoolIn(\n poolAddress,\n tokenOut,\n poolAmountIn\n )\n\n const maxSwap = await getMaxRemoveLiquidity(this, poolAddress, tokenOut)\n if (new Decimal(tokenAmountOut).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`)\n }\n\n const minTokenOutFormatted = await this.amountToUnits(\n await this.getBaseToken(poolAddress),\n minTokenAmountOut,\n poolDecimals\n )\n const estGas = await estimateGas(\n account,\n pool.methods.exitswapPoolAmountIn,\n this.web3.utils.toWei(poolAmountIn),\n minTokenOutFormatted\n )\n\n try {\n result = await pool.methods\n .exitswapPoolAmountIn(this.web3.utils.toWei(poolAmountIn), minTokenOutFormatted)\n .send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to pay pool shares into the pool: ${e.message}`)\n }\n return result\n }\n\n /**\n * Return the spot price of swapping tokenIn to tokenOut\n * @param {String} poolAddress\n * @param {String} tokenIn in token\n * @param {String} tokenOut out token\n * @param {String} swapMarketFe consume market swap fee\n * @return {String}\n */\n async getSpotPrice(\n poolAddress: string,\n tokenIn: string,\n tokenOut: string,\n swapMarketFee: string\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let decimalsTokenIn = 18\n let decimalsTokenOut = 18\n\n const tokenInContract = setContractDefaults(\n new this.web3.eth.Contract(defaultErc20Abi.abi as AbiItem[], tokenIn),\n this.config\n )\n const tokenOutContract = setContractDefaults(\n new this.web3.eth.Contract(defaultErc20Abi.abi as AbiItem[], tokenOut),\n this.config\n )\n try {\n decimalsTokenIn = await tokenInContract.methods.decimals().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: FAILED TO CALL DECIMALS(), USING 18 ${e.message}`)\n }\n try {\n decimalsTokenOut = await tokenOutContract.methods.decimals().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: FAILED TO CALL DECIMALS(), USING 18 ${e.message}`)\n }\n\n let price = null\n try {\n price = await pool.methods\n .getSpotPrice(tokenIn, tokenOut, this.web3.utils.toWei(swapMarketFee))\n .call()\n price = new BigNumber(price.toString())\n } catch (e) {\n LoggerInstance.error(\n 'ERROR: Failed to get spot price of swapping tokenIn to tokenOut'\n )\n }\n\n let decimalsDiff\n if (decimalsTokenIn > decimalsTokenOut) {\n decimalsDiff = decimalsTokenIn - decimalsTokenOut\n price = new BigNumber(price / 10 ** decimalsDiff)\n price = price / 10 ** decimalsTokenOut\n } else {\n decimalsDiff = decimalsTokenOut - decimalsTokenIn\n price = new BigNumber(price * 10 ** (2 * decimalsDiff))\n price = price / 10 ** decimalsTokenOut\n }\n\n return price.toString()\n }\n\n /**\n * How many tokensIn do you need in order to get exact tokenAmountOut.\n * Returns: tokenAmountIn, swapFee, opcFee , consumeMarketSwapFee, publishMarketSwapFee\n * Returns: tokenAmountIn, LPFee, opcFee , publishMarketSwapFee, consumeMarketSwapFee\n * @param tokenIn token to be swaped\n * @param tokenOut token to get\n * @param tokenAmountOut exact amount of tokenOut\n * @param swapMarketFee consume market swap fee\n * @param {number} tokenInDecimals optional number of decimals of the token to be swaped\n * @param {number} tokenOutDecimals optional number of decimals of the token to get\n */\n public async getAmountInExactOut(\n poolAddress: string,\n tokenIn: string,\n tokenOut: string,\n tokenAmountOut: string,\n swapMarketFee: string,\n tokenInDecimals?: number,\n tokenOutDecimals?: number\n ): Promise<PoolPriceAndFees> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n\n const maxSwap = await getMaxSwapExactOut(this, poolAddress, tokenOut)\n\n if (new Decimal(tokenAmountOut).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountOut is greater than ${maxSwap.toString()}`)\n }\n\n const amountOutFormatted = await this.amountToUnits(\n tokenOut,\n tokenAmountOut,\n tokenOutDecimals\n )\n\n let amount = null\n\n try {\n const result = await pool.methods\n .getAmountInExactOut(\n tokenIn,\n tokenOut,\n amountOutFormatted,\n this.web3.utils.toWei(swapMarketFee)\n )\n .call()\n amount = {\n tokenAmount: await this.unitsToAmount(\n tokenOut,\n result.tokenAmountIn,\n tokenOutDecimals\n ),\n liquidityProviderSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.lpFeeAmount,\n tokenInDecimals\n ),\n oceanFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.oceanFeeAmount,\n tokenInDecimals\n ),\n publishMarketSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.publishMarketSwapFeeAmount,\n tokenInDecimals\n ),\n consumeMarketSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.consumeMarketSwapFeeAmount,\n tokenInDecimals\n )\n }\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to calcInGivenOut ${e.message}`)\n }\n return amount\n }\n\n /**\n * How many tokensOut you will get for a exact tokenAmountIn\n * Returns: tokenAmountOut, LPFee, opcFee , publishMarketSwapFee, consumeMarketSwapFee\n * @param tokenIn token to be swaped\n * @param tokenOut token to get\n * @param tokenAmountIn exact amount of tokenIn\n * @param swapMarketFee\n * @param {number} tokenInDecimals optional number of decimals of the token to be swaped\n * @param {number} tokenOutDecimals optional number of decimals of the token to get\n */\n public async getAmountOutExactIn(\n poolAddress: string,\n tokenIn: string,\n tokenOut: string,\n tokenAmountIn: string,\n swapMarketFee: string,\n tokenInDecimals?: number,\n tokenOutDecimals?: number\n ): Promise<PoolPriceAndFees> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n\n const maxSwap = await getMaxSwapExactIn(this, poolAddress, tokenIn)\n if (new Decimal(tokenAmountIn).greaterThan(maxSwap)) {\n throw new Error(`tokenAmountIn is greater than ${maxSwap.toString()}`)\n }\n\n const amountInFormatted = await this.amountToUnits(\n tokenIn,\n tokenAmountIn,\n tokenInDecimals\n )\n\n let amount = null\n\n try {\n const result = await pool.methods\n .getAmountOutExactIn(\n tokenIn,\n tokenOut,\n amountInFormatted,\n this.web3.utils.toWei(swapMarketFee)\n )\n .call()\n\n amount = {\n tokenAmount: await this.unitsToAmount(\n tokenOut,\n result.tokenAmountOut,\n tokenOutDecimals\n ),\n liquidityProviderSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.lpFeeAmount,\n tokenInDecimals\n ),\n oceanFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.oceanFeeAmount,\n tokenInDecimals\n ),\n publishMarketSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.publishMarketSwapFeeAmount,\n tokenInDecimals\n ),\n consumeMarketSwapFeeAmount: await this.unitsToAmount(\n tokenIn,\n result.consumeMarketSwapFeeAmount,\n tokenInDecimals\n )\n }\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to calcOutGivenIn ${e.message}`)\n }\n return amount\n }\n\n /**\n * Returns number of poolshares obtain by staking exact tokenAmountIn tokens\n * @param tokenIn tokenIn\n * @param tokenAmountIn exact number of tokens staked\n * @param {number} poolDecimals optional number of decimals of the poool\n * @param {number} tokenInDecimals optional number of decimals of the token\n */\n public async calcPoolOutGivenSingleIn(\n poolAddress: string,\n tokenIn: string,\n tokenAmountIn: string,\n poolDecimals?: number,\n tokenInDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n\n try {\n const result = await pool.methods\n .calcPoolOutSingleIn(\n tokenIn,\n await this.amountToUnits(tokenIn, tokenAmountIn, tokenInDecimals)\n )\n .call()\n\n amount = await this.unitsToAmount(poolAddress, result, poolDecimals)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to calculate PoolOutGivenSingleIn : ${e.message}`\n )\n }\n return amount\n }\n\n /**\n * Returns number of tokens to be staked to the pool in order to get an exact number of poolshares\n * @param tokenIn tokenIn\n * @param poolAmountOut expected amount of pool shares\n * @param {number} poolDecimals optional number of decimals of the pool\n * @param {number} tokenInDecimals optional number of decimals of the token\n */\n public async calcSingleInGivenPoolOut(\n poolAddress: string,\n tokenIn: string,\n poolAmountOut: string,\n poolDecimals?: number,\n tokenInDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n const amountFormatted = await this.amountToUnits(\n poolAddress,\n poolAmountOut,\n poolDecimals\n )\n try {\n const result = await pool.methods\n .calcSingleInPoolOut(tokenIn, amountFormatted)\n .call()\n\n amount = await this.unitsToAmount(tokenIn, result, tokenInDecimals)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to calculate SingleInGivenPoolOut : ${e.message}`\n )\n }\n return amount\n }\n\n /**\n * Returns expected amount of tokenOut for removing exact poolAmountIn pool shares from the pool\n * @param tokenOut tokenOut\n * @param poolAmountIn amount of shares spent\n * @param {number} poolDecimals optional number of decimals of the pool\n * @param {number} tokenOutDecimals optional number of decimals of the token\n */\n public async calcSingleOutGivenPoolIn(\n poolAddress: string,\n tokenOut: string,\n poolAmountIn: string,\n poolDecimals?: number,\n tokenOutDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n\n try {\n const result = await pool.methods\n .calcSingleOutPoolIn(\n tokenOut,\n await this.amountToUnits(poolAddress, poolAmountIn, poolDecimals)\n )\n .call()\n amount = await this.unitsToAmount(tokenOut, result, tokenOutDecimals)\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to calculate SingleOutGivenPoolIn : ${e}`)\n }\n return amount\n }\n\n /**\n * Returns number of poolshares needed to withdraw exact tokenAmountOut tokens\n * @param tokenOut tokenOut\n * @param tokenAmountOut expected amount of tokensOut\n * @param {number} poolDecimals optional number of decimals of the pool\n * @param {number} tokenOutDecimals optional number of decimals of the token\n */\n public async calcPoolInGivenSingleOut(\n poolAddress: string,\n tokenOut: string,\n tokenAmountOut: string,\n poolDecimals?: number,\n tokenOutDecimals?: number\n ): Promise<string> {\n const pool = setContractDefaults(\n new this.web3.eth.Contract(this.poolAbi, poolAddress),\n this.config\n )\n let amount = null\n\n try {\n const result = await pool.methods\n .calcPoolInSingleOut(\n tokenOut,\n await this.amountToUnits(tokenOut, tokenAmountOut, tokenOutDecimals)\n )\n .call()\n\n amount = await this.unitsToAmount(poolAddress, result, poolDecimals)\n } catch (e) {\n LoggerInstance.error(\n `ERROR: Failed to calculate PoolInGivenSingleOut : ${e.message}`\n )\n }\n return amount\n }\n\n /**\n * Get LOG_SWAP encoded topic\n * @return {String}\n */\n public getSwapEventSignature(): string {\n const abi = this.poolAbi as AbiItem[]\n const eventdata = abi.find(\n ({ name, type }) => type === 'event' && name === 'LOG_SWAP'\n )\n const topic = this.web3.eth.abi.encodeEventSignature(eventdata)\n return topic\n }\n\n /**\n * Get LOG_JOIN encoded topic\n * @return {String}\n */\n public getJoinEventSignature(): string {\n const abi = this.poolAbi as AbiItem[]\n const eventdata = abi.find(\n ({ name, type }) => type === 'event' && name === 'LOG_JOIN'\n )\n const topic = this.web3.eth.abi.encodeEventSignature(eventdata)\n return topic\n }\n\n /**\n * Get LOG_EXIT encoded topic\n * @return {String}\n */\n public getExitEventSignature(): string {\n const abi = this.poolAbi as AbiItem[]\n const eventdata = abi.find(\n ({ name, type }) => type === 'event' && name === 'LOG_EXIT'\n )\n const topic = this.web3.eth.abi.encodeEventSignature(eventdata)\n return topic\n }\n}\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils'\nimport { Contract } from 'web3-eth-contract'\nimport { TransactionReceipt } from 'web3-eth'\nimport Decimal from 'decimal.js'\nimport defaultDispenserAbi from '@oceanprotocol/contracts/artifacts/contracts/pools/dispenser/Dispenser.sol/Dispenser.json'\nimport {\n LoggerInstance as logger,\n getFairGasPrice,\n setContractDefaults,\n estimateGas,\n ConfigHelper\n} from '../../utils/'\nimport { Datatoken } from '../../tokens'\nimport { Config } from '../../models/index.js'\n\nexport interface DispenserToken {\n active: boolean\n owner: string\n maxTokens: string\n maxBalance: string\n balance: string\n isMinter: boolean\n allowedSwapper: string\n}\n\nexport class Dispenser {\n public web3: Web3 = null\n public dispenserAddress: string\n public config: Config\n public dispenserAbi: AbiItem | AbiItem[]\n public dispenserContract: Contract\n\n /**\n * Instantiate Dispenser\n * @param {any} web3\n * @param {String} dispenserAddress\n * @param {any} dispenserABI\n */\n constructor(\n web3: Web3,\n network?: string | number,\n dispenserAddress: string = null,\n dispenserAbi: AbiItem | AbiItem[] = null,\n config?: Config\n ) {\n this.web3 = web3\n this.dispenserAddress = dispenserAddress\n this.dispenserAbi = dispenserAbi || (defaultDispenserAbi.abi as AbiItem[])\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n if (web3)\n this.dispenserContract = setContractDefaults(\n new this.web3.eth.Contract(this.dispenserAbi, this.dispenserAddress),\n this.config\n )\n }\n\n /**\n * Get information about a datatoken dispenser\n * @param {String} dtAddress\n * @return {Promise<FixedPricedExchange>} Exchange details\n */\n public async status(dtAdress: string): Promise<DispenserToken> {\n try {\n const result: DispenserToken = await this.dispenserContract.methods\n .status(dtAdress)\n .call()\n result.maxTokens = this.web3.utils.fromWei(result.maxTokens)\n result.maxBalance = this.web3.utils.fromWei(result.maxBalance)\n result.balance = this.web3.utils.fromWei(result.balance)\n return result\n } catch (e) {\n logger.warn(`No dispenser available for datatoken: ${dtAdress}`)\n }\n return null\n }\n\n /**\n * Estimate gas cost for create method\n * @param {String} dtAddress Datatoken address\n * @param {String} address Owner address\n * @param {String} maxTokens max tokens to dispense\n * @param {String} maxBalance max balance of requester\n * @param {String} allowedSwapper if !=0, only this address can request DTs\n * @return {Promise<any>}\n */\n public async estGasCreate(\n dtAddress: string,\n address: string,\n maxTokens: string,\n maxBalance: string,\n allowedSwapper: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.dispenserContract.methods.create,\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance),\n address,\n allowedSwapper\n )\n }\n\n /**\n * Creates a new Dispenser\n * @param {String} dtAddress Datatoken address\n * @param {String} address Owner address\n * @param {String} maxTokens max tokens to dispense\n * @param {String} maxBalance max balance of requester\n * @param {String} allowedSwapper only account that can ask tokens. set address(0) if not required\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async create(\n dtAddress: string,\n address: string,\n maxTokens: string,\n maxBalance: string,\n allowedSwapper: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.create,\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance),\n address,\n allowedSwapper\n )\n\n // Call createFixedRate contract method\n const trxReceipt = await this.dispenserContract.methods\n .create(\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance),\n address,\n allowedSwapper\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas for activate method\n * @param {String} dtAddress\n * @param {Number} maxTokens max amount of tokens to dispense\n * @param {Number} maxBalance max balance of user. If user balance is >, then dispense will be rejected\n * @param {String} address User address (must be owner of the datatoken)\n * @return {Promise<any>}\n */\n public async estGasActivate(\n dtAddress: string,\n maxTokens: string,\n maxBalance: string,\n address: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.dispenserContract.methods.activate,\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance)\n )\n }\n\n /**\n * Activates a new dispener.\n * @param {String} dtAddress refers to datatoken address.\n * @param {Number} maxTokens max amount of tokens to dispense\n * @param {Number} maxBalance max balance of user. If user balance is >, then dispense will be rejected\n * @param {String} address User address (must be owner of the datatoken)\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async activate(\n dtAddress: string,\n maxTokens: string,\n maxBalance: string,\n address: string\n ): Promise<TransactionReceipt> {\n try {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.activate,\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance)\n )\n\n const trxReceipt = await this.dispenserContract.methods\n .activate(\n dtAddress,\n this.web3.utils.toWei(maxTokens),\n this.web3.utils.toWei(maxBalance)\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to activate dispenser: ${e.message}`)\n }\n return null\n }\n\n /**\n * Estimate gas for deactivate method\n * @param {String} dtAddress\n * @param {String} address User address (must be owner of the datatoken)\n * @return {Promise<any>}\n */\n public async estGasDeactivate(dtAddress: string, address: string): Promise<any> {\n return estimateGas(address, this.dispenserContract.methods.deactivate, dtAddress)\n }\n\n /**\n * Deactivate an existing dispenser.\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async deactivate(\n dtAddress: string,\n address: string\n ): Promise<TransactionReceipt> {\n try {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.deactivate,\n dtAddress\n )\n\n const trxReceipt = await this.dispenserContract.methods.deactivate(dtAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to activate dispenser: ${e.message}`)\n }\n return null\n }\n\n /**\n * Estimate gas for setAllowedSwapper method\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @param {String} newAllowedSwapper refers to the new allowedSwapper\n * @return {Promise<any>}\n */\n public async estGasSetAllowedSwapper(\n dtAddress: string,\n address: string,\n newAllowedSwapper: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.dispenserContract.methods.setAllowedSwapper,\n dtAddress,\n newAllowedSwapper\n )\n }\n\n /**\n * Sets a new allowedSwapper.\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @param {String} newAllowedSwapper refers to the new allowedSwapper\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async setAllowedSwapper(\n dtAddress: string,\n address: string,\n newAllowedSwapper: string\n ): Promise<TransactionReceipt> {\n try {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.setAllowedSwapper,\n dtAddress,\n newAllowedSwapper\n )\n\n const trxReceipt = await this.dispenserContract.methods\n .setAllowedSwapper(dtAddress, newAllowedSwapper)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to activate dispenser: ${e.message}`)\n }\n return null\n }\n\n /**\n * Estimate gas for dispense method\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @param {String} newAllowedSwapper refers to the new allowedSwapper\n * @return {Promise<any>}\n */\n public async estGasDispense(\n dtAddress: string,\n address: string,\n amount: string = '1',\n destination: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.dispenserContract.methods.dispense,\n dtAddress,\n this.web3.utils.toWei(amount),\n destination\n )\n }\n\n /**\n * Dispense datatokens to caller.\n * The dispenser must be active, hold enough DT (or be able to mint more)\n * and respect maxTokens/maxBalance requirements\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address\n * @param {String} amount amount of datatokens required.\n * @param {String} destination who will receive the tokens\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async dispense(\n dtAddress: string,\n address: string,\n amount: string = '1',\n destination: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.dispense,\n dtAddress,\n this.web3.utils.toWei(amount),\n destination\n )\n\n try {\n const trxReceipt = await this.dispenserContract.methods\n .dispense(dtAddress, this.web3.utils.toWei(amount), destination)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to dispense tokens: ${e.message}`)\n }\n return null\n }\n\n /**\n * Estimate gas for ownerWithdraw method\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the datatoken)\n * @param {String} newAllowedSwapper refers to the new allowedSwapper\n * @return {Promise<any>}\n */\n public async estGasOwnerWithdraw(dtAddress: string, address: string): Promise<any> {\n return estimateGas(address, this.dispenserContract.methods.ownerWithdraw, dtAddress)\n }\n\n /**\n * Withdraw all tokens from the dispenser\n * @param {String} dtAddress refers to datatoken address.\n * @param {String} address User address (must be owner of the dispenser)\n * @return {Promise<TransactionReceipt>} TransactionReceipt\n */\n public async ownerWithdraw(\n dtAddress: string,\n address: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.dispenserContract.methods.ownerWithdraw,\n dtAddress\n )\n\n try {\n const trxReceipt = await this.dispenserContract.methods\n .ownerWithdraw(dtAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n logger.error(`ERROR: Failed to withdraw tokens: ${e.message}`)\n }\n return null\n }\n\n /**\n * Check if tokens can be dispensed\n * @param {String} dtAddress\n * @param {String} address User address that will receive datatokens\n * @param {String} amount amount of datatokens required.\n * @return {Promise<Boolean>}\n */\n public async isDispensable(\n dtAddress: string,\n datatoken: Datatoken,\n address: string,\n amount: string = '1'\n ): Promise<Boolean> {\n const status = await this.status(dtAddress)\n if (!status) return false\n // check active\n if (status.active === false) return false\n // check maxBalance\n const userBalance = new Decimal(await datatoken.balance(dtAddress, address))\n if (userBalance.greaterThanOrEqualTo(status.maxBalance)) return false\n // check maxAmount\n if (new Decimal(String(amount)).greaterThan(status.maxTokens)) return false\n // check dispenser balance\n const contractBalance = new Decimal(status.balance)\n if (contractBalance.greaterThanOrEqualTo(amount) || status.isMinter === true)\n return true\n return false\n }\n}\n","import defaultFixedRateExchangeAbi from '@oceanprotocol/contracts/artifacts/contracts/pools/fixedRate/FixedRateExchange.sol/FixedRateExchange.json'\nimport { TransactionReceipt } from 'web3-core'\nimport { Contract } from 'web3-eth-contract'\nimport { AbiItem } from 'web3-utils/types'\nimport Web3 from 'web3'\nimport {\n LoggerInstance,\n getFairGasPrice,\n setContractDefaults,\n amountToUnits,\n unitsToAmount,\n estimateGas,\n ZERO_ADDRESS,\n ConfigHelper\n} from '../../utils'\nimport { Config } from '../../models/index.js'\nimport { PriceAndFees } from '../..'\n\nexport interface FixedPriceExchange {\n active: boolean\n exchangeOwner: string\n datatoken: string\n baseToken: string\n fixedRate: string\n dtDecimals: string\n btDecimals: string\n dtBalance: string\n btBalance: string\n dtSupply: string\n btSupply: string\n withMint: boolean\n allowedSwapper: string\n exchangeId?: string\n}\n\nexport interface FeesInfo {\n opcFee: string\n marketFee: string\n marketFeeCollector: string\n marketFeeAvailable: string\n oceanFeeAvailable: string\n exchangeId: string\n}\nexport interface FixedPriceSwap {\n exchangeId: string\n caller: string\n baseTokenAmount: string\n datatokenAmount: string\n}\n\n/* eslint-disable no-unused-vars */\nexport enum FixedRateCreateProgressStep {\n CreatingExchange,\n ApprovingDatatoken\n}\n/* eslint-enable no-unused-vars */\n\nexport class FixedRateExchange {\n /** Ocean related functions */\n public oceanAddress: string = null\n public fixedRateAddress: string\n public fixedRateExchangeAbi: AbiItem | AbiItem[]\n public web3: Web3\n public fixedRateContract: Contract = null\n\n public config: Config\n public ssAbi: AbiItem | AbiItem[]\n\n /**\n * Instantiate FixedRateExchange\n * @param {any} web3\n * @param {any} fixedRateExchangeAbi\n */\n constructor(\n web3: Web3,\n fixedRateAddress: string,\n network?: string | number,\n fixedRateExchangeAbi: AbiItem | AbiItem[] = null,\n oceanAddress: string = null,\n config?: Config\n ) {\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n this.fixedRateExchangeAbi =\n fixedRateExchangeAbi || (defaultFixedRateExchangeAbi.abi as AbiItem[])\n this.oceanAddress = oceanAddress\n this.fixedRateAddress = fixedRateAddress\n this.fixedRateContract = setContractDefaults(\n new this.web3.eth.Contract(this.fixedRateExchangeAbi, this.fixedRateAddress),\n this.config\n )\n }\n\n async amountToUnits(\n token: string,\n amount: string,\n tokenDecimals: number\n ): Promise<string> {\n return amountToUnits(this.web3, token, amount, tokenDecimals)\n }\n\n async unitsToAmount(\n token: string,\n amount: string,\n tokenDecimals: number\n ): Promise<string> {\n return unitsToAmount(this.web3, token, amount, tokenDecimals)\n }\n\n /**\n * Creates unique exchange identifier.\n * @param {String} baseToken baseToken contract address\n * @param {String} datatoken Datatoken contract address\n * @return {Promise<string>} exchangeId\n */\n public async generateExchangeId(baseToken: string, datatoken: string): Promise<string> {\n const exchangeId = await this.fixedRateContract.methods\n .generateExchangeId(baseToken, datatoken)\n .call()\n return exchangeId\n }\n\n /**\n * Estimate gas cost for buyDT\n * @param {String} account\n * @param {String} dtAmount datatoken amount we want to buy\n * @param {String} datatokenAddress datatokenAddress\n * @param {String} consumeMarketAddress consumeMarketAddress\n * @param {String} consumeMarketFee fee recieved by the consume market when a dt is bought from a fixed rate exchange, percent\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estBuyDT(\n account: string,\n datatokenAddress: string,\n dtAmount: string,\n maxBaseTokenAmount: string,\n consumeMarketAddress: string,\n consumeMarketFee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.buyDT,\n datatokenAddress,\n dtAmount,\n maxBaseTokenAmount,\n consumeMarketAddress,\n consumeMarketFee\n )\n }\n\n /**\n * Atomic swap\n * @param {String} exchangeId ExchangeId\n * @param {String} datatokenAmount Amount of datatokens\n * @param {String} maxBaseTokenAmount max amount of baseToken we want to pay for datatokenAmount\n * @param {String} address User address\n * @param {String} consumeMarketAddress consumeMarketAddress\n * @param {String} consumeMarketFee consumeMarketFee in fraction\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async buyDT(\n address: string,\n exchangeId: string,\n datatokenAmount: string,\n maxBaseTokenAmount: string,\n consumeMarketAddress: string = ZERO_ADDRESS,\n consumeMarketFee: string = '0'\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n const consumeMarketFeeFormatted = this.web3.utils.toWei(consumeMarketFee)\n const dtAmountFormatted = await this.amountToUnits(\n exchange.datatoken,\n datatokenAmount,\n +exchange.dtDecimals\n )\n const maxBtFormatted = await this.amountToUnits(\n exchange.baseToken,\n maxBaseTokenAmount,\n +exchange.btDecimals\n )\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.buyDT,\n exchangeId,\n dtAmountFormatted,\n maxBtFormatted,\n consumeMarketAddress,\n consumeMarketFeeFormatted\n )\n try {\n const trxReceipt = await this.fixedRateContract.methods\n .buyDT(\n exchangeId,\n dtAmountFormatted,\n maxBtFormatted,\n consumeMarketAddress,\n consumeMarketFeeFormatted\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to buy datatokens: ${e.message}`)\n return null\n }\n }\n\n /**\n * Estimate gas cost for sellDT\n * @param {String} account\n * @param {String} dtAmount datatoken amount we want to sell\n * @param {String} datatokenAddress datatokenAddress\n * @param {String} consumeMarketAddress consumeMarketAddress\n * @param {String} consumeMarketFee consumeMarketFee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSellDT(\n account: string,\n datatokenAddress: string,\n dtAmount: string,\n maxBaseTokenAmount: string,\n consumeMarketAddress: string,\n consumeMarketFee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.sellDT,\n datatokenAddress,\n dtAmount,\n maxBaseTokenAmount,\n consumeMarketAddress,\n consumeMarketFee\n )\n }\n\n /**\n * Atomic swap\n * @param {String} exchangeId ExchangeId\n * @param {String} datatokenAmount Amount of datatokens\n * @param {String} minBaseTokenAmount min amount of baseToken we want to receive back\n * @param {String} address User address\n * @param {String} consumeMarketAddress consumeMarketAddress\n * @param {String} consumeMarketFee consumeMarketFee in fraction\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async sellDT(\n address: string,\n exchangeId: string,\n datatokenAmount: string,\n minBaseTokenAmount: string,\n consumeMarketAddress: string = ZERO_ADDRESS,\n consumeMarketFee: string = '0'\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n const consumeMarketFeeFormatted = this.web3.utils.toWei(consumeMarketFee)\n const dtAmountFormatted = await this.amountToUnits(\n exchange.datatoken,\n datatokenAmount,\n +exchange.dtDecimals\n )\n const minBtFormatted = await this.amountToUnits(\n exchange.baseToken,\n minBaseTokenAmount,\n +exchange.btDecimals\n )\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.sellDT,\n exchangeId,\n dtAmountFormatted,\n minBtFormatted,\n consumeMarketAddress,\n consumeMarketFeeFormatted\n )\n try {\n const trxReceipt = await this.fixedRateContract.methods\n .sellDT(\n exchangeId,\n dtAmountFormatted,\n minBtFormatted,\n consumeMarketAddress,\n consumeMarketFeeFormatted\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to sell datatokens: ${e.message}`)\n return null\n }\n }\n\n /**\n * Gets total number of exchanges\n * @param {String} exchangeId ExchangeId\n * @param {Number} datatokenAmount Amount of datatokens\n * @return {Promise<Number>} no of available exchanges\n */\n public async getNumberOfExchanges(): Promise<number> {\n const numExchanges = await this.fixedRateContract.methods\n .getNumberOfExchanges()\n .call()\n return numExchanges\n }\n\n /**\n * Estimate gas cost for setRate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} newRate New rate\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSetRate(\n account: string,\n exchangeId: string,\n newRate: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.setRate,\n exchangeId,\n await this.web3.utils.toWei(newRate)\n )\n }\n\n /**\n * Set new rate\n * @param {String} exchangeId ExchangeId\n * @param {String} newRate New rate\n * @param {String} address User account\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async setRate(\n address: string,\n exchangeId: string,\n newRate: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.setRate,\n exchangeId,\n this.web3.utils.toWei(newRate)\n )\n const trxReceipt = await this.fixedRateContract.methods\n .setRate(exchangeId, this.web3.utils.toWei(newRate))\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for setRate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} newAllowedSwapper new allowed swapper address\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSetAllowedSwapper(\n account: string,\n exchangeId: string,\n newAllowedSwapper: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.setAllowedSwapper,\n exchangeId,\n newAllowedSwapper\n )\n }\n\n /**\n * Set new rate\n * @param {String} exchangeId ExchangeId\n * @param {String} newAllowedSwapper newAllowedSwapper (set address zero if we want to remove allowed swapper)\n * @param {String} address User account\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async setAllowedSwapper(\n address: string,\n exchangeId: string,\n newAllowedSwapper: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.setAllowedSwapper,\n exchangeId,\n newAllowedSwapper\n )\n const trxReceipt = await this.fixedRateContract.methods\n .setAllowedSwapper(exchangeId, newAllowedSwapper)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for activate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estActivate(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.toggleExchangeState, exchangeId)\n }\n\n /**\n * Activate an exchange\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async activate(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n if (exchange.active === true) return null\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.toggleExchangeState,\n exchangeId\n )\n const trxReceipt = await this.fixedRateContract.methods\n .toggleExchangeState(exchangeId)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for deactivate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estDeactivate(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.toggleExchangeState, exchangeId)\n }\n\n /**\n * Deactivate an exchange\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async deactivate(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n if (exchange.active === false) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.toggleExchangeState,\n exchangeId\n )\n\n const trxReceipt = await this.fixedRateContract.methods\n .toggleExchangeState(exchangeId)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Get Rate\n * @param {String} exchangeId ExchangeId\n * @return {Promise<string>} Rate (converted from wei)\n */\n public async getRate(exchangeId: string): Promise<string> {\n const weiRate = await this.fixedRateContract.methods.getRate(exchangeId).call()\n const rate = await this.web3.utils.fromWei(weiRate)\n return rate\n }\n\n /**\n * Get Datatoken Supply in the exchange\n * @param {String} exchangeId ExchangeId\n * @return {Promise<string>} dt supply formatted\n */\n public async getDTSupply(exchangeId: string): Promise<string> {\n const dtSupply = await this.fixedRateContract.methods.getDTSupply(exchangeId).call()\n const exchange = await this.getExchange(exchangeId)\n return await this.unitsToAmount(exchange.datatoken, dtSupply, +exchange.dtDecimals)\n }\n\n /**\n * Get BaseToken Supply in the exchange\n * @param {String} exchangeId ExchangeId\n * @return {Promise<string>} dt supply formatted\n */\n public async getBTSupply(exchangeId: string): Promise<string> {\n const btSupply = await this.fixedRateContract.methods.getBTSupply(exchangeId).call()\n const exchange = await this.getExchange(exchangeId)\n return await this.unitsToAmount(exchange.baseToken, btSupply, +exchange.btDecimals)\n }\n\n /**\n * Get Allower Swapper (if set this is the only account which can use this exchange, else is set at address(0))\n * @param {String} exchangeId ExchangeId\n * @return {Promise<string>} address of allowedSwapper\n */\n public async getAllowedSwapper(exchangeId: string): Promise<string> {\n return await this.fixedRateContract.methods.getAllowedSwapper(exchangeId).call()\n }\n\n /**\n * calcBaseInGivenOutDT - Calculates how many base tokens are needed to get specified amount of datatokens\n * @param {String} exchangeId ExchangeId\n * @param {string} datatokenAmount Amount of datatokens user wants to buy\n * @param {String} consumeMarketFee consumeMarketFee in fraction\n * @return {Promise<PriceAndFees>} how many base tokens are needed and fees\n */\n public async calcBaseInGivenOutDT(\n exchangeId: string,\n datatokenAmount: string,\n consumeMarketFee: string = '0'\n ): Promise<PriceAndFees> {\n const fixedRateExchange = await this.getExchange(exchangeId)\n const result = await this.fixedRateContract.methods\n .calcBaseInGivenOutDT(\n exchangeId,\n await this.amountToUnits(\n fixedRateExchange.datatoken,\n datatokenAmount,\n +fixedRateExchange.dtDecimals\n ),\n this.web3.utils.toWei(consumeMarketFee)\n )\n .call()\n\n const priceAndFees = {\n baseTokenAmount: await this.unitsToAmount(\n fixedRateExchange.baseToken,\n result.baseTokenAmount,\n +fixedRateExchange.btDecimals\n ),\n marketFeeAmount: await this.unitsToAmount(\n fixedRateExchange.baseToken,\n result.marketFeeAmount,\n +fixedRateExchange.btDecimals\n ),\n oceanFeeAmount: await this.unitsToAmount(\n fixedRateExchange.baseToken,\n result.oceanFeeAmount,\n +fixedRateExchange.btDecimals\n ),\n consumeMarketFeeAmount: await this.unitsToAmount(\n fixedRateExchange.baseToken,\n result.consumeMarketFeeAmount,\n +fixedRateExchange.btDecimals\n )\n } as PriceAndFees\n return priceAndFees\n }\n\n /**\n * getBTOut - returns amount in baseToken that user will receive for datatokenAmount sold\n * @param {String} exchangeId ExchangeId\n * @param {Number} datatokenAmount Amount of datatokens\n * @param {String} consumeMarketFee consumeMarketFee in fraction\n * @return {Promise<string>} Amount of baseTokens user will receive\n */\n public async getAmountBTOut(\n exchangeId: string,\n datatokenAmount: string,\n consumeMarketFee: string = '0'\n ): Promise<string> {\n const exchange = await this.getExchange(exchangeId)\n const result = await this.fixedRateContract.methods\n .calcBaseOutGivenInDT(\n exchangeId,\n await this.amountToUnits(\n exchange.datatoken,\n datatokenAmount,\n +exchange.dtDecimals\n ),\n this.web3.utils.toWei(consumeMarketFee)\n )\n .call()\n\n return await this.unitsToAmount(exchange.baseToken, result[0], +exchange.btDecimals)\n }\n\n /**\n * Get exchange details\n * @param {String} exchangeId ExchangeId\n * @return {Promise<FixedPricedExchange>} Exchange details\n */\n public async getExchange(exchangeId: string): Promise<FixedPriceExchange> {\n const result: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n result.dtDecimals = result.dtDecimals.toString()\n result.btDecimals = result.btDecimals.toString()\n result.dtBalance = await this.unitsToAmount(\n result.datatoken,\n result.dtBalance,\n +result.dtDecimals\n )\n result.btBalance = await this.unitsToAmount(\n result.baseToken,\n result.btBalance,\n +result.btDecimals\n )\n result.dtSupply = await this.unitsToAmount(\n result.datatoken,\n result.dtSupply,\n +result.dtDecimals\n )\n result.btSupply = await this.unitsToAmount(\n result.baseToken,\n result.btSupply,\n +result.btDecimals\n )\n result.fixedRate = this.web3.utils.fromWei(result.fixedRate)\n result.exchangeId = exchangeId\n return result\n }\n\n /**\n * Get fee details for an exchange\n * @param {String} exchangeId ExchangeId\n * @return {Promise<FixedPricedExchange>} Exchange details\n */\n public async getFeesInfo(exchangeId: string): Promise<FeesInfo> {\n const result: FeesInfo = await this.fixedRateContract.methods\n .getFeesInfo(exchangeId)\n .call()\n result.opcFee = this.web3.utils.fromWei(result.opcFee.toString())\n result.marketFee = this.web3.utils.fromWei(result.marketFee.toString())\n\n const exchange = await this.getExchange(exchangeId)\n result.marketFeeAvailable = await this.unitsToAmount(\n exchange.baseToken,\n result.marketFeeAvailable,\n +exchange.btDecimals\n )\n result.oceanFeeAvailable = await this.unitsToAmount(\n exchange.baseToken,\n result.oceanFeeAvailable,\n +exchange.btDecimals\n )\n\n result.exchangeId = exchangeId\n return result\n }\n\n /**\n * Get all exchanges\n * @param {String} exchangeId ExchangeId\n * @return {Promise<String[]>} Exchanges list\n */\n public async getExchanges(): Promise<string[]> {\n return await this.fixedRateContract.methods.getExchanges().call()\n }\n\n /**\n * Check if an exchange is active\n * @param {String} exchangeId ExchangeId\n * @return {Promise<Boolean>} Result\n */\n public async isActive(exchangeId: string): Promise<boolean> {\n const result = await this.fixedRateContract.methods.isActive(exchangeId).call()\n return result\n }\n\n /**\n * Estimate gas cost for activate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estActivateMint(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.toggleMintState, exchangeId, true)\n }\n\n /**\n * Activate minting option for fixed rate contract\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async activateMint(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n if (exchange.withMint === true) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.toggleMintState,\n exchangeId,\n true\n )\n const trxReceipt = await this.fixedRateContract.methods\n .toggleMintState(exchangeId, true)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for deactivate\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estDeactivateMint(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.toggleMintState(exchangeId, false),\n exchangeId,\n false\n )\n }\n\n /**\n * Deactivate minting for fixed rate\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async deactivateMint(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n if (exchange.withMint === false) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.toggleMintState,\n exchangeId,\n false\n )\n\n const trxReceipt = await this.fixedRateContract.methods\n .toggleMintState(exchangeId, false)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for collectBT\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} amount amount to be collected\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectBT(\n account: string,\n exchangeId: string,\n amount: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n const amountWei = await this.amountToUnits(\n fixedrate.baseToken,\n amount,\n +fixedrate.btDecimals\n )\n return estimateGas(account, fixedRate.methods.collectBT, exchangeId, amountWei)\n }\n\n /**\n * Collect BaseTokens in the contract (anyone can call this, funds are sent to erc20.paymentCollector)\n * @param {String} address User address\n * @param {String} exchangeId ExchangeId\n * @param {String} amount amount to be collected\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async collectBT(\n address: string,\n exchangeId: string,\n amount: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n\n const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n const amountWei = await this.amountToUnits(\n fixedrate.baseToken,\n amount,\n +fixedrate.btDecimals\n )\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.collectBT,\n exchangeId,\n amountWei\n )\n\n const trxReceipt = await this.fixedRateContract.methods\n .collectBT(exchangeId, amountWei)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for collecDT\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} amount amount to be collected\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectDT(\n account: string,\n exchangeId: string,\n amount: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n\n const amountWei = await this.amountToUnits(\n fixedrate.datatoken,\n amount,\n +fixedrate.dtDecimals\n )\n return estimateGas(account, fixedRate.methods.collectDT, exchangeId, amountWei)\n }\n\n /**\n * Collect datatokens in the contract (anyone can call this, funds are sent to erc20.paymentCollector)\n * @param {String} address User address\n * @param {String} exchangeId ExchangeId\n * @param {String} amount amount to be collected\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async collectDT(\n address: string,\n exchangeId: string,\n amount: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n\n const fixedrate: FixedPriceExchange = await this.fixedRateContract.methods\n .getExchange(exchangeId)\n .call()\n const amountWei = await this.amountToUnits(\n fixedrate.datatoken,\n amount,\n +fixedrate.dtDecimals\n )\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.collectDT,\n exchangeId,\n amountWei\n )\n\n const trxReceipt = await this.fixedRateContract.methods\n .collectDT(exchangeId, amountWei)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for collecMarketFee\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectMarketFee(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.collectMarketFee, exchangeId)\n }\n\n /**\n * Collect market fee and send it to marketFeeCollector (anyone can call it)\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async collectMarketFee(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.collectMarketFee,\n exchangeId\n )\n const trxReceipt = await this.fixedRateContract.methods\n .collectMarketFee(exchangeId)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for collectOceanFee\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estCollectOceanFee(\n account: string,\n exchangeId: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(account, fixedRate.methods.collectMarketFee, exchangeId)\n }\n\n /**\n * Collect ocean fee and send it to OPF collector (anyone can call it)\n * @param {String} exchangeId ExchangeId\n * @param {String} address User address\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async collectOceanFee(\n address: string,\n exchangeId: string\n ): Promise<TransactionReceipt> {\n const exchange = await this.getExchange(exchangeId)\n if (!exchange) return null\n\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.collectOceanFee,\n exchangeId\n )\n const trxReceipt = await this.fixedRateContract.methods\n .collectOceanFee(exchangeId)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Get OPF Collector of fixed rate contract\n * @return {String}\n */\n async getOPCCollector(): Promise<string> {\n let result = null\n try {\n result = await this.fixedRateContract.methods.opcCollector().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get OPC Collector address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get Router address set in fixed rate contract\n * @return {String}\n */\n async getRouter(): Promise<string> {\n let result = null\n try {\n result = await this.fixedRateContract.methods.router().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get Router address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get Exchange Owner given an exchangeId\n * @param {String} exchangeId ExchangeId\n * @return {String} return exchange owner\n */\n async getExchangeOwner(exchangeId: string): Promise<string> {\n let result = null\n try {\n result = await (await this.getExchange(exchangeId)).exchangeOwner\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get OPF Collector address: ${e.message}`)\n }\n return result\n }\n\n /**\n * Estimate gas cost for updateMarketFee\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} newMarketFee New market fee\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estUpdateMarketFee(\n account: string,\n exchangeId: string,\n newMarketFee: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.updateMarketFee,\n exchangeId,\n newMarketFee\n )\n }\n\n /**\n * Set new market fee, only market fee collector can update it\n * @param {String} address user address\n * @param {String} exchangeId ExchangeId\n * @param {String} newMarketFee New market fee\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async updateMarketFee(\n address: string,\n exchangeId: string,\n newMarketFee: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.updateMarketFee,\n exchangeId,\n this.web3.utils.toWei(newMarketFee)\n )\n const trxReceipt = await this.fixedRateContract.methods\n .updateMarketFee(exchangeId, this.web3.utils.toWei(newMarketFee))\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for updateMarketFeeCollector\n * @param {String} account\n * @param {String} exchangeId ExchangeId\n * @param {String} newMarketFee New market fee collector\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estUpdateMarketFeeCollector(\n account: string,\n exchangeId: string,\n newMarketFeeCollector: string,\n contractInstance?: Contract\n ): Promise<number> {\n const fixedRate = contractInstance || this.fixedRateContract\n\n return estimateGas(\n account,\n fixedRate.methods.updateMarketFeeCollector,\n exchangeId,\n newMarketFeeCollector\n )\n }\n\n /**\n * Set new market fee collector, only market fee collector can update it\n * @param {String} address user address\n * @param {String} exchangeId ExchangeId\n * @param {String} newMarketFeeCollector New market fee collector\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async updateMarketFeeCollector(\n address: string,\n exchangeId: string,\n newMarketFeeCollector: string\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(\n address,\n this.fixedRateContract.methods.updateMarketFeeCollector,\n exchangeId,\n newMarketFeeCollector\n )\n const trxReceipt = await this.fixedRateContract.methods\n .updateMarketFeeCollector(exchangeId, newMarketFeeCollector)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n}\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils/types'\nimport { TransactionReceipt } from 'web3-core'\nimport { Contract } from 'web3-eth-contract'\nimport {\n LoggerInstance,\n getFairGasPrice,\n ConfigHelper,\n estimateGas,\n unitsToAmount\n} from '../../utils'\nimport SideStakingTemplate from '@oceanprotocol/contracts/artifacts/contracts/pools/ssContracts/SideStaking.sol/SideStaking.json'\nimport { Config } from '../../models'\n\nexport class SideStaking {\n public ssAbi: AbiItem | AbiItem[]\n public web3: Web3\n public config: Config\n\n constructor(\n web3: Web3,\n network?: string | number,\n ssAbi: AbiItem | AbiItem[] = null,\n config?: Config\n ) {\n if (ssAbi) this.ssAbi = ssAbi\n else this.ssAbi = SideStakingTemplate.abi as AbiItem[]\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n }\n\n async unitsToAmount(\n token: string,\n amount: string,\n tokenDecimals?: number\n ): Promise<string> {\n return unitsToAmount(this.web3, token, amount, tokenDecimals)\n }\n\n /**\n * Get (total vesting amount + token released from the contract when adding liquidity)\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatoken address\n * @return {String}\n */\n async getDatatokenCirculatingSupply(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods\n .getDatatokenCirculatingSupply(datatokenAddress)\n .call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result.toString()\n }\n\n /**\n * Get actual dts in circulation (vested token withdrawn from the contract +\n token released from the contract when adding liquidity)\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatoken address\n * @return {String}\n */\n async getDatatokenCurrentCirculatingSupply(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n try {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n result = await sideStaking.methods\n .getDatatokenCurrentCirculatingSupply(datatokenAddress)\n .call()\n return result.toString()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n }\n\n /**\n * Get Publisher address\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatoken address\n * @return {String}\n */\n async getPublisherAddress(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getPublisherAddress(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String}\n */\n async getBaseToken(ssAddress: string, datatokenAddress: string): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getBaseTokenAddress(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get Pool Address\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String}\n */\n async getPoolAddress(ssAddress: string, datatokenAddress: string): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getPoolAddress(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get baseToken balance in the contract\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String}\n */\n async getBaseTokenBalance(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getBaseTokenBalance(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get dt balance in the staking contract available for being added as liquidity\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getDatatokenBalance(\n ssAddress: string,\n datatokenAddress: string,\n tokenDecimals?: number\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getDatatokenBalance(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals)\n return result\n }\n\n /**\n * Get block when vesting ends\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String} end block for vesting amount\n */\n async getvestingEndBlock(ssAddress: string, datatokenAddress: string): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getvestingEndBlock(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get total amount vesting\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getvestingAmount(\n ssAddress: string,\n datatokenAddress: string,\n tokenDecimals?: number\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getvestingAmount(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals)\n return result\n }\n\n /**\n * Get last block publisher got some vested tokens\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {String}\n */\n async getvestingLastBlock(\n ssAddress: string,\n datatokenAddress: string\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getvestingLastBlock(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n return result\n }\n\n /**\n * Get how much has been taken from the vesting amount\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {number} tokenDecimals optional number of decimals of the token\n * @return {String}\n */\n async getvestingAmountSoFar(\n ssAddress: string,\n datatokenAddress: string,\n tokenDecimals?: number\n ): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.getvestingAmountSoFar(datatokenAddress).call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get: ${e.message}`)\n }\n result = await this.unitsToAmount(datatokenAddress, result, tokenDecimals)\n return result\n }\n\n /**\n * Estimate gas cost for getVesting\n * @param {String} account\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estGetVesting(\n account: string,\n ssAddress: string,\n datatokenAddress: string,\n contractInstance?: Contract\n ): Promise<number> {\n const sideStaking =\n contractInstance || new this.web3.eth.Contract(this.ssAbi as AbiItem[], ssAddress)\n\n return estimateGas(account, sideStaking.methods.getVesting, datatokenAddress)\n }\n\n /** Send vested tokens available to the publisher address, can be called by anyone\n *\n * @param {String} account\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {TransactionReceipt}\n */\n async getVesting(\n account: string,\n ssAddress: string,\n datatokenAddress: string\n ): Promise<TransactionReceipt> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n\n const estGas = await estimateGas(\n account,\n sideStaking.methods.getVesting,\n datatokenAddress\n )\n\n try {\n result = await sideStaking.methods.getVesting(datatokenAddress).send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error('ERROR: Failed to join swap pool amount out')\n }\n return result\n }\n\n /**\n * Estimate gas cost for getVesting\n * @param {String} account\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<number>}\n */\n public async estSetPoolSwapFee(\n account: string,\n ssAddress: string,\n datatokenAddress: string,\n poolAddress: string,\n swapFee: number,\n contractInstance?: Contract\n ): Promise<number> {\n const sideStaking =\n contractInstance || new this.web3.eth.Contract(this.ssAbi as AbiItem[], ssAddress)\n\n return estimateGas(\n account,\n sideStaking.methods.setPoolSwapFee,\n datatokenAddress,\n poolAddress,\n swapFee\n )\n }\n\n /** Send vested tokens available to the publisher address, can be called by anyone\n *\n * @param {String} account\n * @param {String} ssAddress side staking contract address\n * @param {String} datatokenAddress datatokenAddress\n * @return {TransactionReceipt}\n */\n async setPoolSwapFee(\n account: string,\n ssAddress: string,\n datatokenAddress: string,\n poolAddress: string,\n swapFee: number\n ): Promise<TransactionReceipt> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n\n const estGas = await estimateGas(\n account,\n sideStaking.methods.setPoolSwapFee,\n datatokenAddress,\n poolAddress,\n swapFee\n )\n\n try {\n result = await sideStaking.methods\n .setPoolSwapFee(datatokenAddress, poolAddress, swapFee)\n .send({\n from: account,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n } catch (e) {\n LoggerInstance.error('ERROR: Failed to join swap pool amount out')\n }\n return result\n }\n\n /**\n * Get Router address set in side staking contract\n * @param {String} ssAddress side staking contract address\n * @return {String}\n */\n async getRouter(ssAddress: string): Promise<string> {\n const sideStaking = new this.web3.eth.Contract(this.ssAbi, ssAddress)\n let result = null\n try {\n result = await sideStaking.methods.router().call()\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to get Router address: ${e.message}`)\n }\n return result\n }\n}\n","import { Contract } from 'web3-eth-contract'\nimport Web3 from 'web3'\nimport { TransactionReceipt } from 'web3-core'\nimport { AbiItem } from 'web3-utils'\nimport defaultRouter from '@oceanprotocol/contracts/artifacts/contracts/pools/FactoryRouter.sol/FactoryRouter.json'\nimport { getFairGasPrice, setContractDefaults, ConfigHelper, estimateGas } from '../utils'\nimport { Operation } from '../@types/Router'\nimport { Config } from '../models/index.js'\n\n/**\n * Provides an interface for FactoryRouter contract\n */\nexport class Router {\n public routerAddress: string\n public RouterAbi: AbiItem | AbiItem[]\n public web3: Web3\n public config: Config\n public router: Contract\n\n /**\n * Instantiate Router.\n * @param {String} routerAddress\n * @param {AbiItem | AbiItem[]} Router\n * @param {Web3} web3\n */\n constructor(\n routerAddress: string,\n web3: Web3,\n network?: string | number,\n RouterAbi?: AbiItem | AbiItem[],\n config?: Config\n ) {\n this.routerAddress = routerAddress\n this.RouterAbi = RouterAbi || (defaultRouter.abi as AbiItem[])\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n this.router = setContractDefaults(\n new this.web3.eth.Contract(this.RouterAbi, this.routerAddress),\n this.config\n )\n }\n\n /**\n * Estimate gas cost for buyDTBatch method\n * @param {String} address\n * @param {Operation} operations Operations objects array\n * @return {Promise<TransactionReceipt>} Transaction receipt\n */\n public async estGasBuyDTBatch(address: string, operations: Operation[]): Promise<any> {\n return estimateGas(address, this.router.methods.buyDTBatch, operations)\n }\n\n /**\n * BuyDTBatch\n * @param {String} address\n * @param {Operation} operations Operations objects array\n * @return {Promise<TransactionReceipt>} Transaction receipt\n */\n public async buyDTBatch(\n address: string,\n operations: Operation[]\n ): Promise<TransactionReceipt> {\n const estGas = await estimateGas(address, this.router.methods.buyDTBatch, operations)\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.buyDTBatch(operations).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Check if a token is on approved tokens list, if true opfFee is lower in pools with that token/DT\n * @return {Promise<boolean>} true if is on the list.\n */\n public async isApprovedToken(address: string): Promise<boolean> {\n return await this.router.methods.isApprovedToken(address).call()\n }\n\n /** Check if an address is a side staking contract.\n * @return {Promise<boolean>} true if is a SS contract\n */\n public async isSideStaking(address: string): Promise<boolean> {\n return await this.router.methods.isSSContract(address).call()\n }\n\n /** Check if an address is a Fixed Rate contract.\n * @return {Promise<boolean>} true if is a Fixed Rate contract\n */\n public async isFixedPrice(address: string): Promise<boolean> {\n return await this.router.methods.isFixedRateContract(address).call()\n }\n\n /** Get Router Owner\n * @return {Promise<string>} Router Owner address\n */\n public async getOwner(): Promise<string> {\n return await this.router.methods.routerOwner().call()\n }\n\n /** Get NFT Factory address\n * @return {Promise<string>} NFT Factory address\n */\n public async getNFTFactory(): Promise<string> {\n return await this.router.methods.factory().call()\n }\n\n /** Check if an address is a pool template contract.\n * @return {Promise<boolean>} true if is a Template\n */\n public async isPoolTemplate(address: string): Promise<boolean> {\n return await this.router.methods.isPoolTemplate(address).call()\n }\n\n /**\n * Estimate gas cost for addApprovedToken\n * @param {String} address\n * @param {String} tokenAddress token address we want to add\n * @param {Contract} routerContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddApprovedToken(\n address: string,\n tokenAddress: string,\n contractInstance?: Contract\n ): Promise<any> {\n return estimateGas(address, this.router.methods.addApprovedToken, tokenAddress)\n }\n\n /**\n * Add a new token to oceanTokens list, pools with baseToken in this list have NO opf Fee\n * @param {String} address caller address\n * @param {String} tokenAddress token address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addApprovedToken(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addApprovedToken,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addApprovedToken(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeApprovedToken\n * @param {String} address caller address\n * @param {String} tokenAddress token address we want to add\n * @param {Contract} routerContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveApprovedToken(\n address: string,\n tokenAddress: string,\n contractInstance?: Contract\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removeApprovedToken, tokenAddress)\n }\n\n /**\n * Remove a token from oceanTokens list, pools without baseToken in this list have a opf Fee\n * @param {String} address\n * @param {String} tokenAddress address to remove\n * @return {Promise<TransactionReceipt>}\n */\n public async removeApprovedToken(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removeApprovedToken,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.removeApprovedToken(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addSSContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddSSContract(address: string, tokenAddress: string): Promise<any> {\n return estimateGas(address, this.router.methods.addSSContract, tokenAddress)\n }\n\n /**\n * Add a new contract to ssContract list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addSSContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addSSContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addSSContract(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeSSContract method\n * @param {String} address caller address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasRemoveSSContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removeSSContract, tokenAddress)\n }\n\n /**\n * Removes a new contract from ssContract list\n * @param {String} address caller address\n * @param {String} tokenAddress contract address to removed\n * @return {Promise<TransactionReceipt>}\n */\n public async removeSSContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removeSSContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.removeSSContract(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addFixedRateContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddFixedRateContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.addFixedRateContract, tokenAddress)\n }\n\n /**\n * Add a new contract to fixedRate list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addFixedRateContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addFixedRateContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addFixedRateContract(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addFixedRateContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasRemoveFixedRateContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removeFixedRateContract, tokenAddress)\n }\n\n /**\n * Removes a contract from fixedRate list\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async removeFixedRateContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removeFixedRateContract,\n tokenAddress\n )\n\n // Invoke removeFixedRateContract function of the contract\n const trxReceipt = await this.router.methods\n .removeFixedRateContract(tokenAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addDispenserContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddDispenserContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.addDispenserContract, tokenAddress)\n }\n\n /**\n * Add a new contract to dispenser list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addDispenserContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addDispenserContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addDispenserContract(tokenAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addDispenserContract method\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasRemoveDispenserContract(\n address: string,\n tokenAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removeDispenserContract, tokenAddress)\n }\n\n /**\n * Add a new contract to dispenser list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {String} tokenAddress contract address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async removeDispenserContract(\n address: string,\n tokenAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removeDispenserContract,\n tokenAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods\n .removeDispenserContract(tokenAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Get OPF Fee per token\n * @return {Promise<number>} OPC fee for a specific baseToken\n */\n public async getOPCFee(baseToken: string): Promise<number> {\n return await this.router.methods.getOPCFee(baseToken).call()\n }\n\n /** Get Current OPF Fee\n * @return {Promise<number>} OPF fee\n */\n public async getCurrentOPCFee(): Promise<number> {\n return await this.router.methods.swapOceanFee().call()\n }\n\n /**\n * Estimate gas cost for updateOPFFee method\n * @param {String} address\n * @param {String} newFee new OPF Fee\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasUpdateOPCFee(\n address: string,\n newSwapOceanFee: number,\n newSwapNonOceanFee: number,\n newConsumeFee: number,\n newProviderFee: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.router.methods.updateOPCFee,\n newSwapOceanFee,\n newSwapNonOceanFee,\n newConsumeFee,\n newProviderFee\n )\n }\n\n /**\n * Add a new contract to fixedRate list, after is added, can be used when deploying a new pool\n * @param {String} address\n * @param {number} newSwapOceanFee Amount charged for swapping with ocean approved tokens\n * @param {number} newSwapNonOceanFee Amount charged for swapping with non ocean approved tokens\n * @param {number} newConsumeFee Amount charged from consumeFees\n * @param {number} newProviderFee Amount charged for providerFees\n * @return {Promise<TransactionReceipt>}\n */\n public async updateOPCFee(\n address: string,\n newSwapOceanFee: number,\n newSwapNonOceanFee: number,\n newConsumeFee: number,\n newProviderFee: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.updateOPCFee,\n newSwapOceanFee,\n newSwapNonOceanFee,\n newConsumeFee,\n newProviderFee\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods\n .updateOPCFee(newSwapOceanFee, newSwapNonOceanFee, newConsumeFee, newProviderFee)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addPoolTemplate method\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddPoolTemplate(\n address: string,\n templateAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.addPoolTemplate, templateAddress)\n }\n\n /**\n * Add a new template to poolTemplates mapping, after template is added,it can be used\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addPoolTemplate(\n address: string,\n templateAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.addPoolTemplate,\n templateAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods.addPoolTemplate(templateAddress).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removePoolTemplate method\n * @param {String} address\n * @param {String} templateAddress template address to remove\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasRemovePoolTemplate(\n address: string,\n templateAddress: string\n ): Promise<any> {\n return estimateGas(address, this.router.methods.removePoolTemplate, templateAddress)\n }\n\n /**\n * Remove template from poolTemplates mapping, after template is removed,it can be used anymore\n * @param {String} address\n * @param {String} templateAddress template address to remove\n * @return {Promise<TransactionReceipt>}\n */\n public async removePoolTemplate(\n address: string,\n templateAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Router Owner`)\n }\n\n const estGas = await estimateGas(\n address,\n this.router.methods.removePoolTemplate,\n templateAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.router.methods\n .removePoolTemplate(templateAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n}\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils'\nimport { TransactionReceipt } from 'web3-eth'\nimport defaultNftAbi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json'\nimport {\n LoggerInstance,\n getFairGasPrice,\n generateDtName,\n setContractDefaults,\n estimateGas,\n ConfigHelper\n} from '../utils'\nimport { Contract } from 'web3-eth-contract'\nimport { MetadataProof } from '../../src/@types'\nimport { Config } from '../models/index.js'\nimport { MetadataAndTokenURI } from '../@types'\n\n/**\n * ERC721 ROLES\n */\ninterface Roles {\n manager: boolean\n deployERC20: boolean\n updateMetadata: boolean\n store: boolean\n}\n\nexport class Nft {\n public factory721Address: string\n public factory721Abi: AbiItem | AbiItem[]\n public nftAbi: AbiItem | AbiItem[]\n public web3: Web3\n public startBlock: number\n public config: Config\n\n constructor(\n web3: Web3,\n network?: string | number,\n nftAbi?: AbiItem | AbiItem[],\n config?: Config\n ) {\n this.nftAbi = nftAbi || (defaultNftAbi.abi as AbiItem[])\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n }\n\n /**\n * Estimate gas cost for createERC20 token creation\n * @param {String} nftAddress ERC721 addreess\n * @param {String} address User address\n * @param {String} minter User set as initial minter for the ERC20\n * @param {String} paymentCollector initial paymentCollector for this DT\n * @param {String} mpFeeAddress Consume marketplace fee address\n * @param {String} feeToken address of the token marketplace wants to add fee on top\n * @param {String} feeAmount amount of feeToken to be transferred to mpFeeAddress on top, will be converted to WEI\n * @param {String} cap Maximum cap (Number) - will be converted to wei\n * @param {String} name Token name\n * @param {String} symbol Token symbol\n * @param {Number} templateIndex NFT template index\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCreateErc20(\n nftAddress: string,\n address: string,\n minter: string,\n paymentCollector: string,\n mpFeeAddress: string,\n feeToken: string,\n feeAmount: string,\n cap: string,\n name?: string,\n symbol?: string,\n templateIndex?: number,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n return estimateGas(\n address,\n nftContract.methods.createERC20,\n templateIndex,\n [name, symbol],\n [minter, paymentCollector, mpFeeAddress, feeToken],\n [this.web3.utils.toWei(cap), this.web3.utils.toWei(feeAmount)],\n []\n )\n }\n\n /**\n * Create new ERC20 datatoken - only user with ERC20Deployer permission can succeed\n * @param {String} nftAddress ERC721 addreess\n * @param {String} address User address\n * @param {String} minter User set as initial minter for the ERC20\n * @param {String} paymentCollector initial paymentCollector for this DT\n * @param {String} mpFeeAddress Consume marketplace fee address\n * @param {String} feeToken address of the token marketplace wants to add fee on top\n * @param {String} feeAmount amount of feeToken to be transferred to mpFeeAddress on top, will be converted to WEI\n * @param {String} cap Maximum cap (Number) - will be converted to wei\n * @param {String} name Token name\n * @param {String} symbol Token symbol\n * @param {Number} templateIndex NFT template index\n * @return {Promise<string>} ERC20 datatoken address\n */\n public async createErc20(\n nftAddress: string,\n address: string,\n minter: string,\n paymentCollector: string,\n mpFeeAddress: string,\n feeToken: string,\n feeAmount: string,\n cap: string,\n name?: string,\n symbol?: string,\n templateIndex?: number\n ): Promise<string> {\n if ((await this.getNftPermissions(nftAddress, address)).deployERC20 !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n if (!templateIndex) templateIndex = 1\n\n // Generate name & symbol if not present\n if (!name || !symbol) {\n ;({ name, symbol } = generateDtName())\n }\n\n // Create 721contract object\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.createERC20,\n templateIndex,\n [name, symbol],\n [minter, paymentCollector, mpFeeAddress, feeToken],\n [this.web3.utils.toWei(cap), this.web3.utils.toWei(feeAmount)],\n []\n )\n\n // Call createERC20 token function of the contract\n const trxReceipt = await nftContract.methods\n .createERC20(\n templateIndex,\n [name, symbol],\n [minter, paymentCollector, mpFeeAddress, feeToken],\n [this.web3.utils.toWei(cap), this.web3.utils.toWei(feeAmount)],\n []\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n let tokenAddress = null\n try {\n tokenAddress = trxReceipt.events.TokenCreated.returnValues[0]\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to create datatoken : ${e.message}`)\n }\n return tokenAddress\n }\n\n /**\n * Estimate gas cost for add manager call\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {String} manager User adress which is going to be assing manager\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddManager(\n nftAddress: string,\n address: string,\n manager: string,\n contractInstance?: Contract\n ) {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.addManager, manager)\n }\n\n /**\n * Add Manager for NFT Contract (only NFT Owner can succeed)\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {String} manager User adress which is going to be assing manager\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async addManager(nftAddress: string, address: string, manager: string) {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== address) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const estGas = await estimateGas(address, nftContract.methods.addManager, manager)\n\n // Invoke addManager function of the contract\n const trxReceipt = await nftContract.methods.addManager(manager).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeManager method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {String} manager User adress which is going to be removed as manager\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveManager(\n nftAddress: string,\n address: string,\n manager: string,\n contractInstance?: Contract\n ) {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n return estimateGas(address, nftContract.methods.removeManager, manager)\n }\n\n /**\n * Removes a specific manager for NFT Contract (only NFT Owner can succeed)\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {String} manager User adress which is going to be removed as manager\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removeManager(nftAddress: string, address: string, manager: string) {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== address) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const estGas = await estimateGas(address, nftContract.methods.removeManager, manager)\n\n // Invoke removeManager function of the contract\n const trxReceipt = await nftContract.methods.removeManager(manager).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addToCreateERC20List method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} erc20Deployer User adress which is going to have erc20Deployer permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddErc20Deployer(\n nftAddress: string,\n address: string,\n erc20Deployer: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n return estimateGas(address, nftContract.methods.addToCreateERC20List, erc20Deployer)\n }\n\n /**\n * Add ERC20Deployer permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} erc20Deployer User adress which is going to have erc20Deployer permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async addErc20Deployer(\n nftAddress: string,\n address: string,\n erc20Deployer: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftPermissions(nftAddress, address)).manager !== true) {\n throw new Error(`Caller is not Manager`)\n }\n\n // Estimate gas for addToCreateERC20List method\n const estGas = await estimateGas(\n address,\n nftContract.methods.addToCreateERC20List,\n erc20Deployer\n )\n\n // Invoke addToCreateERC20List function of the contract\n const trxReceipt = await nftContract.methods\n .addToCreateERC20List(erc20Deployer)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeFromCreateERC20List method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} erc20Deployer Address of the user to be revoked ERC20Deployer Permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveErc20Deployer(\n nftAddress: string,\n address: string,\n erc20Deployer: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n address,\n nftContract.methods.removeFromCreateERC20List,\n erc20Deployer\n )\n }\n\n /**\n * Remove ERC20Deployer permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} erc20Deployer Address of the user to be revoked ERC20Deployer Permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removeErc20Deployer(\n nftAddress: string,\n address: string,\n erc20Deployer: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if (\n (await this.getNftPermissions(nftAddress, address)).manager !== true ||\n (address === erc20Deployer &&\n (await this.getNftPermissions(nftAddress, address)).deployERC20 !== true)\n ) {\n throw new Error(`Caller is not Manager nor ERC20Deployer`)\n }\n const estGas = await estimateGas(\n address,\n nftContract.methods.removeFromCreateERC20List,\n erc20Deployer\n )\n\n // Call removeFromCreateERC20List function of the contract\n const trxReceipt = await nftContract.methods\n .removeFromCreateERC20List(erc20Deployer)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addToMetadataList method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} metadataUpdater User adress which is going to have Metadata Updater permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddMetadataUpdater(\n nftAddress: string,\n address: string,\n metadataUpdater: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.addToMetadataList, metadataUpdater)\n }\n\n /**\n * Add Metadata Updater permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} metadataUpdater User adress which is going to have Metadata Updater permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async addMetadataUpdater(\n nftAddress: string,\n address: string,\n metadataUpdater: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftPermissions(nftAddress, address)).manager !== true) {\n throw new Error(`Caller is not Manager`)\n }\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.addToMetadataList,\n metadataUpdater\n )\n\n // Call addToMetadataList function of the contract\n const trxReceipt = await nftContract.methods.addToMetadataList(metadataUpdater).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeFromMetadataList method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} metadataUpdater Address of the user to be revoked Metadata updater Permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async esGasRemoveMetadataUpdater(\n nftAddress: string,\n address: string,\n metadataUpdater: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n address,\n nftContract.methods.removeFromMetadataList,\n metadataUpdater\n )\n }\n\n /**\n * Remove Metadata Updater permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} metadataUpdater Address of the user to be revoked Metadata updater Permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removeMetadataUpdater(\n nftAddress: string,\n address: string,\n metadataUpdater: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if (\n (await this.getNftPermissions(nftAddress, address)).manager !== true ||\n (address !== metadataUpdater &&\n (await this.getNftPermissions(nftAddress, address)).updateMetadata !== true)\n ) {\n throw new Error(`Caller is not Manager nor Metadata Updater`)\n }\n\n const estGas = await this.esGasRemoveMetadataUpdater(\n nftAddress,\n address,\n metadataUpdater,\n nftContract\n )\n\n // Call removeFromMetadataList function of the contract\n const trxReceipt = await nftContract.methods\n .removeFromMetadataList(metadataUpdater)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addTo725StoreList method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} storeUpdater User adress which is going to have Store Updater permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddStoreUpdater(\n nftAddress: string,\n address: string,\n storeUpdater: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.addTo725StoreList, storeUpdater)\n }\n\n /**\n * Add Store Updater permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} storeUpdater User adress which is going to have Store Updater permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async addStoreUpdater(\n nftAddress: string,\n address: string,\n storeUpdater: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftPermissions(nftAddress, address)).manager !== true) {\n throw new Error(`Caller is not Manager`)\n }\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.addTo725StoreList,\n storeUpdater\n )\n\n // Call addTo725StoreList function of the contract\n const trxReceipt = await nftContract.methods.addTo725StoreList(storeUpdater).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for removeFrom725StoreList method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} storeUpdater Address of the user to be revoked Store Updater Permission\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveStoreUpdater(\n nftAddress: string,\n address: string,\n storeUpdater: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.removeFrom725StoreList, storeUpdater)\n }\n\n /**\n * Remove Store Updater permission - only Manager can succeed\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Manager adress\n * @param {String} storeUpdater Address of the user to be revoked Store Updater Permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removeStoreUpdater(\n nftAddress: string,\n address: string,\n storeUpdater: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if (\n (await this.getNftPermissions(nftAddress, address)).manager !== true ||\n (address !== storeUpdater &&\n (await this.getNftPermissions(nftAddress, address)).store !== true)\n ) {\n throw new Error(`Caller is not Manager nor storeUpdater`)\n }\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.removeFrom725StoreList,\n storeUpdater\n )\n\n // Call removeFrom725StoreList function of the contract\n const trxReceipt = await nftContract.methods\n .removeFrom725StoreList(storeUpdater)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for cleanPermissions method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCleanPermissions(\n nftAddress: string,\n address: string,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.cleanPermissions)\n }\n\n /**\n * This function allows to remove all ROLES at erc721 level: Managers, ERC20Deployer, MetadataUpdater, StoreUpdater\n * Even NFT Owner has to readd himself as Manager\n * Permissions at erc20 level stay.\n * Only NFT Owner can call it.\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address NFT Owner adress\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n\n public async cleanPermissions(\n nftAddress: string,\n address: string\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== address) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const estGas = await estimateGas(address, nftContract.methods.cleanPermissions)\n\n // Call cleanPermissions function of the contract\n const trxReceipt = await nftContract.methods.cleanPermissions().send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for transfer NFT method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {String} nftReceiver User which will receive the NFT, will also be set as Manager\n * @param {Number} tokenId The id of the token to be transfered\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasTransferNft(\n nftAddress: string,\n nftOwner: string,\n nftReceiver: string,\n tokenId: number,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n nftOwner,\n nftContract.methods.transferFrom,\n nftOwner,\n nftReceiver,\n tokenId\n )\n }\n\n /**\n * Transfers the NFT\n * will clean all permissions both on erc721 and erc20 level.\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {String} nftReceiver User which will receive the NFT, will also be set as Manager\n * @param {Number} tokenId The id of the token to be transfered\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async transferNft(\n nftAddress: string,\n nftOwner: string,\n nftReceiver: string,\n tokenId?: number\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== nftOwner) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const tokenIdentifier = tokenId || 1\n\n const estGas = await estimateGas(\n nftOwner,\n nftContract.methods.transferFrom,\n nftOwner,\n nftReceiver,\n tokenIdentifier\n )\n\n // Call transferFrom function of the contract\n const trxReceipt = await nftContract.methods\n .transferFrom(nftOwner, nftReceiver, tokenIdentifier)\n .send({\n from: nftOwner,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for safeTransfer NFT method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {String} nftReceiver User which will receive the NFT, will also be set as Manager\n * @param {Number} tokenId The id of the token to be transfered\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSafeTransferNft(\n nftAddress: string,\n nftOwner: string,\n nftReceiver: string,\n tokenId: number,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n nftOwner,\n nftContract.methods.safeTransferFrom,\n nftOwner,\n nftReceiver,\n tokenId\n )\n }\n\n /**\n * safeTransferNFT Used for transferring the NFT, can be used by an approved relayer\n * will clean all permissions both on erc721 and erc20 level.\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {String} nftReceiver User which will receive the NFT, will also be set as Manager\n * @param {Number} tokenId The id of the token to be transfered\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async safeTransferNft(\n nftAddress: string,\n nftOwner: string,\n nftReceiver: string,\n tokenId?: number\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if ((await this.getNftOwner(nftAddress)) !== nftOwner) {\n throw new Error(`Caller is not NFT Owner`)\n }\n\n const tokenIdentifier = tokenId || 1\n\n const estGas = await estimateGas(\n nftOwner,\n nftContract.methods.safeTransferFrom,\n nftOwner,\n nftReceiver,\n tokenIdentifier\n )\n\n // Call transferFrom function of the contract\n const trxReceipt = await nftContract.methods\n .safeTransferFrom(nftOwner, nftReceiver, tokenIdentifier)\n .send({\n from: nftOwner,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n // TODO: Finish this description\n /**\n * Estimate gas cost for setMetadata method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} metadataUpdater metadataUpdater address\n * @param {Number} metadataState User which will receive the NFT, will also be set as Manager\n * @param {String} metadataDecryptorUrl\n * @param {Number} tokenId The id of the token to be transfered\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetMetadata(\n nftAddress: string,\n metadataUpdater: string,\n metadataState: number,\n metadataDecryptorUrl: string,\n metadataDecryptorAddress: string,\n flags: string,\n data: string,\n metadataHash: string,\n metadataProofs?: MetadataProof[],\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n if (!metadataProofs) metadataProofs = []\n return estimateGas(\n metadataUpdater,\n nftContract.methods.setMetaData,\n metadataState,\n metadataDecryptorUrl,\n metadataDecryptorAddress,\n flags,\n data,\n metadataHash,\n metadataProofs\n )\n }\n\n /**\n * safeTransferNFT Used for transferring the NFT, can be used by an approved relayer\n * will clean all permissions both on erc721 and erc20 level.\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address Caller address NFT Owner adress\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async setMetadata(\n nftAddress: string,\n address: string,\n metadataState: number,\n metadataDecryptorUrl: string,\n metadataDecryptorAddress: string,\n flags: string,\n data: string,\n metadataHash: string,\n metadataProofs?: MetadataProof[]\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n if (!metadataProofs) metadataProofs = []\n if (!(await this.getNftPermissions(nftAddress, address)).updateMetadata) {\n throw new Error(`Caller is not Metadata updater`)\n }\n const estGas = await estimateGas(\n address,\n nftContract.methods.setMetaData,\n metadataState,\n metadataDecryptorUrl,\n metadataDecryptorAddress,\n flags,\n data,\n metadataHash,\n metadataProofs\n )\n const trxReceipt = await nftContract.methods\n .setMetaData(\n metadataState,\n metadataDecryptorUrl,\n metadataDecryptorAddress,\n flags,\n data,\n metadataHash,\n metadataProofs\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for setMetadata method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} metadataUpdater metadataUpdater address\n * @param {MetaDataAndTokenURI} metadataAndTokenURI metaDataAndTokenURI object\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetMetadataAndTokenURI(\n nftAddress: string,\n metadataUpdater: string,\n metadataAndTokenURI: MetadataAndTokenURI,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const sanitizedMetadataAndTokenURI = {\n ...metadataAndTokenURI,\n metadataProofs: metadataAndTokenURI.metadataProofs || []\n }\n return estimateGas(\n metadataUpdater,\n nftContract.methods.setMetaDataAndTokenURI,\n sanitizedMetadataAndTokenURI\n )\n }\n\n /**\n * Helper function to improve UX sets both MetaData & TokenURI in one tx\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address Caller address\n * @param {MetadataAndTokenURI} metadataAndTokenURI metaDataAndTokenURI object\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async setMetadataAndTokenURI(\n nftAddress: string,\n metadataUpdater: string,\n metadataAndTokenURI: MetadataAndTokenURI\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n if (!(await this.getNftPermissions(nftAddress, metadataUpdater)).updateMetadata) {\n throw new Error(`Caller is not Metadata updater`)\n }\n const sanitizedMetadataAndTokenURI = {\n ...metadataAndTokenURI,\n metadataProofs: metadataAndTokenURI.metadataProofs || []\n }\n const estGas = await estimateGas(\n metadataUpdater,\n nftContract.methods.setMetaDataAndTokenURI,\n sanitizedMetadataAndTokenURI\n )\n const trxReceipt = await nftContract.methods\n .setMetaDataAndTokenURI(sanitizedMetadataAndTokenURI)\n .send({\n from: metadataUpdater,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for setMetadataState method\n * @param {String} nftAddress erc721 contract adress\n * @param {String} nftOwner Current NFT Owner adress\n * @param {Number} metadataState new metadata state\n * @param {Contract} nftContract optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetMetadataState(\n nftAddress: string,\n metadataUpdater: string,\n metadataState: number,\n contractInstance?: Contract\n ): Promise<any> {\n const nftContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(\n metadataUpdater,\n nftContract.methods.setMetaDataState,\n metadataState\n )\n }\n\n /**\n * setMetadataState Used for updating the metadata State\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address Caller address => metadata updater\n * @param {Number} metadataState new metadata state\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async setMetadataState(\n nftAddress: string,\n address: string,\n metadataState: number\n ): Promise<TransactionReceipt> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n if (!(await this.getNftPermissions(nftAddress, address)).updateMetadata) {\n throw new Error(`Caller is not Metadata updater`)\n }\n\n const estGas = await estimateGas(\n address,\n nftContract.methods.setMetaDataState,\n metadataState\n )\n\n // Call transferFrom function of the contract\n const trxReceipt = await nftContract.methods.setMetaDataState(metadataState).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas cost for setTokenURI method\n * @param nftAddress erc721 contract adress\n * @param address user adress\n * @param data input data for TokenURI\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estSetTokenURI(\n nftAddress: string,\n address: string,\n data: string\n ): Promise<any> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n return estimateGas(address, nftContract.methods.setTokenURI, '1', data)\n }\n\n /** set TokenURI on an nft\n * @param nftAddress erc721 contract adress\n * @param address user adress\n * @param data input data for TokenURI\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async setTokenURI(\n nftAddress: string,\n address: string,\n data: string\n ): Promise<any> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n\n const estGas = await estimateGas(address, nftContract.methods.setTokenURI, '1', data)\n const trxReceipt = await nftContract.methods.setTokenURI('1', data).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /** Get Owner\n * @param {String} nftAddress erc721 contract adress\n * @return {Promise<string>} string\n */\n public async getNftOwner(nftAddress: string): Promise<string> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const trxReceipt = await nftContract.methods.ownerOf(1).call()\n return trxReceipt\n }\n\n /** Get users NFT Permissions\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address user adress\n * @return {Promise<Roles>}\n */\n public async getNftPermissions(nftAddress: string, address: string): Promise<Roles> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const roles = await nftContract.methods.getPermissions(address).call()\n return roles\n }\n\n /** Get users Metadata, return Metadata details\n * @param {String} nftAddress erc721 contract adress\n * @return {Promise<Objecta>}\n */\n public async getMetadata(nftAddress: string): Promise<Object> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n return await nftContract.methods.getMetaData().call()\n }\n\n /** Get users ERC20Deployer role\n * @param {String} nftAddress erc721 contract adress\n * @param {String} address user adress\n * @return {Promise<Roles>}\n */\n public async isErc20Deployer(nftAddress: string, address: string): Promise<boolean> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const isERC20Deployer = await nftContract.methods.isERC20Deployer(address).call()\n return isERC20Deployer\n }\n\n /** Gets data at a given `key`\n * @param {String} nftAddress erc721 contract adress\n * @param {String} key the key which value to retrieve\n * @return {Promise<string>} The data stored at the key\n */\n public async getData(nftAddress: string, key: string): Promise<string> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const data = await nftContract.methods.getData(key).call()\n return data\n }\n\n /** Gets data at a given `key`\n * @param {String} nftAddress erc721 contract adress\n * @param {String} id\n * @return {Promise<string>} The data stored at the key\n */\n public async getTokenURI(nftAddress: string, id: number): Promise<string> {\n const nftContract = setContractDefaults(\n new this.web3.eth.Contract(this.nftAbi, nftAddress),\n this.config\n )\n const data = await nftContract.methods.tokenURI(id).call()\n return data\n }\n}\n","import Web3 from 'web3'\nimport { AbiItem } from 'web3-utils'\nimport { TransactionReceipt } from 'web3-eth'\nimport { Contract } from 'web3-eth-contract'\nimport Decimal from 'decimal.js'\nimport defaultDatatokensAbi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20Template.sol/ERC20Template.json'\nimport defaultDatatokensEnterpriseAbi from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC20TemplateEnterprise.sol/ERC20TemplateEnterprise.json'\nimport {\n LoggerInstance,\n getFairGasPrice,\n setContractDefaults,\n getFreOrderParams,\n estimateGas,\n ZERO_ADDRESS,\n ConfigHelper\n} from '../utils'\nimport {\n ConsumeMarketFee,\n FreOrderParams,\n FreCreationParams,\n ProviderFees,\n PublishingMarketFee\n} from '../@types'\nimport { Nft } from './NFT'\nimport { Config } from '../models/index.js'\n\n/**\n * ERC20 ROLES\n */\ninterface Roles {\n minter: boolean\n paymentManager: boolean\n}\n\nexport interface OrderParams {\n consumer: string\n serviceIndex: number\n _providerFee: ProviderFees\n _consumeMarketFee: ConsumeMarketFee\n}\n\nexport interface DispenserParams {\n maxTokens: string\n maxBalance: string\n withMint?: boolean // true if we want to allow the dispenser to be a minter\n allowedSwapper?: string // only account that can ask tokens. set address(0) if not required\n}\n\nexport class Datatoken {\n public factoryAddress: string\n public factoryABI: AbiItem | AbiItem[]\n public datatokensAbi: AbiItem | AbiItem[]\n public datatokensEnterpriseAbi: AbiItem | AbiItem[]\n public web3: Web3\n public config: Config\n public nft: Nft\n\n /**\n * Instantiate ERC20 Datatokens\n * @param {AbiItem | AbiItem[]} datatokensAbi\n * @param {Web3} web3\n */\n constructor(\n web3: Web3,\n network?: string | number,\n datatokensAbi?: AbiItem | AbiItem[],\n datatokensEnterpriseAbi?: AbiItem | AbiItem[],\n config?: Config\n ) {\n this.web3 = web3\n this.datatokensAbi = datatokensAbi || (defaultDatatokensAbi.abi as AbiItem[])\n this.datatokensEnterpriseAbi =\n datatokensEnterpriseAbi || (defaultDatatokensEnterpriseAbi.abi as AbiItem[])\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n this.nft = new Nft(this.web3)\n }\n\n /**\n * Estimate gas cost for mint method\n * @param {String} dtAddress Datatoken address\n * @param {String} spender Spender address\n * @param {string} amount Number of datatokens, as number. Will be converted to wei\n * @param {String} address User adress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasApprove(\n dtAddress: string,\n spender: string,\n amount: string,\n address: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(\n address,\n dtContract.methods.approve,\n spender,\n this.web3.utils.toWei(amount)\n )\n }\n\n /**\n * Approve\n * @param {String} dtAddress Datatoken address\n * @param {String} spender Spender address\n * @param {string} amount Number of datatokens, as number. Will be converted to wei\n * @param {String} address User adress\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async approve(\n dtAddress: string,\n spender: string,\n amount: string,\n address: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.approve,\n spender,\n this.web3.utils.toWei(amount)\n )\n\n // Call mint contract method\n const trxReceipt = await dtContract.methods\n .approve(spender, this.web3.utils.toWei(amount))\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for mint method\n * @param {String} dtAddress Datatoken address\n * @param {String} address Minter address\n * @param {String} amount Number of datatokens, as number. Will be converted to wei\n * @param {String} toAddress only if toAddress is different from the minter\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasMint(\n dtAddress: string,\n address: string,\n amount: string,\n toAddress?: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(\n address,\n dtContract.methods.mint,\n toAddress || address,\n this.web3.utils.toWei(amount)\n )\n }\n\n /**\n * Estimate gas cost for createFixedRate method\n * @param {String} dtAddress Datatoken address\n * @param {String} address Caller address\n * @param {String} fixedPriceAddress\n * @param {FixedRateParams} fixedRateParams\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCreateFixedRate(\n dtAddress: string,\n address: string,\n fixedRateParams: FreCreationParams,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if (!fixedRateParams.allowedConsumer) fixedRateParams.allowedConsumer = ZERO_ADDRESS\n const withMint = fixedRateParams.withMint ? 1 : 0\n\n return estimateGas(\n address,\n dtContract.methods.createFixedRate,\n fixedRateParams.fixedRateAddress,\n [\n fixedRateParams.baseTokenAddress,\n address,\n fixedRateParams.marketFeeCollector,\n fixedRateParams.allowedConsumer\n ],\n [\n fixedRateParams.baseTokenDecimals,\n fixedRateParams.datatokenDecimals,\n fixedRateParams.fixedRate,\n fixedRateParams.marketFee,\n withMint\n ]\n )\n }\n\n /**\n * Creates a new FixedRateExchange setup.\n * @param {String} dtAddress Datatoken address\n * @param {String} address Caller address\n * @param {String} fixedPriceAddress\n * @param {FixedRateParams} fixedRateParams\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async createFixedRate(\n dtAddress: string,\n address: string,\n fixedRateParams: FreCreationParams\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n if (!(await this.isERC20Deployer(dtAddress, address))) {\n throw new Error(`User is not ERC20 Deployer`)\n }\n if (!fixedRateParams.allowedConsumer) fixedRateParams.allowedConsumer = ZERO_ADDRESS\n\n const withMint = fixedRateParams.withMint ? 1 : 0\n\n // should check ERC20Deployer role using erc721 level ..\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.createFixedRate,\n fixedRateParams.fixedRateAddress,\n [\n fixedRateParams.baseTokenAddress,\n fixedRateParams.owner,\n fixedRateParams.marketFeeCollector,\n fixedRateParams.allowedConsumer\n ],\n [\n fixedRateParams.baseTokenDecimals,\n fixedRateParams.datatokenDecimals,\n fixedRateParams.fixedRate,\n fixedRateParams.marketFee,\n withMint\n ]\n )\n\n // Call createFixedRate contract method\n const trxReceipt = await dtContract.methods\n .createFixedRate(\n fixedRateParams.fixedRateAddress,\n [\n fixedRateParams.baseTokenAddress,\n fixedRateParams.owner,\n fixedRateParams.marketFeeCollector,\n fixedRateParams.allowedConsumer\n ],\n [\n fixedRateParams.baseTokenDecimals,\n fixedRateParams.datatokenDecimals,\n fixedRateParams.fixedRate,\n fixedRateParams.marketFee,\n withMint\n ]\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for createDispenser method\n * @param {String} dtAddress Datatoken address\n * @param {String} address Caller address\n * @param {String} dispenserAddress ispenser contract address\n * @param {String} dispenserParams\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCreateDispenser(\n dtAddress: string,\n address: string,\n dispenserAddress: string,\n dispenserParams: DispenserParams,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if (!dispenserParams.allowedSwapper) dispenserParams.allowedSwapper = ZERO_ADDRESS\n\n if (!dispenserParams.withMint) dispenserParams.withMint = false\n\n return estimateGas(\n address,\n dtContract.methods.createDispenser,\n dispenserAddress,\n dispenserParams.maxTokens,\n dispenserParams.maxBalance,\n dispenserParams.withMint,\n dispenserParams.allowedSwapper\n )\n }\n\n /**\n * Creates a new Dispenser\n * @param {String} dtAddress Datatoken address\n * @param {String} address Caller address\n * @param {String} dispenserAddress ispenser contract address\n * @param {String} dispenserParams\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async createDispenser(\n dtAddress: string,\n address: string,\n dispenserAddress: string,\n dispenserParams: DispenserParams\n ): Promise<TransactionReceipt> {\n if (!(await this.isERC20Deployer(dtAddress, address))) {\n throw new Error(`User is not ERC20 Deployer`)\n }\n\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if (!dispenserParams.allowedSwapper) dispenserParams.allowedSwapper = ZERO_ADDRESS\n\n if (!dispenserParams.withMint) dispenserParams.withMint = false\n\n // should check ERC20Deployer role using erc721 level ..\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.createDispenser,\n dispenserAddress,\n dispenserParams.maxTokens,\n dispenserParams.maxBalance,\n dispenserParams.withMint,\n dispenserParams.allowedSwapper\n )\n\n // Call createFixedRate contract method\n const trxReceipt = await dtContract.methods\n .createDispenser(\n dispenserAddress,\n dispenserParams.maxTokens,\n dispenserParams.maxBalance,\n dispenserParams.withMint,\n dispenserParams.allowedSwapper\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n }\n\n /**\n * Mint\n * @param {String} dtAddress Datatoken address\n * @param {String} address Minter address\n * @param {String} amount Number of datatokens, as number. Will be converted to wei\n * @param {String} toAddress only if toAddress is different from the minter\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async mint(\n dtAddress: string,\n address: string,\n amount: string,\n toAddress?: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.getDTPermissions(dtAddress, address)).minter !== true) {\n throw new Error(`Caller is not Minter`)\n }\n\n const capAvailble = await this.getCap(dtAddress)\n if (new Decimal(capAvailble).gte(amount)) {\n const estGas = await estimateGas(\n address,\n dtContract.methods.mint,\n toAddress || address,\n this.web3.utils.toWei(amount)\n )\n\n // Call mint contract method\n const trxReceipt = await dtContract.methods\n .mint(toAddress || address, this.web3.utils.toWei(amount))\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } else {\n throw new Error(`Mint amount exceeds cap available`)\n }\n }\n\n /**\n * Estimate gas cost for addMinter method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} minter User which is going to be a Minter\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddMinter(\n dtAddress: string,\n address: string,\n minter: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.addMinter, minter)\n }\n\n /**\n * Add Minter for an ERC20 datatoken\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} minter User which is going to be a Minter\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async addMinter(\n dtAddress: string,\n address: string,\n minter: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.isERC20Deployer(dtAddress, address)) !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n // Estimate gas cost for addMinter method\n const estGas = await estimateGas(address, dtContract.methods.addMinter, minter)\n\n // Call addMinter function of the contract\n const trxReceipt = await dtContract.methods.addMinter(minter).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas for removeMinter method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} minter User which will be removed from Minter permission\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemoveMinter(\n dtAddress: string,\n address: string,\n minter: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n // should check ERC20Deployer role using erc721 level ..\n\n return estimateGas(address, dtContract.methods.removeMinter, minter)\n }\n\n /**\n * Revoke Minter permission for an ERC20 datatoken\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} minter User which will be removed from Minter permission\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async removeMinter(\n dtAddress: string,\n address: string,\n minter: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.isERC20Deployer(dtAddress, address)) !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n\n const estGas = await estimateGas(address, dtContract.methods.removeMinter, minter)\n\n // Call dtContract function of the contract\n const trxReceipt = await dtContract.methods.removeMinter(minter).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas for addPaymentManager method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} paymentManager User which is going to be a Minter\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasAddPaymentManager(\n dtAddress: string,\n address: string,\n paymentManager: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.addPaymentManager, paymentManager)\n }\n\n /**\n * Add addPaymentManager (can set who's going to collect fee when consuming orders)\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} paymentManager User which is going to be a Minter\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async addPaymentManager(\n dtAddress: string,\n address: string,\n paymentManager: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.isERC20Deployer(dtAddress, address)) !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.addPaymentManager,\n paymentManager\n )\n\n // Call addPaymentManager function of the contract\n const trxReceipt = await dtContract.methods.addPaymentManager(paymentManager).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas for removePaymentManager method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} paymentManager User which will be removed from paymentManager permission\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasRemovePaymentManager(\n dtAddress: string,\n address: string,\n paymentManager: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.removePaymentManager, paymentManager)\n }\n\n /**\n * Revoke paymentManager permission for an ERC20 datatoken\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} paymentManager User which will be removed from paymentManager permission\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async removePaymentManager(\n dtAddress: string,\n address: string,\n paymentManager: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n if ((await this.isERC20Deployer(dtAddress, address)) !== true) {\n throw new Error(`Caller is not ERC20Deployer`)\n }\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.removePaymentManager,\n paymentManager\n )\n\n // Call removeFeeManager function of the contract\n const trxReceipt = await dtContract.methods\n .removePaymentManager(paymentManager)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas for setPaymentCollector method\n * @param dtAddress datatoken address\n * @param address Caller address\n * @param paymentCollector User to be set as new payment collector\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetPaymentCollector(\n dtAddress: string,\n address: string,\n paymentCollector: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.setPaymentCollector, paymentCollector)\n }\n\n /**\n * This function allows to set a new PaymentCollector (receives DT when consuming)\n * If not set the paymentCollector is the NFT Owner\n * only NFT owner can call\n * @param dtAddress datatoken address\n * @param address Caller address\n * @param paymentCollector User to be set as new payment collector\n * @return {Promise<TransactionReceipt>} trxReceipt\n */\n public async setPaymentCollector(\n dtAddress: string,\n address: string,\n paymentCollector: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const isPaymentManager = (await this.getDTPermissions(dtAddress, address))\n .paymentManager\n const nftAddress = !isPaymentManager && (await this.getNFTAddress(dtAddress))\n const isNftOwner = nftAddress && (await this.nft.getNftOwner(nftAddress)) === address\n const nftPermissions =\n nftAddress && !isNftOwner && (await this.nft.getNftPermissions(nftAddress, address))\n const isErc20Deployer = nftPermissions?.deployERC20\n if (!isPaymentManager && !isNftOwner && !isErc20Deployer) {\n throw new Error(`Caller is not Fee Manager, owner or erc20 Deployer`)\n }\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.setPaymentCollector,\n paymentCollector\n )\n\n // Call setFeeCollector method of the contract\n const trxReceipt = await dtContract.methods\n .setPaymentCollector(paymentCollector)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** getPaymentCollector - It returns the current paymentCollector\n * @param dtAddress datatoken address\n * @return {Promise<string>}\n */\n public async getPaymentCollector(dtAddress: string): Promise<string> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const paymentCollector = await dtContract.methods.getPaymentCollector().call()\n return paymentCollector\n }\n\n /**\n * Transfer as number from address to toAddress\n * @param {String} dtAddress Datatoken address\n * @param {String} toAddress Receiver address\n * @param {String} amount Number of datatokens, as number. To be converted to wei.\n * @param {String} address User adress\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async transfer(\n dtAddress: string,\n toAddress: string,\n amount: string,\n address: string\n ): Promise<TransactionReceipt> {\n const weiAmount = this.web3.utils.toWei(amount)\n return this.transferWei(dtAddress, toAddress, weiAmount, address)\n }\n\n /**\n * Estimate gas for transfer method\n * @param {String} dtAddress Datatoken address\n * @param {String} toAddress Receiver address\n * @param {String} amount Number of datatokens, as number. Expressed as wei\n * @param {String} address User adress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasTransfer(\n dtAddress: string,\n toAddress: string,\n amount: string,\n address: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.transfer, toAddress, amount)\n }\n\n /**\n * Transfer in wei from address to toAddress\n * @param {String} dtAddress Datatoken address\n * @param {String} toAddress Receiver address\n * @param {String} amount Number of datatokens, as number. Expressed as wei\n * @param {String} address User adress\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async transferWei(\n dtAddress: string,\n toAddress: string,\n amount: string,\n address: string\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n try {\n const estGas = await estimateGas(\n address,\n dtContract.methods.transfer,\n toAddress,\n amount\n )\n // Call transfer function of the contract\n const trxReceipt = await dtContract.methods.transfer(toAddress, amount).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to transfer tokens: ${e.message}`)\n throw new Error(`Failed Failed to transfer tokens: ${e.message}`)\n }\n }\n\n /** Estimate gas cost for startOrder method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {String} consumer Consumer Address\n * @param {Number} serviceIndex Service index in the metadata\n * @param {providerFees} providerFees provider fees\n * @param {consumeMarketFee} ConsumeMarketFee consume market fees\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasStartOrder(\n dtAddress: string,\n address: string,\n consumer: string,\n serviceIndex: number,\n providerFees: ProviderFees,\n consumeMarketFee?: ConsumeMarketFee,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(\n address,\n dtContract.methods.startOrder,\n consumer,\n serviceIndex,\n providerFees,\n consumeMarketFee\n )\n }\n\n /** Start Order: called by payer or consumer prior ordering a service consume on a marketplace.\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {String} consumer Consumer Address\n * @param {Number} serviceIndex Service index in the metadata\n * @param {providerFees} providerFees provider fees\n * @param {consumeMarketFee} ConsumeMarketFee consume market fees\n * @return {Promise<TransactionReceipt>} string\n */\n public async startOrder(\n dtAddress: string,\n address: string,\n consumer: string,\n serviceIndex: number,\n providerFees: ProviderFees,\n consumeMarketFee?: ConsumeMarketFee\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n if (!consumeMarketFee) {\n consumeMarketFee = {\n consumeMarketFeeAddress: ZERO_ADDRESS,\n consumeMarketFeeToken: ZERO_ADDRESS,\n consumeMarketFeeAmount: '0'\n }\n }\n try {\n const estGas = await estimateGas(\n address,\n dtContract.methods.startOrder,\n consumer,\n serviceIndex,\n providerFees,\n consumeMarketFee\n )\n\n const trxReceipt = await dtContract.methods\n .startOrder(consumer, serviceIndex, providerFees, consumeMarketFee)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to start order : ${e.message}`)\n throw new Error(`Failed to start order: ${e.message}`)\n }\n }\n\n /** Estimate gas cost for reuseOrder method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {String} orderTxId previous valid order\n * @param {providerFees} providerFees provider fees\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasReuseOrder(\n dtAddress: string,\n address: string,\n orderTxId: string,\n providerFees: ProviderFees,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.reuseOrder, orderTxId, providerFees)\n }\n\n /** Reuse Order: called by payer or consumer having a valid order, but with expired provider access.\n * Pays the provider fee again, but it will not require a new datatoken payment\n * Requires previous approval of provider fee.\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {String} orderTxId previous valid order\n * @param {providerFees} providerFees provider fees\n * @return {Promise<TransactionReceipt>} string\n */\n public async reuseOrder(\n dtAddress: string,\n address: string,\n orderTxId: string,\n providerFees: ProviderFees\n ): Promise<TransactionReceipt> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n try {\n const estGas = await estimateGas(\n address,\n dtContract.methods.reuseOrder,\n orderTxId,\n providerFees\n )\n\n const trxReceipt = await dtContract.methods\n .reuseOrder(orderTxId, providerFees)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to call reuse order order : ${e.message}`)\n throw new Error(`Failed to start order: ${e.message}`)\n }\n }\n\n /** Estimate gas cost for buyFromFreAndOrder method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {OrderParams} orderParams Consumer Address\n * @param {FreParams} freParams Amount of tokens that is going to be transfered\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasBuyFromFreAndOrder(\n dtAddress: string,\n address: string,\n orderParams: OrderParams,\n freParams: FreOrderParams,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n new this.web3.eth.Contract(this.datatokensEnterpriseAbi, dtAddress)\n\n return estimateGas(\n address,\n dtContract.methods.buyFromFreAndOrder,\n orderParams,\n freParams\n )\n }\n\n /** Buys 1 DT from the FRE and then startsOrder, while burning that DT\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {OrderParams} orderParams Consumer Address\n * @param {FreParams} freParams Amount of tokens that is going to be transfered\n * @return {Promise<TransactionReceipt>}\n */\n public async buyFromFreAndOrder(\n dtAddress: string,\n address: string,\n orderParams: OrderParams,\n freParams: FreOrderParams\n ): Promise<TransactionReceipt> {\n const dtContract = new this.web3.eth.Contract(this.datatokensEnterpriseAbi, dtAddress)\n try {\n const freContractParams = getFreOrderParams(freParams)\n\n const estGas = await estimateGas(\n address,\n dtContract.methods.buyFromFreAndOrder,\n orderParams,\n freContractParams\n )\n\n const trxReceipt = await dtContract.methods\n .buyFromFreAndOrder(orderParams, freContractParams)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to buy DT From Fre And Order : ${e.message}`)\n throw new Error(`Failed to buy DT From Fre And Order: ${e.message}`)\n }\n }\n\n /** Estimate gas cost for buyFromFreAndOrder method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {OrderParams} orderParams\n * @param {String} dispenserContract\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasBuyFromDispenserAndOrder(\n dtAddress: string,\n address: string,\n orderParams: OrderParams,\n dispenserContract: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n new this.web3.eth.Contract(this.datatokensEnterpriseAbi, dtAddress)\n\n return estimateGas(\n address,\n dtContract.methods.buyFromDispenserAndOrder,\n orderParams,\n dispenserContract\n )\n }\n\n /** Gets DT from dispenser and then startsOrder, while burning that DT\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address which calls\n * @param {OrderParams} orderParams\n * @param {String} dispenserContract\n * @return {Promise<TransactionReceipt>}\n */\n public async buyFromDispenserAndOrder(\n dtAddress: string,\n address: string,\n orderParams: OrderParams,\n dispenserContract: string\n ): Promise<TransactionReceipt> {\n const dtContract = new this.web3.eth.Contract(this.datatokensEnterpriseAbi, dtAddress)\n try {\n const estGas = await estimateGas(\n address,\n dtContract.methods.buyFromDispenserAndOrder,\n orderParams,\n dispenserContract\n )\n\n const trxReceipt = await dtContract.methods\n .buyFromDispenserAndOrder(orderParams, dispenserContract)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n return trxReceipt\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to buy DT From Fre And Order : ${e.message}`)\n throw new Error(`Failed to buy DT From Fre And Order: ${e.message}`)\n }\n }\n\n /** Estimate gas for setData method\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} value Data to be stored into 725Y standard\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasSetData(\n dtAddress: string,\n address: string,\n value: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.setData, value)\n }\n\n /** setData\n * This function allows to store data with a preset key (keccak256(ERC20Address)) into NFT 725 Store\n * only ERC20Deployer can succeed\n * @param {String} dtAddress Datatoken address\n * @param {String} address User address\n * @param {String} value Data to be stored into 725Y standard\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async setData(\n dtAddress: string,\n address: string,\n value: string\n ): Promise<TransactionReceipt> {\n if (!(await this.isERC20Deployer(dtAddress, address))) {\n throw new Error(`User is not ERC20 Deployer`)\n }\n\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n const estGas = await estimateGas(address, dtContract.methods.setData, value)\n\n // Call setData function of the contract\n const trxReceipt = await dtContract.methods.setData(value).send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas for cleanPermissions method\n * @param dtAddress Datatoken address where we want to clean permissions\n * @param address User adress\n * @param {Contract} contractInstance optional contract instance\n * @return {Promise<any>}\n */\n public async estGasCleanPermissions(\n dtAddress: string,\n address: string,\n contractInstance?: Contract\n ): Promise<any> {\n const dtContract =\n contractInstance ||\n setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n return estimateGas(address, dtContract.methods.cleanPermissions)\n }\n\n /**\n * Clean erc20level Permissions (minters, paymentManager and reset the paymentCollector) for an ERC20 datatoken\n * Only NFT Owner (at 721 level) can call it.\n * @param dtAddress Datatoken address where we want to clean permissions\n * @param address User adress\n * @return {Promise<TransactionReceipt>} transactionId\n */\n public async cleanPermissions(\n dtAddress: string,\n address: string\n ): Promise<TransactionReceipt> {\n if ((await this.nft.getNftOwner(await this.getNFTAddress(dtAddress))) !== address) {\n throw new Error('Caller is NOT Nft Owner')\n }\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n\n const estGas = await estimateGas(address, dtContract.methods.cleanPermissions)\n\n // Call cleanPermissions function of the contract\n const trxReceipt = await dtContract.methods.cleanPermissions().send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Returns ERC20 user's permissions for a datatoken\n * @param {String} dtAddress Datatoken adress\n * @param {String} address user adress\n * @return {Promise<Roles>}\n */\n public async getDTPermissions(dtAddress: string, address: string): Promise<Roles> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const roles = await dtContract.methods.permissions(address).call()\n return roles\n }\n\n /** Returns the Datatoken capital\n * @param {String} dtAddress Datatoken adress\n * @return {Promise<string>}\n */\n public async getCap(dtAddress: string): Promise<string> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const cap = await dtContract.methods.cap().call()\n return this.web3.utils.fromWei(cap)\n }\n\n /** It returns the token decimals, how many supported decimal points\n * @param {String} dtAddress Datatoken adress\n * @return {Promise<number>}\n */\n public async getDecimals(dtAddress: string): Promise<string> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const decimals = await dtContract.methods.decimals().call()\n return decimals\n }\n\n /** It returns the token decimals, how many supported decimal points\n * @param {String} dtAddress Datatoken adress\n * @return {Promise<number>}\n */\n public async getNFTAddress(dtAddress: string): Promise<string> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const nftAddress = await dtContract.methods.getERC721Address().call()\n return nftAddress\n }\n\n /** Returns true if address has deployERC20 role\n * @param {String} dtAddress Datatoken adress\n * @param {String} dtAddress Datatoken adress\n * @return {Promise<boolean>}\n */\n public async isERC20Deployer(dtAddress: string, address: string): Promise<boolean> {\n const dtContract = setContractDefaults(\n new this.web3.eth.Contract(this.datatokensAbi, dtAddress),\n this.config\n )\n const isERC20Deployer = await dtContract.methods.isERC20Deployer(address).call()\n return isERC20Deployer\n }\n\n /**\n * Get Address Balance for datatoken\n * @param {String} dtAddress Datatoken adress\n * @param {String} address user adress\n * @return {Promise<String>} balance Number of datatokens. Will be converted from wei\n */\n public async balance(datatokenAddress: string, address: string): Promise<string> {\n const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, {\n from: address\n })\n const balance = await dtContract.methods.balanceOf(address).call()\n return this.web3.utils.fromWei(balance)\n }\n\n /**\n * @dev estGasSetPublishingMarketFee\n * Estimating gas for publishMarketFeeAddress method\n * @param {string} datatokenAddress Datatoken adress\n * @param {string} publishMarketFeeAddress new publish Market Fee Address\n * @param {string} publishMarketFeeToken new publish Market Fee Token\n * @param {string} publishMarketFeeAmount new fee amount\n * @param {String} address user adress\n */\n public async estGasSetPublishingMarketFee(\n datatokenAddress: string,\n publishMarketFeeAddress: string,\n publishMarketFeeToken: string,\n publishMarketFeeAmount: string,\n address: string\n ): Promise<number> {\n // Estimate gas cost for publishMarketFeeAddress method\n const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, {\n from: address\n })\n return estimateGas(\n address,\n dtContract.methods.setPublishingMarketFee,\n publishMarketFeeAddress,\n publishMarketFeeToken,\n publishMarketFeeAmount\n )\n }\n\n /**\n * @dev setPublishingMarketFee\n * Only publishMarketFeeAddress can call it\n * This function allows to set the fee required by the publisherMarket\n * @param {string} datatokenAddress Datatoken adress\n * @param {string} publishMarketFeeAddress new publish Market Fee Address\n * @param {string} publishMarketFeeToken new publish Market Fee Token\n * @param {string} publishMarketFeeAmount new fee amount\n * @param {String} address user adress\n */\n public async setPublishingMarketFee(\n datatokenAddress: string,\n publishMarketFeeAddress: string,\n publishMarketFeeToken: string,\n publishMarketFeeAmount: string,\n address: string\n ) {\n const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, {\n from: address\n })\n const mktFeeAddress = (await dtContract.methods.getPublishingMarketFee().call())[0]\n if (mktFeeAddress !== address) {\n throw new Error(`Caller is not the Publishing Market Fee Address`)\n }\n const estGas = await this.estGasSetPublishingMarketFee(\n datatokenAddress,\n publishMarketFeeAddress,\n publishMarketFeeToken,\n publishMarketFeeAmount,\n address\n )\n await dtContract.methods\n .setPublishingMarketFee(\n publishMarketFeeAddress,\n publishMarketFeeToken,\n publishMarketFeeAmount\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n }\n\n /**\n * @dev getPublishingMarketFee\n * Get publishingMarket Fee\n * This function allows to get the current fee set by the publishing market\n * @param {String} datatokenAddress Datatoken adress\n * @param {String} address user adress\n * @return {Promise<PublishingMarketFee>} Current fee set by the publishing market\n */\n public async getPublishingMarketFee(\n datatokenAddress: string,\n address: string\n ): Promise<PublishingMarketFee> {\n const dtContract = new this.web3.eth.Contract(this.datatokensAbi, datatokenAddress, {\n from: address\n })\n\n const publishingMarketFee = await dtContract.methods.getPublishingMarketFee().call()\n const returnValues = {\n publishMarketFeeAddress: publishingMarketFee[0],\n publishMarketFeeToken: publishingMarketFee[1],\n publishMarketFeeAmount: publishingMarketFee[2]\n }\n return returnValues\n }\n}\n","import { Contract } from 'web3-eth-contract'\nimport Web3 from 'web3'\nimport { TransactionReceipt } from 'web3-core'\nimport { AbiItem } from 'web3-utils'\nimport defaultFactory721Abi from '@oceanprotocol/contracts/artifacts/contracts/ERC721Factory.sol/ERC721Factory.json'\nimport {\n LoggerInstance,\n getFairGasPrice,\n generateDtName,\n getFreCreationParams,\n getErcCreationParams,\n getPoolCreationParams,\n setContractDefaults,\n estimateGas,\n ZERO_ADDRESS,\n ConfigHelper\n} from '../utils'\nimport { Config } from '../models/index.js'\nimport {\n ProviderFees,\n FreCreationParams,\n Erc20CreateParams,\n PoolCreationParams,\n DispenserCreationParams,\n ConsumeMarketFee\n} from '../@types/index.js'\n\ninterface Template {\n templateAddress: string\n isActive: boolean\n}\n\nexport interface TokenOrder {\n tokenAddress: string\n consumer: string\n serviceIndex: number\n _providerFee: ProviderFees\n _consumeMarketFee: ConsumeMarketFee\n}\n\nexport interface NftCreateData {\n name: string\n symbol: string\n templateIndex: number\n tokenURI: string\n transferable: boolean\n owner: string\n}\n\n/**\n * Provides an interface for NFT Factory contract\n */\nexport class NftFactory {\n public factory721Address: string\n public factory721Abi: AbiItem | AbiItem[]\n public web3: Web3\n public config: Config\n public factory721: Contract\n\n /**\n * Instantiate Datatokens.\n * @param {String} factory721Address\n * @param {AbiItem | AbiItem[]} factory721ABI\n * @param {Web3} web3\n */\n constructor(\n factory721Address: string,\n web3: Web3,\n network?: string | number,\n factory721Abi?: AbiItem | AbiItem[],\n config?: Config\n ) {\n this.factory721Address = factory721Address\n this.factory721Abi = factory721Abi || (defaultFactory721Abi.abi as AbiItem[])\n this.web3 = web3\n this.config = config || new ConfigHelper().getConfig(network || 'unknown')\n this.factory721 = setContractDefaults(\n new this.web3.eth.Contract(this.factory721Abi, this.factory721Address),\n this.config\n )\n }\n\n /**\n * Get estimated gas cost for deployERC721Contract value\n * @param {String} address\n * @param {String} nftData\n * @return {Promise<string>} NFT datatoken address\n */\n public async estGasCreateNFT(address: string, nftData: NftCreateData): Promise<string> {\n return estimateGas(\n address,\n this.factory721.methods.deployERC721Contract,\n nftData.name,\n nftData.symbol,\n nftData.templateIndex,\n ZERO_ADDRESS,\n ZERO_ADDRESS,\n nftData.tokenURI,\n nftData.transferable,\n nftData.owner\n )\n }\n\n /**\n * Create new NFT\n * @param {String} address\n * @param {NFTCreateData} nftData\n * @return {Promise<string>} NFT datatoken address\n */\n public async createNFT(address: string, nftData: NftCreateData): Promise<string> {\n if (!nftData.templateIndex) nftData.templateIndex = 1\n\n if (!nftData.name || !nftData.symbol) {\n const { name, symbol } = generateDtName()\n nftData.name = name\n nftData.symbol = symbol\n }\n if (nftData.templateIndex > (await this.getCurrentNFTTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (nftData.templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n if ((await this.getNFTTemplate(nftData.templateIndex)).isActive === false) {\n throw new Error(`Template is not active`)\n }\n const estGas = await estimateGas(\n address,\n this.factory721.methods.deployERC721Contract,\n nftData.name,\n nftData.symbol,\n nftData.templateIndex,\n ZERO_ADDRESS,\n ZERO_ADDRESS,\n nftData.tokenURI,\n nftData.transferable,\n nftData.owner\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .deployERC721Contract(\n nftData.name,\n nftData.symbol,\n nftData.templateIndex,\n ZERO_ADDRESS,\n ZERO_ADDRESS,\n nftData.tokenURI,\n nftData.transferable,\n nftData.owner\n )\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n let tokenAddress = null\n try {\n tokenAddress = trxReceipt.events.NFTCreated.returnValues[0]\n } catch (e) {\n LoggerInstance.error(`ERROR: Failed to create datatoken : ${e.message}`)\n }\n return tokenAddress\n }\n\n /** Get Current NFT Count (NFT created)\n * @return {Promise<number>} Number of NFT created from this factory\n */\n public async getCurrentNFTCount(): Promise<number> {\n const trxReceipt = await this.factory721.methods.getCurrentNFTCount().call()\n return trxReceipt\n }\n\n /** Get Current Datatoken Count\n * @return {Promise<number>} Number of DTs created from this factory\n */\n public async getCurrentTokenCount(): Promise<number> {\n const trxReceipt = await this.factory721.methods.getCurrentTokenCount().call()\n return trxReceipt\n }\n\n /** Get Factory Owner\n * @return {Promise<string>} Factory Owner address\n */\n public async getOwner(): Promise<string> {\n const trxReceipt = await this.factory721.methods.owner().call()\n return trxReceipt\n }\n\n /** Get Current NFT Template Count\n * @return {Promise<number>} Number of NFT Template added to this factory\n */\n public async getCurrentNFTTemplateCount(): Promise<number> {\n const count = await this.factory721.methods.getCurrentNFTTemplateCount().call()\n return count\n }\n\n /** Get Current Template Datatoken (ERC20) Count\n * @return {Promise<number>} Number of ERC20 Template added to this factory\n */\n public async getCurrentTokenTemplateCount(): Promise<number> {\n const count = await this.factory721.methods.getCurrentTemplateCount().call()\n return count\n }\n\n /** Get NFT Template\n * @param {Number} index Template index\n * @return {Promise<Template>} Number of Template added to this factory\n */\n public async getNFTTemplate(index: number): Promise<Template> {\n if (index > (await this.getCurrentNFTTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (index === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n const template = await this.factory721.methods.getNFTTemplate(index).call()\n return template\n }\n\n /** Get Datatoken(erc20) Template\n * @param {Number} index Template index\n * @return {Promise<Template>} DT Template info\n */\n public async getTokenTemplate(index: number): Promise<Template> {\n const template = await this.factory721.methods.getTokenTemplate(index).call()\n return template\n }\n\n /** Check if ERC20 is deployed from the factory\n * @param {String} datatoken Datatoken address we want to check\n * @return {Promise<Boolean>} return true if deployed from this factory\n */\n public async checkDatatoken(datatoken: string): Promise<Boolean> {\n const isDeployed = await this.factory721.methods.erc20List(datatoken).call()\n return isDeployed\n }\n\n /** Check if NFT is deployed from the factory\n * @param {String} nftAddress nftAddress address we want to check\n * @return {Promise<String>} return address(0) if it's not, or the nftAddress if true\n */\n public async checkNFT(nftAddress: string): Promise<String> {\n const confirmAddress = await this.factory721.methods.erc721List(nftAddress).call()\n return confirmAddress\n }\n\n /**\n * Estimate gas cost for add721TokenTemplate method\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddNFTTemplate(\n address: string,\n templateAddress: string\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.add721TokenTemplate,\n templateAddress\n )\n }\n\n /**\n * Add a new erc721 token template - only factory Owner\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addNFTTemplate(\n address: string,\n templateAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateAddress === ZERO_ADDRESS) {\n throw new Error(`Template cannot be ZERO address`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.add721TokenTemplate,\n templateAddress\n )\n\n // Invoke add721TokenTemplate function of the contract\n const trxReceipt = await this.factory721.methods\n .add721TokenTemplate(templateAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for disable721TokenTemplate method\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to disable\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async estGasDisableNFTTemplate(\n address: string,\n templateIndex: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.disable721TokenTemplate,\n templateIndex\n )\n }\n\n /**\n * Disable token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to disable\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async disableNFTTemplate(\n address: string,\n templateIndex: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateIndex > (await this.getCurrentNFTTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n const estGas = await estimateGas(\n address,\n this.factory721.methods.disable721TokenTemplate,\n templateIndex\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .disable721TokenTemplate(templateIndex)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Reactivate a previously disabled token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to reactivate\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async estGasReactivateNFTTemplate(\n address: string,\n templateIndex: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.reactivate721TokenTemplate,\n templateIndex\n )\n }\n\n /**\n * Reactivate a previously disabled token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to reactivate\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async reactivateNFTTemplate(\n address: string,\n templateIndex: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateIndex > (await this.getCurrentNFTTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.reactivate721TokenTemplate,\n templateIndex\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .reactivate721TokenTemplate(templateIndex)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for addTokenTemplate method\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async estGasAddTokenTemplate(\n address: string,\n templateAddress: string\n ): Promise<any> {\n return estimateGas(address, this.factory721.methods.addTokenTemplate, templateAddress)\n }\n\n /**\n * Add a new erc721 token template - only factory Owner\n * @param {String} address\n * @param {String} templateAddress template address to add\n * @return {Promise<TransactionReceipt>}\n */\n public async addTokenTemplate(\n address: string,\n templateAddress: string\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateAddress === ZERO_ADDRESS) {\n throw new Error(`Template cannot be address ZERO`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.addTokenTemplate,\n templateAddress\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .addTokenTemplate(templateAddress)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for disableTokenTemplate method\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to disable\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async estGasDisableTokenTemplate(\n address: string,\n templateIndex: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.disableTokenTemplate,\n templateIndex\n )\n }\n\n /**\n * Disable token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to disable\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async disableTokenTemplate(\n address: string,\n templateIndex: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateIndex > (await this.getCurrentTokenTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n if ((await this.getTokenTemplate(templateIndex)).isActive === false) {\n throw new Error(`Template is already disabled`)\n }\n const estGas = await estimateGas(\n address,\n this.factory721.methods.disableTokenTemplate,\n templateIndex\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .disableTokenTemplate(templateIndex)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for reactivateTokenTemplate method\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to reactivate\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async estGasReactivateTokenTemplate(\n address: string,\n templateIndex: number\n ): Promise<any> {\n return estimateGas(\n address,\n this.factory721.methods.reactivateTokenTemplate,\n templateIndex\n )\n }\n\n /**\n * Reactivate a previously disabled token template - only factory Owner\n * @param {String} address\n * @param {Number} templateIndex index of the template we want to reactivate\n * @return {Promise<TransactionReceipt>} current token template count\n */\n public async reactivateTokenTemplate(\n address: string,\n templateIndex: number\n ): Promise<TransactionReceipt> {\n if ((await this.getOwner()) !== address) {\n throw new Error(`Caller is not Factory Owner`)\n }\n if (templateIndex > (await this.getCurrentTokenTemplateCount())) {\n throw new Error(`Template index doesnt exist`)\n }\n\n if (templateIndex === 0) {\n throw new Error(`Template index cannot be ZERO`)\n }\n if ((await this.getTokenTemplate(templateIndex)).isActive === true) {\n throw new Error(`Template is already active`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.reactivateTokenTemplate,\n templateIndex\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .reactivateTokenTemplate(templateIndex)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas cost for startMultipleTokenOrder method\n * @param address Caller address\n * @param orders an array of struct tokenOrder\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estGasStartMultipleTokenOrder(\n address: string,\n orders: TokenOrder[]\n ): Promise<any> {\n return estimateGas(address, this.factory721.methods.startMultipleTokenOrder, orders)\n }\n\n /**\n * @dev startMultipleTokenOrder\n * Used as a proxy to order multiple services\n * Users can have inifinite approvals for fees for factory instead of having one approval/ erc20 contract\n * Requires previous approval of all :\n * - consumeFeeTokens\n * - publishMarketFeeTokens\n * - erc20 datatokens\n * @param address Caller address\n * @param orders an array of struct tokenOrder\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async startMultipleTokenOrder(\n address: string,\n orders: TokenOrder[]\n ): Promise<TransactionReceipt> {\n if (orders.length > 50) {\n throw new Error(`Too many orders`)\n }\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.startMultipleTokenOrder,\n orders\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .startMultipleTokenOrder(orders)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for createNftWithErc20 method\n * @param address Caller address\n * @param _NftCreateData input data for nft creation\n * @param _ErcCreateData input data for erc20 creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n\n public async estGasCreateNftWithErc20(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams\n ): Promise<any> {\n const ercCreateData = getErcCreationParams(ercParams)\n return estimateGas(\n address,\n this.factory721.methods.createNftWithErc20,\n nftCreateData,\n ercCreateData\n )\n }\n\n /**\n * @dev createNftWithErc20\n * Creates a new NFT, then a ERC20,all in one call\n * @param address Caller address\n * @param _NftCreateData input data for nft creation\n * @param _ErcCreateData input data for erc20 creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n\n public async createNftWithErc20(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams\n ): Promise<TransactionReceipt> {\n const ercCreateData = getErcCreationParams(ercParams)\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.createNftWithErc20,\n nftCreateData,\n ercCreateData\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .createNftWithErc20(nftCreateData, ercCreateData)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /**\n * Estimate gas cost for createNftErc20WithPool method\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param poolParams input data for Pool Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estGasCreateNftErc20WithPool(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n poolParams: PoolCreationParams\n ): Promise<any> {\n const ercCreateData = getErcCreationParams(ercParams)\n const poolData = await getPoolCreationParams(this.web3, poolParams)\n return estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithPool,\n nftCreateData,\n ercCreateData,\n poolData\n )\n }\n\n /**\n * @dev createNftErc20WithPool\n * Creates a new NFT, then a ERC20, then a Pool, all in one call\n * Use this carefully, because if Pool creation fails, you are still going to pay a lot of gas\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param poolParams input data for Pool Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async createNftErc20WithPool(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n poolParams: PoolCreationParams\n ): Promise<TransactionReceipt> {\n const ercCreateData = getErcCreationParams(ercParams)\n const poolData = await getPoolCreationParams(this.web3, poolParams)\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithPool,\n nftCreateData,\n ercCreateData,\n poolData\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .createNftWithErc20WithPool(nftCreateData, ercCreateData, poolData)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas cost for createNftErc20WithFixedRate method\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param freParams input data for FixedRate Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estGasCreateNftErc20WithFixedRate(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n freParams: FreCreationParams\n ): Promise<any> {\n const ercCreateData = getErcCreationParams(ercParams)\n const fixedData = await getFreCreationParams(freParams)\n return estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithFixedRate,\n nftCreateData,\n ercCreateData,\n fixedData\n )\n }\n\n /**\n * @dev createNftErc20WithFixedRate\n * Creates a new NFT, then a ERC20, then a FixedRateExchange, all in one call\n * Use this carefully, because if Fixed Rate creation fails, you are still going to pay a lot of gas\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param freParams input data for FixedRate Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async createNftErc20WithFixedRate(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n freParams: FreCreationParams\n ): Promise<TransactionReceipt> {\n const ercCreateData = getErcCreationParams(ercParams)\n const fixedData = getFreCreationParams(freParams)\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithFixedRate,\n nftCreateData,\n ercCreateData,\n fixedData\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .createNftWithErc20WithFixedRate(nftCreateData, ercCreateData, fixedData)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n\n /** Estimate gas cost for createNftErc20WithFixedRate method\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param dispenserParams input data for Dispenser Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async estGasCreateNftErc20WithDispenser(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n dispenserParams: DispenserCreationParams\n ): Promise<any> {\n const ercCreateData = getErcCreationParams(ercParams)\n return estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithDispenser,\n nftCreateData,\n ercCreateData,\n dispenserParams\n )\n }\n\n /**\n * @dev createNftErc20WithDispenser\n * Creates a new NFT, then a ERC20, then a Dispenser, all in one call\n * Use this carefully, because if Dispenser creation fails, you are still going to pay a lot of gas\n * @param address Caller address\n * @param nftCreateData input data for NFT Creation\n * @param ercParams input data for ERC20 Creation\n * @param dispenserParams input data for Dispenser Creation\n * @return {Promise<TransactionReceipt>} transaction receipt\n */\n public async createNftErc20WithDispenser(\n address: string,\n nftCreateData: NftCreateData,\n ercParams: Erc20CreateParams,\n dispenserParams: DispenserCreationParams\n ): Promise<TransactionReceipt> {\n const ercCreateData = getErcCreationParams(ercParams)\n\n dispenserParams.maxBalance = Web3.utils.toWei(dispenserParams.maxBalance)\n dispenserParams.maxTokens = Web3.utils.toWei(dispenserParams.maxTokens)\n\n const estGas = await estimateGas(\n address,\n this.factory721.methods.createNftWithErc20WithDispenser,\n nftCreateData,\n ercCreateData,\n dispenserParams\n )\n\n // Invoke createToken function of the contract\n const trxReceipt = await this.factory721.methods\n .createNftWithErc20WithDispenser(nftCreateData, ercCreateData, dispenserParams)\n .send({\n from: address,\n gas: estGas + 1,\n gasPrice: await getFairGasPrice(this.web3, this.config)\n })\n\n return trxReceipt\n }\n}\n","import { LogLevel } from '../utils/Logger'\nimport { AbiItem } from 'web3-utils/types'\n\nexport class Config {\n /**\n * Ethereum node URL.\n * @type {string}\n */\n public nodeUri?: string\n\n /**\n * Address of Provider.\n * @type {string}\n */\n public providerAddress?: string\n\n /**\n * Metadata Store URL.\n * @type {string}\n */\n public metadataCacheUri?: string\n\n /**\n * Provider URL.\n * @type {string}\n */\n public providerUri?: string\n\n /**\n * Web3 Provider.\n * @type {any}\n */\n public web3Provider?: any\n\n /**\n * Ocean Token address\n * @type {string}\n */\n public oceanTokenAddress?: string\n\n /**\n * Factory address\n * @type {string}\n */\n public erc721FactoryAddress?: string\n\n /**\n * Factory ABI\n * @type {string}\n */\n public erc721FFactoryABI?: AbiItem | AbiItem[]\n\n /**\n * datatokens ABI\n * @type {string}\n */\n public datatokensABI?: AbiItem | AbiItem[]\n\n /**\n * Pool Template address\n * @type {string}\n */\n public poolTemplateAddress?: string\n\n /**\n * Pool Factory ABI\n * @type {string}\n */\n public poolFactoryABI?: AbiItem | AbiItem[]\n\n /**\n * Pool ABI\n * @type {string}\n */\n public poolABI?: AbiItem | AbiItem[]\n\n /**\n * FixedRateExchangeAddress\n * @type {string}\n */\n public fixedRateExchangeAddress?: string\n\n /**\n * FixedRateExchangeAddressABI\n * @type {any}\n */\n public fixedRateExchangeAddressABI?: AbiItem | AbiItem[]\n\n /**\n * DispenserAddress\n * @type {string}\n */\n public dispenserAddress?: string\n\n /**\n * DispenserABI\n * @type {any}\n */\n public dispenserABI?: AbiItem | AbiItem[]\n\n /**\n * OPFCommunityFeeCollector\n * @type {string}\n */\n public opfCommunityFeeCollector?: string\n\n /**\n * SideStaking address\n * @type {string}\n */\n public sideStakingAddress?: string\n\n /**\n * block number of the deployment\n * @type {number}\n */\n public startBlock?: number\n /**\n * Log level.\n * @type {boolean | LogLevel}\n */\n public verbose?: boolean | LogLevel\n\n /**\n * Message shown when the user creates its own token.\n * @type {string}\n */\n public authMessage?: string\n\n /**\n * Token expiration time in ms.\n * @type {number}\n */\n public authTokenExpiration?: number\n\n /**\n * Parity config\n * @type {string}\n */\n public parityUri?: string\n\n public threshold?: number\n\n /**\n * Chain ID\n * @type {number}\n */\n chainId: number\n\n /**\n * Network name ex: mainnet, rinkeby, polygon\n * @type {string}\n */\n network: string\n\n /**\n * Url of the relevant subgraph instance ex: https://subgraph.mainnet.oceanprotocol.com\n * @type {string}\n */\n subgraphUri: string\n\n /**\n * Url of the blockchain exporer ex: https://etherscan.io\n * @type {string}\n */\n explorerUri: string\n\n /**\n * Ocean toke symbol on the chain, it's used just for convenience to reduce number of calls\n * @type {string}\n */\n oceanTokenSymbol: string\n\n /**\n * Specify the transaction Block Timeout\n * @type {number}\n */\n transactionBlockTimeout: number\n\n /**\n * Specify the transaction Confirmation Blocks\n * @type {number}\n */\n transactionConfirmationBlocks: number\n\n /**\n * Specify the transaction Polling Blocks Timeout\n * @type {number}\n */\n transactionPollingTimeout: number\n\n /**\n * Specify the multiplier for the gas fee\n * @type {number}\n */\n gasFeeMultiplier: number\n}\n\nexport default Config\n","import { LoggerInstance } from './Logger'\n\nexport const zeroX = (input: string): string => zeroXTransformer(input, true)\nexport const noZeroX = (input: string): string => zeroXTransformer(input, false)\nexport function zeroXTransformer(input = '', zeroOutput: boolean): string {\n const { valid, output } = inputMatch(input, /^(?:0x)*([a-f0-9]+)$/i, 'zeroXTransformer')\n return (zeroOutput && valid ? '0x' : '') + output\n}\n\n// Shared functions\nfunction inputMatch(\n input: string,\n regexp: RegExp,\n conversorName: string\n): { valid: boolean; output: string } {\n if (typeof input !== 'string') {\n LoggerInstance.debug('Not input string:')\n LoggerInstance.debug(input)\n throw new Error(`[${conversorName}] Expected string, input type: ${typeof input}`)\n }\n const match = input.match(regexp)\n if (!match) {\n LoggerInstance.warn(`[${conversorName}] Input transformation failed.`)\n return { valid: false, output: input }\n }\n return { valid: true, output: match[1] }\n}\n","import Web3 from 'web3'\nimport { LoggerInstance, getData } from '../utils'\nimport {\n FileInfo,\n ComputeJob,\n ComputeOutput,\n ComputeAlgorithm,\n ComputeAsset,\n ComputeEnvironment,\n ProviderInitialize,\n ProviderComputeInitializeResults\n} from '../@types/'\nimport { noZeroX } from '../utils/ConversionTypeHelper'\nimport fetch from 'cross-fetch'\nexport interface HttpCallback {\n (httpMethod: string, url: string, body: string, header: any): Promise<any>\n}\n\nexport interface ServiceEndpoint {\n serviceName: string\n method: string\n urlPath: string\n}\nexport interface UserCustomParameters {\n [key: string]: any\n}\n\nexport class Provider {\n /**\n * Returns the provider endpoints\n * @return {Promise<ServiceEndpoint[]>}\n */\n async getEndpoints(providerUri: string): Promise<any> {\n try {\n const endpoints = await getData(providerUri)\n return await endpoints.json()\n } catch (e) {\n LoggerInstance.error('Finding the service endpoints failed:', e)\n return null\n }\n }\n\n getEndpointURL(\n servicesEndpoints: ServiceEndpoint[],\n serviceName: string\n ): ServiceEndpoint {\n if (!servicesEndpoints) return null\n return servicesEndpoints.find((s) => s.serviceName === serviceName) as ServiceEndpoint\n }\n\n /**\n * Returns the service endpoints that exist in provider.\n * @param {any} endpoints\n * @return {Promise<ServiceEndpoint[]>}\n */\n public async getServiceEndpoints(providerEndpoint: string, endpoints: any) {\n const serviceEndpoints: ServiceEndpoint[] = []\n for (const i in endpoints.serviceEndpoints) {\n const endpoint: ServiceEndpoint = {\n serviceName: i,\n method: endpoints.serviceEndpoints[i][0],\n urlPath: providerEndpoint + endpoints.serviceEndpoints[i][1]\n }\n serviceEndpoints.push(endpoint)\n }\n return serviceEndpoints\n }\n\n /** Gets current nonce\n * @param {string} providerUri provider uri address\n * @param {string} consumerAddress Publisher address\n * @param {AbortSignal} signal abort signal\n * @param {string} providerEndpoints Identifier of the asset to be registered in ocean\n * @param {string} serviceEndpoints document description object (DDO)=\n * @return {Promise<string>} urlDetails\n */\n public async getNonce(\n providerUri: string,\n consumerAddress: string,\n signal?: AbortSignal,\n providerEndpoints?: any,\n serviceEndpoints?: ServiceEndpoint[]\n ): Promise<string> {\n if (!providerEndpoints) {\n providerEndpoints = await this.getEndpoints(providerUri)\n }\n if (!serviceEndpoints) {\n serviceEndpoints = await this.getServiceEndpoints(providerUri, providerEndpoints)\n }\n const path = this.getEndpointURL(serviceEndpoints, 'nonce')\n ? this.getEndpointURL(serviceEndpoints, 'nonce').urlPath\n : null\n if (!path) return null\n try {\n const response = await fetch(path + `?userAddress=${consumerAddress}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n return (await response.json()).nonce.toString()\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('HTTP request failed')\n }\n }\n\n public async signProviderRequest(\n web3: Web3,\n accountId: string,\n message: string,\n password?: string\n ): Promise<string> {\n const consumerMessage = web3.utils.soliditySha3({\n t: 'bytes',\n v: web3.utils.utf8ToHex(message)\n })\n const isMetaMask =\n web3 && web3.currentProvider && (web3.currentProvider as any).isMetaMask\n if (isMetaMask)\n return await web3.eth.personal.sign(consumerMessage, accountId, password)\n else return await web3.eth.sign(consumerMessage, accountId)\n }\n\n /** Encrypt data using the Provider's own symmetric key\n * @param {string} data data in json format that needs to be sent , it can either be a DDO or a File array\n * @param {string} providerUri provider uri address\n * @param {AbortSignal} signal abort signal\n * @return {Promise<string>} urlDetails\n */\n public async encrypt(\n data: any,\n providerUri: string,\n signal?: AbortSignal\n ): Promise<string> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const path = this.getEndpointURL(serviceEndpoints, 'encrypt')\n ? this.getEndpointURL(serviceEndpoints, 'encrypt').urlPath\n : null\n if (!path) return null\n try {\n const response = await fetch(path, {\n method: 'POST',\n body: JSON.stringify(data),\n headers: {\n 'Content-Type': 'application/octet-stream'\n },\n signal: signal\n })\n return await response.text()\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('HTTP request failed')\n }\n }\n\n /** Get DDO File details (if possible)\n * @param {string} did did\n * @param {number} serviceId the id of the service for which to check the files\n * @param {string} providerUri uri of the provider that will be used to check the file\n * @param {AbortSignal} signal abort signal\n * @return {Promise<FileInfo[]>} urlDetails\n */\n public async checkDidFiles(\n did: string,\n serviceId: number,\n providerUri: string,\n signal?: AbortSignal\n ): Promise<FileInfo[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const args = { did: did, serviceId: serviceId }\n const files: FileInfo[] = []\n const path = this.getEndpointURL(serviceEndpoints, 'fileinfo')\n ? this.getEndpointURL(serviceEndpoints, 'fileinfo').urlPath\n : null\n if (!path) return null\n try {\n const response = await fetch(path, {\n method: 'POST',\n body: JSON.stringify(args),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const results: FileInfo[] = await response.json()\n for (const result of results) {\n files.push(result)\n }\n return files\n } catch (e) {\n return null\n }\n }\n\n /** Get URL details (if possible)\n * @param {string} url or did\n * @param {string} providerUri uri of the provider that will be used to check the file\n * @param {AbortSignal} signal abort signal\n * @return {Promise<FileInfo[]>} urlDetails\n */\n public async checkFileUrl(\n url: string,\n providerUri: string,\n signal?: AbortSignal\n ): Promise<FileInfo[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const args = { url: url, type: 'url' }\n const files: FileInfo[] = []\n const path = this.getEndpointURL(serviceEndpoints, 'fileinfo')\n ? this.getEndpointURL(serviceEndpoints, 'fileinfo').urlPath\n : null\n if (!path) return null\n try {\n const response = await fetch(path, {\n method: 'POST',\n body: JSON.stringify(args),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const results: FileInfo[] = await response.json()\n for (const result of results) {\n files.push(result)\n }\n return files\n } catch (e) {\n return null\n }\n }\n\n /** Get Compute Environments\n * @return {Promise<ComputeEnvironment[]>} urlDetails\n */\n public async getComputeEnvironments(\n providerUri: string,\n signal?: AbortSignal\n ): Promise<ComputeEnvironment[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const path = this.getEndpointURL(serviceEndpoints, 'computeEnvironments')?.urlPath\n if (!path) return null\n try {\n const response = await fetch(path, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const envs: ComputeEnvironment[] = await response.json()\n return envs\n } catch (e) {\n LoggerInstance.error(e.message)\n return null\n }\n }\n\n /** Initialize a service request.\n * @param {DDO | string} asset\n * @param {number} serviceIndex\n * @param {string} serviceType\n * @param {string} consumerAddress\n * @param {UserCustomParameters} userCustomParameters\n * @param {string} providerUri Identifier of the asset to be registered in ocean\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ProviderInitialize>} ProviderInitialize data\n */\n public async initialize(\n did: string,\n serviceId: string,\n fileIndex: number,\n consumerAddress: string,\n providerUri: string,\n signal?: AbortSignal,\n userCustomParameters?: UserCustomParameters,\n computeEnv?: string,\n validUntil?: number\n ): Promise<ProviderInitialize> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n let initializeUrl = this.getEndpointURL(serviceEndpoints, 'initialize')\n ? this.getEndpointURL(serviceEndpoints, 'initialize').urlPath\n : null\n\n if (!initializeUrl) return null\n initializeUrl += `?documentId=${did}`\n initializeUrl += `&serviceId=${serviceId}`\n initializeUrl += `&fileIndex=${fileIndex}`\n initializeUrl += `&consumerAddress=${consumerAddress}`\n if (userCustomParameters)\n initializeUrl += '&userdata=' + encodeURI(JSON.stringify(userCustomParameters))\n if (computeEnv) initializeUrl += '&environment=' + encodeURI(computeEnv)\n if (validUntil) initializeUrl += '&validUntil=' + validUntil\n try {\n const response = await fetch(initializeUrl, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const results: ProviderInitialize = await response.json()\n return results\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('Asset URL not found or not available.')\n }\n }\n\n /** Initialize a compute request.\n * @param {ComputeAsset} assets\n * @param {ComputeAlgorithmber} algorithm\n * @param {string} computeEnv\n * @param {number} validUntil\n * @param {string} providerUri Identifier of the asset to be registered in ocean\n * @param {string} accountId\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ProviderComputeInitialize>} ProviderComputeInitialize data\n */\n public async initializeCompute(\n assets: ComputeAsset[],\n algorithm: ComputeAlgorithm,\n computeEnv: string,\n validUntil: number,\n providerUri: string,\n accountId: string,\n signal?: AbortSignal\n ): Promise<ProviderComputeInitializeResults> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const providerData = {\n datasets: assets,\n algorithm: algorithm,\n compute: {\n env: computeEnv,\n validUntil: validUntil\n },\n consumerAddress: accountId\n }\n const initializeUrl = this.getEndpointURL(serviceEndpoints, 'initializeCompute')\n ? this.getEndpointURL(serviceEndpoints, 'initializeCompute').urlPath\n : null\n if (!initializeUrl) return null\n try {\n const response = await fetch(initializeUrl, {\n method: 'POST',\n body: JSON.stringify(providerData),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n const results = await response.json()\n return results\n } catch (e) {\n LoggerInstance.error(e)\n throw new Error('ComputeJob cannot be initialized')\n }\n }\n\n /** Gets fully signed URL for download\n * @param {string} did\n * @param {string} accountId\n * @param {string} serviceId\n * @param {number} fileIndex\n * @param {string} providerUri\n * @param {Web3} web3\n * @param {UserCustomParameters} userCustomParameters\n * @return {Promise<string>}\n */\n public async getDownloadUrl(\n did: string,\n accountId: string,\n serviceId: string,\n fileIndex: number,\n transferTxId: string,\n providerUri: string,\n web3: Web3,\n userCustomParameters?: UserCustomParameters\n ): Promise<any> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const downloadUrl = this.getEndpointURL(serviceEndpoints, 'download')\n ? this.getEndpointURL(serviceEndpoints, 'download').urlPath\n : null\n if (!downloadUrl) return null\n const nonce = Date.now()\n const signature = await this.signProviderRequest(web3, accountId, did + nonce)\n let consumeUrl = downloadUrl\n consumeUrl += `?fileIndex=${fileIndex}`\n consumeUrl += `&documentId=${did}`\n consumeUrl += `&transferTxId=${transferTxId}`\n consumeUrl += `&serviceId=${serviceId}`\n consumeUrl += `&consumerAddress=${accountId}`\n consumeUrl += `&nonce=${nonce}`\n consumeUrl += `&signature=${signature}`\n if (userCustomParameters)\n consumeUrl += '&userdata=' + encodeURI(JSON.stringify(userCustomParameters))\n return consumeUrl\n }\n\n /** Instruct the provider to start a compute job\n * @param {string} did\n * @param {string} consumerAddress\n * @param {string} computeEnv\n * @param {ComputeAlgorithm} algorithm\n * @param {string} providerUri\n * @param {Web3} web3\n * @param {AbortSignal} signal abort signal\n * @param {ComputeOutput} output\n * @return {Promise<ComputeJob | ComputeJob[]>}\n */\n public async computeStart(\n providerUri: string,\n web3: Web3,\n consumerAddress: string,\n computeEnv: string,\n dataset: ComputeAsset,\n algorithm: ComputeAlgorithm,\n signal?: AbortSignal,\n additionalDatasets?: ComputeAsset[],\n output?: ComputeOutput\n ): Promise<ComputeJob | ComputeJob[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeStartUrl = this.getEndpointURL(serviceEndpoints, 'computeStart')\n ? this.getEndpointURL(serviceEndpoints, 'computeStart').urlPath\n : null\n\n const nonce = Date.now()\n let signatureMessage = consumerAddress\n signatureMessage += dataset.documentId\n signatureMessage += nonce\n const signature = await this.signProviderRequest(\n web3,\n consumerAddress,\n signatureMessage\n )\n const payload = Object()\n payload.consumerAddress = consumerAddress\n payload.signature = signature\n payload.nonce = nonce\n payload.environment = computeEnv\n payload.dataset = dataset\n payload.algorithm = algorithm\n if (payload.additionalDatasets) payload.additionalDatasets = additionalDatasets\n if (output) payload.output = output\n if (!computeStartUrl) return null\n try {\n const response = await fetch(computeStartUrl, {\n method: 'POST',\n body: JSON.stringify(payload),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n\n if (response?.ok) {\n const params = await response.json()\n return params\n }\n LoggerInstance.error('Compute start failed: ', response.status, response.statusText)\n LoggerInstance.error('Payload was:', payload)\n return null\n } catch (e) {\n LoggerInstance.error('Compute start failed:')\n LoggerInstance.error(e)\n LoggerInstance.error('Payload was:', payload)\n return null\n }\n }\n\n /** Instruct the provider to Stop the execution of a to stop a compute job.\n * @param {string} did\n * @param {string} consumerAddress\n * @param {string} jobId\n * @param {string} providerUri\n * @param {Web3} web3\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ComputeJob | ComputeJob[]>}\n */\n public async computeStop(\n did: string,\n consumerAddress: string,\n jobId: string,\n providerUri: string,\n web3: Web3,\n signal?: AbortSignal\n ): Promise<ComputeJob | ComputeJob[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeStopUrl = this.getEndpointURL(serviceEndpoints, 'computeStop')\n ? this.getEndpointURL(serviceEndpoints, 'computeStop').urlPath\n : null\n\n const nonce = await this.getNonce(\n providerUri,\n consumerAddress,\n signal,\n providerEndpoints,\n serviceEndpoints\n )\n\n let signatureMessage = consumerAddress\n signatureMessage += jobId || ''\n signatureMessage += (did && `${noZeroX(did)}`) || ''\n signatureMessage += nonce\n const signature = await this.signProviderRequest(\n web3,\n consumerAddress,\n signatureMessage\n )\n const payload = Object()\n payload.signature = signature\n payload.documentId = noZeroX(did)\n payload.consumerAddress = consumerAddress\n if (jobId) payload.jobId = jobId\n\n if (!computeStopUrl) return null\n try {\n const response = await fetch(computeStopUrl, {\n method: 'PUT',\n body: JSON.stringify(payload),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n\n if (response?.ok) {\n const params = await response.json()\n return params\n }\n LoggerInstance.error('Compute stop failed:', response.status, response.statusText)\n LoggerInstance.error('Payload was:', payload)\n return null\n } catch (e) {\n LoggerInstance.error('Compute stop failed:')\n LoggerInstance.error(e)\n LoggerInstance.error('Payload was:', payload)\n return null\n }\n }\n\n /** Get compute status for a specific jobId/documentId/owner.\n * @param {string} providerUri The URI of the provider we want to query\n * @param {string} consumerAddress The consumer ethereum address\n * @param {string} jobId The ID of a compute job.\n * @param {string} did The ID of the asset\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ComputeJob | ComputeJob[]>}\n */\n public async computeStatus(\n providerUri: string,\n consumerAddress: string,\n jobId?: string,\n did?: string,\n signal?: AbortSignal\n ): Promise<ComputeJob | ComputeJob[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeStatusUrl = this.getEndpointURL(serviceEndpoints, 'computeStatus')\n ? this.getEndpointURL(serviceEndpoints, 'computeStatus').urlPath\n : null\n\n let url = `?consumerAddress=${consumerAddress}`\n url += (did && `&documentId=${noZeroX(did)}`) || ''\n url += (jobId && `&jobId=${jobId}`) || ''\n\n if (!computeStatusUrl) return null\n try {\n const response = await fetch(computeStatusUrl + url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n if (response?.ok) {\n const params = await response.json()\n return params\n }\n LoggerInstance.error(\n 'Get compute status failed:',\n response.status,\n response.statusText\n )\n return null\n } catch (e) {\n LoggerInstance.error('Get compute status failed')\n LoggerInstance.error(e)\n return null\n }\n }\n\n /** Get compute result url\n * @param {string} providerUri The URI of the provider we want to query\n * @param {Web3} web3 Web3 instance\n * @param {string} consumerAddress The consumer ethereum address\n * @param {string} jobId The ID of a compute job.\n * @param {number} index Result index\n * @return {Promise<string>}\n */\n public async getComputeResultUrl(\n providerUri: string,\n web3: Web3,\n consumerAddress: string,\n jobId: string,\n index: number\n ): Promise<string> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeResultUrl = this.getEndpointURL(serviceEndpoints, 'computeResult')\n ? this.getEndpointURL(serviceEndpoints, 'computeResult').urlPath\n : null\n\n const nonce = Date.now()\n let signatureMessage = consumerAddress\n signatureMessage += jobId\n signatureMessage += index.toString()\n signatureMessage += nonce\n const signature = await this.signProviderRequest(\n web3,\n consumerAddress,\n signatureMessage\n )\n if (!computeResultUrl) return null\n let resultUrl = computeResultUrl\n resultUrl += `?consumerAddress=${consumerAddress}`\n resultUrl += `&jobId=${jobId}`\n resultUrl += `&index=${index.toString()}`\n resultUrl += `&nonce=${nonce}`\n resultUrl += (signature && `&signature=${signature}`) || ''\n return resultUrl\n }\n\n /** Deletes a compute job.\n * @param {string} did\n * @param {string} consumerAddress\n * @param {string} jobId\n * @param {string} providerUri\n * @param {Web3} web3\n * @param {AbortSignal} signal abort signal\n * @return {Promise<ComputeJob | ComputeJob[]>}\n */\n public async computeDelete(\n did: string,\n consumerAddress: string,\n jobId: string,\n providerUri: string,\n web3: Web3,\n signal?: AbortSignal\n ): Promise<ComputeJob | ComputeJob[]> {\n const providerEndpoints = await this.getEndpoints(providerUri)\n const serviceEndpoints = await this.getServiceEndpoints(\n providerUri,\n providerEndpoints\n )\n const computeDeleteUrl = this.getEndpointURL(serviceEndpoints, 'computeDelete')\n ? this.getEndpointURL(serviceEndpoints, 'computeDelete').urlPath\n : null\n\n const nonce = await this.getNonce(\n providerUri,\n consumerAddress,\n signal,\n providerEndpoints,\n serviceEndpoints\n )\n\n let signatureMessage = consumerAddress\n signatureMessage += jobId || ''\n signatureMessage += (did && `${noZeroX(did)}`) || ''\n signatureMessage += nonce\n const signature = await this.signProviderRequest(\n web3,\n consumerAddress,\n signatureMessage\n )\n const payload = Object()\n payload.documentId = noZeroX(did)\n payload.consumerAddress = consumerAddress\n payload.jobId = jobId\n if (signature) payload.signature = signature\n\n if (!computeDeleteUrl) return null\n try {\n const response = await fetch(computeDeleteUrl, {\n method: 'DELETE',\n body: JSON.stringify(payload),\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n\n if (response?.ok) {\n const params = await response.json()\n return params\n }\n LoggerInstance.error(\n 'Delete compute job failed:',\n response.status,\n response.statusText\n )\n LoggerInstance.error('Payload was:', payload)\n return null\n } catch (e) {\n LoggerInstance.error('Delete compute job failed:')\n LoggerInstance.error(e)\n LoggerInstance.error('Payload was:', payload)\n return null\n }\n }\n\n /** Check for a valid provider at URL\n * @param {String} url provider uri address\n * @param {AbortSignal} signal abort signal\n * @return {Promise<boolean>} string\n */\n public async isValidProvider(url: string, signal?: AbortSignal): Promise<boolean> {\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n },\n signal: signal\n })\n if (response?.ok) {\n const params = await response.json()\n if (params && params.providerAddress) return true\n }\n return false\n } catch (error) {\n LoggerInstance.error(`Error validating provider: ${error.message}`)\n return false\n }\n }\n}\n\nexport const ProviderInstance = new Provider()\nexport default ProviderInstance\n"],"names":["LogLevel","Logger","constructor","logLevel","Error","this","setLevel","bypass","args","dispatch","Infinity","debug","Verbose","log","Log","warn","Warn","error","verb","level","console","LoggerInstance","generateDtName","wordList","list","wordListDefault","random1","Math","floor","random","adjectives","length","random2","nouns","indexNumber","adjective","replace","c","toUpperCase","noun","name","symbol","substring","minAbi","constant","inputs","outputs","type","payable","stateMutability","anonymous","indexed","ZERO_ADDRESS","GASLIMIT_DEFAULT","setContractDefaults","contract","config","transactionBlockTimeout","transactionConfirmationBlocks","transactionPollingTimeout","getFairGasPrice","web3","x","BigNumber","eth","getGasPrice","gasFeeMultiplier","multipliedBy","integerValue","ROUND_DOWN","toString","getErcCreationParams","ercParams","templateIndex","strings","addresses","minter","paymentCollector","mpFeeAddress","feeToken","uints","Web3","utils","toWei","cap","feeAmount","bytess","getFreOrderParams","freParams","exchangeContract","exchangeId","maxBaseTokenAmount","swapMarketFee","marketFeeAddress","getFreCreationParams","allowedConsumer","withMint","fixedPriceAddress","fixedRateAddress","baseTokenAddress","owner","marketFeeCollector","baseTokenDecimals","datatokenDecimals","fixedRate","marketFee","getPoolCreationParams","poolParams","ssContract","baseTokenSender","publisherAddress","poolTemplateAddress","ssParams","rate","vestingAmount","vestedBlocks","amountToUnits","initialBaseTokenLiquidity","swapFees","swapFeeLiquidityProvider","swapFeeMarketRunner","unitsToAmount","token","amount","tokenDecimals","tokenContract","Contract","decimals","methods","call","amountFormatted","div","exponentiatedBy","EXPONENTIAL_AT","e","message","times","estimateGas","from","functionToEstimateGas","estimatedGas","apply","err","estGas","fetchData","url","opts","result","fetch","ok","method","text","downloadFileBrowser","anchor","document","createElement","download","href","click","downloadFile","index","response","filename","headers","get","match","split","pop","data","arrayBuffer","getData","postData","payload","async","body","postWithHeaders","configHelperNetworksBase","chainId","network","metadataCacheUri","nodeUri","providerUri","subgraphUri","explorerUri","oceanTokenAddress","oceanTokenSymbol","fixedRateExchangeAddress","dispenserAddress","startBlock","configHelperNetworks","ConfigHelper","getAddressesFromEnv","customAddresses","configAddresses","FixedPrice","Dispenser","Staking","poolTemplate","ERC721Factory","OPFCommunityFeeCollector","Ocean","erc721FactoryAddress","sideStakingAddress","opfCommunityFeeCollector","process","env","AQUARIUS_URI","DefaultContractsAddresses","getConfig","infuraProjectId","filterBy","find","generateDid","erc721Address","toChecksumAddress","sha256","getHash","signHash","address","signedMessage","sign","substr","r","slice","s","v","estApprove","account","tokenAddress","spender","contractInstance","approve","force","currentAllowence","allowance","Decimal","greaterThanOrEqualTo","send","gas","gasPrice","approveWei","allowanceWei","gt","estTransfer","recipient","transfer","trxReceipt","balance","balanceOf","sleep","ms","Promise","resolve","setTimeout","calcMaxExactOut","calcMaxExactIn","getMaxSwapExactOut","poolInstance","poolAddress","getReserve","getMaxSwapExactIn","getMaxAddLiquidity","getMaxRemoveLiquidity","Aquarius","aquariusURL","did","signal","path","json","status","txid","tries","ddo","event","valid","jsonResponse","JSON","stringify","hash","proof","validatorAddress","publicKey","errors","MaxUint256","Pool","poolAbi","PoolTemplate","abi","fromWei","fee","defaultErc20Abi","setSwapFee","pool","getNumTokens","totalSupply","getCurrentTokens","getFinalTokens","getController","getBaseTokenAddress","getDatatokenAddress","getMarketFee","_publishMarketCollector","isBound","getBalance","isFinalized","getSwapFee","weight","getNormalizedWeight","getDenormalizedWeight","getTotalDenormalizedWeight","publishMarketFees","getCurrentOPCFees","communityFees","collectOPC","collectMarketFee","getMarketFeeCollector","newPublishMarketAddress","newPublishMarketSwapFee","updatePublishMarketFee","tokenInOutMarket","amountsInOutMaxFee","poolContract","tokenAmountIn","tokenIn","tokenInDecimals","minAmountOut","tokenOut","tokenOutDecimals","maxPrice","getBaseToken","swapExactAmountIn","maxSwap","greaterThan","maxAmountIn","tokenAmountOut","swapExactAmountOut","minPoolAmountOut","joinswapExternAmountIn","amountInFormatted","poolAmountIn","minTokenAmountOut","exitswapPoolAmountIn","poolDecimals","calcSingleOutGivenPoolIn","minTokenOutFormatted","decimalsTokenIn","decimalsTokenOut","tokenInContract","tokenOutContract","decimalsDiff","price","getSpotPrice","amountOutFormatted","getAmountInExactOut","tokenAmount","liquidityProviderSwapFeeAmount","lpFeeAmount","oceanFeeAmount","publishMarketSwapFeeAmount","consumeMarketSwapFeeAmount","getAmountOutExactIn","calcPoolOutSingleIn","poolAmountOut","calcSingleInPoolOut","calcSingleOutPoolIn","calcPoolInSingleOut","getSwapEventSignature","eventdata","encodeEventSignature","getJoinEventSignature","getExitEventSignature","dispenserAbi","dispenserContract","defaultDispenserAbi","dtAdress","maxTokens","maxBalance","logger","dtAddress","allowedSwapper","create","activate","deactivate","newAllowedSwapper","setAllowedSwapper","destination","dispense","ownerWithdraw","datatoken","active","String","isMinter","FixedRateCreateProgressStep","FixedRateExchange","fixedRateExchangeAbi","oceanAddress","fixedRateContract","ssAbi","defaultFixedRateExchangeAbi","baseToken","generateExchangeId","datatokenAddress","dtAmount","consumeMarketAddress","consumeMarketFee","buyDT","datatokenAmount","exchange","getExchange","consumeMarketFeeFormatted","dtAmountFormatted","dtDecimals","maxBtFormatted","btDecimals","sellDT","minBaseTokenAmount","minBtFormatted","getNumberOfExchanges","newRate","setRate","toggleExchangeState","weiRate","getRate","dtSupply","getDTSupply","btSupply","getBTSupply","getAllowedSwapper","fixedRateExchange","calcBaseInGivenOutDT","baseTokenAmount","marketFeeAmount","consumeMarketFeeAmount","calcBaseOutGivenInDT","dtBalance","btBalance","getFeesInfo","opcFee","marketFeeAvailable","oceanFeeAvailable","getExchanges","isActive","toggleMintState","fixedrate","amountWei","collectBT","collectDT","collectOceanFee","opcCollector","router","exchangeOwner","newMarketFee","updateMarketFee","newMarketFeeCollector","updateMarketFeeCollector","SideStaking","SideStakingTemplate","ssAddress","sideStaking","getDatatokenCirculatingSupply","getDatatokenCurrentCirculatingSupply","getPublisherAddress","getPoolAddress","getBaseTokenBalance","getDatatokenBalance","getvestingEndBlock","getvestingAmount","getvestingLastBlock","getvestingAmountSoFar","getVesting","swapFee","setPoolSwapFee","Router","routerAddress","RouterAbi","defaultRouter","operations","buyDTBatch","isApprovedToken","isSSContract","isFixedRateContract","routerOwner","factory","isPoolTemplate","addApprovedToken","getOwner","removeApprovedToken","addSSContract","removeSSContract","addFixedRateContract","removeFixedRateContract","addDispenserContract","removeDispenserContract","getOPCFee","swapOceanFee","newSwapOceanFee","newSwapNonOceanFee","newConsumeFee","newProviderFee","updateOPCFee","templateAddress","addPoolTemplate","removePoolTemplate","Nft","nftAbi","factory721Address","factory721Abi","defaultNftAbi","nftAddress","createERC20","getNftPermissions","deployERC20","nftContract","events","TokenCreated","returnValues","manager","addManager","getNftOwner","removeManager","erc20Deployer","addToCreateERC20List","removeFromCreateERC20List","metadataUpdater","addToMetadataList","removeFromMetadataList","updateMetadata","esGasRemoveMetadataUpdater","storeUpdater","addTo725StoreList","removeFrom725StoreList","store","cleanPermissions","nftOwner","nftReceiver","tokenId","transferFrom","tokenIdentifier","safeTransferFrom","metadataState","metadataDecryptorUrl","metadataDecryptorAddress","flags","metadataHash","metadataProofs","setMetaData","metadataAndTokenURI","sanitizedMetadataAndTokenURI","setMetaDataAndTokenURI","setMetaDataState","setTokenURI","ownerOf","getPermissions","getMetaData","isERC20Deployer","key","id","tokenURI","Datatoken","datatokensAbi","datatokensEnterpriseAbi","factoryAddress","factoryABI","nft","defaultDatatokensAbi","defaultDatatokensEnterpriseAbi","dtContract","toAddress","mint","fixedRateParams","createFixedRate","dispenserParams","createDispenser","getDTPermissions","capAvailble","getCap","gte","addMinter","removeMinter","paymentManager","addPaymentManager","removePaymentManager","setPaymentCollector","isPaymentManager","getNFTAddress","isNftOwner","nftPermissions","getPaymentCollector","weiAmount","transferWei","consumer","serviceIndex","providerFees","startOrder","consumeMarketFeeAddress","consumeMarketFeeToken","orderTxId","reuseOrder","orderParams","buyFromFreAndOrder","freContractParams","buyFromDispenserAndOrder","value","setData","permissions","getERC721Address","publishMarketFeeAddress","publishMarketFeeToken","publishMarketFeeAmount","setPublishingMarketFee","getPublishingMarketFee","estGasSetPublishingMarketFee","publishingMarketFee","NftFactory","factory721","defaultFactory721Abi","nftData","deployERC721Contract","transferable","getCurrentNFTTemplateCount","getNFTTemplate","NFTCreated","getCurrentNFTCount","getCurrentTokenCount","getCurrentTemplateCount","getTokenTemplate","erc20List","erc721List","add721TokenTemplate","disable721TokenTemplate","reactivate721TokenTemplate","addTokenTemplate","disableTokenTemplate","getCurrentTokenTemplateCount","reactivateTokenTemplate","orders","startMultipleTokenOrder","nftCreateData","ercCreateData","createNftWithErc20","poolData","createNftWithErc20WithPool","fixedData","createNftWithErc20WithFixedRate","createNftWithErc20WithDispenser","Config","providerAddress","web3Provider","erc721FFactoryABI","datatokensABI","poolFactoryABI","poolABI","fixedRateExchangeAddressABI","dispenserABI","verbose","authMessage","authTokenExpiration","parityUri","threshold","noZeroX","input","zeroOutput","output","regexp","conversorName","inputMatch","zeroXTransformer","Provider","endpoints","getEndpointURL","servicesEndpoints","serviceName","providerEndpoint","serviceEndpoints","i","push","urlPath","consumerAddress","providerEndpoints","getEndpoints","getServiceEndpoints","nonce","accountId","password","consumerMessage","soliditySha3","t","utf8ToHex","currentProvider","isMetaMask","personal","serviceId","files","results","_this$getEndpointURL","fileIndex","userCustomParameters","computeEnv","validUntil","initializeUrl","encodeURI","assets","algorithm","providerData","datasets","compute","transferTxId","downloadUrl","Date","now","consumeUrl","signProviderRequest","dataset","additionalDatasets","computeStartUrl","signatureMessage","documentId","signature","Object","environment","statusText","jobId","computeStopUrl","getNonce","computeStatusUrl","computeResultUrl","resultUrl","computeDeleteUrl","params","ProviderInstance"],"mappings":"opCACYA,IAAAA,GAAZ,SAAYA,GACVA,oBACAA,qBACAA,mBACAA,iBACAA,yBALF,CAAYA,IAAAA,aASCC,EACXC,YAAoBC,EAAqBH,EAASI,YAA9BD,gBAAAE,cAAAF,EAEbG,SAASH,GACdE,KAAKF,SAAWA,EAGXI,UAAUC,GACfH,KAAKI,SAAS,OAAQC,YAAoBF,GAGrCG,SAASH,GACdH,KAAKI,SAAS,QAAST,EAASY,WAAYJ,GAGvCK,OAAOL,GACZH,KAAKI,SAAS,MAAOT,EAASc,OAAQN,GAGjCO,QAAQP,GACbH,KAAKI,SAAS,OAAQT,EAASgB,QAASR,GAGnCS,SAAST,GACdH,KAAKI,SAAS,QAAST,EAASI,SAAUI,GAGpCC,SAASS,EAAcC,KAAoBX,GAC7CH,KAAKF,UAAYgB,GACnBC,QAAQF,MAASV,IAKVa,MAAAA,EAAiB,IAAIpB,+qECtClBqB,EAAeC,GAI7B,MAAMC,EAAOD,GAAYE,EACnBC,EAAUC,KAAKC,MAAMD,KAAKE,SAAWL,EAAKM,WAAWC,QACrDC,EAAUL,KAAKC,MAAMD,KAAKE,SAAWL,EAAKS,MAAMF,QAChDG,EAAcP,KAAKC,MAAsB,IAAhBD,KAAKE,UAG9BM,EAAYX,EAAKM,WAAWJ,GAASU,QAAQ,MAAQC,GAAMA,EAAEC,eAC7DC,EAAOf,EAAKS,MAAMD,GAASI,QAAQ,MAAQC,GAAMA,EAAEC,eAQzD,MAAO,CAAEE,QANOL,KAAaI,UAMdE,WAHbN,EAAUO,UAAU,EAAG,GAAKH,EAAKG,UAAU,EAAG,IAC9CJ,iBAAiBJ,WCrBRS,EAAS,CACpB,CACEC,UAAU,EACVC,OAAQ,GACRL,KAAM,OACNM,QAAS,CACP,CACEN,KAAM,GACNO,KAAM,WAGVC,SAAS,EACTC,gBAAiB,OACjBF,KAAM,YAER,CACEH,UAAU,EACVC,OAAQ,CACN,CACEL,KAAM,WACNO,KAAM,WAER,CACEP,KAAM,SACNO,KAAM,YAGVP,KAAM,UACNM,QAAS,CACP,CACEN,KAAM,GACNO,KAAM,SAGVC,SAAS,EACTC,gBAAiB,aACjBF,KAAM,YAER,CACEH,UAAU,EACVC,OAAQ,GACRL,KAAM,cACNM,QAAS,CACP,CACEN,KAAM,GACNO,KAAM,YAGVC,SAAS,EACTC,gBAAiB,OACjBF,KAAM,YAER,CACEH,UAAU,EACVC,OAAQ,CACN,CACEL,KAAM,QACNO,KAAM,WAER,CACEP,KAAM,MACNO,KAAM,WAER,CACEP,KAAM,SACNO,KAAM,YAGVP,KAAM,eACNM,QAAS,CACP,CACEN,KAAM,GACNO,KAAM,SAGVC,SAAS,EACTC,gBAAiB,aACjBF,KAAM,YAER,CACEH,UAAU,EACVC,OAAQ,GACRL,KAAM,WACNM,QAAS,CACP,CACEN,KAAM,GACNO,KAAM,UAGVC,SAAS,EACTC,gBAAiB,OACjBF,KAAM,YAER,CACEH,UAAU,EACVC,OAAQ,CACN,CACEL,KAAM,SACNO,KAAM,YAGVP,KAAM,YACNM,QAAS,CACP,CACEN,KAAM,UACNO,KAAM,YAGVC,SAAS,EACTC,gBAAiB,OACjBF,KAAM,YAER,CACEH,UAAU,EACVC,OAAQ,GACRL,KAAM,SACNM,QAAS,CACP,CACEN,KAAM,GACNO,KAAM,WAGVC,SAAS,EACTC,gBAAiB,OACjBF,KAAM,YAER,CACEH,UAAU,EACVC,OAAQ,CACN,CACEL,KAAM,MACNO,KAAM,WAER,CACEP,KAAM,SACNO,KAAM,YAGVP,KAAM,WACNM,QAAS,CACP,CACEN,KAAM,GACNO,KAAM,SAGVC,SAAS,EACTC,gBAAiB,aACjBF,KAAM,YAER,CACEH,UAAU,EACVC,OAAQ,CACN,CACEL,KAAM,SACNO,KAAM,WAER,CACEP,KAAM,WACNO,KAAM,YAGVP,KAAM,YACNM,QAAS,CACP,CACEN,KAAM,GACNO,KAAM,YAGVC,SAAS,EACTC,gBAAiB,OACjBF,KAAM,YAER,CACEC,SAAS,EACTC,gBAAiB,UACjBF,KAAM,YAER,CACEG,WAAW,EACXL,OAAQ,CACN,CACEM,SAAS,EACTX,KAAM,QACNO,KAAM,WAER,CACEI,SAAS,EACTX,KAAM,UACNO,KAAM,WAER,CACEI,SAAS,EACTX,KAAM,QACNO,KAAM,YAGVP,KAAM,WACNO,KAAM,SAER,CACEG,WAAW,EACXL,OAAQ,CACN,CACEM,SAAS,EACTX,KAAM,OACNO,KAAM,WAER,CACEI,SAAS,EACTX,KAAM,KACNO,KAAM,WAER,CACEI,SAAS,EACTX,KAAM,QACNO,KAAM,YAGVP,KAAM,WACNO,KAAM,UC7NGK,EAAe,6CACfC,EAAmB,aCchBC,EAAoBC,EAAoBC,GAStD,OARIA,IACEA,EAAOC,0BACTF,EAASE,wBAA0BD,EAAOC,yBACxCD,EAAOE,gCACTH,EAASG,8BAAgCF,EAAOE,+BAC9CF,EAAOG,4BACTJ,EAASI,0BAA4BH,EAAOG,4BAEzCJ,iBAGaK,EAAgBC,EAAYL,GAChD,MAAMM,EAAI,IAAIC,QAAgBF,EAAKG,IAAIC,eACvC,OAAIT,GAAUA,EAAOU,iBACZJ,EACJK,aAAaX,EAAOU,kBACpBE,aAAaL,EAAUM,YACvBC,SAAS,IACFR,EAAEQ,SAAS,aAGTC,EAAqBC,GACnC,IAAIhC,EAAcC,EAKlB,OAHK+B,EAAUhC,MAASgC,EAAU/B,UAC5BD,KAAAA,EAAMC,OAAAA,GAAWnB,KAEhB,CACLmD,cAAeD,EAAUC,cACzBC,QAAS,CAACF,EAAUhC,MAAQA,EAAMgC,EAAU/B,QAAUA,GACtDkC,UAAW,CACTH,EAAUI,OACVJ,EAAUK,iBACVL,EAAUM,aACVN,EAAUO,UAEZC,MAAO,CAACC,EAAKC,MAAMC,MAAMX,EAAUY,KAAMH,EAAKC,MAAMC,MAAMX,EAAUa,YACpEC,OAAQ,aAIIC,EAAkBC,GAChC,MAAO,CACLC,iBAAkBD,EAAUC,iBAC5BC,WAAYF,EAAUE,WACtBC,mBAAoBV,EAAKC,MAAMC,MAAMK,EAAUG,oBAC/CC,cAAeX,EAAKC,MAAMC,MAAMK,EAAUI,eAC1CC,iBAAkBL,EAAUK,2BAIhBC,EAAqBN,GAC9BA,EAAUO,kBAAiBP,EAAUO,gBAAkB3C,GAC5D,MAAM4C,EAAWR,EAAUQ,SAAW,EAAI,EAE1C,MAAO,CACLC,kBAAmBT,EAAUU,iBAC7BvB,UAAW,CACTa,EAAUW,iBACVX,EAAUY,MACVZ,EAAUa,mBACVb,EAAUO,iBAEZf,MAAO,CACLQ,EAAUc,kBACVd,EAAUe,kBACVtB,EAAKC,MAAMC,MAAMK,EAAUgB,WAC3BvB,EAAKC,MAAMC,MAAMK,EAAUiB,WAC3BT,mBAKgBU,EACpB7C,EACA8C,GAEA,MAAO,CACLhC,UAAW,CACTgC,EAAWC,WACXD,EAAWR,iBACXQ,EAAWE,gBACXF,EAAWG,iBACXH,EAAWN,mBACXM,EAAWI,qBAEbC,SAAU,CACR/B,EAAKC,MAAMC,MAAMwB,EAAWM,MAC5BN,EAAWL,kBACXrB,EAAKC,MAAMC,MAAMwB,EAAWO,eAC5BP,EAAWQ,mBACLC,EACJvD,EACA8C,EAAWR,iBACXQ,EAAWU,4BAGfC,SAAU,CACRrC,EAAKC,MAAMC,MAAMwB,EAAWY,0BAC5BtC,EAAKC,MAAMC,MAAMwB,EAAWa,sCAKZC,EACpB5D,EACA6D,EACAC,EACAC,GAEA,IACE,MAAMC,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQ+E,GACpD,IAAIK,EAAWH,SAAwBC,EAAcG,QAAQD,WAAWE,OACvD,MAAbF,IACFA,EAAW,IAGb,MAAMG,EAAkB,IAAInE,EAAU4D,GAAQQ,IAC5C,IAAIpE,EAAU,IAAIqE,gBAAgBL,IAIpC,OADAhE,EAAUP,OAAO,CAAE6E,eAAgB,KAC5BH,EAAgB5D,WACvB,MAAOgE,GACPjH,EAAeJ,uDAAuDqH,EAAEC,2BAItDnB,EACpBvD,EACA6D,EACAC,EACAC,GAEA,IACE,MAAMC,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQ+E,GACpD,IAAIK,EAAWH,SAAwBC,EAAcG,QAAQD,WAAWE,OAUxE,MATiB,MAAbF,IACFA,EAAW,IAEbhE,EAAUP,OAAO,CAAE6E,eAAgB,KAEX,IAAItE,EAAU4D,GAAQa,MAC5C,IAAIzE,EAAU,IAAIqE,gBAAgBL,IAGbzD,WACvB,MAAOgE,GACPjH,EAAeJ,sDAAsDqH,EAAEC,2BAWrDE,EACpBC,EACAC,KACGnI,GAEH,IAAIoI,EDnL0B,ICoL9B,IACEA,QAAqBD,EAAsBE,MAAM,KAAMrI,GAAMiI,YAC3D,CACEC,KAAMA,GAER,CAACI,EAAKC,IAAYD,EDzLQ,ICyLiBC,GAE7C,MAAOT,GACPjH,EAAeJ,oCAAqCqH,GAEtD,OAAOM,iBC3LaI,EAAUC,EAAaC,GAC3C,MAAMC,QAAeC,EAAMH,EAAKC,GAChC,IAAKC,EAAOE,GAGV,MAFAhI,EAAeJ,2BAA2BiI,EAAKI,WAAWL,KAC1D5H,EAAeJ,mCAAmCkI,EAAOI,UACnDJ,EAER,OAAOA,iBAGaK,EAAoBP,GACxC,MAAMQ,EAASC,SAASC,cAAc,KACtCF,EAAOG,SAAW,GAClBH,EAAOI,KAAOZ,EACdQ,EAAOK,uBAGaC,EACpBd,EACAe,GAEA,MAAMC,QAAiBb,EAAMH,GAC7B,IAAKgB,EAASZ,GACZ,UAAUjJ,MAAM,mBAElB,IAAI8J,EACJ,IACEA,EAAWD,EAASE,QACjBC,IAAI,uBACJC,MAAM,4BAA4B,GACrC,SACA,IACEH,EAAWjB,EAAIqB,MAAM,KAAKC,MAC1B,SACAL,SAAkBF,KAItB,MAAO,CAAEQ,WAAYP,EAASQ,cAAeP,SAAAA,kBAGzBQ,EAAQzB,GAC5B,OAAOG,EAAMH,EAAK,CAChBK,OAAQ,MACRa,QAAS,CACP,eAAgB,qCAuBAQ,EAAS1B,EAAa2B,GAI1C,OAtBFC,eACE5B,EACA2B,EACAT,GAEA,OACSf,EAAMH,EADA,MAAX2B,EACgB,CAChBtB,OAAQ,OACRwB,KAAMF,EACNT,QAUY,CACd,eAAgB,qBARE,CAChBb,OAAQ,SASLyB,CAAgB9B,EAAK2B,mNCvE9B,MAAMI,EAAmC,CACvCC,QAAS,KACTC,QAAS,UACTC,iBAAkB,wCAClBC,QAAS,wBACTC,YAAa,wBACbC,YAAa,KACbC,YAAa,KACbC,kBAAmB,KACnBC,iBAAkB,QAClB1E,oBAAqB,KACrB2E,yBAA0B,KAC1BC,iBAAkB,KAClBC,WAAY,EACZnI,wBAAyB,GACzBC,8BAA+B,EAC/BC,0BAA2B,IAC3BO,iBAAkB,GAGP2H,EAAiC,MAEvCb,QAIAA,GACHC,QAAS,KACTC,QAAS,cACTC,iBAAkB,wBAClBE,YAAa,gCAGVL,GACHC,QAAS,EACTC,QAAS,UACTE,QAAS,+BACTC,YAAa,gDACbC,YAAa,gDACbC,YAAa,+BACbrH,iBAAkB,WAGf8G,GACHC,QAAS,EACTC,QAAS,UACTE,QAAS,+BACTC,YAAa,gDACbC,YAAa,gDACbC,YAAa,+BACbrH,iBAAkB,WAGf8G,GACHC,QAAS,EACTC,QAAS,UACTE,QAAS,+BACTC,YAAa,gDACbC,YAAa,gDACbC,YAAa,uBACbK,WAAY,SACZnI,wBAAyB,IACzBC,8BAA+B,EAC/BC,0BAA2B,KAC3BO,iBAAkB,YAGf8G,GACHC,QAAS,IACTC,QAAS,UACTE,QAAS,uCACTC,YAAa,gDACbC,YAAa,gDACbC,YAAa,0BACbE,iBAAkB,gBAGfT,GACHC,QAAS,KACTC,QAAS,WACTE,QAAS,4CACTC,YAAa,iDACbC,YAAa,iDACbC,YAAa,gCACbrH,iBAAkB,WAGf8G,GACHC,QAAS,OACTC,QAAS,eACTE,QAAS,6CACTC,YAAa,qDACbC,YAAa,qDACbC,YAAa,2DAGVP,GACHC,QAAS,MACTC,QAAS,SACTE,QAAS,sCACTC,YAAa,+CACbC,YAAa,+CACbC,YAAa,iCACbrH,iBAAkB,WAGf8G,GACHC,QAAS,GACTC,QAAS,MACTE,QAAS,mCACTC,YAAa,4CACbC,YAAa,4CACbC,YAAa,uBACbrH,iBAAkB,YAGf8G,GACHC,QAAS,IACTC,QAAS,YACTE,QAAS,4BACTC,YAAa,kDACbC,YAAa,kDACbC,YAAa,iCACbrH,iBAAkB,YAGf8G,GACHC,QAAS,KACTC,QAAS,YACTE,QAAS,6CACTC,YAAa,kDACbC,YAAa,kDACbC,YAAa,iCACbrH,iBAAkB,cAIT4H,EAEJC,oBAAoBb,EAAiBc,GAE1C,IAAIC,EAGJ,GAAID,EACF,IACE,MAAME,WACJA,EADIC,UAEJA,EAFIC,QAGJA,EAHIC,aAIJA,EAJIC,cAKJA,EALIC,yBAMJA,EANIC,MAOJA,EAPIvB,QAQJA,EARIW,WASJA,GACEI,EAAgBd,GACpBe,KACEQ,qBAAsBH,EACtBI,mBAAoBN,EACpBO,yBAA0BJ,EAC1BxF,oBAAqBsF,EACrBX,yBAA0BQ,EAC1BP,iBAAkBQ,EAClBX,kBAAmBgB,EACnBvB,QAASA,EACTW,WAAYA,GACRgB,QAAQC,IAAIC,cAAgB,CAAE3B,iBAAkByB,QAAQC,IAAIC,eAElE,MAAOxE,SAMT,GAAIyE,EAA0B7B,GAAU,CACtC,MAAMgB,WACJA,EADIC,UAEJA,EAFIC,QAGJA,EAHIC,aAIJA,EAJIE,yBAKJA,EALID,cAMJA,EANIE,MAOJA,EAPIvB,QAQJA,EARIW,WASJA,GACEmB,EAA0B7B,GAC9Be,KACEQ,qBAAsBH,EACtBI,mBAAoBN,EACpBO,yBAA0BJ,EAC1BxF,oBAAqBsF,EACrBX,yBAA0BQ,EAC1BP,iBAAkBQ,EAClBX,kBAAmBgB,EACnBvB,QAASA,EACTW,WAAYA,GACRgB,QAAQC,IAAIC,cAAgB,CAAE3B,iBAAkByB,QAAQC,IAAIC,eAItE,OAAOb,EAGFe,UAAU9B,EAA0B+B,GACzC,MAAMC,EAA8B,iBAAZhC,EAAuB,UAAY,UAC3D,IAAI1H,EAASqI,EAAqBsB,KAAM9K,GAAMA,EAAE6K,KAAchC,GAE9D,OAAK1H,GAMLA,OAAcA,EADkBnD,KAAK0L,oBAAoBvI,EAAO0H,eAOpD1H,GAAQ4H,QAJJ6B,KACTzJ,EAAO4H,WAAW6B,IACrBzJ,EAAO4H,YATT/J,EAAeJ,4CAA4CiK,sBClNjDkC,EAAYC,EAAuBpC,GAGjD,OAFAoC,EAAgBpI,EAAKC,MAAMoI,kBAAkBD,aAC5BE,EAAOF,EAAgBpC,EAAQ3G,SAAS,KAC/BA,sBAGZkJ,EAAQhD,GACtB,IACE,OAAO+C,EAAO/C,GAAMlG,WACpB,MAAOgE,GACPjH,EAAeJ,MAAM,kBAAmBqH,EAAEC,yBCXxBkF,EAAS5J,EAAY0E,EAAiBmF,GAC1D,IAAIC,QAAsB9J,EAAKG,IAAI4J,KAAKrF,EAASmF,GACjDC,EAAgBA,EAAcE,OAAO,GACrC,MAAMC,EAAI,KAAOH,EAAcI,MAAM,EAAG,IAClCC,EAAI,KAAOL,EAAcI,MAAM,GAAI,KACzC,IAAIE,EAAI,KAAON,EAAcI,MAAM,IAAK,KAIxC,MAFU,SAANE,IAAcA,EAAI,QACZ,SAANA,IAAcA,EAAI,QACf,CAAEA,EAAAA,EAAGH,EAAAA,EAAGE,EAAAA,kBCYKE,EACpBrK,EACAsK,EACAC,EACAC,EACA1G,EACA2G,GAIA,OAAO7F,EAAY0F,GAFGG,GAAoB,IAAIzK,EAAKG,IAAI8D,SAASnF,EAAQyL,IAE9BpG,QAAQuG,QAASF,EAAS1G,kBAYhD4G,EACpB1K,EACAsK,EACAC,EACAC,EACA1G,EACA6G,GAAQ,EACR5G,GAEA,MAAMC,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQyL,GACpD,IAAKI,EAAO,CACV,MAAMC,QAAyBC,EAAU7K,EAAMuK,EAAcD,EAASE,GACtE,GAAI,IAAIM,EAAQF,GAAkBG,qBAAqB,IAAID,EAAQhH,IACjE,OAAO8G,EAGX,IAAItF,EAAS,KACb,MAAMjB,QAAwBd,EAAcvD,EAAMuK,EAAczG,EAAQC,GAClEmB,QAAeN,EACnB0F,EACAtG,EAAcG,QAAQuG,QACtBF,EACAnG,GAGF,IACEiB,QAAetB,EAAcG,QAAQuG,QAAQF,EAASnG,GAAiB2G,KAAK,CAC1EnG,KAAMyF,EACNW,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBC,EAAM,QAExC,MAAOyE,GACPjH,EAAeJ,4DACyCqH,EAAEC,WAG5D,OAAOY,iBAWa6F,EACpBnL,EACAsK,EACAC,EACAC,EACA1G,EACA6G,GAAQ,GAER,MAAM3G,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQyL,GACpD,IAAKI,EAAO,CACV,MAAMC,QAAyBQ,EAAapL,EAAMuK,EAAcD,EAASE,GACzE,GAAI,IAAItK,EAAU0K,GAAkBS,GAAG,IAAInL,EAAU4D,IACnD,OAAO8G,EAGX,IAAItF,EAAS,KACb,MAAMJ,QAAeN,EACnB0F,EACAtG,EAAcG,QAAQuG,QACtBF,EACA1G,GAGF,IACEwB,QAAetB,EAAcG,QAAQuG,QAAQF,EAAS1G,GAAQkH,KAAK,CACjEnG,KAAMyF,EACNW,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBC,EAAM,QAExC,MAAOyE,GACPjH,EAAeJ,4DACyCqH,EAAEC,WAG5D,OAAOY,iBAYagG,EACpBtL,EACAsK,EACAC,EACAgB,EACAzH,EACA2G,GAIA,OAAO7F,EAAY0F,GAFGG,GAAoB,IAAIzK,EAAKG,IAAI8D,SAASnF,EAAQyL,IAE9BpG,QAAQqH,SAAUD,EAAWzH,kBAWnD0H,EACpBxL,EACAsK,EACAC,EACAgB,EACAzH,GAEA,MAAME,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQyL,GAEpD,IAAIjF,EAAS,KACb,MAAMjB,QAAwBd,EAAcvD,EAAMuK,EAAczG,GAC1DoB,QAAeN,EACnB0F,EACAtG,EAAcG,QAAQqH,SACtBD,EACAlH,GAGF,IACEiB,QAAetB,EAAcG,QAAQqH,SAASD,EAAWlH,GAAiB2G,KAAK,CAC7EnG,KAAMyF,EACNW,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBC,EAAM,QAExC,MAAOyE,GACPjH,EAAeJ,4CAA4CqH,EAAEC,WAE/D,OAAOY,iBAWauF,EACpB7K,EACAuK,EACAD,EACAE,EACAzG,GAEA,MAAMC,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQyL,GAC9CkB,QAAmBzH,EAAcG,QAAQ0G,UAAUP,EAASE,GAASpG,OAE3E,aAAaR,EAAc5D,EAAMuK,EAAckB,EAAY1H,kBAUvCqH,EACpBpL,EACAuK,EACAD,EACAE,EACAzG,GAEA,MAAMC,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQyL,GACpD,aAAavG,EAAcG,QAAQ0G,UAAUP,EAASE,GAASpG,sBAW3CsH,EACpB1L,EACAuK,EACAD,EACAvG,GAEA,MAAMC,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQyL,GAC9CkB,QAAmBzH,EAAcG,QAAQwH,UAAUrB,GAASlG,OAElE,aAAaR,EAAc5D,EAAMuK,EAAckB,EAAY1H,kBASvCG,EAASlE,EAAYuK,GACzC,MAAMvG,EAAgB,IAAIhE,EAAKG,IAAI8D,SAASnF,EAAQyL,GACpD,aAAavG,EAAcG,QAAQD,WAAWE,sBC9P1BwH,EAAMC,GAC1B,WAAWC,QAASC,IAClBC,WAAWD,EAASF,cCFRI,GAAgBP,GAC9B,WAAWZ,EAAQY,GAASpH,IAAI,YAGlB4H,GAAeR,GAC7B,WAAWZ,EAAQY,GAASpH,IAAI,kBAEZ6H,GACpBC,EACAC,EACA9B,GAGA,OAAO0B,SADeG,EAAaE,WAAWD,EAAa9B,mBAIvCgC,GACpBH,EACAC,EACA9B,GAGA,OAAO2B,SADeE,EAAaE,WAAWD,EAAa9B,mBAIvCiC,GACpBJ,EACAC,EACA9B,GAIA,OAAO2B,SAFeE,EAAaE,WAAWD,EAAa9B,mBAKvCkC,GACpBL,EACAC,EACA9B,GAIA,OAAO2B,SAFeE,EAAaE,WAAWD,EAAa9B,UCxChDmC,GAMXrQ,YAAYsQ,QALLA,mBAMLnQ,KAAKmQ,YAAcA,EAQD3F,cAAC4F,EAAaC,GAChC,MAAMC,EAAOtQ,KAAKmQ,YAAc,4BAA8BC,EAC9D,IACE,MAAMxG,QAAiBb,EAAMuH,EAAM,CACjCrH,OAAQ,MACRa,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAGV,GAAIzG,EAASZ,GAEX,aADkBY,EAAS2G,OAG3B,UAAUxQ,MAAM,mCAAqC6J,EAAS4G,QAEhE,MAAOvI,GAEP,MADAjH,EAAeJ,MAAMqH,OACXlI,MAAM,wBAYIyK,kBACtB4F,EACAK,EACAJ,GAEA,IAAIK,EAAQ,EACZ,EAAG,CACD,IACE,MAAMJ,EAAOtQ,KAAKmQ,YAAc,4BAA8BC,EACxDxG,QAAiBb,EAAMuH,EAAM,CACjCrH,OAAQ,MACRa,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAEV,GAAIzG,EAASZ,GAAI,CACf,MAAM2H,QAAY/G,EAAS2G,OAC3B,IAAIE,SAGUE,EADZ,GAAIA,EAAIC,OAASD,EAAIC,MAAMH,OAASA,EAAM,OAAOE,GAGrD,MAAO1I,UAGHmH,EAAM,MACZsB,UACOA,EAAQ,KACjB,YASmBlG,eAACmG,EAAUN,GAC9B,MAAMG,EAA2B,CAC/BK,OAAO,GAET,IAAIC,EACJ,IACE,MAAMR,EAAOtQ,KAAKmQ,YAAc,oCAE1BvG,QAAiBb,EAAMuH,EAAM,CACjCrH,OAAQ,OACRwB,KAAMsG,KAAKC,UAAUL,GACrB7G,QAAS,CACP,eAAgB,4BAElBuG,OAAQA,IAGVS,QAAqBlH,EAAS2G,OACN,MAApB3G,EAAS4G,QACXA,EAAOK,OAAQ,EACfL,EAAOS,KAAOH,EAAaG,KAC3BT,EAAOU,MAAQ,CACbC,iBAAkBL,EAAaM,UAC/B3D,EAAGqD,EAAarD,EAAE,GAClBE,EAAGmD,EAAanD,EAAE,GAClBC,EAAGkD,EAAalD,KAGlB4C,EAAOa,OAASP,EAChB9P,EAAeJ,MAAM,4BAA6BgJ,EAAS4G,OAAQA,EAAOa,SAE5E,MAAOzQ,GACPI,EAAeJ,MAAM,8BAA+BA,GAEtD,OAAO4P,GC1FX,MAAMc,GACJ,uFAKWC,GAKX1R,YACE2D,EACAqH,EACA2G,EAA+B,KAC/BrO,QARKqO,oBACAhO,iBACCL,cAQOnD,KAAKwR,QAAdA,GACgBC,EAAaC,IACjC1R,KAAKwD,KAAOA,EACZxD,KAAKmD,OAASA,IAAU,IAAIsI,GAAekB,UAAU9B,GAAW,WAG/CL,oBACjBnD,EACAC,EACAC,GAEA,OAAOR,EAAc/G,KAAKwD,KAAM6D,EAAOC,EAAQC,GAG9BiD,oBACjBnD,EACAC,EACAC,GAEA,OAAOH,EAAcpH,KAAKwD,KAAM6D,EAAOC,EAAQC,GAS9BiD,oBAACsD,EAAiB+B,GACnC,IAAI/G,EAAS,KACb,IACE,MAAMzB,EAAQpE,EACZ,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAED+L,QAAgB7H,EAAMM,QAAQwH,UAAUrB,GAASlG,OACvDkB,EAAS9I,KAAKwD,KAAKqB,MAAM8M,QAAQzC,GACjC,MAAOjH,GACPjH,EAAeJ,+CAA+CqH,EAAEC,WAElE,OAAOY,EAaiB0B,oBACxBsD,EACA+B,EACA+B,EACA3D,GASA,OAAO7F,EAAY0F,GANjBG,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASoK,EAAgBH,IAAkB7B,GAC7D7P,KAAKmD,SAGgCwE,QAAQmK,WAAYF,GAS/CpH,iBACdsD,EACA+B,EACA+B,GAEA,MAAMG,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,EAAa,CACpDxH,KAAMyF,IAER9N,KAAKmD,QAEP,IAAI2F,EAAS,KACb,MAAMJ,QAAeN,EAAY0F,EAASiE,EAAKpK,QAAQmK,WAAYF,GAEnE,IACE9I,QAAeiJ,EAAKpK,QAAQmK,WAAW9R,KAAKwD,KAAKqB,MAAMC,MAAM8M,IAAMpD,KAAK,CACtEnG,KAAMyF,EACNW,IAAK/F,EACLgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAElD,MAAO8E,GACPjH,EAAeJ,6CAA6CqH,EAAEC,WAEhE,OAAOY,EAQS0B,mBAACqF,GACjB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQqK,eAAepK,OAC3C,MAAOK,GACPjH,EAAeJ,gDAAgDqH,EAAEC,WAEnE,OAAOY,EAQqB0B,+BAACqF,GAC7B,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAImE,EAAS,KACb,IACE,MAAMwB,QAAeiJ,EAAKpK,QAAQsK,cAAcrK,OAChDN,EAAStH,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,GACjC,MAAOb,GACPjH,EAAeJ,2DACwCqH,EAAEC,WAG3D,OAAOZ,EASakD,uBAACqF,GACrB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQuK,mBAAmBtK,OAC/C,MAAOK,GACPjH,EAAeJ,0DACuCqH,EAAEC,WAG1D,OAAOY,EASW0B,qBAACqF,GACnB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQwK,iBAAiBvK,OAC7C,MAAOK,GACPjH,EAAeJ,mEACgDqH,EAAEC,WAGnE,OAAOY,EAQU0B,oBAACqF,GAClB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQyK,gBAAgBxK,OAC5C,MAAOK,GACPjH,EAAeJ,uDAAuDqH,EAAEC,WAE1E,OAAOY,EAQS0B,mBAACqF,GACjB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQ0K,sBAAsBzK,OAClD,MAAOK,GACPjH,EAAeJ,iDAAiDqH,EAAEC,WAEpE,OAAOY,EAQS0B,mBAACqF,GACjB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQ2K,sBAAsB1K,OAClD,MAAOK,GACPjH,EAAeJ,iDAAiDqH,EAAEC,WAEpE,OAAOY,EAQS0B,mBAACqF,GACjB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQ4K,eAAe3K,OAC3C,MAAOK,GACPjH,EAAeJ,4CAA4CqH,EAAEC,WAE/D,YAAY1E,KAAKqB,MAAM8M,QAAQ7I,GAAQ7E,WAQduG,4BAACqF,GAC1B,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQ6K,0BAA0B5K,OACtD,MAAOK,GACPjH,EAAeJ,0DACuCqH,EAAEC,WAG1D,OAAOY,EAUI0B,cAACqF,EAAqBxI,GACjC,MAAM0K,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQ8K,QAAQpL,GAAOO,OAC3C,MAAOK,GACPjH,EAAeJ,yEACMqH,EAAEC,WAEzB,OAAOY,EAUO0B,iBACdqF,EACAxI,EACAE,GAEA,IAAID,EAAS,KACb,IACE,MAAMyK,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAED2F,QAAeiJ,EAAKpK,QAAQ+K,WAAWrL,GAAOO,OACpDN,aAAoBF,cAAcC,EAAOyB,EAAQvB,GACjD,MAAOU,GACPjH,EAAeJ,qEACIqH,EAAEC,WAEvB,OAAOZ,EAAOrD,WASCuG,kBAACqF,GAChB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QAAQgL,cAAc/K,OAC1C,MAAOK,GACPjH,EAAeJ,2DACwCqH,EAAEC,WAG3D,OAAOY,EAQO0B,iBAACqF,GACf,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAIyO,EAAM,KACV,IACE,MAAM9I,QAAeiJ,EAAKpK,QAAQiL,aAAahL,OAC/CgK,EAAM5R,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,GAC9B,MAAOb,GACPjH,EAAeJ,wCAAwCqH,EAAEC,WAE3D,OAAO0J,EAWgBpH,0BAACqF,EAAqBxI,GAC7C,MAAM0K,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI0P,EAAS,KACb,IACE,MAAM/J,QAAeiJ,EAAKpK,QAAQmL,oBAAoBzL,GAAOO,OAC7DiL,EAAS7S,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,GACjC,MAAOb,GACPjH,EAAeJ,4DACyCqH,EAAEC,WAG5D,OAAO2K,EASkBrI,4BAACqF,EAAqBxI,GAC/C,MAAM0K,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI0P,EAAS,KACb,IACE,MAAM/J,QAAeiJ,EAAKpK,QAAQoL,sBAAsB1L,GAAOO,OAC/DiL,EAAS7S,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,GACjC,MAAOb,GACPjH,EAAeJ,qEACkDqH,EAAEC,WAGrE,OAAO2K,EASuBrI,iCAACqF,GAC/B,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI0P,EAAS,KACb,IACE,MAAM/J,QAAeiJ,EAAKpK,QAAQqL,6BAA6BpL,OAC/DiL,EAAS7S,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,GACjC,MAAOb,GACPjH,EAAeJ,gEAC6CqH,EAAEC,WAGhE,OAAO2K,EAWUrI,oBACjBqF,EACAxI,EACAE,GAEA,MAAMwK,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI0P,EAAS,KACb,IACE,MAAM/J,QAAeiJ,EAAKpK,QAAQsL,kBAAkB5L,GAAOO,OAC3DiL,aAAoBzL,cAAcC,EAAOyB,EAAQvB,GACjD,MAAOU,GACPjH,EAAeJ,uDAAuDqH,EAAEC,WAE1E,OAAO2K,EAOiBrI,2BAACqF,GACzB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAEE,aADgC4O,EAAKpK,QAAQuL,oBAAoBtL,OAEjE,MAAOK,GACPjH,EAAeJ,0DACuCqH,EAAEC,YASrCsC,wBAACqF,GACtB,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAEE,aADgC4O,EAAKpK,QAAQuL,oBAAoBtL,OAEjE,MAAOK,GACPjH,EAAeJ,0DACuCqH,EAAEC,YAYtCsC,uBACpBqF,EACAxI,EACAE,GAEA,MAAMwK,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI0P,EAAS,KACb,IACE,MAAM/J,QAAeiJ,EAAKpK,QAAQwL,cAAc9L,GAAOO,OACvDiL,aAAoBzL,cAAcC,EAAOyB,EAAQvB,GACjD,MAAOU,GACPjH,EAAeJ,0DACuCqH,EAAEC,WAG1D,OAAO2K,EAUiBrI,oBACxB6C,EACAwC,EACA5B,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAsB3B,GACtD7P,KAAKmD,SAGgCwE,QAAQyL,YASnC5I,iBAAC6C,EAAiBwC,GAChC,MAAMkC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,MAAMJ,QAAeN,EAAYiF,EAAS0E,EAAKpK,QAAQyL,YAEvD,IACEtK,QAAeiJ,EAAKpK,QAAQyL,aAAa5E,KAAK,CAC5CnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAElD,MAAO8E,GACPjH,EAAeJ,iDAAiDqH,EAAEC,WAEpE,OAAOY,EAWuB0B,0BAC9B6C,EACAwC,EACA5B,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAsB3B,GACtD7P,KAAKmD,SAGgCwE,QAAQ0L,kBAU7B7I,uBACpB6C,EACAwC,GAEA,cAAgByD,sBAAsBzD,KAAkBxC,EACtD,UAAUtN,0CAEZ,MAAMgS,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,MAAMJ,QAAeN,EAAYiF,EAAS0E,EAAKpK,QAAQ0L,kBAEvD,IACEvK,QAAeiJ,EAAKpK,QAAQ0L,mBAAmB7E,KAAK,CAClDnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAElD,MAAO8E,GACPjH,EAAeJ,iDAAiDqH,EAAEC,WAEpE,OAAOY,EAY6B0B,gCACpC6C,EACAwC,EACA0D,EACAC,EACAvF,GASA,OAAO7F,EACLiF,GAPAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAsB3B,GACtD7P,KAAKmD,SAKMwE,QAAQ8L,uBACrBF,EACAvT,KAAKwD,KAAKqB,MAAMC,MAAM0O,IAYEhJ,6BAC1B6C,EACAwC,EACA0D,EACAC,GAEA,cAAgBF,sBAAsBzD,KAAkBxC,EACtD,UAAUtN,0CAEZ,MAAMgS,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KAEb,MAAMJ,QAAeN,EACnBiF,EACA0E,EAAKpK,QAAQ8L,uBACbF,EACAvT,KAAKwD,KAAKqB,MAAMC,MAAM0O,IAExB,IACE1K,QAAeiJ,EAAKpK,QACjB8L,uBACCF,EACAvT,KAAKwD,KAAKqB,MAAMC,MAAM0O,IAEvBhF,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAEpD,MAAO8E,GACPjH,EAAeJ,mDAAmDqH,EAAEC,WAEtE,OAAOY,EAYwB0B,2BAC/B6C,EACAwC,EACA6D,EACAC,EACA1F,GAEA,MAAM2F,EACJ3F,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAsB3B,GACtD7P,KAAKmD,QAGH0Q,aAA2B9M,cAC/B2M,EAAiBI,QACjBH,EAAmBE,cACnBH,EAAiBK,iBAGbC,aAA0BjN,cAC9B2M,EAAiBO,SACjBN,EAAmBK,aACnBN,EAAiBQ,kBAGbC,EAAWR,EAAmBQ,SAChCnU,KAAK+G,yBACQqN,aAAavE,GACxB8D,EAAmBQ,UAErB7C,GAEJ,OAAOlJ,EACLiF,EACAuG,EAAajM,QAAQ0M,kBACrB,CACEX,EAAiBI,QACjBJ,EAAiBO,SACjBP,EAAiBlO,kBAEnB,CACEqO,EACAG,EACAG,EACAnU,KAAKwD,KAAKqB,MAAMC,MAAM6O,EAAmBpO,iBAkBxBiF,wBACrB6C,EACAwC,EACA6D,EACAC,GAEA,MAAM5B,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAGDmR,QAAgBvE,GAAkB/P,KAAM6P,EAAa6D,EAAiBI,SAC5E,GAAI,IAAIxF,EAAQqF,EAAmBE,eAAeU,YAAYD,GAC5D,UAAUvU,uCAAuCuU,EAAQrQ,cAG3D,MAAM4P,aAA2B9M,cAC/B2M,EAAiBI,QACjBH,EAAmBE,cACnBH,EAAiBK,iBAGbC,aAA0BjN,cAC9B2M,EAAiBO,SACjBN,EAAmBK,aACnBN,EAAiBQ,kBAGbC,EAAWR,EAAmBQ,oBACrBpN,yBACEqN,aAAavE,GACxB8D,EAAmBQ,UAErB7C,GAEE5I,QAAeN,EACnBiF,EACA0E,EAAKpK,QAAQ0M,kBACb,CACEX,EAAiBI,QACjBJ,EAAiBO,SACjBP,EAAiBlO,kBAEnB,CACEqO,EACAG,EACAG,EACAnU,KAAKwD,KAAKqB,MAAMC,MAAM6O,EAAmBpO,iBAI7C,IAAIuD,EAAS,KACb,IACEA,QAAeiJ,EAAKpK,QACjB0M,kBACC,CACEX,EAAiBI,QACjBJ,EAAiBO,SACjBP,EAAiBlO,kBAEnB,CACEqO,EACAG,EACAG,EACAnU,KAAKwD,KAAKqB,MAAMC,MAAM6O,EAAmBpO,iBAG5CiJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAEpD,MAAO8E,GACPjH,EAAeJ,iDAAiDqH,EAAEC,WAGpE,OAAOY,EAYyB0B,4BAChC6C,EACAwC,EACA6D,EACAC,EACA1F,GAEA,MAAM2F,EACJ3F,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAsB3B,GACtD7P,KAAKmD,QAGHqR,aAAyBzN,cAC7B2M,EAAiBI,QACjBH,EAAmBa,YACnBd,EAAiBK,iBAGbU,aAA4B1N,cAChC2M,EAAiBO,SACjBN,EAAmBc,eACnBf,EAAiBQ,kBAGbC,EAAWR,EAAmBQ,oBACrBpN,yBACEqN,aAAavE,GACxB8D,EAAmBQ,UAErB7C,GAEJ,OAAOlJ,EACLiF,EACAuG,EAAajM,QAAQ+M,mBACrB,CACEhB,EAAiBI,QACjBJ,EAAiBO,SACjBP,EAAiBlO,kBAEnB,CACEgP,EACAC,EACAN,EACAnU,KAAKwD,KAAKqB,MAAMC,MAAM6O,EAAmBpO,iBAavBiF,yBACtBsD,EACA+B,EACA6D,EACAC,GAEA,MAAM5B,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KAEb,MAAMwL,QAAgB3E,GAAmB3P,KAAM6P,EAAa6D,EAAiBO,UAC7E,GAAI,IAAI3F,EAAQqF,EAAmBc,gBAAgBF,YAAYD,GAC7D,UAAUvU,wCAAwCuU,EAAQrQ,cAG5D,MAAMuQ,aAAyBzN,cAC7B2M,EAAiBI,QACjBH,EAAmBa,YACnBd,EAAiBK,iBAGbU,aAA4B1N,cAChC2M,EAAiBO,SACjBN,EAAmBc,eACnBf,EAAiBQ,kBAGbC,EAAWR,EAAmBQ,SAChCnU,KAAK+G,yBACQqN,aAAavE,GACxB8D,EAAmBQ,UAErB7C,GAEE5I,QAAeN,EACnB0F,EACAiE,EAAKpK,QAAQ+M,mBACb,CACEhB,EAAiBI,QACjBJ,EAAiBO,SACjBP,EAAiBlO,kBAEnB,CACEgP,EACAC,EACAN,EACAnU,KAAKwD,KAAKqB,MAAMC,MAAM6O,EAAmBpO,iBAI7C,IACEuD,QAAeiJ,EAAKpK,QACjB+M,mBACC,CACEhB,EAAiBI,QACjBJ,EAAiBO,SACjBP,EAAiBlO,kBAEnB,CACEgP,EACAC,EACAN,EACAnU,KAAKwD,KAAKqB,MAAMC,MAAM6O,EAAmBpO,iBAG5CiJ,KAAK,CACJnG,KAAMyF,EACNW,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAEpD,MAAO8E,GACPjH,EAAeJ,iDAAiDqH,EAAEC,WAEpE,OAAOY,EAa6B0B,gCACpC6C,EACAwC,EACAgE,EACAc,EACA1G,GASA,OAAO7F,EACLiF,GAPAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAsB3B,GACtD7P,KAAKmD,SAKMwE,QAAQiN,uBACrBf,EACAc,GAewBnK,6BAC1BsD,EACA+B,EACAgE,EACAc,EACAZ,GAEA,MAAMhC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,MAAMgL,aAAqBM,aAAavE,GAClCyE,QAAgBtE,GAAmBhQ,KAAM6P,EAAaiE,GAC5D,GAAI,IAAIxF,EAAQuF,GAAeU,YAAYD,GACzC,UAAUvU,wCAAwCuU,EAAQrQ,cAG5D,MAAM4Q,aAA+B9N,cACnC+M,EACAD,EACAE,GAEIrL,QAAeN,EACnB0F,EACAiE,EAAKpK,QAAQiN,uBACbC,EACA7U,KAAKwD,KAAKqB,MAAMC,MAAM6P,IAGxB,IACE7L,QAAeiJ,EAAKpK,QACjBiN,uBACCC,EACA7U,KAAKwD,KAAKqB,MAAMC,MAAM6P,IAEvBnG,KAAK,CACJnG,KAAMyF,EACNW,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAEpD,MAAO8E,GACPjH,EAAeJ,sEACEqH,EAAEC,WAErB,OAAOY,EAY2B0B,8BAClC6C,EACAwC,EACAiF,EACAC,EACA9G,GASA,OAAO7F,EACLiF,GAPAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAsB3B,GACtD7P,KAAKmD,SAKMwE,QAAQqN,qBACrBF,EACAC,GAesBvK,2BACxBsD,EACA+B,EACAiF,EACAC,EACAE,GAEA,MAAMlD,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAI2F,EAAS,KACb,MAAMmL,aAAsBG,aAAavE,GAEnC4E,aAA4BS,yBAChCrF,EACAoE,EACAa,GAGIR,QAAgBrE,GAAsBjQ,KAAM6P,EAAaoE,GAC/D,GAAI,IAAI3F,EAAQmG,GAAgBF,YAAYD,GAC1C,UAAUvU,wCAAwCuU,EAAQrQ,cAG5D,MAAMkR,aAAkCpO,yBAC3BqN,aAAavE,GACxBkF,EACAE,GAEIvM,QAAeN,EACnB0F,EACAiE,EAAKpK,QAAQqN,qBACbhV,KAAKwD,KAAKqB,MAAMC,MAAMgQ,GACtBK,GAGF,IACErM,QAAeiJ,EAAKpK,QACjBqN,qBAAqBhV,KAAKwD,KAAKqB,MAAMC,MAAMgQ,GAAeK,GAC1D3G,KAAK,CACJnG,KAAMyF,EACNW,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAEpD,MAAO8E,GACPjH,EAAeJ,yDAAyDqH,EAAEC,WAE5E,OAAOY,EAWS0B,mBAChBqF,EACAiE,EACAG,EACA1O,GAEA,MAAMwM,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAIiS,EAAkB,GAClBC,EAAmB,GAEvB,MAAMC,EAAkBrS,EACtB,SAASO,KAAKG,IAAI8D,SAASoK,EAAgBH,IAAkBoC,GAC7D9T,KAAKmD,QAEDoS,EAAmBtS,EACvB,SAASO,KAAKG,IAAI8D,SAASoK,EAAgBH,IAAkBuC,GAC7DjU,KAAKmD,QAEP,IACEiS,QAAwBE,EAAgB3N,QAAQD,WAAWE,OAC3D,MAAOK,GACPjH,EAAeJ,oDAAoDqH,EAAEC,WAEvE,IACEmN,QAAyBE,EAAiB5N,QAAQD,WAAWE,OAC7D,MAAOK,GACPjH,EAAeJ,oDAAoDqH,EAAEC,WAGvE,IAYIsN,EAZAC,EAAQ,KACZ,IACEA,QAAc1D,EAAKpK,QAChB+N,aAAa5B,EAASG,EAAUjU,KAAKwD,KAAKqB,MAAMC,MAAMS,IACtDqC,OACH6N,EAAQ,IAAI/R,EAAU+R,EAAMxR,YAC5B,MAAOgE,GACPjH,EAAeJ,MACb,mEAeJ,OAVIwU,EAAkBC,GACpBG,EAAeJ,EAAkBC,EACjCI,EAAQ,IAAI/R,EAAU+R,EAAQ,IAAMD,GACpCC,GAAgB,IAAMJ,IAEtBG,EAAeH,EAAmBD,EAClCK,EAAQ,IAAI/R,EAAU+R,EAAQ,KAAO,EAAID,IACzCC,GAAgB,IAAMJ,GAGjBI,EAAMxR,WAciBuG,0BAC9BqF,EACAiE,EACAG,EACAQ,EACAlP,EACAwO,EACAG,GAEA,MAAMnC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAGDmR,QAAgB3E,GAAmB3P,KAAM6P,EAAaoE,GAE5D,GAAI,IAAI3F,EAAQmG,GAAgBF,YAAYD,GAC1C,UAAUvU,wCAAwCuU,EAAQrQ,cAG5D,MAAM0R,aAAgC5O,cACpCkN,EACAQ,EACAP,GAGF,IAAI5M,EAAS,KAEb,IACE,MAAMwB,QAAeiJ,EAAKpK,QACvBiO,oBACC9B,EACAG,EACA0B,EACA3V,KAAKwD,KAAKqB,MAAMC,MAAMS,IAEvBqC,OACHN,EAAS,CACPuO,uBAAwBzO,cACtB6M,EACAnL,EAAO+K,cACPK,GAEF4B,0CAA2C1O,cACzC0M,EACAhL,EAAOiN,YACPhC,GAEFiC,0BAA2B5O,cACzB0M,EACAhL,EAAOkN,eACPjC,GAEFkC,sCAAuC7O,cACrC0M,EACAhL,EAAOmN,2BACPlC,GAEFmC,sCAAuC9O,cACrC0M,EACAhL,EAAOoN,2BACPnC,IAGJ,MAAO9L,GACPjH,EAAeJ,yCAAyCqH,EAAEC,WAE5D,OAAOZ,EAauBkD,0BAC9BqF,EACAiE,EACAG,EACAJ,EACAtO,EACAwO,EACAG,GAEA,MAAMnC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAGDmR,QAAgBvE,GAAkB/P,KAAM6P,EAAaiE,GAC3D,GAAI,IAAIxF,EAAQuF,GAAeU,YAAYD,GACzC,UAAUvU,uCAAuCuU,EAAQrQ,cAG3D,MAAM4Q,aAA+B9N,cACnC+M,EACAD,EACAE,GAGF,IAAIzM,EAAS,KAEb,IACE,MAAMwB,QAAeiJ,EAAKpK,QACvBwO,oBACCrC,EACAG,EACAY,EACA7U,KAAKwD,KAAKqB,MAAMC,MAAMS,IAEvBqC,OAEHN,EAAS,CACPuO,uBAAwBzO,cACtB6M,EACAnL,EAAO2L,eACPP,GAEF4B,0CAA2C1O,cACzC0M,EACAhL,EAAOiN,YACPhC,GAEFiC,0BAA2B5O,cACzB0M,EACAhL,EAAOkN,eACPjC,GAEFkC,sCAAuC7O,cACrC0M,EACAhL,EAAOmN,2BACPlC,GAEFmC,sCAAuC9O,cACrC0M,EACAhL,EAAOoN,2BACPnC,IAGJ,MAAO9L,GACPjH,EAAeJ,yCAAyCqH,EAAEC,WAE5D,OAAOZ,EAU4BkD,+BACnCqF,EACAiE,EACAD,EACAoB,EACAlB,GAEA,MAAMhC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAImE,EAAS,KAEb,IACE,MAAMwB,QAAeiJ,EAAKpK,QACvByO,oBACCtC,aACW/M,cAAc+M,EAASD,EAAeE,IAElDnM,OAEHN,aAAoBF,cAAcyI,EAAa/G,EAAQmM,GACvD,MAAOhN,GACPjH,EAAeJ,2DACwCqH,EAAEC,WAG3D,OAAOZ,EAU4BkD,+BACnCqF,EACAiE,EACAuC,EACApB,EACAlB,GAEA,MAAMhC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAImE,EAAS,KACb,MAAMO,aAA6Bd,cACjC8I,EACAwG,EACApB,GAEF,IACE,MAAMnM,QAAeiJ,EAAKpK,QACvB2O,oBAAoBxC,EAASjM,GAC7BD,OAEHN,aAAoBF,cAAc0M,EAAShL,EAAQiL,GACnD,MAAO9L,GACPjH,EAAeJ,2DACwCqH,EAAEC,WAG3D,OAAOZ,EAU4BkD,+BACnCqF,EACAoE,EACAa,EACAG,EACAf,GAEA,MAAMnC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAImE,EAAS,KAEb,IACE,MAAMwB,QAAeiJ,EAAKpK,QACvB4O,oBACCtC,aACWlN,cAAc8I,EAAaiF,EAAcG,IAErDrN,OACHN,aAAoBF,cAAc6M,EAAUnL,EAAQoL,GACpD,MAAOjM,GACPjH,EAAeJ,2DAA2DqH,KAE5E,OAAOX,EAU4BkD,+BACnCqF,EACAoE,EACAQ,EACAQ,EACAf,GAEA,MAAMnC,EAAO9O,EACX,SAASO,KAAKG,IAAI8D,SAASzH,KAAKwR,QAAS3B,GACzC7P,KAAKmD,QAEP,IAAImE,EAAS,KAEb,IACE,MAAMwB,QAAeiJ,EAAKpK,QACvB6O,oBACCvC,aACWlN,cAAckN,EAAUQ,EAAgBP,IAEpDtM,OAEHN,aAAoBF,cAAcyI,EAAa/G,EAAQmM,GACvD,MAAOhN,GACPjH,EAAeJ,2DACwCqH,EAAEC,WAG3D,OAAOZ,EAOFmP,wBACL,MACMC,EADM1W,KAAKwR,QACK1E,KACpB,EAAG3K,KAAAA,EAAMO,KAAAA,KAAoB,UAATA,GAA6B,aAATP,GAG1C,OADcnC,KAAKwD,KAAKG,IAAI+N,IAAIiF,qBAAqBD,GAQhDE,wBACL,MACMF,EADM1W,KAAKwR,QACK1E,KACpB,EAAG3K,KAAAA,EAAMO,KAAAA,KAAoB,UAATA,GAA6B,aAATP,GAG1C,OADcnC,KAAKwD,KAAKG,IAAI+N,IAAIiF,qBAAqBD,GAQhDG,wBACL,MACMH,EADM1W,KAAKwR,QACK1E,KACpB,EAAG3K,KAAAA,EAAMO,KAAAA,KAAoB,UAATA,GAA6B,aAATP,GAG1C,OADcnC,KAAKwD,KAAKG,IAAI+N,IAAIiF,qBAAqBD,UC7lD5C5K,GAaXjM,YACE2D,EACAqH,EACAS,EAA2B,KAC3BwL,EAAoC,KACpC3T,QAjBKK,KAAa,UACb8H,6BACAnI,mBACA2T,yBACAC,yBAeL/W,KAAKwD,KAAOA,EACZxD,KAAKsL,iBAAmBA,EACxBtL,KAAK8W,aAAeA,GAAiBE,EAAoBtF,IACzD1R,KAAKmD,OAASA,IAAU,IAAIsI,GAAekB,UAAU9B,GAAW,WAC5DrH,IACFxD,KAAK+W,kBAAoB9T,EACvB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK8W,aAAc9W,KAAKsL,kBACnDtL,KAAKmD,SASQqH,aAACyM,GAClB,IACE,MAAMnO,aAAoCiO,kBAAkBpP,QACzD6I,OAAOyG,GACPrP,OAIH,OAHAkB,EAAOoO,UAAYlX,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,EAAOoO,WAClDpO,EAAOqO,WAAanX,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,EAAOqO,YACnDrO,EAAOoG,QAAUlP,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,EAAOoG,SACzCpG,EACP,MAAOb,GACPmP,EAAO1W,8CAA8CuW,KAEvD,YAYuBzM,mBACvB6M,EACAhK,EACA6J,EACAC,EACAG,GAEA,OAAOlP,EACLiF,EACArN,KAAK+W,kBAAkBpP,QAAQ4P,OAC/BF,EACArX,KAAKwD,KAAKqB,MAAMC,MAAMoS,GACtBlX,KAAKwD,KAAKqB,MAAMC,MAAMqS,GACtB9J,EACAiK,GAae9M,aACjB6M,EACAhK,EACA6J,EACAC,EACAG,GAEA,MAAM5O,QAAeN,EACnBiF,EACArN,KAAK+W,kBAAkBpP,QAAQ4P,OAC/BF,EACArX,KAAKwD,KAAKqB,MAAMC,MAAMoS,GACtBlX,KAAKwD,KAAKqB,MAAMC,MAAMqS,GACtB9J,EACAiK,GAiBF,kBAb8BP,kBAAkBpP,QAC7C4P,OACCF,EACArX,KAAKwD,KAAKqB,MAAMC,MAAMoS,GACtBlX,KAAKwD,KAAKqB,MAAMC,MAAMqS,GACtB9J,EACAiK,GAED9I,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAa3BqH,qBACzB6M,EACAH,EACAC,EACA9J,GAEA,OAAOjF,EACLiF,EACArN,KAAK+W,kBAAkBpP,QAAQ6P,SAC/BH,EACArX,KAAKwD,KAAKqB,MAAMC,MAAMoS,GACtBlX,KAAKwD,KAAKqB,MAAMC,MAAMqS,IAYL3M,eACnB6M,EACAH,EACAC,EACA9J,GAEA,IACE,MAAM3E,QAAeN,EACnBiF,EACArN,KAAK+W,kBAAkBpP,QAAQ6P,SAC/BH,EACArX,KAAKwD,KAAKqB,MAAMC,MAAMoS,GACtBlX,KAAKwD,KAAKqB,MAAMC,MAAMqS,IAcxB,kBAX8BJ,kBAAkBpP,QAC7C6P,SACCH,EACArX,KAAKwD,KAAKqB,MAAMC,MAAMoS,GACtBlX,KAAKwD,KAAKqB,MAAMC,MAAMqS,IAEvB3I,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GACPmP,EAAOxW,8CAA8CqH,EAAEC,WAEzD,YAS2BsC,uBAAC6M,EAAmBhK,GAC/C,OAAOjF,EAAYiF,EAASrN,KAAK+W,kBAAkBpP,QAAQ8P,WAAYJ,GASlD7M,iBACrB6M,EACAhK,GAEA,IACE,MAAM3E,QAAeN,EACnBiF,EACArN,KAAK+W,kBAAkBpP,QAAQ8P,WAC/BJ,GAQF,kBAL8BN,kBAAkBpP,QAAQ8P,WAAWJ,GAAW7I,KAAK,CACjFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGlD,MAAO8E,GACPmP,EAAOxW,8CAA8CqH,EAAEC,WAEzD,YAUkCsC,8BAClC6M,EACAhK,EACAqK,GAEA,OAAOtP,EACLiF,EACArN,KAAK+W,kBAAkBpP,QAAQgQ,kBAC/BN,EACAK,GAW0BlN,wBAC5B6M,EACAhK,EACAqK,GAEA,IACE,MAAMhP,QAAeN,EACnBiF,EACArN,KAAK+W,kBAAkBpP,QAAQgQ,kBAC/BN,EACAK,GAUF,kBAP8BX,kBAAkBpP,QAC7CgQ,kBAAkBN,EAAWK,GAC7BlJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GACPmP,EAAOxW,8CAA8CqH,EAAEC,WAEzD,YAUyBsC,qBACzB6M,EACAhK,EACA/F,EAAiB,IACjBsQ,GAEA,OAAOxP,EACLiF,EACArN,KAAK+W,kBAAkBpP,QAAQkQ,SAC/BR,EACArX,KAAKwD,KAAKqB,MAAMC,MAAMwC,GACtBsQ,GAciBpN,eACnB6M,EACAhK,EACA/F,EAAiB,IACjBsQ,GAEA,MAAMlP,QAAeN,EACnBiF,EACArN,KAAK+W,kBAAkBpP,QAAQkQ,SAC/BR,EACArX,KAAKwD,KAAKqB,MAAMC,MAAMwC,GACtBsQ,GAGF,IAQE,kBAP8Bb,kBAAkBpP,QAC7CkQ,SAASR,EAAWrX,KAAKwD,KAAKqB,MAAMC,MAAMwC,GAASsQ,GACnDpJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GACPmP,EAAOxW,2CAA2CqH,EAAEC,WAEtD,YAU8BsC,0BAAC6M,EAAmBhK,GAClD,OAAOjF,EAAYiF,EAASrN,KAAK+W,kBAAkBpP,QAAQmQ,cAAeT,GASlD7M,oBACxB6M,EACAhK,GAEA,MAAM3E,QAAeN,EACnBiF,EACArN,KAAK+W,kBAAkBpP,QAAQmQ,cAC/BT,GAGF,IAQE,kBAP8BN,kBAAkBpP,QAC7CmQ,cAAcT,GACd7I,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GACPmP,EAAOxW,2CAA2CqH,EAAEC,WAEtD,YAUwBsC,oBACxB6M,EACAU,EACA1K,EACA/F,EAAiB,KAEjB,MAAMkJ,aAAoBA,OAAO6G,GACjC,SAAK7G,IAEiB,IAAlBA,EAAOwH,QAES,IAAI1J,QAAcyJ,EAAU7I,QAAQmI,EAAWhK,IACnDkB,qBAAqBiC,EAAO2G,aAExC,IAAI7I,EAAQ2J,OAAO3Q,IAASiN,YAAY/D,EAAO0G,aAE3B,IAAI5I,EAAQkC,EAAOtB,SACvBX,qBAAqBjH,KAA+B,IAApBkJ,EAAO0H,WC5XnDC,IAAAA,IAAZ,SAAYA,GACVA,2CACAA,+CAFF,CAAYA,KAAAA,cAMCC,GAgBXvY,YACE2D,EACAqC,EACAgF,EACAwN,EAA4C,KAC5CC,EAAuB,KACvBnV,QApBKmV,aAAuB,UACvBzS,6BACAwS,iCACA7U,iBACA+U,kBAA8B,UAE9BpV,mBACAqV,aAeLxY,KAAKwD,KAAOA,EACZxD,KAAKmD,OAASA,IAAU,IAAIsI,GAAekB,UAAU9B,GAAW,WAChE7K,KAAKqY,qBACHA,GAAyBI,EAA4B/G,IACvD1R,KAAKsY,aAAeA,EACpBtY,KAAK6F,iBAAmBA,EACxB7F,KAAKuY,kBAAoBtV,EACvB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKqY,qBAAsBrY,KAAK6F,kBAC3D7F,KAAKmD,QAIUqH,oBACjBnD,EACAC,EACAC,GAEA,OAAOR,EAAc/G,KAAKwD,KAAM6D,EAAOC,EAAQC,GAG9BiD,oBACjBnD,EACAC,EACAC,GAEA,OAAOH,EAAcpH,KAAKwD,KAAM6D,EAAOC,EAAQC,GASlBiD,yBAACkO,EAAmBX,GAIjD,kBAH8BQ,kBAAkB5Q,QAC7CgR,mBAAmBD,EAAWX,GAC9BnQ,OAcgB4C,eACnBsD,EACA8K,EACAC,EACAvT,EACAwT,EACAC,EACA9K,GAIA,OAAO7F,EACL0F,GAHgBG,GAAoBjO,KAAKuY,mBAI/B5Q,QAAQqR,MAClBJ,EACAC,EACAvT,EACAwT,EACAC,GAccvO,YAChB6C,EACAhI,EACA4T,EACA3T,EACAwT,EAA+B/V,EAC/BgW,EAA2B,KAE3B,MAAMG,aAAsBC,YAAY9T,GAClC+T,EAA4BpZ,KAAKwD,KAAKqB,MAAMC,MAAMiU,GAClDM,aAA+BtS,cACnCmS,EAASnB,UACTkB,GACCC,EAASI,YAENC,aAA4BxS,cAChCmS,EAASR,UACTpT,GACC4T,EAASM,YAGN9Q,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQqR,MAC/B3T,EACAgU,EACAE,EACAT,EACAM,GAEF,IAcE,kBAb8Bb,kBAAkB5Q,QAC7CqR,MACC3T,EACAgU,EACAE,EACAT,EACAM,GAED5K,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GAEP,OADAjH,EAAeJ,0CAA0CqH,EAAEC,iBAezCsC,gBACpBsD,EACA8K,EACAC,EACAvT,EACAwT,EACAC,EACA9K,GAIA,OAAO7F,EACL0F,GAHgBG,GAAoBjO,KAAKuY,mBAI/B5Q,QAAQ8R,OAClBb,EACAC,EACAvT,EACAwT,EACAC,GAcevO,aACjB6C,EACAhI,EACA4T,EACAS,EACAZ,EAA+B/V,EAC/BgW,EAA2B,KAE3B,MAAMG,aAAsBC,YAAY9T,GAClC+T,EAA4BpZ,KAAKwD,KAAKqB,MAAMC,MAAMiU,GAClDM,aAA+BtS,cACnCmS,EAASnB,UACTkB,GACCC,EAASI,YAENK,aAA4B5S,cAChCmS,EAASR,UACTgB,GACCR,EAASM,YAEN9Q,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQ8R,OAC/BpU,EACAgU,EACAM,EACAb,EACAM,GAEF,IAcE,kBAb8Bb,kBAAkB5Q,QAC7C8R,OACCpU,EACAgU,EACAM,EACAb,EACAM,GAED5K,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GAEP,OADAjH,EAAeJ,2CAA2CqH,EAAEC,iBAW/BsC,6BAI/B,kBAHgC+N,kBAAkB5Q,QAC/CiS,uBACAhS,OAYkB4C,iBACrBsD,EACAzI,EACAwU,EACA5L,GAIA,OAAO7F,EACL0F,GAHgBG,GAAoBjO,KAAKuY,mBAI/B5Q,QAAQmS,QAClBzU,aACW7B,KAAKqB,MAAMC,MAAM+U,IAWZrP,cAClB6C,EACAhI,EACAwU,GAEA,MAAMnR,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQmS,QAC/BzU,EACArF,KAAKwD,KAAKqB,MAAMC,MAAM+U,IASxB,kBAP8BtB,kBAAkB5Q,QAC7CmS,QAAQzU,EAAYrF,KAAKwD,KAAKqB,MAAMC,MAAM+U,IAC1CrL,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAarBqH,2BAC/BsD,EACAzI,EACAqS,EACAzJ,GAIA,OAAO7F,EACL0F,GAHgBG,GAAoBjO,KAAKuY,mBAI/B5Q,QAAQgQ,kBAClBtS,EACAqS,GAW0BlN,wBAC5B6C,EACAhI,EACAqS,GAEA,MAAMhP,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQgQ,kBAC/BtS,EACAqS,GASF,kBAP8Ba,kBAAkB5Q,QAC7CgQ,kBAAkBtS,EAAYqS,GAC9BlJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAY9BqH,kBACtBsD,EACAzI,EACA4I,GAIA,OAAO7F,EAAY0F,GAFDG,GAAoBjO,KAAKuY,mBAEL5Q,QAAQoS,oBAAqB1U,GAShDmF,eACnB6C,EACAhI,GAEA,MAAM6T,aAAsBC,YAAY9T,GACxC,IAAK6T,EAAU,YACf,IAAwB,IAApBA,EAASlB,OAAiB,YAC9B,MAAMtP,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQoS,oBAC/B1U,GASF,kBAP8BkT,kBAAkB5Q,QAC7CoS,oBAAoB1U,GACpBmJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAY5BqH,oBACxBsD,EACAzI,EACA4I,GAIA,OAAO7F,EAAY0F,GAFDG,GAAoBjO,KAAKuY,mBAEL5Q,QAAQoS,oBAAqB1U,GAS9CmF,iBACrB6C,EACAhI,GAEA,MAAM6T,aAAsBC,YAAY9T,GACxC,IAAK6T,EAAU,YACf,IAAwB,IAApBA,EAASlB,OAAkB,YAE/B,MAAMtP,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQoS,oBAC/B1U,GAWF,kBAR8BkT,kBAAkB5Q,QAC7CoS,oBAAoB1U,GACpBmJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAWlCqH,cAACnF,GACnB,MAAM2U,aAAqBzB,kBAAkB5Q,QAAQsS,QAAQ5U,GAAYuC,OAEzE,kBADwBpE,KAAKqB,MAAM8M,QAAQqI,GASrBxP,kBAACnF,GACvB,MAAM6U,aAAsB3B,kBAAkB5Q,QAAQwS,YAAY9U,GAAYuC,OACxEsR,aAAsBC,YAAY9T,GACxC,kBAAkB+B,cAAc8R,EAASnB,UAAWmC,GAAWhB,EAASI,YAQlD9O,kBAACnF,GACvB,MAAM+U,aAAsB7B,kBAAkB5Q,QAAQ0S,YAAYhV,GAAYuC,OACxEsR,aAAsBC,YAAY9T,GACxC,kBAAkB+B,cAAc8R,EAASR,UAAW0B,GAAWlB,EAASM,YAQ5ChP,wBAACnF,GAC7B,kBAAkBkT,kBAAkB5Q,QAAQ2S,kBAAkBjV,GAAYuC,OAU3C4C,2BAC/BnF,EACA4T,EACAF,EAA2B,KAE3B,MAAMwB,aAA+BpB,YAAY9T,GAC3CyD,aAAoByP,kBAAkB5Q,QACzC6S,qBACCnV,aACW0B,cACTwT,EAAkBxC,UAClBkB,GACCsB,EAAkBjB,YAErBtZ,KAAKwD,KAAKqB,MAAMC,MAAMiU,IAEvBnR,OAwBH,MAtBqB,CACnB6S,2BAA4BrT,cAC1BmT,EAAkB7B,UAClB5P,EAAO2R,iBACNF,EAAkBf,YAErBkB,2BAA4BtT,cAC1BmT,EAAkB7B,UAClB5P,EAAO4R,iBACNH,EAAkBf,YAErBxD,0BAA2B5O,cACzBmT,EAAkB7B,UAClB5P,EAAOkN,gBACNuE,EAAkBf,YAErBmB,kCAAmCvT,cACjCmT,EAAkB7B,UAClB5P,EAAO6R,wBACNJ,EAAkBf,aAaEhP,qBACzBnF,EACA4T,EACAF,EAA2B,KAE3B,MAAMG,aAAsBC,YAAY9T,GAClCyD,aAAoByP,kBAAkB5Q,QACzCiT,qBACCvV,aACW0B,cACTmS,EAASnB,UACTkB,GACCC,EAASI,YAEZtZ,KAAKwD,KAAKqB,MAAMC,MAAMiU,IAEvBnR,OAEH,kBAAkBR,cAAc8R,EAASR,UAAW5P,EAAO,IAAKoQ,EAASM,YAQnDhP,kBAACnF,GACvB,MAAMyD,aAAwCyP,kBAAkB5Q,QAC7DwR,YAAY9T,GACZuC,OAyBH,OAxBAkB,EAAOwQ,WAAaxQ,EAAOwQ,WAAWrV,WACtC6E,EAAO0Q,WAAa1Q,EAAO0Q,WAAWvV,WACtC6E,EAAO+R,qBAAuBzT,cAC5B0B,EAAOiP,UACPjP,EAAO+R,WACN/R,EAAOwQ,YAEVxQ,EAAOgS,qBAAuB1T,cAC5B0B,EAAO4P,UACP5P,EAAOgS,WACNhS,EAAO0Q,YAEV1Q,EAAOoR,oBAAsB9S,cAC3B0B,EAAOiP,UACPjP,EAAOoR,UACNpR,EAAOwQ,YAEVxQ,EAAOsR,oBAAsBhT,cAC3B0B,EAAO4P,UACP5P,EAAOsR,UACNtR,EAAO0Q,YAEV1Q,EAAO3C,UAAYnG,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,EAAO3C,WAClD2C,EAAOzD,WAAaA,EACbyD,EAQe0B,kBAACnF,GACvB,MAAMyD,aAA8ByP,kBAAkB5Q,QACnDoT,YAAY1V,GACZuC,OACHkB,EAAOkS,OAAShb,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,EAAOkS,OAAO/W,YACtD6E,EAAO1C,UAAYpG,KAAKwD,KAAKqB,MAAM8M,QAAQ7I,EAAO1C,UAAUnC,YAE5D,MAAMiV,aAAsBC,YAAY9T,GAaxC,OAZAyD,EAAOmS,8BAAgC7T,cACrC8R,EAASR,UACT5P,EAAOmS,oBACN/B,EAASM,YAEZ1Q,EAAOoS,6BAA+B9T,cACpC8R,EAASR,UACT5P,EAAOoS,mBACNhC,EAASM,YAGZ1Q,EAAOzD,WAAaA,EACbyD,EAQgB0B,qBACvB,kBAAkB+N,kBAAkB5Q,QAAQwT,eAAevT,OAQxC4C,eAACnF,GAEpB,kBAD0BkT,kBAAkB5Q,QAAQyT,SAAS/V,GAAYuC,OAW/C4C,sBAC1BsD,EACAzI,EACA4I,GAIA,OAAO7F,EAAY0F,GAFDG,GAAoBjO,KAAKuY,mBAEL5Q,QAAQ0T,gBAAiBhW,GAAY,GASpDmF,mBACvB6C,EACAhI,GAEA,MAAM6T,aAAsBC,YAAY9T,GACxC,IAAK6T,EAAU,YACf,IAA0B,IAAtBA,EAASvT,SAAmB,YAEhC,MAAM+C,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQ0T,gBAC/BhW,GACA,GASF,kBAP8BkT,kBAAkB5Q,QAC7C0T,gBAAgBhW,GAAY,GAC5BmJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYxBqH,wBAC5BsD,EACAzI,EACA4I,GAIA,OAAO7F,EACL0F,GAHgBG,GAAoBjO,KAAKuY,mBAI/B5Q,QAAQ0T,gBAAgBhW,GAAY,GAC9CA,GACA,GAUuBmF,qBACzB6C,EACAhI,GAEA,MAAM6T,aAAsBC,YAAY9T,GACxC,IAAK6T,EAAU,YACf,IAA0B,IAAtBA,EAASvT,SAAoB,YAEjC,MAAM+C,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQ0T,gBAC/BhW,GACA,GAWF,kBAR8BkT,kBAAkB5Q,QAC7C0T,gBAAgBhW,GAAY,GAC5BmJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAc7BqH,mBACvBsD,EACAzI,EACAiC,EACA2G,GAEA,MAAM9H,EAAY8H,GAAoBjO,KAAKuY,kBACrC+C,aAA2C/C,kBAAkB5Q,QAChEwR,YAAY9T,GACZuC,OACG2T,aAAuBxU,cAC3BuU,EAAU5C,UACVpR,GACCgU,EAAU9B,YAEb,OAAOpR,EAAY0F,EAAS3H,EAAUwB,QAAQ6T,UAAWnW,EAAYkW,GAUjD/Q,gBACpB6C,EACAhI,EACAiC,GAGA,eAD4B6R,YAAY9T,GACzB,YAEf,MAAMiW,aAA2C/C,kBAAkB5Q,QAChEwR,YAAY9T,GACZuC,OACG2T,aAAuBxU,cAC3BuU,EAAU5C,UACVpR,GACCgU,EAAU9B,YAGP9Q,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQ6T,UAC/BnW,EACAkW,GAUF,kBAP8BhD,kBAAkB5Q,QAC7C6T,UAAUnW,EAAYkW,GACtB/M,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAa7BqH,mBACvBsD,EACAzI,EACAiC,EACA2G,GAEA,MAAM9H,EAAY8H,GAAoBjO,KAAKuY,kBACrC+C,aAA2C/C,kBAAkB5Q,QAChEwR,YAAY9T,GACZuC,OAEG2T,aAAuBxU,cAC3BuU,EAAUvD,UACVzQ,GACCgU,EAAUhC,YAEb,OAAOlR,EAAY0F,EAAS3H,EAAUwB,QAAQ8T,UAAWpW,EAAYkW,GAUjD/Q,gBACpB6C,EACAhI,EACAiC,GAGA,eAD4B6R,YAAY9T,GACzB,YAEf,MAAMiW,aAA2C/C,kBAAkB5Q,QAChEwR,YAAY9T,GACZuC,OACG2T,aAAuBxU,cAC3BuU,EAAUvD,UACVzQ,GACCgU,EAAUhC,YAGP5Q,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQ8T,UAC/BpW,EACAkW,GAUF,kBAP8BhD,kBAAkB5Q,QAC7C8T,UAAUpW,EAAYkW,GACtB/M,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYtBqH,0BAC9BsD,EACAzI,EACA4I,GAIA,OAAO7F,EAAY0F,GAFDG,GAAoBjO,KAAKuY,mBAEL5Q,QAAQ0L,iBAAkBhO,GASrCmF,uBAC3B6C,EACAhI,GAGA,eAD4B8T,YAAY9T,GACzB,YAEf,MAAMqD,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQ0L,iBAC/BhO,GASF,kBAP8BkT,kBAAkB5Q,QAC7C0L,iBAAiBhO,GACjBmJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYvBqH,yBAC7BsD,EACAzI,EACA4I,GAIA,OAAO7F,EAAY0F,GAFDG,GAAoBjO,KAAKuY,mBAEL5Q,QAAQ0L,iBAAkBhO,GAStCmF,sBAC1B6C,EACAhI,GAGA,eAD4B8T,YAAY9T,GACzB,YAEf,MAAMqD,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQ+T,gBAC/BrW,GASF,kBAP8BkT,kBAAkB5Q,QAC7C+T,gBAAgBrW,GAChBmJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UASjCqH,wBACnB,IAAI1B,EAAS,KACb,IACEA,aAAoByP,kBAAkB5Q,QAAQgU,eAAe/T,OAC7D,MAAOK,GACPjH,EAAeJ,qDAAqDqH,EAAEC,WAExE,OAAOY,EAOM0B,kBACb,IAAI1B,EAAS,KACb,IACEA,aAAoByP,kBAAkB5Q,QAAQiU,SAAShU,OACvD,MAAOK,GACPjH,EAAeJ,8CAA8CqH,EAAEC,WAEjE,OAAOY,EAQa0B,uBAACnF,GACrB,IAAIyD,EAAS,KACb,IACEA,mBAA2BqQ,YAAY9T,IAAawW,cACpD,MAAO5T,GACPjH,EAAeJ,qDAAqDqH,EAAEC,WAExE,OAAOY,EAWsB0B,yBAC7BsD,EACAzI,EACAyW,EACA7N,GAIA,OAAO7F,EACL0F,GAHgBG,GAAoBjO,KAAKuY,mBAI/B5Q,QAAQoU,gBAClB1W,EACAyW,GAWwBtR,sBAC1B6C,EACAhI,EACAyW,GAEA,MAAMpT,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQoU,gBAC/B1W,EACArF,KAAKwD,KAAKqB,MAAMC,MAAMgX,IASxB,kBAP8BvD,kBAAkB5Q,QAC7CoU,gBAAgB1W,EAAYrF,KAAKwD,KAAKqB,MAAMC,MAAMgX,IAClDtN,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAadqH,kCACtCsD,EACAzI,EACA2W,EACA/N,GAIA,OAAO7F,EACL0F,GAHgBG,GAAoBjO,KAAKuY,mBAI/B5Q,QAAQsU,yBAClB5W,EACA2W,GAWiCxR,+BACnC6C,EACAhI,EACA2W,GAEA,MAAMtT,QAAeN,EACnBiF,EACArN,KAAKuY,kBAAkB5Q,QAAQsU,yBAC/B5W,EACA2W,GASF,kBAP8BzD,kBAAkB5Q,QAC7CsU,yBAAyB5W,EAAY2W,GACrCxN,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,iBCtpC3C+Y,GAKXrc,YACE2D,EACAqH,EACA2N,EAA6B,KAC7BrV,QARKqV,kBACAhV,iBACAL,cAQMnD,KAAKwY,MAAZA,GACc2D,EAAoBzK,IACtC1R,KAAKwD,KAAOA,EACZxD,KAAKmD,OAASA,IAAU,IAAIsI,GAAekB,UAAU9B,GAAW,WAG/CL,oBACjBnD,EACAC,EACAC,GAEA,OAAOH,EAAcpH,KAAKwD,KAAM6D,EAAOC,EAAQC,GASdiD,oCACjC4R,EACAxD,GAEA,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QACxB2U,8BAA8B1D,GAC9BhR,OACH,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAElD,OAAOY,EAAO7E,WAU0BuG,2CACxC4R,EACAxD,GAEA,IACE,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KAIb,OAHAA,QAAeuT,EAAY1U,QACxB4U,qCAAqC3D,GACrChR,OACIkB,EAAO7E,WACd,MAAOgE,GACPjH,EAAeJ,+BAA+BqH,EAAEC,YAU3BsC,0BACvB4R,EACAxD,GAEA,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQ6U,oBAAoB5D,GAAkBhR,OACzE,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAElD,OAAOY,EASS0B,mBAAC4R,EAAmBxD,GACpC,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQ0K,oBAAoBuG,GAAkBhR,OACzE,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAElD,OAAOY,EASW0B,qBAAC4R,EAAmBxD,GACtC,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQ8U,eAAe7D,GAAkBhR,OACpE,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAElD,OAAOY,EASgB0B,0BACvB4R,EACAxD,GAEA,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQ+U,oBAAoB9D,GAAkBhR,OACzE,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAElD,OAAOY,EAUgB0B,0BACvB4R,EACAxD,EACArR,GAEA,MAAM8U,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQgV,oBAAoB/D,GAAkBhR,OACzE,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAGlD,OADAY,aAAoB1B,cAAcwR,EAAkB9P,EAAQvB,GACrDuB,EASe0B,yBAAC4R,EAAmBxD,GAC1C,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQiV,mBAAmBhE,GAAkBhR,OACxE,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAElD,OAAOY,EAUa0B,uBACpB4R,EACAxD,EACArR,GAEA,MAAM8U,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQkV,iBAAiBjE,GAAkBhR,OACtE,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAGlD,OADAY,aAAoB1B,cAAcwR,EAAkB9P,EAAQvB,GACrDuB,EASgB0B,0BACvB4R,EACAxD,GAEA,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQmV,oBAAoBlE,GAAkBhR,OACzE,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAElD,OAAOY,EAUkB0B,4BACzB4R,EACAxD,EACArR,GAEA,MAAM8U,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQoV,sBAAsBnE,GAAkBhR,OAC3E,MAAOK,GACPjH,EAAeJ,+BAA+BqH,EAAEC,WAGlD,OADAY,aAAoB1B,cAAcwR,EAAkB9P,EAAQvB,GACrDuB,EAWiB0B,oBACxBsD,EACAsO,EACAxD,EACA3K,GAKA,OAAO7F,EAAY0F,GAFjBG,GAAoB,SAASzK,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAoB4D,IAElCzU,QAAQqV,WAAYpE,GAU9CpO,iBACdsD,EACAsO,EACAxD,GAEA,MAAMyD,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KAEb,MAAMJ,QAAeN,EACnB0F,EACAuO,EAAY1U,QAAQqV,WACpBpE,GAGF,IACE9P,QAAeuT,EAAY1U,QAAQqV,WAAWpE,GAAkBpK,KAAK,CACnEnG,KAAMyF,EACNW,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAElD,MAAO8E,GACPjH,EAAeJ,MAAM,8CAEvB,OAAOkI,EAWqB0B,wBAC5BsD,EACAsO,EACAxD,EACA/I,EACAoN,EACAhP,GAKA,OAAO7F,EACL0F,GAHAG,GAAoB,SAASzK,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAoB4D,IAI5DzU,QAAQuV,eACpBtE,EACA/I,EACAoN,GAWgBzS,qBAClBsD,EACAsO,EACAxD,EACA/I,EACAoN,GAEA,MAAMZ,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KAEb,MAAMJ,QAAeN,EACnB0F,EACAuO,EAAY1U,QAAQuV,eACpBtE,EACA/I,EACAoN,GAGF,IACEnU,QAAeuT,EAAY1U,QACxBuV,eAAetE,EAAkB/I,EAAaoN,GAC9CzO,KAAK,CACJnG,KAAMyF,EACNW,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAEpD,MAAO8E,GACPjH,EAAeJ,MAAM,8CAEvB,OAAOkI,EAQM0B,gBAAC4R,GACd,MAAMC,EAAc,SAAS7Y,KAAKG,IAAI8D,SAASzH,KAAKwY,MAAO4D,GAC3D,IAAItT,EAAS,KACb,IACEA,QAAeuT,EAAY1U,QAAQiU,SAAShU,OAC5C,MAAOK,GACPjH,EAAeJ,8CAA8CqH,EAAEC,WAEjE,OAAOY,SCjYEqU,GAaXtd,YACEud,EACA5Z,EACAqH,EACAwS,EACAla,QAjBKia,0BACAC,sBACA7Z,iBACAL,mBACAyY,cAeL5b,KAAKod,cAAgBA,EACrBpd,KAAKqd,UAAYA,GAAcC,EAAc5L,IAC7C1R,KAAKwD,KAAOA,EACZxD,KAAKmD,OAASA,IAAU,IAAIsI,GAAekB,UAAU9B,GAAW,WAChE7K,KAAK4b,OAAS3Y,EACZ,SAASO,KAAKG,IAAI8D,SAASzH,KAAKqd,UAAWrd,KAAKod,eAChDpd,KAAKmD,QAUoBqH,uBAAC6C,EAAiBkQ,GAC7C,OAAOnV,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQ6V,WAAYD,GASvC/S,iBACrB6C,EACAkQ,GAEA,MAAM7U,QAAeN,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQ6V,WAAYD,GAS1E,kBAN8B3B,OAAOjU,QAAQ6V,WAAWD,GAAY/O,KAAK,CACvEnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UASxBqH,sBAAC6C,GAC3B,kBAAkBuO,OAAOjU,QAAQ8V,gBAAgBpQ,GAASzF,OAMlC4C,oBAAC6C,GACzB,kBAAkBuO,OAAOjU,QAAQ+V,aAAarQ,GAASzF,OAMhC4C,mBAAC6C,GACxB,kBAAkBuO,OAAOjU,QAAQgW,oBAAoBtQ,GAASzF,OAM3C4C,iBACnB,kBAAkBoR,OAAOjU,QAAQiW,cAAchW,OAMvB4C,sBACxB,kBAAkBoR,OAAOjU,QAAQkW,UAAUjW,OAMlB4C,qBAAC6C,GAC1B,kBAAkBuO,OAAOjU,QAAQmW,eAAezQ,GAASzF,OAUxB4C,6BACjC6C,EACAU,EACAE,GAEA,OAAO7F,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQoW,iBAAkBhQ,GASvCvD,uBAC3B6C,EACAU,GAEA,cAAgBiQ,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQoW,iBACpBhQ,GAUF,kBAN8B6N,OAAOjU,QAAQoW,iBAAiBhQ,GAAcS,KAAK,CAC/EnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAadqH,gCACpC6C,EACAU,EACAE,GAEA,OAAO7F,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQsW,oBAAqBlQ,GASvCvD,0BAC9B6C,EACAU,GAEA,cAAgBiQ,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQsW,oBACpBlQ,GAUF,kBAN8B6N,OAAOjU,QAAQsW,oBAAoBlQ,GAAcS,KAAK,CAClFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYpBqH,0BAAC6C,EAAiBU,GAChD,OAAO3F,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQuW,cAAenQ,GASvCvD,oBACxB6C,EACAU,GAEA,cAAgBiQ,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQuW,cACpBnQ,GAUF,kBAN8B6N,OAAOjU,QAAQuW,cAAcnQ,GAAcS,KAAK,CAC5EnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYjBqH,6BACjC6C,EACAU,GAEA,OAAO3F,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQwW,iBAAkBpQ,GASvCvD,uBAC3B6C,EACAU,GAEA,cAAgBiQ,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQwW,iBACpBpQ,GAUF,kBAN8B6N,OAAOjU,QAAQwW,iBAAiBpQ,GAAcS,KAAK,CAC/EnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYbqH,iCACrC6C,EACAU,GAEA,OAAO3F,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQyW,qBAAsBrQ,GASvCvD,2BAC/B6C,EACAU,GAEA,cAAgBiQ,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQyW,qBACpBrQ,GAUF,kBAN8B6N,OAAOjU,QAAQyW,qBAAqBrQ,GAAcS,KAAK,CACnFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYVqH,oCACxC6C,EACAU,GAEA,OAAO3F,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQ0W,wBAAyBtQ,GASvCvD,8BAClC6C,EACAU,GAEA,cAAgBiQ,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQ0W,wBACpBtQ,GAYF,kBAR8B6N,OAAOjU,QAClC0W,wBAAwBtQ,GACxBS,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYfqH,iCACrC6C,EACAU,GAEA,OAAO3F,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQ2W,qBAAsBvQ,GASvCvD,2BAC/B6C,EACAU,GAEA,cAAgBiQ,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQ2W,qBACpBvQ,GAUF,kBAN8B6N,OAAOjU,QAAQ2W,qBAAqBvQ,GAAcS,KAAK,CACnFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYVqH,oCACxC6C,EACAU,GAEA,OAAO3F,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQ4W,wBAAyBxQ,GASvCvD,8BAClC6C,EACAU,GAEA,cAAgBiQ,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQ4W,wBACpBxQ,GAYF,kBAR8B6N,OAAOjU,QAClC4W,wBAAwBxQ,GACxBS,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAShCqH,gBAACkO,GACrB,kBAAkBkD,OAAOjU,QAAQ6W,UAAU9F,GAAW9Q,OAM3B4C,yBAC3B,kBAAkBoR,OAAOjU,QAAQ8W,eAAe7W,OASnB4C,yBAC7B6C,EACAqR,EACAC,EACAC,EACAC,GAEA,OAAOzW,EACLiF,EACArN,KAAK4b,OAAOjU,QAAQmX,aACpBJ,EACAC,EACAC,EACAC,GAaqBrU,mBACvB6C,EACAqR,EACAC,EACAC,EACAC,GAEA,cAAgBb,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQmX,aACpBJ,EACAC,EACAC,EACAC,GAYF,kBAR8BjD,OAAOjU,QAClCmX,aAAaJ,EAAiBC,EAAoBC,EAAeC,GACjErQ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYpBqH,4BAChC6C,EACA0R,GAEA,OAAO3W,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQqX,gBAAiBD,GASvCvU,sBAC1B6C,EACA0R,GAEA,cAAgBf,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQqX,gBACpBD,GAUF,kBAN8BnD,OAAOjU,QAAQqX,gBAAgBD,GAAiBvQ,KAAK,CACjFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYfqH,+BACnC6C,EACA0R,GAEA,OAAO3W,EAAYiF,EAASrN,KAAK4b,OAAOjU,QAAQsX,mBAAoBF,GASvCvU,yBAC7B6C,EACA0R,GAEA,cAAgBf,aAAgB3Q,EAC9B,UAAUtN,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAK4b,OAAOjU,QAAQsX,mBACpBF,GAYF,kBAR8BnD,OAAOjU,QAClCsX,mBAAmBF,GACnBvQ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,iBCtlB3C+b,GAQXrf,YACE2D,EACAqH,EACAsU,EACAhc,QAXKic,8BACAC,0BACAF,mBACA3b,iBACA+H,uBACApI,cAQLnD,KAAKmf,OAASA,GAAWG,EAAc5N,IACvC1R,KAAKwD,KAAOA,EACZxD,KAAKmD,OAASA,IAAU,IAAIsI,GAAekB,UAAU9B,GAAW,WAmBpCL,wBAC5B+U,EACAlS,EACA9I,EACAC,EACAC,EACAC,EACAM,EACAD,EACA5C,EACAC,EACAgC,EACA6J,GAQA,OAAO7F,EACLiF,GANAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAIKwE,QAAQ6X,YACpBpb,EACA,CAACjC,EAAMC,GACP,CAACmC,EAAQC,EAAkBC,EAAcC,GACzC,CAAC1E,KAAKwD,KAAKqB,MAAMC,MAAMC,GAAM/E,KAAKwD,KAAKqB,MAAMC,MAAME,IACnD,IAmBoBwF,kBACtB+U,EACAlS,EACA9I,EACAC,EACAC,EACAC,EACAM,EACAD,EACA5C,EACAC,EACAgC,GAEA,IAAwE,gBAAxDqb,kBAAkBF,EAAYlS,IAAUqS,YACtD,UAAU3f,qCAEPqE,IAAeA,EAAgB,GAG/BjC,GAASC,KACRD,KAAAA,EAAMC,OAAAA,GAAWnB,KAIvB,MAAM0e,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGDuF,QAAeN,EACnBiF,EACAsS,EAAYhY,QAAQ6X,YACpBpb,EACA,CAACjC,EAAMC,GACP,CAACmC,EAAQC,EAAkBC,EAAcC,GACzC,CAAC1E,KAAKwD,KAAKqB,MAAMC,MAAMC,GAAM/E,KAAKwD,KAAKqB,MAAMC,MAAME,IACnD,IAIIiK,QAAmB0Q,EAAYhY,QAClC6X,YACCpb,EACA,CAACjC,EAAMC,GACP,CAACmC,EAAQC,EAAkBC,EAAcC,GACzC,CAAC1E,KAAKwD,KAAKqB,MAAMC,MAAMC,GAAM/E,KAAKwD,KAAKqB,MAAMC,MAAME,IACnD,IAEDwJ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,IAAI4K,EAAe,KACnB,IACEA,EAAekB,EAAW2Q,OAAOC,aAAaC,aAAa,GAC3D,MAAO7X,GACPjH,EAAeJ,6CAA6CqH,EAAEC,WAEhE,OAAO6F,EAWoBvD,uBAC3B+U,EACAlS,EACA0S,EACA9R,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAG+BwE,QAAQqY,WAAYD,GAUvCvV,iBAAC+U,EAAoBlS,EAAiB0S,GAC3D,MAAMJ,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,cAAgB8c,YAAYV,KAAiBlS,EAC3C,UAAUtN,iCAGZ,MAAM2I,QAAeN,EAAYiF,EAASsS,EAAYhY,QAAQqY,WAAYD,GAS1E,aANyBJ,EAAYhY,QAAQqY,WAAWD,GAASvR,KAAK,CACpEnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcpBqH,0BAC9B+U,EACAlS,EACA0S,EACA9R,GAQA,OAAO7F,EAAYiF,GALjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAE+BwE,QAAQuY,cAAeH,GAUvCvV,oBAAC+U,EAAoBlS,EAAiB0S,GAC9D,MAAMJ,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,cAAgB8c,YAAYV,KAAiBlS,EAC3C,UAAUtN,iCAGZ,MAAM2I,QAAeN,EAAYiF,EAASsS,EAAYhY,QAAQuY,cAAeH,GAS7E,aANyBJ,EAAYhY,QAAQuY,cAAcH,GAASvR,KAAK,CACvEnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcjBqH,6BACjC+U,EACAlS,EACA8S,EACAlS,GAQA,OAAO7F,EAAYiF,GALjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAE+BwE,QAAQyY,qBAAsBD,GAU3C3V,uBAC3B+U,EACAlS,EACA8S,GAEA,MAAMR,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,IAAoE,gBAApDsc,kBAAkBF,EAAYlS,IAAU0S,QACtD,UAAUhgB,+BAIZ,MAAM2I,QAAeN,EACnBiF,EACAsS,EAAYhY,QAAQyY,qBACpBD,GAYF,aARyBR,EAAYhY,QAClCyY,qBAAqBD,GACrB3R,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAchBqH,gCACpC+U,EACAlS,EACA8S,EACAlS,GASA,OAAO7F,EACLiF,GAPAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAKKwE,QAAQ0Y,0BACpBF,GAW4B3V,0BAC9B+U,EACAlS,EACA8S,GAEA,MAAMR,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,IACkE,gBAApDsc,kBAAkBF,EAAYlS,IAAU0S,SACnD1S,IAAY8S,IACyD,gBAAxDV,kBAAkBF,EAAYlS,IAAUqS,YAEtD,UAAU3f,iDAEZ,MAAM2I,QAAeN,EACnBiF,EACAsS,EAAYhY,QAAQ0Y,0BACpBF,GAYF,aARyBR,EAAYhY,QAClC0Y,0BAA0BF,GAC1B3R,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcjBqH,+BACnC+U,EACAlS,EACAiT,EACArS,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAG+BwE,QAAQ4Y,kBAAmBD,GAUtC9V,yBAC7B+U,EACAlS,EACAiT,GAEA,MAAMX,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,IAAoE,gBAApDsc,kBAAkBF,EAAYlS,IAAU0S,QACtD,UAAUhgB,+BAGZ,MAAM2I,QAAeN,EACnBiF,EACAsS,EAAYhY,QAAQ4Y,kBACpBD,GAUF,aANyBX,EAAYhY,QAAQ4Y,kBAAkBD,GAAiB9R,KAAK,CACnFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcbqH,iCACrC+U,EACAlS,EACAiT,EACArS,GASA,OAAO7F,EACLiF,GAPAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAKKwE,QAAQ6Y,uBACpBF,GAW8B9V,4BAChC+U,EACAlS,EACAiT,GAEA,MAAMX,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,IACkE,gBAApDsc,kBAAkBF,EAAYlS,IAAU0S,SACnD1S,IAAYiT,IAC4D,gBAA3Db,kBAAkBF,EAAYlS,IAAUoT,eAEtD,UAAU1gB,oDAGZ,MAAM2I,aAAoBgY,2BACxBnB,EACAlS,EACAiT,EACAX,GAYF,aARyBA,EAAYhY,QAClC6Y,uBAAuBF,GACvB9R,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcpBqH,4BAChC+U,EACAlS,EACAsT,EACA1S,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAG+BwE,QAAQiZ,kBAAmBD,GAUzCnW,sBAC1B+U,EACAlS,EACAsT,GAEA,MAAMhB,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,IAAoE,gBAApDsc,kBAAkBF,EAAYlS,IAAU0S,QACtD,UAAUhgB,+BAGZ,MAAM2I,QAAeN,EACnBiF,EACAsS,EAAYhY,QAAQiZ,kBACpBD,GAUF,aANyBhB,EAAYhY,QAAQiZ,kBAAkBD,GAAcnS,KAAK,CAChFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcfqH,+BACnC+U,EACAlS,EACAsT,EACA1S,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAG+BwE,QAAQkZ,uBAAwBF,GAU3CnW,yBAC7B+U,EACAlS,EACAsT,GAEA,MAAMhB,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,IACkE,gBAApDsc,kBAAkBF,EAAYlS,IAAU0S,SACnD1S,IAAYsT,IACmD,gBAAlDlB,kBAAkBF,EAAYlS,IAAUyT,MAEtD,UAAU/gB,gDAGZ,MAAM2I,QAAeN,EACnBiF,EACAsS,EAAYhY,QAAQkZ,uBACpBF,GAYF,aARyBhB,EAAYhY,QAClCkZ,uBAAuBF,GACvBnS,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAanBqH,6BACjC+U,EACAlS,EACAY,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAG+BwE,QAAQoZ,kBAarBvW,uBAC3B+U,EACAlS,GAEA,MAAMsS,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,cAAgB8c,YAAYV,KAAiBlS,EAC3C,UAAUtN,iCAGZ,MAAM2I,QAAeN,EAAYiF,EAASsS,EAAYhY,QAAQoZ,kBAS9D,aANyBpB,EAAYhY,QAAQoZ,mBAAmBvS,KAAK,CACnEnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAetBqH,wBAC5B+U,EACAyB,EACAC,EACAC,EACAjT,GASA,OAAO7F,EACL4Y,GAPA/S,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAKKwE,QAAQwZ,aACpBH,EACAC,EACAC,GAaoB1W,kBACtB+U,EACAyB,EACAC,EACAC,GAEA,MAAMvB,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,cAAgB8c,YAAYV,KAAiByB,EAC3C,UAAUjhB,iCAGZ,MAAMqhB,EAAkBF,GAAW,EAE7BxY,QAAeN,EACnB4Y,EACArB,EAAYhY,QAAQwZ,aACpBH,EACAC,EACAG,GAYF,aARyBzB,EAAYhY,QAClCwZ,aAAaH,EAAUC,EAAaG,GACpC5S,KAAK,CACJnG,KAAM2Y,EACNvS,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAepBqH,4BAChC+U,EACAyB,EACAC,EACAC,EACAjT,GASA,OAAO7F,EACL4Y,GAPA/S,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAKKwE,QAAQ0Z,iBACpBL,EACAC,EACAC,GAawB1W,sBAC1B+U,EACAyB,EACAC,EACAC,GAEA,MAAMvB,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,cAAgB8c,YAAYV,KAAiByB,EAC3C,UAAUjhB,iCAGZ,MAAMqhB,EAAkBF,GAAW,EAE7BxY,QAAeN,EACnB4Y,EACArB,EAAYhY,QAAQ0Z,iBACpBL,EACAC,EACAG,GAYF,aARyBzB,EAAYhY,QAClC0Z,iBAAiBL,EAAUC,EAAaG,GACxC5S,KAAK,CACJnG,KAAM2Y,EACNvS,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAiBxBqH,wBAC5B+U,EACAe,EACAgB,EACAC,EACAC,EACAC,EACAtX,EACAuX,EACAC,EACA1T,GASA,OADK0T,IAAgBA,EAAiB,IAC/BvZ,EACLkY,GAPArS,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAKKwE,QAAQia,YACpBN,EACAC,EACAC,EACAC,EACAtX,EACAuX,EACAC,GAWoBnX,kBACtB+U,EACAlS,EACAiU,EACAC,EACAC,EACAC,EACAtX,EACAuX,EACAC,GAEA,MAAMhC,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,GADKwe,IAAgBA,EAAiB,iBACrBlC,kBAAkBF,EAAYlS,IAAUoT,eACvD,UAAU1gB,wCAEZ,MAAM2I,QAAeN,EACnBiF,EACAsS,EAAYhY,QAAQia,YACpBN,EACAC,EACAC,EACAC,EACAtX,EACAuX,EACAC,GAkBF,aAhByBhC,EAAYhY,QAClCia,YACCN,EACAC,EACAC,EACAC,EACAtX,EACAuX,EACAC,GAEDnT,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcbqH,mCACvC+U,EACAe,EACAuB,EACA5T,GAEA,MAAM0R,EACJ1R,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAEH2e,OACDD,GACHF,eAAgBE,EAAoBF,gBAAkB,KAExD,OAAOvZ,EACLkY,EACAX,EAAYhY,QAAQoa,uBACpBD,GAW+BtX,6BACjC+U,EACAe,EACAuB,GAEA,MAAMlC,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAEP,gBAAiBsc,kBAAkBF,EAAYe,IAAkBG,eAC/D,UAAU1gB,wCAEZ,MAAM+hB,OACDD,GACHF,eAAgBE,EAAoBF,gBAAkB,KAElDjZ,QAAeN,EACnBkY,EACAX,EAAYhY,QAAQoa,uBACpBD,GAUF,aARyBnC,EAAYhY,QAClCoa,uBAAuBD,GACvBtT,KAAK,CACJnG,KAAMiY,EACN7R,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcnBqH,6BACjC+U,EACAe,EACAgB,EACArT,GASA,OAAO7F,EACLkY,GAPArS,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,SAKKwE,QAAQqa,iBACpBV,GAWyB9W,uBAC3B+U,EACAlS,EACAiU,GAEA,MAAM3B,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,gBAAiBsc,kBAAkBF,EAAYlS,IAAUoT,eACvD,UAAU1gB,wCAGZ,MAAM2I,QAAeN,EACnBiF,EACAsS,EAAYhY,QAAQqa,iBACpBV,GAUF,aANyB3B,EAAYhY,QAAQqa,iBAAiBV,GAAe9S,KAAK,CAChFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYzBqH,qBACzB+U,EACAlS,EACAlD,GAOA,OAAO/B,EAAYiF,EALCpK,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGiCwE,QAAQsa,YAAa,IAAK9X,GAS5CK,kBACtB+U,EACAlS,EACAlD,GAEA,MAAMwV,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGDuF,QAAeN,EAAYiF,EAASsS,EAAYhY,QAAQsa,YAAa,IAAK9X,GAMhF,aALyBwV,EAAYhY,QAAQsa,YAAY,IAAK9X,GAAMqE,KAAK,CACvEnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAS5BqH,kBAAC+U,GACvB,MAAMI,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,aADyBwc,EAAYhY,QAAQua,QAAQ,GAAGta,OAS5B4C,wBAAC+U,EAAoBlS,GACjD,MAAMsS,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,aADoBwc,EAAYhY,QAAQwa,eAAe9U,GAASzF,OAQ1C4C,kBAAC+U,GACvB,MAAMI,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAEP,aAAawc,EAAYhY,QAAQya,cAAcxa,OAQrB4C,sBAAC+U,EAAoBlS,GAC/C,MAAMsS,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,aAD8Bwc,EAAYhY,QAAQ0a,gBAAgBhV,GAASzF,OASzD4C,cAAC+U,EAAoB+C,GACvC,MAAM3C,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,aADmBwc,EAAYhY,QAAQ0C,QAAQiY,GAAK1a,OAS9B4C,kBAAC+U,EAAoBgD,GAC3C,MAAM5C,EAAc1c,EAClB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKmf,OAAQI,GACxCvf,KAAKmD,QAGP,aADmBwc,EAAYhY,QAAQ6a,SAASD,GAAI3a,cCtqC3C6a,GAcX5iB,YACE2D,EACAqH,EACA6X,EACAC,EACAxf,QAlBKyf,2BACAC,uBACAH,0BACAC,oCACAnf,iBACAL,mBACA2f,WAcL9iB,KAAKwD,KAAOA,EACZxD,KAAK0iB,cAAgBA,GAAkBK,EAAqBrR,IAC5D1R,KAAK2iB,wBACHA,GAA4BK,EAA+BtR,IAC7D1R,KAAKmD,OAASA,IAAU,IAAIsI,GAAekB,UAAU9B,GAAW,WAChE7K,KAAK8iB,IAAM,IAAI5D,GAAIlf,KAAKwD,MAYAgH,oBACxB6M,EACArJ,EACA1G,EACA+F,EACAY,GASA,OAAO7F,EACLiF,GAPAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAKIwE,QAAQuG,QACnBF,EACAhO,KAAKwD,KAAKqB,MAAMC,MAAMwC,IAYNkD,cAClB6M,EACArJ,EACA1G,EACA+F,GAEA,MAAM4V,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGDuF,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQuG,QACnBF,EACAhO,KAAKwD,KAAKqB,MAAMC,MAAMwC,IAWxB,aAPyB2b,EAAWtb,QACjCuG,QAAQF,EAAShO,KAAKwD,KAAKqB,MAAMC,MAAMwC,IACvCkH,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAc/BqH,iBACrB6M,EACAhK,EACA/F,EACA4b,EACAjV,GASA,OAAO7F,EACLiF,GAPAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAKIwE,QAAQwb,KACnBD,GAAa7V,EACbrN,KAAKwD,KAAKqB,MAAMC,MAAMwC,IAaQkD,4BAChC6M,EACAhK,EACA+V,EACAnV,GAEA,MAAMgV,EACJhV,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAMT,OAHKigB,EAAgB1d,kBAAiB0d,EAAgB1d,gBAAkB3C,GAGjEqF,EACLiF,EACA4V,EAAWtb,QAAQ0b,gBACnBD,EAAgBvd,iBAChB,CACEud,EAAgBtd,iBAChBuH,EACA+V,EAAgBpd,mBAChBod,EAAgB1d,iBAElB,CACE0d,EAAgBnd,kBAChBmd,EAAgBld,kBAChBkd,EAAgBjd,UAChBid,EAAgBhd,UAhBHgd,EAAgBzd,SAAW,EAAI,IA8BtB6E,sBAC1B6M,EACAhK,EACA+V,GAEA,MAAMH,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAEP,eAAiBkf,gBAAgBhL,EAAWhK,GAC1C,UAAUtN,oCAEPqjB,EAAgB1d,kBAAiB0d,EAAgB1d,gBAAkB3C,GAExE,MAAM4C,EAAWyd,EAAgBzd,SAAW,EAAI,EAI1C+C,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQ0b,gBACnBD,EAAgBvd,iBAChB,CACEud,EAAgBtd,iBAChBsd,EAAgBrd,MAChBqd,EAAgBpd,mBAChBod,EAAgB1d,iBAElB,CACE0d,EAAgBnd,kBAChBmd,EAAgBld,kBAChBkd,EAAgBjd,UAChBid,EAAgBhd,UAChBT,IA2BJ,aAtByBsd,EAAWtb,QACjC0b,gBACCD,EAAgBvd,iBAChB,CACEud,EAAgBtd,iBAChBsd,EAAgBrd,MAChBqd,EAAgBpd,mBAChBod,EAAgB1d,iBAElB,CACE0d,EAAgBnd,kBAChBmd,EAAgBld,kBAChBkd,EAAgBjd,UAChBid,EAAgBhd,UAChBT,IAGH6I,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcpBqH,4BAChC6M,EACAhK,EACA/B,EACAgY,EACArV,GAEA,MAAMgV,EACJhV,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAOT,OAJKmgB,EAAgBhM,iBAAgBgM,EAAgBhM,eAAiBvU,GAEjEugB,EAAgB3d,WAAU2d,EAAgB3d,UAAW,GAEnDyC,EACLiF,EACA4V,EAAWtb,QAAQ4b,gBACnBjY,EACAgY,EAAgBpM,UAChBoM,EAAgBnM,WAChBmM,EAAgB3d,SAChB2d,EAAgBhM,gBAYQ9M,sBAC1B6M,EACAhK,EACA/B,EACAgY,GAEA,eAAiBjB,gBAAgBhL,EAAWhK,GAC1C,UAAUtN,oCAGZ,MAAMkjB,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGFmgB,EAAgBhM,iBAAgBgM,EAAgBhM,eAAiBvU,GAEjEugB,EAAgB3d,WAAU2d,EAAgB3d,UAAW,GAI1D,MAAM+C,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQ4b,gBACnBjY,EACAgY,EAAgBpM,UAChBoM,EAAgBnM,WAChBmM,EAAgB3d,SAChB2d,EAAgBhM,gBAiBlB,aAbyB2L,EAAWtb,QACjC4b,gBACCjY,EACAgY,EAAgBpM,UAChBoM,EAAgBnM,WAChBmM,EAAgB3d,SAChB2d,EAAgBhM,gBAEjB9I,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAarCqH,WACf6M,EACAhK,EACA/F,EACA4b,GAEA,MAAMD,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,IAAiE,gBAAjDqgB,iBAAiBnM,EAAWhK,IAAU9I,OACpD,UAAUxE,8BAGZ,MAAM0jB,aAAyBC,OAAOrM,GACtC,GAAI,IAAI/I,EAAQmV,GAAaE,IAAIrc,GAAS,CACxC,MAAMoB,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQwb,KACnBD,GAAa7V,EACbrN,KAAKwD,KAAKqB,MAAMC,MAAMwC,IAWxB,aAPyB2b,EAAWtb,QACjCwb,KAAKD,GAAa7V,EAASrN,KAAKwD,KAAKqB,MAAMC,MAAMwC,IACjDkH,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAIpD,UAAUpD,2CAYcyK,sBAC1B6M,EACAhK,EACA9I,EACA0J,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAG8BwE,QAAQic,UAAWrf,GAWtCiG,gBACpB6M,EACAhK,EACA9I,GAEA,MAAM0e,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,IAAyD,eAAzCkf,gBAAgBhL,EAAWhK,GACzC,UAAUtN,qCAGZ,MAAM2I,QAAeN,EAAYiF,EAAS4V,EAAWtb,QAAQic,UAAWrf,GASxE,aANyB0e,EAAWtb,QAAQic,UAAUrf,GAAQiK,KAAK,CACjEnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcrBqH,yBAC7B6M,EACAhK,EACA9I,EACA0J,GAWA,OAAO7F,EAAYiF,GARjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAK8BwE,QAAQkc,aAActf,GAYtCiG,mBACvB6M,EACAhK,EACA9I,GAEA,MAAM0e,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,IAAyD,eAAzCkf,gBAAgBhL,EAAWhK,GACzC,UAAUtN,qCAGZ,MAAM2I,QAAeN,EAAYiF,EAAS4V,EAAWtb,QAAQkc,aAActf,GAS3E,aANyB0e,EAAWtb,QAAQkc,aAAatf,GAAQiK,KAAK,CACpEnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAchBqH,8BAClC6M,EACAhK,EACAyW,EACA7V,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAG8BwE,QAAQoc,kBAAmBD,GAWtCtZ,wBAC5B6M,EACAhK,EACAyW,GAEA,MAAMb,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,IAAyD,eAAzCkf,gBAAgBhL,EAAWhK,GACzC,UAAUtN,qCAGZ,MAAM2I,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQoc,kBACnBD,GAUF,aANyBb,EAAWtb,QAAQoc,kBAAkBD,GAAgBtV,KAAK,CACjFnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcbqH,iCACrC6M,EACAhK,EACAyW,EACA7V,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAG8BwE,QAAQqc,qBAAsBF,GAWtCtZ,2BAC/B6M,EACAhK,EACAyW,GAEA,MAAMb,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,IAAyD,eAAzCkf,gBAAgBhL,EAAWhK,GACzC,UAAUtN,qCAGZ,MAAM2I,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQqc,qBACnBF,GAYF,aARyBb,EAAWtb,QACjCqc,qBAAqBF,GACrBtV,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAchBqH,gCACpC6M,EACAhK,EACA7I,EACAyJ,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAG8BwE,QAAQsc,oBAAqBzf,GAYtCgG,0BAC9B6M,EACAhK,EACA7I,GAEA,MAAMye,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAED+gB,cAA+BV,iBAAiBnM,EAAWhK,IAC9DyW,eACGvE,GAAc2E,cAAgCC,cAAc9M,GAC5D+M,EAAa7E,cAA0BuD,IAAI7C,YAAYV,KAAiBlS,EACxEgX,EACJ9E,IAAe6E,cAA0BtB,IAAIrD,kBAAkBF,EAAYlS,GAE7E,IAAK6W,IAAqBE,WADFC,SAAAA,EAAgB3E,aAEtC,UAAU3f,4DAGZ,MAAM2I,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQsc,oBACnBzf,GAYF,aARyBye,EAAWtb,QACjCsc,oBAAoBzf,GACpBgK,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAUtBqH,0BAAC6M,GAC/B,MAAM4L,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,aAD+B8f,EAAWtb,QAAQ2c,sBAAsB1c,OAYrD4C,eACnB6M,EACA6L,EACA5b,EACA+F,GAEA,MAAMkX,EAAYvkB,KAAKwD,KAAKqB,MAAMC,MAAMwC,GACxC,YAAYkd,YAAYnN,EAAW6L,EAAWqB,EAAWlX,GAYhC7C,qBACzB6M,EACA6L,EACA5b,EACA+F,EACAY,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAG8BwE,QAAQqH,SAAUkU,EAAW5b,GAW9CkD,kBACtB6M,EACA6L,EACA5b,EACA+F,GAEA,MAAM4V,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAEP,IACE,MAAMuF,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQqH,SACnBkU,EACA5b,GAQF,aALyB2b,EAAWtb,QAAQqH,SAASkU,EAAW5b,GAAQkH,KAAK,CAC3EnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGlD,MAAO8E,GAEP,MADAjH,EAAeJ,2CAA2CqH,EAAEC,eAClDnI,2CAA2CkI,EAAEC,YAc9BsC,uBAC3B6M,EACAhK,EACAoX,EACAC,EACAC,EACA5L,EACA9K,GASA,OAAO7F,EACLiF,GAPAY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAKIwE,QAAQid,WACnBH,EACAC,EACAC,EACA5L,GAamBvO,iBACrB6M,EACAhK,EACAoX,EACAC,EACAC,EACA5L,GAEA,MAAMkK,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAEF4V,IACHA,EAAmB,CACjB8L,wBAAyB9hB,EACzB+hB,sBAAuB/hB,EACvB4X,uBAAwB,MAG5B,IACE,MAAMjS,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQid,WACnBH,EACAC,EACAC,EACA5L,GAUF,aAPyBkK,EAAWtb,QACjCid,WAAWH,EAAUC,EAAcC,EAAc5L,GACjDvK,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GAEP,MADAjH,EAAeJ,wCAAwCqH,EAAEC,eAC/CnI,gCAAgCkI,EAAEC,YAYnBsC,uBAC3B6M,EACAhK,EACA0X,EACAJ,EACA1W,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAG8BwE,QAAQqd,WAAYD,EAAWJ,GAYjDna,iBACrB6M,EACAhK,EACA0X,EACAJ,GAEA,MAAM1B,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAEP,IACE,MAAMuF,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQqd,WACnBD,EACAJ,GAUF,aAPyB1B,EAAWtb,QACjCqd,WAAWD,EAAWJ,GACtBnW,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GAEP,MADAjH,EAAeJ,mDAAmDqH,EAAEC,eAC1DnI,gCAAgCkI,EAAEC,YAYXsC,+BACnC6M,EACAhK,EACA4X,EACA9f,EACA8I,GAMA,OAAO7F,EACLiF,GAJAY,GACA,SAASzK,KAAKG,IAAI8D,SAASzH,KAAK2iB,wBAAyBtL,IAI9C1P,QAAQud,mBACnBD,EACA9f,GAW2BqF,yBAC7B6M,EACAhK,EACA4X,EACA9f,GAEA,MAAM8d,EAAa,SAASzf,KAAKG,IAAI8D,SAASzH,KAAK2iB,wBAAyBtL,GAC5E,IACE,MAAM8N,EAAoBjgB,EAAkBC,GAEtCuD,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQud,mBACnBD,EACAE,GAUF,aAPyBlC,EAAWtb,QACjCud,mBAAmBD,EAAaE,GAChC3W,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GAEP,MADAjH,EAAeJ,sDAAsDqH,EAAEC,eAC7DnI,8CAA8CkI,EAAEC,YAYnBsC,qCACzC6M,EACAhK,EACA4X,EACAlO,EACA9I,GAMA,OAAO7F,EACLiF,GAJAY,GACA,SAASzK,KAAKG,IAAI8D,SAASzH,KAAK2iB,wBAAyBtL,IAI9C1P,QAAQyd,yBACnBH,EACAlO,GAWiCvM,+BACnC6M,EACAhK,EACA4X,EACAlO,GAEA,MAAMkM,EAAa,SAASzf,KAAKG,IAAI8D,SAASzH,KAAK2iB,wBAAyBtL,GAC5E,IACE,MAAM3O,QAAeN,EACnBiF,EACA4V,EAAWtb,QAAQyd,yBACnBH,EACAlO,GAUF,aAPyBkM,EAAWtb,QACjCyd,yBAAyBH,EAAalO,GACtCvI,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,MAAO8E,GAEP,MADAjH,EAAeJ,sDAAsDqH,EAAEC,eAC7DnI,8CAA8CkI,EAAEC,YAWpCsC,oBACxB6M,EACAhK,EACAgY,EACApX,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAG8BwE,QAAQ2d,QAASD,GAWtC7a,cAClB6M,EACAhK,EACAgY,GAEA,eAAiBhD,gBAAgBhL,EAAWhK,GAC1C,UAAUtN,oCAGZ,MAAMkjB,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGDuF,QAAeN,EAAYiF,EAAS4V,EAAWtb,QAAQ2d,QAASD,GAStE,aANyBpC,EAAWtb,QAAQ2d,QAAQD,GAAO7W,KAAK,CAC9DnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYjBqH,6BACjC6M,EACAhK,EACAY,GASA,OAAO7F,EAAYiF,GANjBY,GACAhL,EACE,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,SAG8BwE,QAAQoZ,kBAUpBvW,uBAC3B6M,EACAhK,GAEA,cAAgByV,IAAI7C,uBAAuBkE,cAAc9M,MAAiBhK,EACxE,UAAUtN,MAAM,2BAElB,MAAMkjB,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGDuF,QAAeN,EAAYiF,EAAS4V,EAAWtb,QAAQoZ,kBAS7D,aANyBkC,EAAWtb,QAAQoZ,mBAAmBvS,KAAK,CAClEnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAWvBqH,uBAAC6M,EAAmBhK,GAC/C,MAAM4V,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,aADoB8f,EAAWtb,QAAQ4d,YAAYlY,GAASzF,OAQ3C4C,aAAC6M,GAClB,MAAM4L,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAED4B,QAAYke,EAAWtb,QAAQ5C,MAAM6C,OAC3C,YAAYpE,KAAKqB,MAAM8M,QAAQ5M,GAOTyF,kBAAC6M,GACvB,MAAM4L,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,aADuB8f,EAAWtb,QAAQD,WAAWE,OAQ7B4C,oBAAC6M,GACzB,MAAM4L,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,aADyB8f,EAAWtb,QAAQ6d,mBAAmB5d,OASrC4C,sBAAC6M,EAAmBhK,GAC9C,MAAM4V,EAAahgB,EACjB,SAASO,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAerL,GAC/CrX,KAAKmD,QAGP,aAD8B8f,EAAWtb,QAAQ0a,gBAAgBhV,GAASzF,OAUxD4C,cAACoO,EAA0BvL,GAC7C,MAAM4V,EAAa,SAASzf,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAe9J,EAAkB,CAClFvQ,KAAMgF,IAEF6B,QAAgB+T,EAAWtb,QAAQwH,UAAU9B,GAASzF,OAC5D,YAAYpE,KAAKqB,MAAM8M,QAAQzC,GAYQ1E,mCACvCoO,EACA6M,EACAC,EACAC,EACAtY,GAMA,OAAOjF,EACLiF,EAJiB,SAAS7J,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAe9J,EAAkB,CAClFvQ,KAAMgF,IAIK1F,QAAQie,uBACnBH,EACAC,EACAC,GAc+Bnb,6BACjCoO,EACA6M,EACAC,EACAC,EACAtY,GAEA,MAAM4V,EAAa,SAASzf,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAe9J,EAAkB,CAClFvQ,KAAMgF,IAGR,UAD6B4V,EAAWtb,QAAQke,yBAAyBje,QAAQ,KAC3DyF,EACpB,UAAUtN,yDAEZ,MAAM2I,aAAoBod,6BACxBlN,EACA6M,EACAC,EACAC,EACAtY,SAEI4V,EAAWtb,QACdie,uBACCH,EACAC,EACAC,GAEDnX,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYnBqH,6BACjCoO,EACAvL,GAEA,MAAM4V,EAAa,SAASzf,KAAKG,IAAI8D,SAASzH,KAAK0iB,cAAe9J,EAAkB,CAClFvQ,KAAMgF,IAGF0Y,QAA4B9C,EAAWtb,QAAQke,yBAAyBje,OAM9E,MALqB,CACnB6d,wBAAyBM,EAAoB,GAC7CL,sBAAuBK,EAAoB,GAC3CJ,uBAAwBI,EAAoB,WC50CrCC,GAaXnmB,YACEuf,EACA5b,EACAqH,EACAwU,EACAlc,QAjBKic,8BACAC,0BACA7b,iBACAL,mBACA8iB,kBAeLjmB,KAAKof,kBAAoBA,EACzBpf,KAAKqf,cAAgBA,GAAkB6G,EAAqBxU,IAC5D1R,KAAKwD,KAAOA,EACZxD,KAAKmD,OAASA,IAAU,IAAIsI,GAAekB,UAAU9B,GAAW,WAChE7K,KAAKimB,WAAahjB,EAChB,SAASO,KAAKG,IAAI8D,SAASzH,KAAKqf,cAAerf,KAAKof,mBACpDpf,KAAKmD,QAUmBqH,sBAAC6C,EAAiB8Y,GAC5C,OAAO/d,EACLiF,EACArN,KAAKimB,WAAWte,QAAQye,qBACxBD,EAAQhkB,KACRgkB,EAAQ/jB,OACR+jB,EAAQ/hB,cACRrB,EACAA,EACAojB,EAAQ3D,SACR2D,EAAQE,aACRF,EAAQpgB,OAUUyE,gBAAC6C,EAAiB8Y,GAGtC,GAFKA,EAAQ/hB,gBAAe+hB,EAAQ/hB,cAAgB,IAE/C+hB,EAAQhkB,OAASgkB,EAAQ/jB,OAAQ,CACpC,MAAMD,KAAEA,EAAFC,OAAQA,GAAWnB,IACzBklB,EAAQhkB,KAAOA,EACfgkB,EAAQ/jB,OAASA,EAEnB,GAAI+jB,EAAQ/hB,yBAA4BkiB,6BACtC,UAAUvmB,qCAGZ,GAA8B,IAA1BomB,EAAQ/hB,cACV,UAAUrE,uCAEZ,IAAoE,gBAApDwmB,eAAeJ,EAAQ/hB,gBAAgBgX,SACrD,UAAUrb,gCAEZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQye,qBACxBD,EAAQhkB,KACRgkB,EAAQ/jB,OACR+jB,EAAQ/hB,cACRrB,EACAA,EACAojB,EAAQ3D,SACR2D,EAAQE,aACRF,EAAQpgB,OAIJkJ,aAAwBgX,WAAWte,QACtCye,qBACCD,EAAQhkB,KACRgkB,EAAQ/jB,OACR+jB,EAAQ/hB,cACRrB,EACAA,EACAojB,EAAQ3D,SACR2D,EAAQE,aACRF,EAAQpgB,OAETyI,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAGpD,IAAI4K,EAAe,KACnB,IACEA,EAAekB,EAAW2Q,OAAO4G,WAAW1G,aAAa,GACzD,MAAO7X,GACPjH,EAAeJ,6CAA6CqH,EAAEC,WAEhE,OAAO6F,EAMsBvD,2BAE7B,kBAD8Byb,WAAWte,QAAQ8e,qBAAqB7e,OAOvC4C,6BAE/B,kBAD8Byb,WAAWte,QAAQ+e,uBAAuB9e,OAOrD4C,iBAEnB,kBAD8Byb,WAAWte,QAAQ5B,QAAQ6B,OAOpB4C,mCAErC,kBADyByb,WAAWte,QAAQ2e,6BAA6B1e,OAOlC4C,qCAEvC,kBADyByb,WAAWte,QAAQgf,0BAA0B/e,OAQ7C4C,qBAACb,GAC1B,GAAIA,aAAoB2c,6BACtB,UAAUvmB,qCAGZ,GAAc,IAAV4J,EACF,UAAU5J,uCAGZ,kBAD4BkmB,WAAWte,QAAQ4e,eAAe5c,GAAO/B,OAQ1C4C,uBAACb,GAE5B,kBAD4Bsc,WAAWte,QAAQif,iBAAiBjd,GAAO/B,OAQ9C4C,qBAACuN,GAE1B,kBAD8BkO,WAAWte,QAAQkf,UAAU9O,GAAWnQ,OAQnD4C,eAAC+U,GAEpB,kBADkC0G,WAAWte,QAAQmf,WAAWvH,GAAY3X,OAU7C4C,2BAC/B6C,EACA0R,GAEA,OAAO3W,EACLiF,EACArN,KAAKimB,WAAWte,QAAQof,oBACxBhI,GAUuBvU,qBACzB6C,EACA0R,GAEA,cAAgBf,aAAgB3Q,EAC9B,UAAUtN,qCAEZ,GAAIgf,IAAoBhc,EACtB,UAAUhD,yCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQof,oBACxBhI,GAYF,kBAR8BkH,WAAWte,QACtCof,oBAAoBhI,GACpBvQ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYjBqH,+BACnC6C,EACAjJ,GAEA,OAAOgE,EACLiF,EACArN,KAAKimB,WAAWte,QAAQqf,wBACxB5iB,GAU2BoG,yBAC7B6C,EACAjJ,GAEA,cAAgB4Z,aAAgB3Q,EAC9B,UAAUtN,qCAEZ,GAAIqE,aAA4BkiB,6BAC9B,UAAUvmB,qCAGZ,GAAsB,IAAlBqE,EACF,UAAUrE,uCAEZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQqf,wBACxB5iB,GAYF,kBAR8B6hB,WAAWte,QACtCqf,wBAAwB5iB,GACxBoK,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYdqH,kCACtC6C,EACAjJ,GAEA,OAAOgE,EACLiF,EACArN,KAAKimB,WAAWte,QAAQsf,2BACxB7iB,GAU8BoG,4BAChC6C,EACAjJ,GAEA,cAAgB4Z,aAAgB3Q,EAC9B,UAAUtN,qCAEZ,GAAIqE,aAA4BkiB,6BAC9B,UAAUvmB,qCAGZ,GAAsB,IAAlBqE,EACF,UAAUrE,uCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQsf,2BACxB7iB,GAYF,kBAR8B6hB,WAAWte,QACtCsf,2BAA2B7iB,GAC3BoK,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYnBqH,6BACjC6C,EACA0R,GAEA,OAAO3W,EAAYiF,EAASrN,KAAKimB,WAAWte,QAAQuf,iBAAkBnI,GAS3CvU,uBAC3B6C,EACA0R,GAEA,cAAgBf,aAAgB3Q,EAC9B,UAAUtN,qCAEZ,GAAIgf,IAAoBhc,EACtB,UAAUhD,yCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQuf,iBACxBnI,GAYF,kBAR8BkH,WAAWte,QACtCuf,iBAAiBnI,GACjBvQ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYfqH,iCACrC6C,EACAjJ,GAEA,OAAOgE,EACLiF,EACArN,KAAKimB,WAAWte,QAAQwf,qBACxB/iB,GAU6BoG,2BAC/B6C,EACAjJ,GAEA,cAAgB4Z,aAAgB3Q,EAC9B,UAAUtN,qCAEZ,GAAIqE,aAA4BgjB,+BAC9B,UAAUrnB,qCAGZ,GAAsB,IAAlBqE,EACF,UAAUrE,uCAEZ,IAA8D,gBAA9C6mB,iBAAiBxiB,IAAgBgX,SAC/C,UAAUrb,sCAEZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQwf,qBACxB/iB,GAYF,kBAR8B6hB,WAAWte,QACtCwf,qBAAqB/iB,GACrBoK,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAYZqH,oCACxC6C,EACAjJ,GAEA,OAAOgE,EACLiF,EACArN,KAAKimB,WAAWte,QAAQ0f,wBACxBjjB,GAUgCoG,8BAClC6C,EACAjJ,GAEA,cAAgB4Z,aAAgB3Q,EAC9B,UAAUtN,qCAEZ,GAAIqE,aAA4BgjB,+BAC9B,UAAUrnB,qCAGZ,GAAsB,IAAlBqE,EACF,UAAUrE,uCAEZ,IAA8D,gBAA9C6mB,iBAAiBxiB,IAAgBgX,SAC/C,UAAUrb,oCAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQ0f,wBACxBjjB,GAYF,kBAR8B6hB,WAAWte,QACtC0f,wBAAwBjjB,GACxBoK,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAWZqH,oCACxC6C,EACAia,GAEA,OAAOlf,EAAYiF,EAASrN,KAAKimB,WAAWte,QAAQ4f,wBAAyBD,GAe3C9c,8BAClC6C,EACAia,GAEA,GAAIA,EAAO5lB,OAAS,GAClB,UAAU3B,yBAGZ,MAAM2I,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQ4f,wBACxBD,GAYF,kBAR8BrB,WAAWte,QACtC4f,wBAAwBD,GACxB9Y,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcjBqH,+BACnC6C,EACAma,EACArjB,GAEA,MAAMsjB,EAAgBvjB,EAAqBC,GAC3C,OAAOiE,EACLiF,EACArN,KAAKimB,WAAWte,QAAQ+f,mBACxBF,EACAC,GAa2Bjd,yBAC7B6C,EACAma,EACArjB,GAEA,MAAMsjB,EAAgBvjB,EAAqBC,GAErCuE,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQ+f,mBACxBF,EACAC,GAYF,kBAR8BxB,WAAWte,QACtC+f,mBAAmBF,EAAeC,GAClCjZ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAcbqH,mCACvC6C,EACAma,EACArjB,EACAmC,GAEA,MAAMmhB,EAAgBvjB,EAAqBC,GACrCwjB,QAAiBthB,EAAsBrG,KAAKwD,KAAM8C,GACxD,OAAO8B,EACLiF,EACArN,KAAKimB,WAAWte,QAAQigB,2BACxBJ,EACAC,EACAE,GAc+Bnd,6BACjC6C,EACAma,EACArjB,EACAmC,GAEA,MAAMmhB,EAAgBvjB,EAAqBC,GACrCwjB,QAAiBthB,EAAsBrG,KAAKwD,KAAM8C,GAElDoC,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQigB,2BACxBJ,EACAC,EACAE,GAYF,kBAR8B1B,WAAWte,QACtCigB,2BAA2BJ,EAAeC,EAAeE,GACzDnZ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAaRqH,wCAC5C6C,EACAma,EACArjB,EACAgB,GAEA,MAAMsiB,EAAgBvjB,EAAqBC,GACrC0jB,QAAkBpiB,EAAqBN,GAC7C,OAAOiD,EACLiF,EACArN,KAAKimB,WAAWte,QAAQmgB,gCACxBN,EACAC,EACAI,GAcoCrd,kCACtC6C,EACAma,EACArjB,EACAgB,GAEA,MAAMsiB,EAAgBvjB,EAAqBC,GACrC0jB,EAAYpiB,EAAqBN,GAEjCuD,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQmgB,gCACxBN,EACAC,EACAI,GAYF,kBAR8B5B,WAAWte,QACtCmgB,gCAAgCN,EAAeC,EAAeI,GAC9DrZ,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,UAaRqH,wCAC5C6C,EACAma,EACArjB,EACAmf,GAEA,MAAMmE,EAAgBvjB,EAAqBC,GAC3C,OAAOiE,EACLiF,EACArN,KAAKimB,WAAWte,QAAQogB,gCACxBP,EACAC,EACAnE,GAcoC9Y,kCACtC6C,EACAma,EACArjB,EACAmf,GAEA,MAAMmE,EAAgBvjB,EAAqBC,GAE3Cmf,EAAgBnM,WAAavS,EAAKC,MAAMC,MAAMwe,EAAgBnM,YAC9DmM,EAAgBpM,UAAYtS,EAAKC,MAAMC,MAAMwe,EAAgBpM,WAE7D,MAAMxO,QAAeN,EACnBiF,EACArN,KAAKimB,WAAWte,QAAQogB,gCACxBP,EACAC,EACAnE,GAYF,kBAR8B2C,WAAWte,QACtCogB,gCAAgCP,EAAeC,EAAenE,GAC9D9U,KAAK,CACJnG,KAAMgF,EACNoB,IAAK/F,EAAS,EACdgG,eAAgBnL,EAAgBvD,KAAKwD,KAAMxD,KAAKmD,iBCn2B3C6kB,sBAKJjd,oBAMAkd,4BAMAnd,6BAMAE,wBAMAkd,yBAMA/c,8BAMAiB,iCAMA+b,8BAMAC,0BAMA1hB,gCAMA2hB,2BAMAC,oBAMAjd,qCAMAkd,wCAMAjd,6BAMAkd,yBAMAlc,qCAMAD,+BAMAd,uBAKAkd,oBAMAC,wBAMAC,gCAMAC,sBAEAC,sBAMPje,oBAMAC,oBAMAI,wBAMAC,wBAMAE,6BAMAhI,oCAMAC,0CAMAC,sCAMAO,+BChMWilB,GAAWC,YACSA,EAAQ,GAAIC,GAC3C,MAAMnY,MAAEA,EAAFoY,OAASA,GAKjB,SACEF,EACAG,EACAC,GAEA,GAAqB,iBAAVJ,EAGT,MAFA/nB,EAAeV,MAAM,qBACrBU,EAAeV,MAAMyoB,OACXhpB,gEAAgEgpB,GAE5E,MAAM/e,EAAQ+e,EAAM/e,MAfwB,yBAgB5C,OAAKA,EAIE,CAAE6G,OAAO,EAAMoY,OAAQjf,EAAM,KAHlChJ,EAAeN,wDACR,CAAEmQ,OAAO,EAAOoY,OAAQF,IAlBPK,CAAWL,GACrC,OAAQC,GAAcnY,EAAQ,KAAO,IAAMoY,EAHKI,CAAiBN,GAAO,SCwB7DO,GAKO9e,mBAACQ,GACjB,IACE,MAAMue,QAAkBlf,EAAQW,GAChC,aAAaue,EAAUhZ,OACvB,MAAOtI,GAEP,OADAjH,EAAeJ,MAAM,wCAAyCqH,SAKlEuhB,eACEC,EACAC,GAEA,OAAKD,EACEA,EAAkB3c,KAAMa,GAAMA,EAAE+b,cAAgBA,QAQzBlf,0BAACmf,EAA0BJ,GACzD,MAAMK,EAAsC,GAC5C,IAAK,MAAMC,KAAKN,EAAUK,iBAMxBA,EAAiBE,KALiB,CAChCJ,YAAaG,EACb5gB,OAAQsgB,EAAUK,iBAAiBC,GAAG,GACtCE,QAASJ,EAAmBJ,EAAUK,iBAAiBC,GAAG,KAI9D,OAAOD,EAWYpf,eACnBQ,EACAgf,EACA3Z,EACA4Z,EACAL,GAEKK,IACHA,aAA+BC,aAAalf,IAEzC4e,IACHA,aAA8BO,oBAAoBnf,EAAaif,IAEjE,MAAM3Z,EAAOtQ,KAAKwpB,eAAeI,EAAkB,SAC/C5pB,KAAKwpB,eAAeI,EAAkB,SAASG,QAC/C,KACJ,IAAKzZ,EAAM,YACX,IACE,MAAM1G,QAAiBb,EAAMuH,kBAAuB0Z,IAAmB,CACrE/gB,OAAQ,MACRa,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAEV,aAAczG,EAAS2G,QAAQ6Z,MAAMnmB,WACrC,MAAOgE,GAEP,MADAjH,EAAeJ,MAAMqH,OACXlI,MAAM,wBAIYyK,0BAC9BhH,EACA6mB,EACAniB,EACAoiB,GAEA,MAAMC,EAAkB/mB,EAAKqB,MAAM2lB,aAAa,CAC9CC,EAAG,QACH7c,EAAGpK,EAAKqB,MAAM6lB,UAAUxiB,KAI1B,OADE1E,GAAQA,EAAKmnB,iBAAoBnnB,EAAKmnB,gBAAwBC,iBAEjDpnB,EAAKG,IAAIknB,SAAStd,KAAKgd,EAAiBF,EAAWC,SAChD9mB,EAAKG,IAAI4J,KAAKgd,EAAiBF,GAS/B7f,cAClBL,EACAa,EACAqF,GAEA,MAAM4Z,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEI3Z,EAAOtQ,KAAKwpB,eAAeI,EAAkB,WAC/C5pB,KAAKwpB,eAAeI,EAAkB,WAAWG,QACjD,KACJ,IAAKzZ,EAAM,YACX,IACE,MAAM1G,QAAiBb,EAAMuH,EAAM,CACjCrH,OAAQ,OACRwB,KAAMsG,KAAKC,UAAU7G,GACrBL,QAAS,CACP,eAAgB,4BAElBuG,OAAQA,IAEV,aAAazG,EAASV,OACtB,MAAOjB,GAEP,MADAjH,EAAeJ,MAAMqH,OACXlI,MAAM,wBAWMyK,oBACxB4F,EACA0a,EACA9f,EACAqF,GAEA,MAAM4Z,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEI9pB,EAAO,CAAEiQ,IAAKA,EAAK0a,UAAWA,GAC9BC,EAAoB,GACpBza,EAAOtQ,KAAKwpB,eAAeI,EAAkB,YAC/C5pB,KAAKwpB,eAAeI,EAAkB,YAAYG,QAClD,KACJ,IAAKzZ,EAAM,YACX,IACE,MAAM1G,QAAiBb,EAAMuH,EAAM,CACjCrH,OAAQ,OACRwB,KAAMsG,KAAKC,UAAU7Q,GACrB2J,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAEJ2a,QAA4BphB,EAAS2G,OAC3C,IAAK,MAAMzH,KAAUkiB,EACnBD,EAAMjB,KAAKhhB,GAEb,OAAOiiB,EACP,MAAO9iB,GACP,aAUqBuC,mBACvB5B,EACAoC,EACAqF,GAEA,MAAM4Z,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEI9pB,EAAO,CAAEyI,IAAKA,EAAKlG,KAAM,OACzBqoB,EAAoB,GACpBza,EAAOtQ,KAAKwpB,eAAeI,EAAkB,YAC/C5pB,KAAKwpB,eAAeI,EAAkB,YAAYG,QAClD,KACJ,IAAKzZ,EAAM,YACX,IACE,MAAM1G,QAAiBb,EAAMuH,EAAM,CACjCrH,OAAQ,OACRwB,KAAMsG,KAAKC,UAAU7Q,GACrB2J,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAEJ2a,QAA4BphB,EAAS2G,OAC3C,IAAK,MAAMzH,KAAUkiB,EACnBD,EAAMjB,KAAKhhB,GAEb,OAAOiiB,EACP,MAAO9iB,GACP,aAO+BuC,6BACjCQ,EACAqF,SAEA,MAAM4Z,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEI3Z,WAAOtQ,KAAKwpB,eAAeI,EAAkB,+BAAtCqB,EAA8DlB,QAC3E,IAAKzZ,EAAM,YACX,IACE,MAAM1G,QAAiBb,EAAMuH,EAAM,CACjCrH,OAAQ,MACRa,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAGV,aADyCzG,EAAS2G,OAElD,MAAOtI,GAEP,OADAjH,EAAeJ,MAAMqH,EAAEC,eAeJsC,iBACrB4F,EACA0a,EACAI,EACAlB,EACAhf,EACAqF,EACA8a,EACAC,EACAC,GAEA,MAAMpB,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEF,IAAIqB,EAAgBtrB,KAAKwpB,eAAeI,EAAkB,cACtD5pB,KAAKwpB,eAAeI,EAAkB,cAAcG,QACpD,KAEJ,IAAKuB,EAAe,YACpBA,kBAAgClb,IAChCkb,iBAA+BR,IAC/BQ,iBAA+BJ,IAC/BI,uBAAqCtB,IACjCmB,IACFG,GAAiB,aAAeC,UAAUxa,KAAKC,UAAUma,KACvDC,IAAYE,GAAiB,gBAAkBC,UAAUH,IACzDC,IAAYC,GAAiB,eAAiBD,GAClD,IACE,MAAMzhB,QAAiBb,EAAMuiB,EAAe,CAC1CriB,OAAQ,MACRa,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAGV,aAD0CzG,EAAS2G,OAEnD,MAAOtI,GAEP,MADAjH,EAAeJ,MAAMqH,OACXlI,MAAM,0CAcUyK,wBAC5BghB,EACAC,EACAL,EACAC,EACArgB,EACAqf,EACAha,GAEA,MAAM4Z,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEIyB,EAAe,CACnBC,SAAUH,EACVC,UAAWA,EACXG,QAAS,CACPpf,IAAK4e,EACLC,WAAYA,GAEdrB,gBAAiBK,GAEbiB,EAAgBtrB,KAAKwpB,eAAeI,EAAkB,qBACxD5pB,KAAKwpB,eAAeI,EAAkB,qBAAqBG,QAC3D,KACJ,IAAKuB,EAAe,YACpB,IACE,MAAM1hB,QAAiBb,EAAMuiB,EAAe,CAC1CriB,OAAQ,OACRwB,KAAMsG,KAAKC,UAAU0a,GACrB5hB,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAGV,aADsBzG,EAAS2G,OAE/B,MAAOtI,GAEP,MADAjH,EAAeJ,MAAMqH,OACXlI,MAAM,qCAcOyK,qBACzB4F,EACAia,EACAS,EACAI,EACAW,EACA7gB,EACAxH,EACA2nB,GAEA,MAAMlB,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEI6B,EAAc9rB,KAAKwpB,eAAeI,EAAkB,YACtD5pB,KAAKwpB,eAAeI,EAAkB,YAAYG,QAClD,KACJ,IAAK+B,EAAa,YAClB,MAAM1B,EAAQ2B,KAAKC,MAEnB,IAAIC,EAAaH,EAUjB,OATAG,iBAA4Bf,IAC5Be,kBAA6B7b,IAC7B6b,oBAA+BJ,IAC/BI,iBAA4BnB,IAC5BmB,uBAAkC5B,IAClC4B,aAAwB7B,IACxB6B,4BAR6BC,oBAAoB1oB,EAAM6mB,EAAWja,EAAMga,KASpEe,IACFc,GAAc,aAAeV,UAAUxa,KAAKC,UAAUma,KACjDc,EAcgBzhB,mBACvBQ,EACAxH,EACAwmB,EACAoB,EACAe,EACAV,EACApb,EACA+b,EACAnD,GAEA,MAAMgB,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEIoC,EAAkBrsB,KAAKwpB,eAAeI,EAAkB,gBAC1D5pB,KAAKwpB,eAAeI,EAAkB,gBAAgBG,QACtD,KAEEK,EAAQ2B,KAAKC,MACnB,IAAIM,EAAmBtC,EACvBsC,GAAoBH,EAAQI,WAC5BD,GAAoBlC,EACpB,MAAMoC,aAAuBN,oBAC3B1oB,EACAwmB,EACAsC,GAEI/hB,EAAUkiB,SAShB,GARAliB,EAAQyf,gBAAkBA,EAC1Bzf,EAAQiiB,UAAYA,EACpBjiB,EAAQ6f,MAAQA,EAChB7f,EAAQmiB,YAActB,EACtB7gB,EAAQ4hB,QAAUA,EAClB5hB,EAAQkhB,UAAYA,EAChBlhB,EAAQ6hB,qBAAoB7hB,EAAQ6hB,mBAAqBA,GACzDnD,IAAQ1e,EAAQ0e,OAASA,IACxBoD,EAAiB,YACtB,IACE,MAAMziB,QAAiBb,EAAMsjB,EAAiB,CAC5CpjB,OAAQ,OACRwB,KAAMsG,KAAKC,UAAUzG,GACrBT,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAGV,aAAIzG,GAAAA,EAAUZ,SACSY,EAAS2G,QAGhCvP,EAAeJ,MAAM,yBAA0BgJ,EAAS4G,OAAQ5G,EAAS+iB,YACzE3rB,EAAeJ,MAAM,eAAgB2J,SAErC,MAAOtC,GAIP,OAHAjH,EAAeJ,MAAM,yBACrBI,EAAeJ,MAAMqH,GACrBjH,EAAeJ,MAAM,eAAgB2J,SAcjBC,kBACtB4F,EACA4Z,EACA4C,EACA5hB,EACAxH,EACA6M,GAEA,MAAM4Z,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEI4C,EAAiB7sB,KAAKwpB,eAAeI,EAAkB,eACzD5pB,KAAKwpB,eAAeI,EAAkB,eAAeG,QACrD,KAEEK,aAAmB0C,SACvB9hB,EACAgf,EACA3Z,EACA4Z,EACAL,GAGF,IAAI0C,EAAmBtC,EACvBsC,GAAoBM,GAAS,GAC7BN,GAAqBlc,MAAU0Y,GAAQ1Y,MAAW,GAClDkc,GAAoBlC,EACpB,MAAMoC,aAAuBN,oBAC3B1oB,EACAwmB,EACAsC,GAEI/hB,EAAUkiB,SAMhB,GALAliB,EAAQiiB,UAAYA,EACpBjiB,EAAQgiB,WAAazD,GAAQ1Y,GAC7B7F,EAAQyf,gBAAkBA,EACtB4C,IAAOriB,EAAQqiB,MAAQA,IAEtBC,EAAgB,YACrB,IACE,MAAMjjB,QAAiBb,EAAM8jB,EAAgB,CAC3C5jB,OAAQ,MACRwB,KAAMsG,KAAKC,UAAUzG,GACrBT,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAGV,aAAIzG,GAAAA,EAAUZ,SACSY,EAAS2G,QAGhCvP,EAAeJ,MAAM,uBAAwBgJ,EAAS4G,OAAQ5G,EAAS+iB,YACvE3rB,EAAeJ,MAAM,eAAgB2J,SAErC,MAAOtC,GAIP,OAHAjH,EAAeJ,MAAM,wBACrBI,EAAeJ,MAAMqH,GACrBjH,EAAeJ,MAAM,eAAgB2J,SAafC,oBACxBQ,EACAgf,EACA4C,EACAxc,EACAC,GAEA,MAAM4Z,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEI8C,EAAmB/sB,KAAKwpB,eAAeI,EAAkB,iBAC3D5pB,KAAKwpB,eAAeI,EAAkB,iBAAiBG,QACvD,KAEJ,IAAInhB,sBAA0BohB,IAI9B,GAHAphB,GAAQwH,kBAAsB0Y,GAAQ1Y,MAAW,GACjDxH,GAAQgkB,aAAmBA,KAAY,IAElCG,EAAkB,YACvB,IACE,MAAMnjB,QAAiBb,EAAMgkB,EAAmBnkB,EAAK,CACnDK,OAAQ,MACRa,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAEV,aAAIzG,GAAAA,EAAUZ,SACSY,EAAS2G,QAGhCvP,EAAeJ,MACb,6BACAgJ,EAAS4G,OACT5G,EAAS+iB,kBAGX,MAAO1kB,GAGP,OAFAjH,EAAeJ,MAAM,6BACrBI,EAAeJ,MAAMqH,SAaOuC,0BAC9BQ,EACAxH,EACAwmB,EACA4C,EACAjjB,GAEA,MAAMsgB,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEI+C,EAAmBhtB,KAAKwpB,eAAeI,EAAkB,iBAC3D5pB,KAAKwpB,eAAeI,EAAkB,iBAAiBG,QACvD,KAEEK,EAAQ2B,KAAKC,MACnB,IAAIM,EAAmBtC,EACvBsC,GAAoBM,EACpBN,GAAoB3iB,EAAM1F,WAC1BqoB,GAAoBlC,EACpB,MAAMoC,aAAuBN,oBAC3B1oB,EACAwmB,EACAsC,GAEF,IAAKU,EAAkB,YACvB,IAAIC,EAAYD,EAMhB,OALAC,uBAAiCjD,IACjCiD,aAAuBL,IACvBK,aAAuBtjB,EAAM1F,aAC7BgpB,aAAuB7C,IACvB6C,GAAcT,iBAA2BA,KAAgB,GAClDS,EAYiBziB,oBACxB4F,EACA4Z,EACA4C,EACA5hB,EACAxH,EACA6M,GAEA,MAAM4Z,aAA+BC,aAAalf,GAC5C4e,aAA8BO,oBAClCnf,EACAif,GAEIiD,EAAmBltB,KAAKwpB,eAAeI,EAAkB,iBAC3D5pB,KAAKwpB,eAAeI,EAAkB,iBAAiBG,QACvD,KAEEK,aAAmB0C,SACvB9hB,EACAgf,EACA3Z,EACA4Z,EACAL,GAGF,IAAI0C,EAAmBtC,EACvBsC,GAAoBM,GAAS,GAC7BN,GAAqBlc,MAAU0Y,GAAQ1Y,MAAW,GAClDkc,GAAoBlC,EACpB,MAAMoC,aAAuBN,oBAC3B1oB,EACAwmB,EACAsC,GAEI/hB,EAAUkiB,SAMhB,GALAliB,EAAQgiB,WAAazD,GAAQ1Y,GAC7B7F,EAAQyf,gBAAkBA,EAC1Bzf,EAAQqiB,MAAQA,EACZJ,IAAWjiB,EAAQiiB,UAAYA,IAE9BU,EAAkB,YACvB,IACE,MAAMtjB,QAAiBb,EAAMmkB,EAAkB,CAC7CjkB,OAAQ,SACRwB,KAAMsG,KAAKC,UAAUzG,GACrBT,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAGV,aAAIzG,GAAAA,EAAUZ,SACSY,EAAS2G,QAGhCvP,EAAeJ,MACb,6BACAgJ,EAAS4G,OACT5G,EAAS+iB,YAEX3rB,EAAeJ,MAAM,eAAgB2J,SAErC,MAAOtC,GAIP,OAHAjH,EAAeJ,MAAM,8BACrBI,EAAeJ,MAAMqH,GACrBjH,EAAeJ,MAAM,eAAgB2J,SAUbC,sBAAC5B,EAAayH,GACxC,IACE,MAAMzG,QAAiBb,EAAMH,EAAK,CAChCK,OAAQ,MACRa,QAAS,CACP,eAAgB,oBAElBuG,OAAQA,IAEV,SAAIzG,GAAAA,EAAUZ,GAAI,CAChB,MAAMmkB,QAAevjB,EAAS2G,OAC9B,GAAI4c,GAAUA,EAAOlF,gBAAiB,SAExC,SACA,MAAOrnB,GAEP,OADAI,EAAeJ,oCAAoCA,EAAMsH,gBAMlDklB,MAAAA,GAAmB,IAAI9D"}
|