HookParameters UI for transactions.

This commit is contained in:
muzam1l
2023-03-03 18:32:03 +05:30
parent b50b300307
commit 39699a1cb9
6 changed files with 125 additions and 20 deletions

View File

@@ -20,6 +20,7 @@ import { TxUI } from './ui'
import { default as _estimateFee } from '../../utils/estimateFee' import { default as _estimateFee } from '../../utils/estimateFee'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { combineFlags, extractFlags, transactionFlags } from '../../state/constants/flags' import { combineFlags, extractFlags, transactionFlags } from '../../state/constants/flags'
import { SetHookData, toHex } from '../../utils/setHook'
export interface TransactionProps { export interface TransactionProps {
header: string header: string
@@ -40,16 +41,30 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
const prepareOptions = useCallback( const prepareOptions = useCallback(
(state: Partial<TransactionState> = txState) => { (state: Partial<TransactionState> = txState) => {
const { selectedTransaction, selectedDestAccount, selectedAccount, txFields, selectedFlags } = const {
state selectedTransaction,
selectedDestAccount,
selectedAccount,
txFields,
selectedFlags,
hookParameters
} = state
const TransactionType = selectedTransaction?.value || null const TransactionType = selectedTransaction?.value || null
const Destination = selectedDestAccount?.value || txFields?.Destination const Destination = selectedDestAccount?.value || txFields?.Destination
const Account = selectedAccount?.value || null const Account = selectedAccount?.value || null
const Flags = combineFlags(selectedFlags?.map(flag => flag.value)) || txFields?.Flags const Flags = combineFlags(selectedFlags?.map(flag => flag.value)) || txFields?.Flags
const HookParameters = Object.entries(hookParameters || {}).reduce<
SetHookData['HookParameters']
>((acc, [_, { label, value }]) => {
return acc.concat({
HookParameter: { HookParameterName: toHex(label), HookParameterValue: toHex(value) }
})
}, [])
return prepareTransaction({ return prepareTransaction({
...txFields, ...txFields,
HookParameters,
Flags, Flags,
TransactionType, TransactionType,
Destination, Destination,

View File

@@ -29,8 +29,14 @@ interface UIProps {
export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estimateFee }) => { export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estimateFee }) => {
const { accounts } = useSnapshot(state) const { accounts } = useSnapshot(state)
const { selectedAccount, selectedDestAccount, selectedTransaction, txFields, selectedFlags } = const {
txState selectedAccount,
selectedDestAccount,
selectedTransaction,
txFields,
selectedFlags,
hookParameters
} = txState
const accountOptions: SelectOption[] = accounts.map(acc => ({ const accountOptions: SelectOption[] = accounts.map(acc => ({
label: acc.name, label: acc.name,
@@ -111,7 +117,7 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
[selectedTransaction?.value] [selectedTransaction?.value]
) )
const richFields = ['TransactionType', 'Account'] const richFields = ['TransactionType', 'Account', 'HookParameters']
if (fields.Destination !== undefined) { if (fields.Destination !== undefined) {
richFields.push('Destination') richFields.push('Destination')
} }
@@ -121,8 +127,6 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
} }
const otherFields = Object.keys(txFields).filter(k => !richFields.includes(k)) as [keyof TxFields] const otherFields = Object.keys(txFields).filter(k => !richFields.includes(k)) as [keyof TxFields]
const hookParams = [{ id: 1 }]
return ( return (
<Container <Container
css={{ css={{
@@ -271,15 +275,73 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
</TxField> </TxField>
) )
})} })}
<TxField multiLine label="Hook parameters">
<Flex column fluid>
{Object.entries(hookParameters).map(([id, { label, value }]) => (
<Flex column key={id} css={{ mb: '$2' }}>
<Flex row>
<Input
placeholder="Parameter name"
value={label}
onChange={e => {
setState({
hookParameters: {
...hookParameters,
[id]: { label: e.target.value, value }
}
})
}}
/>
<Input
css={{ mx: '$2' }}
placeholder="Value"
value={value}
onChange={e => {
setState({
hookParameters: {
...hookParameters,
[id]: { label, value: e.target.value }
}
})
}}
/>
<Button
onClick={() => {
const { [id]: _, ...rest } = hookParameters
setState({ hookParameters: rest })
}}
variant="destroy"
>
<Trash weight="regular" size="16px" />
</Button>
</Flex>
</Flex>
))}
<Button
outline
fullWidth
type="button"
onClick={() => {
const id = Object.keys(hookParameters).length
setState({
hookParameters: { ...hookParameters, [id]: { label: '', value: '' } }
})
}}
>
<Plus size="16px" />
Add Hook Parameter
</Button>
</Flex>
</TxField>
</Flex> </Flex>
</Container> </Container>
) )
} }
export const TxField: FC<{ label: string; children: ReactNode; isMulti?: boolean }> = ({ export const TxField: FC<{ label: string; children: ReactNode; multiLine?: boolean }> = ({
label, label,
children, children,
isMulti = false multiLine = false
}) => { }) => {
return ( return (
<Flex <Flex
@@ -287,14 +349,14 @@ export const TxField: FC<{ label: string; children: ReactNode; isMulti?: boolean
fluid fluid
css={{ css={{
justifyContent: 'flex-end', justifyContent: 'flex-end',
alignItems: isMulti ? 'flex-start' : 'center', alignItems: multiLine ? 'flex-start' : 'center',
position: 'relative', position: 'relative',
mb: '$3', mb: '$3',
mt: '1px', mt: '1px',
pr: '1px' pr: '1px'
}} }}
> >
<Text muted css={{ mr: '$3', mt: isMulti ? '$2' : 0 }}> <Text muted css={{ mr: '$3', mt: multiLine ? '$2' : 0 }}>
{label}:{' '} {label}:{' '}
</Text> </Text>
<Flex css={{ width: '70%', alignItems: 'center' }}>{children}</Flex> <Flex css={{ width: '70%', alignItems: 'center' }}>{children}</Flex>

View File

@@ -6,7 +6,7 @@ import calculateHookOn, { TTS } from '../../utils/hookOnCalculator'
import { Link } from '../../components' import { Link } from '../../components'
import { ref } from 'valtio' import { ref } from 'valtio'
import estimateFee from '../../utils/estimateFee' import estimateFee from '../../utils/estimateFee'
import { SetHookData } from '../../utils/setHook' import { SetHookData, toHex } from '../../utils/setHook'
import ResultLink from '../../components/ResultLink' import ResultLink from '../../components/ResultLink'
import { xrplSend } from './xrpl-client' import { xrplSend } from './xrpl-client'
@@ -18,13 +18,6 @@ export const sha256 = async (string: string) => {
return hashHex return hashHex
} }
function toHex(str: string) {
var result = ''
for (var i = 0; i < str.length; i++) {
result += str.charCodeAt(i).toString(16)
}
return result.toUpperCase()
}
function arrayBufferToHex(arrayBuffer?: ArrayBuffer | null) { function arrayBufferToHex(arrayBuffer?: ArrayBuffer | null) {
if (!arrayBuffer) { if (!arrayBuffer) {

View File

@@ -31,6 +31,10 @@ export const sendTransaction = async (
...opts ...opts
} }
const { logPrefix = '' } = options || {} const { logPrefix = '' } = options || {}
state.transactionLogs.push({
type: 'log',
message: `${logPrefix}${JSON.stringify(tx, null, 2)}`
})
try { try {
const signedAccount = derive.familySeed(account.secret) const signedAccount = derive.familySeed(account.secret)
const { signedTransaction } = sign(tx, signedAccount) const { signedTransaction } = sign(tx, signedAccount)

View File

@@ -5,17 +5,23 @@ import state from '.'
import { showAlert } from '../state/actions/showAlert' import { showAlert } from '../state/actions/showAlert'
import { parseJSON } from '../utils/json' import { parseJSON } from '../utils/json'
import { extractFlags, getFlags } from './constants/flags' import { extractFlags, getFlags } from './constants/flags'
import { fromHex } from '../utils/setHook'
export type SelectOption = { export type SelectOption = {
value: string value: string
label: string label: string
} }
export type HookParameters = {
[key: string]: SelectOption
}
export interface TransactionState { export interface TransactionState {
selectedTransaction: SelectOption | null selectedTransaction: SelectOption | null
selectedAccount: SelectOption | null selectedAccount: SelectOption | null
selectedDestAccount: SelectOption | null selectedDestAccount: SelectOption | null
selectedFlags: SelectOption[] | null selectedFlags: SelectOption[] | null
hookParameters: HookParameters
txIsLoading: boolean txIsLoading: boolean
txIsDisabled: boolean txIsDisabled: boolean
txFields: TxFields txFields: TxFields
@@ -36,6 +42,7 @@ export const defaultTransaction: TransactionState = {
selectedAccount: null, selectedAccount: null,
selectedDestAccount: null, selectedDestAccount: null,
selectedFlags: null, selectedFlags: null,
hookParameters: {},
txIsLoading: false, txIsLoading: false,
txIsDisabled: false, txIsDisabled: false,
txFields: {}, txFields: {},
@@ -160,7 +167,7 @@ export const prepareState = (value: string, transactionType?: string) => {
return return
} }
const { Account, TransactionType, Destination, ...rest } = options const { Account, TransactionType, Destination, HookParameters, ...rest } = options
let tx: Partial<TransactionState> = {} let tx: Partial<TransactionState> = {}
const schema = getTxFields(transactionType) const schema = getTxFields(transactionType)
@@ -190,6 +197,14 @@ export const prepareState = (value: string, transactionType?: string) => {
tx.selectedTransaction = null tx.selectedTransaction = null
} }
if (HookParameters && HookParameters instanceof Array) {
tx.hookParameters = HookParameters.reduce<TransactionState["hookParameters"]>((acc, cur, idx) => {
const param = { label: fromHex(cur.HookParameter?.HookParameterName || ""), value: fromHex(cur.HookParameter?.HookParameterValue || "") }
acc[idx] = param;
return acc;
}, {})
}
if (schema.Destination !== undefined) { if (schema.Destination !== undefined) {
const dest = state.accounts.find(acc => acc.address === Destination) const dest = state.accounts.find(acc => acc.address === Destination)
if (dest) { if (dest) {

View File

@@ -74,3 +74,19 @@ export const getInvokeOptions = (content?: string) => {
return invokeOptions return invokeOptions
} }
export function toHex(str: string) {
var result = ''
for (var i = 0; i < str.length; i++) {
result += str.charCodeAt(i).toString(16)
}
return result.toUpperCase()
}
export function fromHex(hex: string) {
var str = ''
for (var i = 0; i < hex.length; i += 2) {
str += String.fromCharCode(parseInt(hex.substring(i, i + 2), 16))
}
return str
}