Compare commits
14 Commits
feat/tx-pa
...
fix/nft-cr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3340857575 | ||
|
|
e1f34c4beb | ||
|
|
54a89c969e | ||
|
|
ded867d997 | ||
|
|
0fce9af77c | ||
|
|
55c68c580a | ||
|
|
832a7997d1 | ||
|
|
4528e5a16e | ||
|
|
38f064c6d8 | ||
|
|
fbf4565dbc | ||
|
|
9001c64fed | ||
|
|
03b768db4e | ||
|
|
825af0db89 | ||
|
|
31043f33ab |
71
components/Sequence.tsx
Normal file
71
components/Sequence.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { FC, useCallback, useState } from 'react'
|
||||
import state from '../state'
|
||||
import { Flex, Input, Button } from '.'
|
||||
import fetchAccountInfo from '../utils/accountInfo'
|
||||
import { useSnapshot } from 'valtio'
|
||||
|
||||
interface AccountSequenceProps {
|
||||
address?: string
|
||||
}
|
||||
const AccountSequence: FC<AccountSequenceProps> = ({ address }) => {
|
||||
const { accounts } = useSnapshot(state)
|
||||
const account = accounts.find(acc => acc.address === address)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const setSequence = useCallback(
|
||||
(sequence: number) => {
|
||||
const acc = state.accounts.find(acc => acc.address == address)
|
||||
if (!acc) return
|
||||
acc.sequence = sequence
|
||||
},
|
||||
[address]
|
||||
)
|
||||
const handleUpdateSequence = useCallback(
|
||||
async (silent?: boolean) => {
|
||||
if (!account) return
|
||||
setIsLoading(true)
|
||||
|
||||
const info = await fetchAccountInfo(account.address, { silent })
|
||||
if (info) {
|
||||
setSequence(info.Sequence)
|
||||
}
|
||||
|
||||
setIsLoading(false)
|
||||
},
|
||||
[account, setSequence]
|
||||
)
|
||||
const disabled = !account
|
||||
return (
|
||||
<Flex row align="center" fluid>
|
||||
<Input
|
||||
placeholder="Account sequence"
|
||||
value={account?.sequence || ""}
|
||||
disabled={!account}
|
||||
type="number"
|
||||
readOnly={true}
|
||||
/>
|
||||
<Button
|
||||
size="xs"
|
||||
variant="primary"
|
||||
type="button"
|
||||
outline
|
||||
disabled={disabled}
|
||||
isDisabled={disabled}
|
||||
isLoading={isLoading}
|
||||
css={{
|
||||
background: '$backgroundAlt',
|
||||
position: 'absolute',
|
||||
right: '$2',
|
||||
fontSize: '$xs',
|
||||
cursor: 'pointer',
|
||||
alignContent: 'center',
|
||||
display: 'flex'
|
||||
}}
|
||||
onClick={() => handleUpdateSequence()}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccountSequence
|
||||
@@ -21,6 +21,7 @@ import { prepareDeployHookTx, sha256 } from '../state/actions/deployHook'
|
||||
import estimateFee from '../utils/estimateFee'
|
||||
import { getParameters, getInvokeOptions, transactionOptions, SetHookData } from '../utils/setHook'
|
||||
import { capitalize } from '../utils/helpers'
|
||||
import AccountSequence from './Sequence'
|
||||
|
||||
export const SetHookDialog: React.FC<{ accountAddress: string }> = React.memo(
|
||||
({ accountAddress }) => {
|
||||
@@ -190,6 +191,10 @@ export const SetHookDialog: React.FC<{ accountAddress: string }> = React.memo(
|
||||
onChange={(acc: any) => setSelectedAccount(acc)}
|
||||
/>
|
||||
</Box>
|
||||
<Box css={{ width: '100%', position: 'relative' }}>
|
||||
<Label>Sequence</Label>
|
||||
<AccountSequence address={selectedAccount?.value} />
|
||||
</Box>
|
||||
<Box css={{ width: '100%' }}>
|
||||
<Label>Invoke on transactions</Label>
|
||||
<Controller
|
||||
|
||||
@@ -47,7 +47,8 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
|
||||
selectedAccount,
|
||||
txFields,
|
||||
selectedFlags,
|
||||
hookParameters
|
||||
hookParameters,
|
||||
memos
|
||||
} = state
|
||||
|
||||
const TransactionType = selectedTransaction?.value || null
|
||||
@@ -61,6 +62,13 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
|
||||
HookParameter: { HookParameterName: toHex(label), HookParameterValue: toHex(value) }
|
||||
})
|
||||
}, [])
|
||||
const Memos = memos
|
||||
? Object.entries(memos).reduce<SetHookData['Memos']>((acc, [_, { format, data, type }]) => {
|
||||
return acc?.concat({
|
||||
Memo: { MemoData: toHex(data), MemoFormat: toHex(format), MemoType: toHex(type) }
|
||||
})
|
||||
}, [])
|
||||
: undefined
|
||||
|
||||
return prepareTransaction({
|
||||
...txFields,
|
||||
@@ -68,7 +76,8 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
|
||||
Flags,
|
||||
TransactionType,
|
||||
Destination,
|
||||
Account
|
||||
Account,
|
||||
Memos
|
||||
})
|
||||
},
|
||||
[txState]
|
||||
@@ -84,15 +93,29 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
|
||||
}
|
||||
}, [selectedAccount?.value, selectedTransaction?.value, setState, txIsLoading])
|
||||
|
||||
const getJsonString = useCallback(
|
||||
(state?: Partial<TransactionState>) =>
|
||||
JSON.stringify(prepareOptions?.(state) || {}, null, editorSettings.tabSize),
|
||||
[editorSettings.tabSize, prepareOptions]
|
||||
)
|
||||
|
||||
const saveEditorState = useCallback(
|
||||
(value: string = '', transactionType?: string) => {
|
||||
const pTx = prepareState(value, transactionType)
|
||||
if (pTx) {
|
||||
pTx.editorValue = getJsonString(pTx)
|
||||
return setState(pTx)
|
||||
}
|
||||
},
|
||||
[getJsonString, setState]
|
||||
)
|
||||
|
||||
const submitTest = useCallback(async () => {
|
||||
let st: TransactionState | undefined
|
||||
const tt = txState.selectedTransaction?.value
|
||||
if (viewType === 'json') {
|
||||
// save the editor state first
|
||||
const pst = prepareState(editorValue || '', tt)
|
||||
if (!pst) return
|
||||
|
||||
st = setState(pst)
|
||||
st = saveEditorState(editorValue, tt)
|
||||
if (!st) return
|
||||
}
|
||||
|
||||
const account = accounts.find(acc => acc.address === selectedAccount?.value)
|
||||
@@ -123,23 +146,18 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
|
||||
}
|
||||
setState({ txIsLoading: false })
|
||||
}, [
|
||||
txState.selectedTransaction?.value,
|
||||
viewType,
|
||||
accounts,
|
||||
txIsDisabled,
|
||||
setState,
|
||||
header,
|
||||
saveEditorState,
|
||||
editorValue,
|
||||
txState,
|
||||
selectedAccount?.value,
|
||||
prepareOptions
|
||||
])
|
||||
|
||||
const getJsonString = useCallback(
|
||||
(state?: Partial<TransactionState>) =>
|
||||
JSON.stringify(prepareOptions?.(state) || {}, null, editorSettings.tabSize),
|
||||
[editorSettings.tabSize, prepareOptions]
|
||||
)
|
||||
|
||||
const resetState = useCallback(
|
||||
(transactionType: SelectOption | undefined = defaultTransactionType) => {
|
||||
const fields = getTxFields(transactionType?.value)
|
||||
@@ -192,11 +210,21 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
|
||||
[accounts, prepareOptions, setState, txState]
|
||||
)
|
||||
|
||||
const switchToJson = useCallback(() => {
|
||||
const editorValue = getJsonString()
|
||||
setState({ viewType: 'json', editorValue })
|
||||
}, [getJsonString, setState])
|
||||
|
||||
const switchToUI = useCallback(() => {
|
||||
setState({ viewType: 'ui' })
|
||||
}, [setState])
|
||||
|
||||
return (
|
||||
<Box css={{ position: 'relative', height: 'calc(100% - 28px)' }} {...props}>
|
||||
{viewType === 'json' ? (
|
||||
<TxJson
|
||||
getJsonString={getJsonString}
|
||||
saveEditorState={saveEditorState}
|
||||
header={header}
|
||||
state={txState}
|
||||
setState={setState}
|
||||
@@ -204,6 +232,7 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
|
||||
/>
|
||||
) : (
|
||||
<TxUI
|
||||
switchToJson={switchToJson}
|
||||
state={txState}
|
||||
resetState={resetState}
|
||||
setState={setState}
|
||||
@@ -224,8 +253,8 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (viewType === 'ui') {
|
||||
setState({ viewType: 'json' })
|
||||
} else setState({ viewType: 'ui' })
|
||||
switchToJson()
|
||||
} else switchToUI()
|
||||
}}
|
||||
outline
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { FC, useCallback, useEffect, useState } from 'react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import state, { prepareState, transactionsData, TransactionState } from '../../state'
|
||||
import state, { transactionsData, TransactionState } from '../../state'
|
||||
import Text from '../Text'
|
||||
import { Flex, Link } from '..'
|
||||
import { showAlert } from '../../state/actions/showAlert'
|
||||
@@ -11,27 +11,27 @@ import Monaco from '../Monaco'
|
||||
import type monaco from 'monaco-editor'
|
||||
|
||||
interface JsonProps {
|
||||
getJsonString?: (state?: Partial<TransactionState>) => string
|
||||
getJsonString: (st?: Partial<TransactionState>) => string
|
||||
saveEditorState: (val?: string, tt?: string) => TransactionState | undefined
|
||||
header?: string
|
||||
setState: (pTx?: Partial<TransactionState> | undefined) => void
|
||||
state: TransactionState
|
||||
estimateFee?: () => Promise<string | undefined>
|
||||
}
|
||||
|
||||
export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, setState }) => {
|
||||
export const TxJson: FC<JsonProps> = ({
|
||||
getJsonString,
|
||||
state: txState,
|
||||
header,
|
||||
setState,
|
||||
saveEditorState
|
||||
}) => {
|
||||
const { editorSettings, accounts } = useSnapshot(state)
|
||||
const { editorValue, estimatedFee } = txState
|
||||
const { editorValue, estimatedFee, editorIsSaved } = txState
|
||||
const [currTxType, setCurrTxType] = useState<string | undefined>(
|
||||
txState.selectedTransaction?.value
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setState({
|
||||
editorValue: getJsonString?.()
|
||||
})
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const parsed = parseJSON(editorValue)
|
||||
if (!parsed) return
|
||||
@@ -44,29 +44,19 @@ export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, s
|
||||
}
|
||||
}, [editorValue])
|
||||
|
||||
const saveState = (value: string, transactionType?: string) => {
|
||||
const tx = prepareState(value, transactionType)
|
||||
if (tx) {
|
||||
setState(tx)
|
||||
setState({
|
||||
editorValue: getJsonString?.(tx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const discardChanges = () => {
|
||||
showAlert('Confirm', {
|
||||
body: 'Are you sure to discard these changes?',
|
||||
confirmText: 'Yes',
|
||||
onCancel: () => {},
|
||||
onConfirm: () => setState({ editorValue: getJsonString?.() })
|
||||
onConfirm: () => setState({ editorValue: getJsonString() })
|
||||
})
|
||||
}
|
||||
|
||||
const onExit = (value: string) => {
|
||||
const options = parseJSON(value)
|
||||
if (options) {
|
||||
saveState(value, currTxType)
|
||||
saveEditorState(value, currTxType)
|
||||
return
|
||||
}
|
||||
showAlert('Error!', {
|
||||
@@ -163,8 +153,6 @@ export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, s
|
||||
})
|
||||
}, [getSchemas, monacoInst])
|
||||
|
||||
const hasUnsaved = useMemo(() => editorValue !== getJsonString?.(), [editorValue, getJsonString])
|
||||
|
||||
return (
|
||||
<Monaco
|
||||
rootProps={{
|
||||
@@ -174,7 +162,7 @@ export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, s
|
||||
id={header}
|
||||
height="100%"
|
||||
value={editorValue}
|
||||
onChange={val => setState({ editorValue: val })}
|
||||
onChange={val => setState({ editorValue: val, editorIsSaved: false })}
|
||||
onMount={(editor, monaco) => {
|
||||
editor.updateOptions({
|
||||
minimap: { enabled: false },
|
||||
@@ -190,12 +178,12 @@ export const TxJson: FC<JsonProps> = ({ getJsonString, state: txState, header, s
|
||||
model?.onWillDispose(() => onExit(model.getValue()))
|
||||
}}
|
||||
overlay={
|
||||
hasUnsaved ? (
|
||||
!editorIsSaved ? (
|
||||
<Flex row align="center" css={{ fontSize: '$xs', color: '$textMuted', ml: 'auto' }}>
|
||||
<Text muted small>
|
||||
This file has unsaved changes.
|
||||
</Text>
|
||||
<Link css={{ ml: '$1' }} onClick={() => saveState(editorValue || '', currTxType)}>
|
||||
<Link css={{ ml: '$1' }} onClick={() => saveEditorState(editorValue, currTxType)}>
|
||||
save
|
||||
</Link>
|
||||
<Link css={{ ml: '$1' }} onClick={discardChanges}>
|
||||
|
||||
@@ -19,15 +19,23 @@ import { Button } from '..'
|
||||
import Textarea from '../Textarea'
|
||||
import { getFlags } from '../../state/constants/flags'
|
||||
import { Plus, Trash } from 'phosphor-react'
|
||||
import AccountSequence from '../Sequence'
|
||||
|
||||
interface UIProps {
|
||||
setState: (pTx?: Partial<TransactionState> | undefined) => TransactionState | undefined
|
||||
resetState: (tt?: SelectOption) => TransactionState | undefined
|
||||
state: TransactionState
|
||||
estimateFee?: (...arg: any) => Promise<string | undefined>
|
||||
switchToJson: () => void
|
||||
}
|
||||
|
||||
export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estimateFee }) => {
|
||||
export const TxUI: FC<UIProps> = ({
|
||||
state: txState,
|
||||
setState,
|
||||
resetState,
|
||||
estimateFee,
|
||||
switchToJson
|
||||
}) => {
|
||||
const { accounts } = useSnapshot(state)
|
||||
const {
|
||||
selectedAccount,
|
||||
@@ -35,7 +43,8 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
|
||||
selectedTransaction,
|
||||
txFields,
|
||||
selectedFlags,
|
||||
hookParameters
|
||||
hookParameters,
|
||||
memos
|
||||
} = txState
|
||||
|
||||
const accountOptions: SelectOption[] = accounts.map(acc => ({
|
||||
@@ -101,8 +110,6 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
|
||||
[handleEstimateFee, resetState, setState]
|
||||
)
|
||||
|
||||
const switchToJson = () => setState({ viewType: 'json' })
|
||||
|
||||
// default tx
|
||||
useEffect(() => {
|
||||
if (selectedTransaction?.value) return
|
||||
@@ -117,7 +124,7 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
|
||||
[selectedTransaction?.value]
|
||||
)
|
||||
|
||||
const richFields = ['TransactionType', 'Account', 'HookParameters']
|
||||
const richFields = ['TransactionType', 'Account', 'HookParameters', 'Memos']
|
||||
if (fields.Destination !== undefined) {
|
||||
richFields.push('Destination')
|
||||
}
|
||||
@@ -155,6 +162,9 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
|
||||
onChange={(acc: any) => handleSetAccount(acc)} // TODO make react-select have correct types for acc
|
||||
/>
|
||||
</TxField>
|
||||
<TxField label="Sequence">
|
||||
<AccountSequence address={selectedAccount?.value} />
|
||||
</TxField>
|
||||
{richFields.includes('Destination') && (
|
||||
<TxField label="Destination account">
|
||||
<Select
|
||||
@@ -333,6 +343,83 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
|
||||
</Button>
|
||||
</Flex>
|
||||
</TxField>
|
||||
<TxField multiLine label="Memos">
|
||||
<Flex column fluid>
|
||||
{Object.entries(memos).map(([id, memo]) => (
|
||||
<Flex column key={id} css={{ mb: '$2' }}>
|
||||
<Flex
|
||||
row
|
||||
css={{
|
||||
flexWrap: 'wrap',
|
||||
width: '100%'
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
placeholder="Memo type"
|
||||
value={memo.type}
|
||||
onChange={e => {
|
||||
setState({
|
||||
memos: {
|
||||
...memos,
|
||||
[id]: { ...memo, type: e.target.value }
|
||||
}
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
placeholder="Data"
|
||||
css={{ mx: '$2' }}
|
||||
value={memo.data}
|
||||
onChange={e => {
|
||||
setState({
|
||||
memos: {
|
||||
...memos,
|
||||
[id]: { ...memo, data: e.target.value }
|
||||
}
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
placeholder="Format"
|
||||
value={memo.format}
|
||||
onChange={e => {
|
||||
setState({
|
||||
memos: {
|
||||
...memos,
|
||||
[id]: { ...memo, format: e.target.value }
|
||||
}
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
css={{ ml: '$2' }}
|
||||
onClick={() => {
|
||||
const { [id]: _, ...rest } = memos
|
||||
setState({ memos: rest })
|
||||
}}
|
||||
variant="destroy"
|
||||
>
|
||||
<Trash weight="regular" size="16px" />
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
))}
|
||||
<Button
|
||||
outline
|
||||
fullWidth
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const id = Object.keys(memos).length
|
||||
setState({
|
||||
memos: { ...memos, [id]: { data: '', format: '', type: '' } }
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Plus size="16px" />
|
||||
Add Memo
|
||||
</Button>
|
||||
</Flex>
|
||||
</TxField>
|
||||
</Flex>
|
||||
</Container>
|
||||
)
|
||||
|
||||
@@ -124,7 +124,8 @@
|
||||
},
|
||||
"Flags": "1",
|
||||
"Destination": "",
|
||||
"Fee": "10"
|
||||
"Fee": "10",
|
||||
"Owner": ""
|
||||
},
|
||||
{
|
||||
"TransactionType": "OfferCancel",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import toast from 'react-hot-toast'
|
||||
import state, { FaucetAccountRes } from '../index'
|
||||
import fetchAccountInfo from '../../utils/accountInfo';
|
||||
|
||||
export const names = [
|
||||
'Alice',
|
||||
@@ -35,40 +36,37 @@ export const addFaucetAccount = async (name?: string, showToast: boolean = false
|
||||
})
|
||||
const json: FaucetAccountRes | { error: string } = await res.json()
|
||||
if ('error' in json) {
|
||||
if (showToast) {
|
||||
return toast.error(json.error, { id: toastId })
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (showToast) {
|
||||
toast.success('New account created', { id: toastId })
|
||||
}
|
||||
const currNames = state.accounts.map(acc => acc.name)
|
||||
state.accounts.push({
|
||||
name: name || names.filter(name => !currNames.includes(name))[0],
|
||||
xrp: (json.xrp || 0 * 1000000).toString(),
|
||||
address: json.address,
|
||||
secret: json.secret,
|
||||
sequence: 1,
|
||||
hooks: [],
|
||||
isLoading: false,
|
||||
version: '2'
|
||||
})
|
||||
if (!showToast) return;
|
||||
return toast.error(json.error, { id: toastId })
|
||||
}
|
||||
const currNames = state.accounts.map(acc => acc.name)
|
||||
const info = await fetchAccountInfo(json.address, { silent: true })
|
||||
state.accounts.push({
|
||||
name: name || names.filter(name => !currNames.includes(name))[0],
|
||||
xrp: (json.xrp || 0 * 1000000).toString(),
|
||||
address: json.address,
|
||||
secret: json.secret,
|
||||
sequence: info?.Sequence || 1,
|
||||
hooks: [],
|
||||
isLoading: false,
|
||||
version: '2'
|
||||
})
|
||||
if (showToast) {
|
||||
toast.success('New account created', { id: toastId })
|
||||
}
|
||||
}
|
||||
|
||||
// fetch initial faucets
|
||||
;(async function fetchFaucets() {
|
||||
if (typeof window !== 'undefined') {
|
||||
if (state.accounts.length === 0) {
|
||||
await addFaucetAccount()
|
||||
// setTimeout(() => {
|
||||
// addFaucetAccount();
|
||||
// }, 10000);
|
||||
// fetch initial faucets
|
||||
; (async function fetchFaucets() {
|
||||
if (typeof window !== 'undefined') {
|
||||
if (state.accounts.length === 0) {
|
||||
await addFaucetAccount()
|
||||
// setTimeout(() => {
|
||||
// addFaucetAccount();
|
||||
// }, 10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
})()
|
||||
})()
|
||||
|
||||
export const addFunds = async (address: string) => {
|
||||
const toastId = toast.loading('Requesting funds')
|
||||
|
||||
@@ -16,17 +16,27 @@ export type HookParameters = {
|
||||
[key: string]: SelectOption
|
||||
}
|
||||
|
||||
export type Memos = {
|
||||
[key: string]: {
|
||||
type: string
|
||||
format: string
|
||||
data: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface TransactionState {
|
||||
selectedTransaction: SelectOption | null
|
||||
selectedAccount: SelectOption | null
|
||||
selectedDestAccount: SelectOption | null
|
||||
selectedFlags: SelectOption[] | null
|
||||
hookParameters: HookParameters
|
||||
memos: Memos
|
||||
txIsLoading: boolean
|
||||
txIsDisabled: boolean
|
||||
txFields: TxFields
|
||||
viewType: 'json' | 'ui'
|
||||
editorValue?: string
|
||||
editorIsSaved: boolean
|
||||
estimatedFee?: string
|
||||
}
|
||||
|
||||
@@ -43,6 +53,8 @@ export const defaultTransaction: TransactionState = {
|
||||
selectedDestAccount: null,
|
||||
selectedFlags: null,
|
||||
hookParameters: {},
|
||||
memos: {},
|
||||
editorIsSaved: true,
|
||||
txIsLoading: false,
|
||||
txIsDisabled: false,
|
||||
txFields: {},
|
||||
@@ -167,7 +179,7 @@ export const prepareState = (value: string, transactionType?: string) => {
|
||||
return
|
||||
}
|
||||
|
||||
const { Account, TransactionType, Destination, HookParameters, ...rest } = options
|
||||
const { Account, TransactionType, Destination, HookParameters, Memos, ...rest } = options
|
||||
let tx: Partial<TransactionState> = {}
|
||||
const schema = getTxFields(transactionType)
|
||||
|
||||
@@ -205,6 +217,14 @@ export const prepareState = (value: string, transactionType?: string) => {
|
||||
}, {})
|
||||
}
|
||||
|
||||
if (Memos && Memos instanceof Array) {
|
||||
tx.memos = Memos.reduce<TransactionState["memos"]>((acc, cur, idx) => {
|
||||
const memo = { data: fromHex(cur.Memo?.MemoData || ""), type: fromHex(cur.Memo?.MemoType || ""), format: fromHex(cur.Memo?.MemoFormat || "") }
|
||||
acc[idx] = memo;
|
||||
return acc;
|
||||
}, {})
|
||||
}
|
||||
|
||||
if (schema.Destination !== undefined) {
|
||||
const dest = state.accounts.find(acc => acc.address === Destination)
|
||||
if (dest) {
|
||||
@@ -253,6 +273,7 @@ export const prepareState = (value: string, transactionType?: string) => {
|
||||
})
|
||||
|
||||
tx.txFields = rest
|
||||
tx.editorIsSaved = true;
|
||||
|
||||
return tx
|
||||
}
|
||||
|
||||
31
utils/accountInfo.ts
Normal file
31
utils/accountInfo.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import toast from 'react-hot-toast'
|
||||
|
||||
import { xrplSend } from '../state/actions/xrpl-client'
|
||||
|
||||
interface AccountInfo {
|
||||
Account: string,
|
||||
Sequence: number,
|
||||
Flags: number,
|
||||
Balance?: string,
|
||||
}
|
||||
|
||||
const fetchAccountInfo = async (
|
||||
address: string,
|
||||
opts: { silent?: boolean } = {}
|
||||
): Promise<AccountInfo | undefined> => {
|
||||
try {
|
||||
const res = await xrplSend({
|
||||
id: `hooks-builder-req-info-${address}`,
|
||||
command: 'account_info',
|
||||
account: address
|
||||
})
|
||||
return res.account_data;
|
||||
} catch (err) {
|
||||
if (!opts.silent) {
|
||||
console.error(err)
|
||||
toast.error('Could not fetch account info!')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default fetchAccountInfo
|
||||
@@ -20,6 +20,13 @@ export type SetHookData = {
|
||||
}
|
||||
$metaData?: any
|
||||
}[]
|
||||
Memos?: {
|
||||
Memo: {
|
||||
MemoType: string,
|
||||
MemoData: string
|
||||
MemoFormat: string
|
||||
}
|
||||
}[]
|
||||
// HookGrants: {
|
||||
// HookGrant: {
|
||||
// Authorize: string;
|
||||
|
||||
Reference in New Issue
Block a user