diff --git a/package.json b/package.json index 6516e5a..9f811aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dapphero/dapphero-dom", - "version": "0.4.1", + "version": "0.4.2", "license": "MIT", "source": "src/index.ts", "main": "dist/dapphero-dom.js", diff --git a/src/features/customContract/index.ts b/src/features/customContract/index.ts index 9f54ecb..667f5ce 100644 --- a/src/features/customContract/index.ts +++ b/src/features/customContract/index.ts @@ -1,5 +1,5 @@ // Constants -import { DATA_FEATURE, DATA_PROPERTY, DATA_MODIFIER } from '../../lib/constants'; +import { DATA_FEATURE, DATA_PROPERTY, DATA_MODIFIER, ETHER_UNITS } from '../../lib/constants'; export const customContract = { id: 'customContract', @@ -85,13 +85,13 @@ export const customContract = { id: 'displayUnits', defaultValue: 'ether', attribute: `${DATA_MODIFIER}-display-units`, - validator: (value) => ['wei', 'ether'].includes(value), + validator: (value) => ETHER_UNITS.includes(value), }, { id: 'contractUnits', defaultValue: 'wei', attribute: `${DATA_MODIFIER}-contract-units`, - validator: (value) => ['wei', 'ether'].includes(value), + validator: (value) => ETHER_UNITS.includes(value), }, { id: 'displayDecimals', diff --git a/src/features/customContract/parser.ts b/src/features/customContract/parser.ts index ae5b4ea..2487b4a 100644 --- a/src/features/customContract/parser.ts +++ b/src/features/customContract/parser.ts @@ -47,13 +47,38 @@ export const customContractParser = ( // Check if method name exists in ABI const methodId = methodIdKey.value; const methodName = methodNameKey.value; - const contractMethod = contractABI.find((method) => methodName === method.name); + const contractMethods = contractABI.filter((method) => methodName === method.name); + // If no contract methods are found, return error + if (contractMethods.length === 0) { + return console.error(`(DH-DOM) | Method name "${methodName}" does not exists on the contract ABI`); + } + + // placeholder for the contract method we will be working with. + let contractMethod = contractABI.find((method) => methodName === method.name); + + //If we are over loaded, check how many inputs this method has. + if (contractMethods.length > 1) { + //Get all the inputs for the Method. + const contractInputs = Array.from( + document.querySelectorAll(createAttributeSelector(`data-dh-property-method-id`, methodId)), + ).filter((element) => !(element.getAttribute('id') || '').includes('dh')).filter((element) => element.nodeName === 'INPUT') + + //Get the method that has the number of imputs which matches + contractMethod = contractMethods.filter((method) => method.inputs.length === contractInputs.length)[0] + + //If the number of inputs does not match either function, then it's an error. + } + if (!contractMethod) { return console.error(`(DH-DOM) | Method name "${methodName}" does not exists on the contract ABI`); } - const isTransaction = contractMethod.stateMutability !== 'view'; + + // Transactions are transactions if they are not view, pure or constant + const isTransaction = !Boolean(['view', 'pure', 'constant'].filter(el => contractMethod.stateMutability === el).length) + + // const isTransaction = contractMethod.stateMutability !== 'view'; const hasOutputs = contractMethod.outputs.length > 0; // Get customContract children properties @@ -75,26 +100,56 @@ export const customContractParser = ( const parsedInputs = inputs .map((input) => { const value = input.getAttribute(property.attribute); + + // we need to check if the start of value is [ and the end is ] and the middle item is a number. + const getIsArray = (value) => { + if (value.charAt(0) === '[' && value.charAt(value.length - 1) === ']' && !isNaN(value.substring(1, value.length - 1))) { + return parseInt(value.substring(1, value.length - 1), 10) + } else { + return false + } + } + + const inputArrayValue = getIsArray(value) + const shouldAutoClear = input.getAttribute(`${DATA_PROPERTY}-auto-clear`) === 'true' // Check each input name in ABI equals to the value defined in the DOM - const isInputFound = contractMethod.inputs.some((input) => input.name === value); + const isInputFound = contractMethod.inputs.some((input) => { + if (input.name === value) return true + //check if the actually array value is less than or equal to the input array length + //note that a zero position value would evaluate falsey, hense we deep equal to false. + if (inputArrayValue !== false && inputArrayValue <= contractMethod.inputs.length - 1) { + return true + } + // There is no match for input name, or for array possition, so return false. + return false + }); + + // Now that we know it's an array, check if the array value is valid. + // Note we will have to also check if ALL the array inputs are found. + // Note you could also mix&match the array idnex with a named input (Or too complicated?) const emptyString = '$true'; const isEmptyString = value === emptyString; if (!['EthValue', emptyString].includes(value) && !isInputFound) { + return console.error( - `Input name "${value}" for method ${methodName} does not exists on the contract ABI`, + `(DH-DOM) * Input name "${value}" for method ${methodName} does not exists on the contract ABI`, ); } + // TODO: [DEV-312] This is part of the error for anonymous inputs if (isEmptyString && contractMethod.inputs.length > 1) { return console.error( - `Input with empty string (anonymous input) cannot be set since exists more than one input on the contract ABI`, + `(DH-DOM) Input with empty string (anonymous input) + cannot be set since exists more than one input on the contract ABI, + use Array input array Index. (See documentation: docs.dapphero.io) `, ); } + return { element: input, id: property.id, @@ -123,6 +178,7 @@ export const customContractParser = ( )}`, ); } + const parsedChilrenElements = childrenElements.map((childrenElement) => { if (property.attribute.endsWith('output-name')) { const value = childrenElement.getAttribute(property.attribute); @@ -145,6 +201,7 @@ export const customContractParser = ( contractElement.hasAttribute(property.attribute), ); + // TODO: [DEV-121] Figure out why validation fails when output-name is not included if (!childrenElement) { return; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 86cea87..bdecccb 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -15,6 +15,26 @@ export const ELEMENT_TYPES = { video: 'video', }; +export const ETHER_UNITS = ['wei', 'ether', +'1', +'10', +'100', +'1000', +'10000', +'100000', +'1000000', +'10000000', +'100000000', +'1000000000', +'10000000000', +'100000000000', +'1000000000000', +'10000000000000', +'100000000000000', +'1000000000000000', +'100000000000000000', +'1000000000000000000'] + export const TAG_TYPES = { H1: ELEMENT_TYPES.text, H2: ELEMENT_TYPES.text,