@stellar-expert/ui-framework 1.16.8 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +1168 -3
  2. package/account/account-address.js +127 -127
  3. package/account/available-balance.js +22 -22
  4. package/account/identicon.js +90 -90
  5. package/account/signer-key.js +65 -64
  6. package/api/explorer-api-hooks.js +209 -202
  7. package/api/explorer-api-paginated-list-hooks.js +441 -440
  8. package/api/explorer-batch-info-loader.js +111 -85
  9. package/api/explorer-tx-api.js +28 -28
  10. package/api/ledger-stream.js +15 -0
  11. package/asset/amount.js +56 -56
  12. package/asset/asset-icon.js +41 -41
  13. package/asset/asset-issuer.js +21 -21
  14. package/asset/asset-link.js +107 -107
  15. package/asset/asset-list-hooks.js +59 -59
  16. package/asset/asset-meta-hooks.js +88 -88
  17. package/asset/asset-selector.js +72 -71
  18. package/claimable-balance/claimable-balance-claimants.js +23 -18
  19. package/contract/contract-api.js +15 -0
  20. package/contract/invocation-info-view.js +10 -2
  21. package/contract/sc-val.js +131 -107
  22. package/controls/button-group.js +25 -19
  23. package/controls/button.js +93 -78
  24. package/controls/code-block.js +42 -34
  25. package/controls/dropdown.js +318 -287
  26. package/controls/external-link.js +10 -4
  27. package/controls/info-tooltip.js +23 -16
  28. package/controls/slider.js +29 -19
  29. package/controls/tabs.js +94 -94
  30. package/controls/tooltip.js +244 -240
  31. package/controls/update-highlighter.js +32 -27
  32. package/date/date-selector.js +56 -54
  33. package/date/elapsed-time.js +28 -21
  34. package/dex/price-dynamic.js +53 -44
  35. package/directory/directory-hooks.js +109 -97
  36. package/effect/effect-description.js +346 -344
  37. package/errors/error-boundary.js +110 -97
  38. package/filter/editors/account-filter-view.js +20 -0
  39. package/filter/editors/asset-filter-view.js +9 -0
  40. package/filter/editors/timestamp-filter-view.js +34 -0
  41. package/filter/editors/type-filter-view.js +148 -0
  42. package/filter/filter-editors.js +102 -0
  43. package/filter/filter-view.js +218 -0
  44. package/filter/filter.scss +57 -0
  45. package/horizon/horizon-account-helpers.js +104 -104
  46. package/horizon/horizon-ledger-helpers.js +35 -35
  47. package/horizon/horizon-trades-helper.js +88 -88
  48. package/horizon/horizon-transaction-helpers.js +36 -36
  49. package/index.d.ts +1271 -0
  50. package/index.js +95 -93
  51. package/interaction/accordion.js +43 -35
  52. package/interaction/autofocus.js +13 -9
  53. package/interaction/block-select.js +64 -53
  54. package/interaction/copy-to-clipboard.js +25 -18
  55. package/interaction/inline-progress.js +20 -15
  56. package/interaction/qr-code.js +34 -34
  57. package/interaction/responsive.js +20 -20
  58. package/interaction/spoiler.js +52 -39
  59. package/interaction/theme-selector.js +13 -10
  60. package/ledger/ledger-entry-href-formatter.js +27 -26
  61. package/ledger/ledger-entry-link.js +93 -58
  62. package/ledger/ledger-info-parser.js +46 -18
  63. package/meta/page-meta-tags.js +243 -238
  64. package/module/dynamic-module.js +47 -47
  65. package/package.json +71 -40
  66. package/state/on-screen-hooks.js +22 -22
  67. package/state/page-visibility-helpers.js +29 -16
  68. package/state/page-visibility-hooks.js +13 -11
  69. package/state/screen-orientation-hooks.js +19 -15
  70. package/state/state-hooks.js +76 -76
  71. package/state/stellar-network-hooks.js +56 -44
  72. package/state/theme.js +29 -28
  73. package/stellar/key-type.js +92 -91
  74. package/stellar/ledger-generic-id.js +39 -39
  75. package/stellar/signature-hint-utils.js +65 -65
  76. package/toast/toast-notifications-block.js +59 -59
  77. package/tx/op-description-view.js +945 -942
  78. package/tx/op-icon.js +98 -98
  79. package/tx/parser/op-balance-changes.js +66 -66
  80. package/tx/parser/op-descriptor.js +51 -48
  81. package/tx/parser/tx-details-parser.js +81 -81
  82. package/tx/parser/tx-matcher.js +371 -371
  83. package/tx/parser/type-filter-matcher.js +126 -126
  84. package/tx/tx-list-hooks.js +32 -18
  85. package/tx/tx-operations-list.js +117 -116
