Skip to content

feat: parse argument value by custom type #537

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 31, 2024
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@fortawesome/free-solid-svg-icons": "6.4.0",
"@fortawesome/react-native-fontawesome": "0.2.7",
"@hathor/unleash-client": "0.1.0",
"@hathor/wallet-lib": "1.9.0",
"@hathor/wallet-lib": "1.10.0",
"@notifee/react-native": "5.7.0",
"@react-native-async-storage/async-storage": "1.19.0",
"@react-native-firebase/app": "16.7.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import {
import { useDispatch, useSelector } from 'react-redux';
import { t } from 'ttag';
import { get } from 'lodash';
import { Network } from '@hathor/wallet-lib';
import { COLORS } from '../../../styles/themes';
import { commonStyles } from '../theme';
import { onExceptionCaptured } from '../../../actions';
import { NANOCONTRACT_BLUEPRINTINFO_STATUS as STATUS } from '../../../constants';
import { DEFAULT_TOKEN, NANOCONTRACT_BLUEPRINTINFO_STATUS as STATUS } from '../../../constants';
import { FeedbackContent } from '../../FeedbackContent';
import Spinner from '../../Spinner';
import { getTimestampFormat, parseScriptData, renderValue } from '../../../utils';

/**
* Get method info from registered blueprint data.
Expand Down Expand Up @@ -63,10 +65,16 @@ export const NanoContractMethodArgs = ({ blueprintId, method, ncArgs }) => {
return null;
}
const dispatch = useDispatch();
const network = useSelector((state) => new Network(state.networkSettings.network));
const tokens = useSelector((state) => state.tokens);

const blueprintInfo = useSelector((state) => state.nanoContract.blueprint[blueprintId]);
// It results a in a list of entries like:
// >>> [['oracle_script', 'abc'], ['token_uid', '00'], ['date_last_bet', 123]]
// >>>[
// >>> ['oracle_script', 'abc', 'TxOutputScript'],
// >>> ['token_uid', '00', 'TokenUid'],
// >>> ['date_last_bet', 123, 'Timestamp']
// >>>]
// or a fallback like:
// >>> [['Position 0', 'abc'], ['Position 1', '00'], ['Position 2', 123]]
const argEntries = useMemo(() => {
Expand All @@ -76,7 +84,11 @@ export const NanoContractMethodArgs = ({ blueprintId, method, ncArgs }) => {

const methodInfo = getMethodInfoFromBlueprint(blueprintInfo, method);
if (methodInfo) {
return ncArgs.map((arg, idx) => [methodInfo.args[idx].name, arg]);
return ncArgs.map((arg, idx) => [
methodInfo.args[idx]?.name || t`Position ${idx}`,
arg,
methodInfo.args[idx]?.type || 'str',
]);
}

// Send this condition to sentry because it should never happen.
Expand Down Expand Up @@ -109,7 +121,7 @@ export const NanoContractMethodArgs = ({ blueprintId, method, ncArgs }) => {
&& (
<View style={[commonStyles.card]}>
<View style={[commonStyles.cardStack]}>
{argEntries.map(([argName, argValue]) => (
{argEntries.map(([argName, argValue, argType]) => (
<View
key={argName}
style={commonStyles.cardStackItem}
Expand All @@ -118,7 +130,14 @@ export const NanoContractMethodArgs = ({ blueprintId, method, ncArgs }) => {
<Text style={styles.argPositionText}>{argName}</Text>
</View>
<View style={styles.argValue}>
<Text style={styles.argValueText}>{argValue}</Text>
<Text style={styles.argValueText}>
<ArgValue
type={argType}
value={argValue}
network={network}
tokens={tokens}
/>
</Text>
</View>
</View>
))}
Expand All @@ -129,6 +148,60 @@ export const NanoContractMethodArgs = ({ blueprintId, method, ncArgs }) => {
)
};

/**
* Component resposible to render the appropriate format for the value
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* Component resposible to render the appropriate format for the value
* Component responsible to render the appropriate format for the value

* taking in consideration the type.
*
* Remarks
* The values received in here when derived from 'byte' type like
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* The values received in here when derived from 'byte' type like
* The values received here when derived from 'byte' type like

* 'TxOutputScript', 'TokenUid' and 'VertexId' are already in its
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* 'TxOutputScript', 'TokenUid' and 'VertexId' are already in its
* 'TxOutputScript', 'TokenUid' and 'VertexId' are already in their

* hexadecimal format.
*
* Values of type 'Address', which also derives from 'byte' are
* in its base58 format.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* in its base58 format.
* in base58 format.

*
* Values of type 'SignedData[Result]' arrives here using its data
* part already.
Copy link
Contributor

Choose a reason for hiding this comment

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

What does this mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I mean, it is already in presentation format.

*
* @param {Object} props
* @param {string} props.type An argument type
* @param {string} props.value An argument value
* @param {Object} props.network A network object
* @param {Object} props.tokens A map of registered tokens
*/
const ArgValue = ({ type, value, network, tokens }) => {
if (type === 'Amount') {
return renderValue(value);
}

if (type === 'Timestamp') {
return getTimestampFormat(value);
}

if (type === 'TxOutputScript') {
const parsedScript = parseScriptData(value, network);
if (parsedScript && parsedScript.getType() === 'data') {
return parsedScript.data;
}

if (parsedScript) {
return parsedScript.address.base58;
}
}

if (type === 'TokenUid') {
if (value === DEFAULT_TOKEN.uid) {
return DEFAULT_TOKEN.symbol;
}

if (value in tokens) {
return tokens[value].symbol;
}
}

return value;
};

const styles = StyleSheet.create({
argPosition: {
flexShrink: 10,
Expand Down
26 changes: 26 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -497,3 +497,29 @@ export function hasError(invalidModel) {
.values({ ...invalidModel })
.reduce((_hasError, currValue) => _hasError || !isEmpty(currValue), false);
}

/**
* Parses a script data to return an instance of script type.
*
* @example
* parseScriptData('P2PKH or P2SH script', networkObj);
* >>> { address, timelock }
*
* @example
* parseScriptData('Data script', networkObj);
* >>> { data }
*
* @param {string} scriptData A script in its hexadecimal format
* @param {Object} network A network object
*
* @return {P2PKH | P2SH | ScriptData | null} Parsed script object
*/
export const parseScriptData = (scriptData, network) => {
try {
const script = hathorLib.bufferUtils.hexToBuffer(scriptData);
return hathorLib.scriptsUtils.parseScript(script, network);
} catch {
// Avoid to throw exception when we can't parse the script no matter the reason
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Avoid to throw exception when we can't parse the script no matter the reason
// Avoid throwing exception when we can't parse the script no matter the reason

return null;
Copy link
Contributor

Choose a reason for hiding this comment

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

log debug here?

}
}