Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
6 changes: 3 additions & 3 deletions src/features/customContract/index.ts
Original file line number Diff line number Diff line change
@@ -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',
Expand Down Expand Up @@ -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',
Expand Down
67 changes: 62 additions & 5 deletions src/features/customContract/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
Comment on lines +58 to +71
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer const and use of destructuring for avoiding variable mutations and code simplicity

Code example:

Suggested change
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.
}
//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');
// If we are over loaded, check how many inputs this method has.
const contractMethod =
contractMethods.length > 1
? contractMethods.filter((method) => method.inputs.length === contractInputs.length)[0]
: contractABI.find(({ name }) => methodName === name);


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
Expand All @@ -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
}
}
Comment on lines +105 to +111
Copy link
Contributor

@lndgalante lndgalante Jun 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer a RegExp for this scenario since it would be easier to understand and maintain

Suggested change
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 getIsArray = (value) => {
const [position] = value.match(/\d+/g) || [];
const isPosition = !isNaN(position);
return isPosition ? Number(position) : 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,
Expand Down Expand Up @@ -123,6 +178,7 @@ export const customContractParser = (
)}`,
);
}

const parsedChilrenElements = childrenElements.map((childrenElement) => {
if (property.attribute.endsWith('output-name')) {
const value = childrenElement.getAttribute(property.attribute);
Expand All @@ -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;
Expand Down
20 changes: 20 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down