@@ -1,98 +1,111 @@
1
- import React from 'react'
2
- import PropTypes from 'prop-types'
3
- import {navigation as nav} from '@stellar-expert/navigation'
4
- import {BlockSelect} from '../interaction/block-select'
5
-
6
- export class ErrorBoundary extends React.Component {
7
- constructor(props) {
8
- super(props)
9
- this.state = {lastError: null, url: null}
10
- }
11
-
12
- componentDidCatch(e, errorInfo) {
13
- e.componentStack = errorInfo?.componentStack
14
- console.error(e)
15
- this.setState({lastError: e, url: window.location.href}, () => {
16
- const stopListening = nav.history.listen((location) => {
17
- if (this.state.url !== window.location.href) {
18
- stopListening()
19
- this.setState({lastError: null, url: null})
20
- }
21
- })
22
- })
23
- }
24
-
25
- renderError() {
26
- const {errorBoundarySendErrors = true} = this.props
27
- return <>
28
- {this.renderErrorDetails()}
29
- {errorBoundarySendErrors && this.renderSendErrorBlock()}
30
- </>
31
- }
32
-
33
- renderSendErrorBlock() {
34
- const {lastError, url} = this.state
35
- const {message, stack, componentStack} = lastError
36
- const compiledText = `Error details:
37
- "${message}" at ${url}
38
- ${stack}
39
- ${componentStack ? 'Components stack: ' + componentStack : ''}
40
- ${navigator.userAgent}`
41
- return <div className="space dimmed text-small text-right">
42
- If this error persists please{' '}
43
- <a href={'mailto:support@stellar.expert?subject=Exception&body=' + encodeURIComponent(compiledText)}
44
- target="_blank">contact our support</a>.
45
- </div>
46
- }
47
-
48
- renderErrorDetails() {
49
- const {lastError, url} = this.state
50
- const {message, stack, componentStack} = lastError
51
- const text = `"${message}" at ${url}`
52
- const {errorBoundaryErrorDetails = true} = this.props
53
- if (errorBoundaryErrorDetails === false)
54
- return null
55
- if (errorBoundaryErrorDetails === true) {
56
- return <div className="error space text-small" style={{overflow: 'auto', maxWidth: '100%', padding: '1rem 2rem'}}>
57
- <BlockSelect as="div">
58
- <div className="micro-space">{text}</div>
59
- <div className="text-tiny">
60
- <pre style={{whiteSpace: 'pre-wrap'}}>{stack}</pre>
61
- <div>{navigator.userAgent}</div>
62
- </div>
63
- </BlockSelect>
64
- </div>
65
- }
66
- return <>{errorBoundaryErrorDetails}</>
67
- }
68
-
69
- render() {
70
- if (!this.state.lastError)
71
- return this.props.children
72
- const {title = 'Unhandled error occurred', wrapper, ...otherProps} = this.props
73
- if (wrapper)
74
- return React.createElement(wrapper, {...otherProps}, this.renderError())
75
- return <div className="segment blank">
76
- <h3 className="color-danger">{title}</h3>
77
- <hr className="flare"/>
78
- {this.renderError()}
79
- </div>
80
- }
81
-
82
- static propTypes = {
83
- errorBoundaryTitle: PropTypes.string,
84
- errorBoundarySendErrors: PropTypes.bool,
85
- errorBoundaryErrorDetails: PropTypes.oneOfType([PropTypes.bool, PropTypes.any])
86
- }
87
- }
88
-
89
- export function withErrorBoundary(wrapped, {errorBoundaryTitle, errorBoundarySendErrors, errorBoundaryErrorDetails} = {}) {
90
- function ErrorBoundaryWrapper(props) {
91
- const nested = /*#__PURE__*/React.createElement(wrapped, props)
92
- return <ErrorBoundary {...{errorBoundaryTitle, errorBoundarySendErrors, errorBoundaryErrorDetails}}>{nested}</ErrorBoundary>
93
- }
94
-
95
- ErrorBoundaryWrapper.displayName = `withErrorBoundary(${wrapped.displayName || wrapped.name})`
96
- ErrorBoundaryWrapper.WrappedComponent = wrapped
97
- return ErrorBoundaryWrapper
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import {navigation as nav} from '@stellar-expert/navigation'
4
+ import {BlockSelect} from '../interaction/block-select'
5
+
6
+ /**
7
+ * React error boundary that catches rendering errors and displays a fallback UI
8
+ * @extends React.Component
9
+ */
10
+ export class ErrorBoundary extends React.Component {
11
+ constructor(props) {
12
+ super(props)
13
+ this.state = {lastError: null, url: null}
14
+ }
15
+
16
+ componentDidCatch(e, errorInfo) {
17
+ e.componentStack = errorInfo?.componentStack
18
+ console.error(e)
19
+ this.setState({lastError: e, url: window.location.href}, () => {
20
+ const stopListening = nav.history.listen((location) => {
21
+ if (this.state.url !== window.location.href) {
22
+ stopListening()
23
+ this.setState({lastError: null, url: null})
24
+ }
25
+ })
26
+ })
27
+ }
28
+
29
+ renderError() {
30
+ const {errorBoundarySendErrors = true} = this.props
31
+ return <>
32
+ {this.renderErrorDetails()}
33
+ {errorBoundarySendErrors && this.renderSendErrorBlock()}
34
+ </>
35
+ }
36
+
37
+ renderSendErrorBlock() {
38
+ const {lastError, url} = this.state
39
+ const {message, stack, componentStack} = lastError
40
+ const compiledText = `Error details:
41
+ "${message}" at ${url}
42
+ ${stack}
43
+ ${componentStack ? 'Components stack: ' + componentStack : ''}
44
+ ${navigator.userAgent}`
45
+ return <div className="space dimmed text-small text-right">
46
+ If this error persists please{' '}
47
+ <a href={'mailto:support@stellar.expert?subject=Exception&body=' + encodeURIComponent(compiledText)}
48
+ target="_blank">contact our support</a>.
49
+ </div>
50
+ }
51
+
52
+ renderErrorDetails() {
53
+ const {lastError, url} = this.state
54
+ const {message, stack, componentStack} = lastError
55
+ const text = `"${message}" at ${url}`
56
+ const {errorBoundaryErrorDetails = true} = this.props
57
+ if (errorBoundaryErrorDetails === false)
58
+ return null
59
+ if (errorBoundaryErrorDetails === true) {
60
+ return <div className="error space text-small" style={{overflow: 'auto', maxWidth: '100%', padding: '1rem 2rem'}}>
61
+ <BlockSelect as="div">
62
+ <div className="micro-space">{text}</div>
63
+ <div className="text-tiny">
64
+ <pre style={{whiteSpace: 'pre-wrap'}}>{stack}</pre>
65
+ <div>{navigator.userAgent}</div>
66
+ </div>
67
+ </BlockSelect>
68
+ </div>
69
+ }
70
+ return <>{errorBoundaryErrorDetails}</>
71
+ }
72
+
73
+ render() {
74
+ if (!this.state.lastError)
75
+ return this.props.children
76
+ const {title = 'Unhandled error occurred', wrapper, ...otherProps} = this.props
77
+ if (wrapper)
78
+ return React.createElement(wrapper, {...otherProps}, this.renderError())
79
+ return <div className="segment blank">
80
+ <h3 className="color-danger">{title}</h3>
81
+ <hr className="flare"/>
82
+ {this.renderError()}
83
+ </div>
84
+ }
85
+
86
+ static propTypes = {
87
+ errorBoundaryTitle: PropTypes.string,
88
+ errorBoundarySendErrors: PropTypes.bool,
89
+ errorBoundaryErrorDetails: PropTypes.oneOfType([PropTypes.bool, PropTypes.any])
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Higher-order component that wraps a component with an ErrorBoundary
95
+ * @param {function} wrapped - React component to wrap
96
+ * @param {Object} [options]
97
+ * @param {string} [options.errorBoundaryTitle] - Title displayed in the error UI
98
+ * @param {boolean} [options.errorBoundarySendErrors] - Show "contact support" link
99
+ * @param {boolean|*} [options.errorBoundaryErrorDetails] - Show error details (true), hide (false), or provide custom content
100
+ * @return {function} Wrapped component with error boundary
101
+ */
102
+ export function withErrorBoundary(wrapped, {errorBoundaryTitle, errorBoundarySendErrors, errorBoundaryErrorDetails} = {}) {
103
+ function ErrorBoundaryWrapper(props) {
104
+ const nested = /*#__PURE__*/React.createElement(wrapped, props)
105
+ return <ErrorBoundary {...{errorBoundaryTitle, errorBoundarySendErrors, errorBoundaryErrorDetails}}>{nested}</ErrorBoundary>
106
+ }
107
+
108
+ ErrorBoundaryWrapper.displayName = `withErrorBoundary(${wrapped.displayName || wrapped.name})`
109
+ ErrorBoundaryWrapper.WrappedComponent = wrapped
110
+ return ErrorBoundaryWrapper
98
111
  }
@@ -0,0 +1,20 @@
1
+ import React, {useCallback, useState} from 'react'
2
+ import {StrKey} from '@stellar/stellar-base'
3
+ import {AccountAddress} from '../../account/account-address'
4
+ import {useAutoFocusRef} from '../../interaction/autofocus'
5
+
6
+ export function AccountEditor({value, setValue}) {
7
+ const [internalValue, setInternalValue] = useState(value || '')
8
+ const onChange = useCallback(function (e) {
9
+ const v = e.target.value.trim()
10
+ setInternalValue(v)
11
+ if (StrKey.isValidEd25519PublicKey(v) || StrKey.isValidContract(v)) {
12
+ setValue(v)
13
+ }
14
+ }, [setValue])
15
+ if (!setValue)
16
+ return <AccountAddress account={value} link={false}/>
17
+
18
+ return <input type="text" value={internalValue} onChange={onChange} ref={useAutoFocusRef}
19
+ style={{width: '26em', maxWidth: '56vw'}} className="condensed"/>
20
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react'
2
+ import {AssetLink} from '../../asset/asset-link'
3
+ import {AssetSelector} from '../../asset/asset-selector'
4
+
5
+ export function AssetEditor({value, setValue}) {
6
+ if (!setValue)
7
+ return <AssetLink asset={value} link={false}/>
8
+ return <AssetSelector value={value} onChange={setValue} title={value ? undefined : 'Choose asset'} expanded/>
9
+ }
@@ -0,0 +1,34 @@
1
+ import React, {useCallback, useState} from 'react'
2
+ import {UtcTimestamp} from '../../date/utc-timestamp'
3
+ import {DateSelector} from '../../date/date-selector'
4
+ import {useAutoFocusRef} from '../../interaction/autofocus'
5
+
6
+ export function TimestampEditor({value, setValue, edit}) {
7
+ value = parseInt(value, 10)
8
+ const [internalValue, setInternalValue] = useState(value || undefined)
9
+
10
+ const confirm = useCallback(function () {
11
+ setInternalValue(internalValue => {
12
+ if (internalValue) {
13
+ setValue(internalValue)
14
+ }
15
+ return internalValue
16
+ })
17
+ }, [setValue])
18
+
19
+ const onKeyDown = useCallback(function (e) {
20
+ if (e.key === 'Enter') {
21
+ confirm()
22
+ }
23
+ if (e.key === 'Escape') {
24
+ setValue(value)
25
+ }
26
+ }, [confirm, setValue, value])
27
+ if (!setValue)
28
+ return <UtcTimestamp date={value} className="condensed"/>
29
+ return <>
30
+ <DateSelector value={internalValue} onChange={setInternalValue} onKeyDown={onKeyDown} ref={edit ? useAutoFocusRef : null}/>
31
+ <a href="#" className="icon-ok" onClick={confirm}/>
32
+ &nbsp;
33
+ </>
34
+ }
@@ -0,0 +1,148 @@
1
+ import React from 'react'
2
+ import {Dropdown} from '../../controls/dropdown'
3
+
4
+ export function OperationTypeEditor({value, setValue}) {
5
+ if (!setValue) {
6
+ const option = typeEditorOptions.find(opt => opt.value === value)
7
+ return <span>{option ? option.title : 'Unknown operation type'}</span>
8
+ }
9
+
10
+ return <Dropdown title="Choose operation type" expanded onChange={setValue}
11
+ options={typeEditorOptions.map(({title, value}) => ({value, title}))}/>
12
+ }
13
+
14
+ const typeEditorOptions = [
15
+ {
16
+ title: 'Group: payments',
17
+ description: 'Including CreateAccount, AccountMerge, Payment, PathPaymentStrictReceive, PathPaymentStrictSend, CreateClaimableBalance, ClaimClaimableBalance, Clawback, ClawbackClaimableBalance, Inflation operations',
18
+ value: 'payments'
19
+ },
20
+ {
21
+ title: 'Group: trustlines',
22
+ description: 'Including ChangeTrust, AllowTrust, SetTrustLineFlags operations',
23
+ value: 'trustlines'
24
+ },
25
+ {
26
+ title: 'Group: DEX trading',
27
+ description: 'Including ManageSellOffer, ManageBuyOffer, CreatePassiveSellOffer, LiquidityPoolDeposit, LiquidityPoolWithdraw operations',
28
+ value: 'dex'
29
+ },
30
+ {
31
+ title: 'Group: account settings',
32
+ description: 'Including CreateAccount, SetOptions, ChangeTrust, AllowTrust, AccountMerge, Inflation, ManageData, BumpSequence, BeginSponsoringFutureReserves, EndSponsoringFutureReserves, RevokeSponsorship, SetTrustLineFlags operations',
33
+ value: 'settings'
34
+ },
35
+ {
36
+ title: 'Group: smart contracts',
37
+ description: 'Including InvokeHostFunction, BumpFootprintExpiration, RestoreFootprint operations',
38
+ value: 'soroban'
39
+ },
40
+ {
41
+ title: 'CreateAccount',
42
+ value: '0'
43
+ },
44
+ {
45
+ title: 'Payment',
46
+ value: '1'
47
+ },
48
+ {
49
+ title: 'PathPaymentStrictReceive',
50
+ value: '2'
51
+ },
52
+ {
53
+ title: 'ManageSellOffer',
54
+ value: '3'
55
+ },
56
+ {
57
+ title: 'CreatePassiveSellOffer',
58
+ value: '4'
59
+ },
60
+ {
61
+ title: 'SetOptions',
62
+ value: '5'
63
+ },
64
+ {
65
+ title: 'ChangeTrust',
66
+ value: '6'
67
+ },
68
+ {
69
+ title: 'AllowTrust',
70
+ value: '7'
71
+ },
72
+ {
73
+ title: 'AccountMerge',
74
+ value: '8'
75
+ },
76
+ {
77
+ title: 'Inflation',
78
+ value: '9'
79
+ },
80
+ {
81
+ title: 'ManageData',
82
+ value: '10'
83
+ },
84
+ {
85
+ title: 'BumpSequence',
86
+ value: '11'
87
+ },
88
+ {
89
+ title: 'ManageBuyOffer',
90
+ value: '12'
91
+ },
92
+ {
93
+ title: 'PathPaymentStrictSend',
94
+ value: '13'
95
+ },
96
+ {
97
+ title: 'CreateClaimableBalance',
98
+ value: '14'
99
+ },
100
+ {
101
+ title: 'ClaimClaimableBalance',
102
+ value: '15'
103
+ },
104
+ {
105
+ title: 'BeginSponsoringFutureReserves',
106
+ value: '16'
107
+ },
108
+ {
109
+ title: 'EndSponsoringFutureReserves',
110
+ value: '17'
111
+ },
112
+ {
113
+ title: 'RevokeSponsorship',
114
+ value: '18'
115
+ },
116
+ {
117
+ title: 'Clawback',
118
+ value: '19'
119
+ },
120
+ {
121
+ title: 'ClawbackClaimableBalance',
122
+ value: '20'
123
+ },
124
+ {
125
+ title: 'SetTrustLineFlags',
126
+ value: '21'
127
+ },
128
+ {
129
+ title: 'LiquidityPoolDeposit',
130
+ value: '22'
131
+ },
132
+ {
133
+ title: 'LiquidityPoolWithdraw',
134
+ value: '23'
135
+ },
136
+ {
137
+ title: 'InvokeHostFunction',
138
+ value: '24'
139
+ },
140
+ {
141
+ title: 'BumpFootprintExpiration',
142
+ value: '25'
143
+ },
144
+ {
145
+ title: 'RestoreFootprint',
146
+ value: '26'
147
+ }
148
+ ]
@@ -0,0 +1,102 @@
1
+ import React, {useCallback, useState} from 'react'
2
+ import {StrKey} from '@stellar/stellar-base'
3
+ import {shortenString} from '@stellar-expert/formatter'
4
+ import {AssetLink} from '../asset/asset-link'
5
+ import {useAutoFocusRef} from '../interaction/autofocus'
6
+ import {OperationTypeEditor} from './editors/type-filter-view'
7
+ import {AssetEditor} from './editors/asset-filter-view'
8
+ import {AccountEditor} from './editors/account-filter-view'
9
+ import {TimestampEditor} from './editors/timestamp-filter-view'
10
+
11
+ export function TextEditor({value, setValue, mask}) {
12
+ const [internalValue, setInternalValue] = useState(value || '')
13
+
14
+ const onChange = useCallback(function (e) {
15
+ let v = e.target.value.trim()
16
+ if (mask instanceof RegExp) {
17
+ v = v.replace(mask, '')
18
+ }
19
+ if (typeof mask === 'function') {
20
+ v = mask(v)
21
+ }
22
+ setInternalValue(v)
23
+ }, [mask])
24
+
25
+ const confirm = useCallback(function () {
26
+ setInternalValue(internalValue => {
27
+ setValue(internalValue)
28
+ return internalValue
29
+ })
30
+ }, [setValue])
31
+
32
+ const onKeyDown = useCallback(function (e) {
33
+ if (e.key === 'Enter') {
34
+ confirm()
35
+ }
36
+ if (e.key === 'Escape') {
37
+ setValue(value)
38
+ }
39
+ }, [confirm, setValue, value])
40
+
41
+ if (!setValue) {
42
+ value = value.toString()
43
+ return <span>{value.length > 20 ? shortenString(value, 12) : value}</span>
44
+ }
45
+
46
+ return <>
47
+ <input type="text" value={internalValue} ref={useAutoFocusRef} onChange={onChange} onKeyDown={onKeyDown}
48
+ style={{width: '16em', maxWidth: '50vw'}}/>&nbsp;
49
+ <a href="#" className="icon-ok" onClick={confirm}/>
50
+ </>
51
+ }
52
+
53
+ function OfferIdEditor({value, setValue}) {
54
+ return <TextEditor value={value} setValue={setValue} mask={/[\D]/g}/>
55
+ }
56
+
57
+ function LiquidityPoolEditor({value, setValue}) {
58
+ if (!setValue) {
59
+ if (/^[a-f0-9]{64}$/.test(value)) { //remap hex format to pool id format
60
+ try {
61
+ value = StrKey.encodeLiquidityPool(Buffer.from(value, 'hex'))
62
+ } catch (_) {
63
+ }
64
+ }
65
+ if (!StrKey.isValidLiquidityPool(value))
66
+ return <span className="dimmed">(Invalid pool)</span>
67
+ if (value.startsWith('native'))
68
+ return <span className="dimmed">(Native pool)</span>
69
+ return <AssetLink asset={value} link={false}/>
70
+ }
71
+ return <TextEditor value={value} setValue={setValue} mask={/[\W]/g}/>
72
+ }
73
+
74
+ function MemoEditor({value, setValue}) {
75
+ return <TextEditor value={value} setValue={setValue} mask={v => v.substring(0, 64)}/>
76
+ }
77
+
78
+ export function TopicEditor({value, setValue}) {
79
+ if (!setValue)
80
+ return <code className="word-break">{value}</code>
81
+ return <TextEditor value={value} setValue={setValue}/>
82
+ }
83
+
84
+ const editorMapping = {
85
+ topic: TopicEditor,
86
+ type: OperationTypeEditor,
87
+ account: AccountEditor,
88
+ source: AccountEditor,
89
+ destination: AccountEditor,
90
+ asset: AssetEditor,
91
+ src_asset: AssetEditor,
92
+ dest_asset: AssetEditor,
93
+ from: TimestampEditor,
94
+ to: TimestampEditor,
95
+ memo: MemoEditor,
96
+ offer: OfferIdEditor,
97
+ pool: LiquidityPoolEditor
98
+ }
99
+
100
+ export function resolveFilterEditor(field) {
101
+ return editorMapping[field]
102
+ }