@stellar-expert/ui-framework 1.16.8 → 1.17.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.
- package/CLAUDE.md +35 -0
- package/README.md +1125 -3
- package/account/account-address.js +127 -127
- package/account/available-balance.js +22 -22
- package/account/identicon.js +90 -90
- package/account/signer-key.js +65 -64
- package/api/explorer-api-hooks.js +209 -202
- package/api/explorer-api-paginated-list-hooks.js +441 -440
- package/api/explorer-batch-info-loader.js +111 -85
- package/api/explorer-tx-api.js +28 -28
- package/api/ledger-stream.js +15 -0
- package/asset/amount.js +56 -56
- package/asset/asset-icon.js +41 -41
- package/asset/asset-issuer.js +21 -21
- package/asset/asset-link.js +107 -107
- package/asset/asset-list-hooks.js +59 -59
- package/asset/asset-meta-hooks.js +88 -88
- package/asset/asset-selector.js +72 -71
- package/claimable-balance/claimable-balance-claimants.js +23 -18
- package/contract/contract-api.js +15 -0
- package/contract/invocation-info-view.js +10 -2
- package/contract/sc-val.js +131 -107
- package/controls/button-group.js +25 -19
- package/controls/button.js +93 -78
- package/controls/code-block.js +42 -34
- package/controls/dropdown.js +318 -287
- package/controls/external-link.js +10 -4
- package/controls/info-tooltip.js +23 -16
- package/controls/slider.js +29 -19
- package/controls/tabs.js +94 -94
- package/controls/tooltip.js +244 -240
- package/controls/update-highlighter.js +32 -27
- package/date/date-selector.js +56 -54
- package/date/elapsed-time.js +28 -21
- package/dex/price-dynamic.js +53 -44
- package/directory/directory-hooks.js +109 -97
- package/effect/effect-description.js +346 -344
- package/errors/error-boundary.js +110 -97
- package/horizon/horizon-account-helpers.js +104 -104
- package/horizon/horizon-ledger-helpers.js +35 -35
- package/horizon/horizon-trades-helper.js +88 -88
- package/horizon/horizon-transaction-helpers.js +36 -36
- package/index.d.ts +1241 -0
- package/interaction/accordion.js +43 -35
- package/interaction/autofocus.js +13 -9
- package/interaction/block-select.js +64 -53
- package/interaction/copy-to-clipboard.js +25 -18
- package/interaction/inline-progress.js +20 -15
- package/interaction/qr-code.js +34 -34
- package/interaction/responsive.js +20 -20
- package/interaction/spoiler.js +52 -39
- package/interaction/theme-selector.js +13 -10
- package/ledger/ledger-entry-href-formatter.js +27 -26
- package/ledger/ledger-entry-link.js +93 -58
- package/ledger/ledger-info-parser.js +46 -18
- package/meta/page-meta-tags.js +243 -238
- package/module/dynamic-module.js +47 -47
- package/package.json +41 -40
- package/state/on-screen-hooks.js +22 -22
- package/state/page-visibility-helpers.js +29 -16
- package/state/page-visibility-hooks.js +13 -11
- package/state/screen-orientation-hooks.js +19 -15
- package/state/state-hooks.js +76 -76
- package/state/stellar-network-hooks.js +56 -44
- package/state/theme.js +29 -28
- package/stellar/key-type.js +92 -91
- package/stellar/ledger-generic-id.js +39 -39
- package/stellar/signature-hint-utils.js +65 -65
- package/toast/toast-notifications-block.js +59 -59
- package/tx/op-description-view.js +945 -942
- package/tx/op-icon.js +98 -98
- package/tx/parser/op-balance-changes.js +66 -66
- package/tx/parser/op-descriptor.js +51 -48
- package/tx/parser/tx-details-parser.js +81 -81
- package/tx/parser/tx-matcher.js +371 -371
- package/tx/parser/type-filter-matcher.js +126 -126
- package/tx/tx-list-hooks.js +32 -18
- package/tx/tx-operations-list.js +117 -116
package/asset/asset-selector.js
CHANGED
|
@@ -1,72 +1,73 @@
|
|
|
1
|
-
import React, {useCallback, useRef, useState} from 'react'
|
|
2
|
-
import {Dropdown} from '../controls/dropdown'
|
|
3
|
-
import {AssetLink} from './asset-link'
|
|
4
|
-
import {useAssetList} from './asset-list-hooks'
|
|
5
|
-
import './asset-selector.scss'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* @param {
|
|
10
|
-
* @param {
|
|
11
|
-
* @param {
|
|
12
|
-
* @param {
|
|
13
|
-
* @param {
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
* @
|
|
1
|
+
import React, {useCallback, useRef, useState} from 'react'
|
|
2
|
+
import {Dropdown} from '../controls/dropdown'
|
|
3
|
+
import {AssetLink} from './asset-link'
|
|
4
|
+
import {useAssetList} from './asset-list-hooks'
|
|
5
|
+
import './asset-selector.scss'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Asset picker dropdown with search
|
|
9
|
+
* @param {AssetSelectorOnAssetChanged} onChange - On asset selected callback
|
|
10
|
+
* @param {string} [value] - Selected asset
|
|
11
|
+
* @param {string[]} [predefinedAssets] - Optional lists of predefined assets that should be shown at the top of the dropdown list
|
|
12
|
+
* @param {boolean} [restricted] - If set, the selector is limited to the predefined assets list only
|
|
13
|
+
* @param {string} [title] - Dropdown selector title
|
|
14
|
+
* @param {string} [expanded] - Expanded by default
|
|
15
|
+
* @return {JSX.Element}
|
|
16
|
+
* @constructor
|
|
17
|
+
*/
|
|
18
|
+
export function AssetSelector({value, predefinedAssets, onChange, restricted, title, expanded}) {
|
|
19
|
+
const [search, setSearch] = useState('')
|
|
20
|
+
const searchRef = useRef()
|
|
21
|
+
const options = []
|
|
22
|
+
|
|
23
|
+
const focusSearch = useCallback(() => {
|
|
24
|
+
setTimeout(() => searchRef.current?.focus(), 200)
|
|
25
|
+
}, [])
|
|
26
|
+
|
|
27
|
+
if (predefinedAssets) {
|
|
28
|
+
for (const asset of predefinedAssets) {
|
|
29
|
+
options.push({
|
|
30
|
+
value: asset,
|
|
31
|
+
title: <AssetLink link={false} asset={asset}/>,
|
|
32
|
+
hidden: search && !asset.split('-')[0].toLowerCase().includes(search.toLowerCase())
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let loadNextPage
|
|
38
|
+
if (!restricted) {
|
|
39
|
+
const {assets, loadPage, loading} = useAssetList({search: search?.trim() || undefined})
|
|
40
|
+
for (let {asset} of assets) {
|
|
41
|
+
if (!predefinedAssets || !predefinedAssets.includes(asset)) {
|
|
42
|
+
options.push({value: asset, title: <AssetLink link={false} asset={asset}/>})
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (!options.filter(opt => !opt.hidden).length) {
|
|
46
|
+
if (loading) {
|
|
47
|
+
options.push({value: '...', disabled: true, title: <div className="loader"/>})
|
|
48
|
+
} else {
|
|
49
|
+
options.push({
|
|
50
|
+
value: 'no',
|
|
51
|
+
disabled: true,
|
|
52
|
+
title: <div className="dimmed text-center text-small">(not found)</div>
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
loadNextPage = loadPage
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return <Dropdown solo className="asset-selector" options={options} value={value} onOpen={focusSearch} title={title} expanded={expanded}
|
|
60
|
+
showToggle={!title} onChange={onChange} onScroll={e => e.rel === 'bottom' && loadNextPage?.call(this)} header={<>
|
|
61
|
+
<h3>Select an asset</h3>
|
|
62
|
+
<div className="relative">
|
|
63
|
+
<input type="text" value={search} ref={searchRef} onChange={e => setSearch(e.target.value)}
|
|
64
|
+
placeholder="Search by asset code or website"/>
|
|
65
|
+
<i className="icon-search dimmed"/>
|
|
66
|
+
</div>
|
|
67
|
+
</>}/>
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @callback AssetSelectorOnAssetChanged
|
|
72
|
+
* @param {string} value
|
|
72
73
|
*/
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import {xdrParseClaimant} from '@stellar-expert/claimable-balance-utils'
|
|
3
|
-
import {AccountAddress} from '../account/account-address'
|
|
4
|
-
import {CodeBlock} from '../controls/code-block'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {xdrParseClaimant} from '@stellar-expert/claimable-balance-utils'
|
|
3
|
+
import {AccountAddress} from '../account/account-address'
|
|
4
|
+
import {CodeBlock} from '../controls/code-block'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Displays a list of claimable balance claimants with their addresses and predicates
|
|
8
|
+
* @param {Object} props
|
|
9
|
+
* @param {Array<Object>} props.claimants - Array of claimant objects (raw XDR or parsed)
|
|
10
|
+
*/
|
|
11
|
+
export const ClaimableBalanceClaimants = React.memo(function ClaimableBalanceClaimants({claimants}) {
|
|
12
|
+
const parsed = claimants.map(c => {
|
|
13
|
+
if (c.destination && c.predicate && !c._predicate)
|
|
14
|
+
return c
|
|
15
|
+
return xdrParseClaimant(c)
|
|
16
|
+
})
|
|
17
|
+
return <>
|
|
18
|
+
{parsed.map((c, i) => <span key={i + c.destination}>{i > 0 && ', '}
|
|
19
|
+
<AccountAddress account={c.destination}/> {typeof c.predicate === 'string' ?
|
|
20
|
+
c.predicate :
|
|
21
|
+
<div className="block-indent"><CodeBlock>{JSON.stringify(c.predicate, null, 2)}</CodeBlock></div>}
|
|
22
|
+
</span>)}
|
|
23
|
+
</>
|
|
19
24
|
})
|
package/contract/contract-api.js
CHANGED
|
@@ -2,6 +2,11 @@ import {useEffect, useState} from 'react'
|
|
|
2
2
|
import {useExplorerApi} from '../api/explorer-api-hooks'
|
|
3
3
|
import {getCurrentStellarNetwork} from '../state/stellar-network-hooks'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* React hook that fetches contract information from the Explorer API
|
|
7
|
+
* @param {string} address - Contract address
|
|
8
|
+
* @return {ExplorerApiResult}
|
|
9
|
+
*/
|
|
5
10
|
export function useContractInfo(address) {
|
|
6
11
|
return useExplorerApi('contract/' + address, {
|
|
7
12
|
processResult(data) {
|
|
@@ -14,10 +19,20 @@ export function useContractInfo(address) {
|
|
|
14
19
|
})
|
|
15
20
|
}
|
|
16
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Generate a URL to download the WASM source for a contract
|
|
24
|
+
* @param {string} hash - Contract WASM hash
|
|
25
|
+
* @return {string} Full URL to the contract WASM source
|
|
26
|
+
*/
|
|
17
27
|
export function generateContractSourceLink(hash) {
|
|
18
28
|
return `${explorerApiOrigin}/explorer/${getCurrentStellarNetwork()}/contract/wasm/${hash}`
|
|
19
29
|
}
|
|
20
30
|
|
|
31
|
+
/**
|
|
32
|
+
* React hook that fetches contract WASM binary source by hash
|
|
33
|
+
* @param {string} hash - Contract WASM hash
|
|
34
|
+
* @return {ArrayBuffer|null|undefined} WASM binary (undefined while loading, null if not found)
|
|
35
|
+
*/
|
|
21
36
|
export function useContractSource(hash) {
|
|
22
37
|
const [source, setSource] = useState()
|
|
23
38
|
useEffect(() => {
|
|
@@ -8,6 +8,14 @@ import {parseScValValue, primitiveTypes, ScVal, ScValStruct} from './sc-val'
|
|
|
8
8
|
import {useContractSource} from './contract-api'
|
|
9
9
|
import {sacInterface} from './sac-interface'
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Basic Soroban contract invocation info
|
|
13
|
+
* @param {string} [contract] - Contract address
|
|
14
|
+
* @param {string} func - Invoked function name
|
|
15
|
+
* @param {Array|string} args - Function arguments (ScVal array or XDR string)
|
|
16
|
+
* @param {string|xdr.ScVal} [result] - Invocation result
|
|
17
|
+
* @param {string} [sac] - Stellar Asset Contract identifier
|
|
18
|
+
*/
|
|
11
19
|
export default function InvocationInfoView({contract, func, args, result, sac}) {
|
|
12
20
|
if (typeof args === 'string') {
|
|
13
21
|
args = parseScValValue(args)
|
|
@@ -45,13 +53,13 @@ const ExtendedInvocationInfoView = React.memo(function ({contract, func, args, r
|
|
|
45
53
|
const fd = meta.functions[func]
|
|
46
54
|
if (!fd)
|
|
47
55
|
return <div className="error"><i className="icon-warning-circle"/> Failed to parse contract code</div>
|
|
48
|
-
const shouldIndent = args.length > 2 ||
|
|
56
|
+
const shouldIndent = args.length > 2 || fd.inputs.some(i => !primitiveTypes.has(i.type)) // multi-line display for large argument number or complex types
|
|
49
57
|
const contractInfo = sac ?
|
|
50
58
|
<> from asset <AssetLink asset={sac}/></> :
|
|
51
59
|
<span className="text-tiny dimmed">
|
|
52
60
|
 SDK v{meta.sdkVersion.split('#')[0]} RUST v{shortenString(meta.rustVersion, 12)}
|
|
53
61
|
</span>
|
|
54
|
-
const contractArgNames =
|
|
62
|
+
const contractArgNames = fd.inputs.map(i => i.name)
|
|
55
63
|
//TODO: show contract validation info
|
|
56
64
|
return <div>
|
|
57
65
|
<div>
|
package/contract/sc-val.js
CHANGED
|
@@ -1,108 +1,132 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import cn from 'classnames'
|
|
3
|
-
import {xdr, scValToBigInt} from '@stellar/stellar-base'
|
|
4
|
-
import {xdrParserUtils} from '@stellar-expert/tx-meta-effects-parser'
|
|
5
|
-
import {shortenString} from '@stellar-expert/formatter'
|
|
6
|
-
import {AccountAddress} from '../account/account-address'
|
|
7
|
-
import './sc-val.scss'
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
case '
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
case '
|
|
44
|
-
|
|
45
|
-
case '
|
|
46
|
-
case '
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
case '
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return
|
|
67
|
-
case '
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
case '
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import cn from 'classnames'
|
|
3
|
+
import {xdr, scValToBigInt} from '@stellar/stellar-base'
|
|
4
|
+
import {xdrParserUtils} from '@stellar-expert/tx-meta-effects-parser'
|
|
5
|
+
import {shortenString} from '@stellar-expert/formatter'
|
|
6
|
+
import {AccountAddress} from '../account/account-address'
|
|
7
|
+
import './sc-val.scss'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Renders a Stellar smart contract value (ScVal) in a human-readable format
|
|
11
|
+
* @param {Object} props
|
|
12
|
+
* @param {string|xdr.ScVal|Array} props.value - ScVal as base64 XDR string, parsed XDR object, or array
|
|
13
|
+
* @param {boolean} [props.nested=false] - Whether this is a nested rendering (internal use)
|
|
14
|
+
* @param {boolean} [props.indent=false] - Enable block-level indentation for nested structures
|
|
15
|
+
* @param {boolean} [props.wrapObjects=true] - Wrap maps and arrays with brackets
|
|
16
|
+
*/
|
|
17
|
+
export const ScVal = React.memo(function ScVal({value, nested = false, indent = false, wrapObjects = true}) {
|
|
18
|
+
if (!nested)
|
|
19
|
+
return <code className={cn('sc-val', {block: indent})}><ScVal value={value} indent={indent} nested/></code>
|
|
20
|
+
if (!value)
|
|
21
|
+
return 'void'
|
|
22
|
+
if (typeof value === 'string') {
|
|
23
|
+
value = xdr.ScVal.fromXDR(value, 'base64')
|
|
24
|
+
}
|
|
25
|
+
if (value instanceof Array) {
|
|
26
|
+
const values = value.map((v, i) => <ScValStruct key={i} indent={indent} separate={value.length - i}>
|
|
27
|
+
<ScVal value={v} indent={indent} nested/>
|
|
28
|
+
</ScValStruct>)
|
|
29
|
+
return wrapObjects ? <>[{values}]</> : <>{values}</>
|
|
30
|
+
}
|
|
31
|
+
const val = value._value
|
|
32
|
+
switch (value._arm) {
|
|
33
|
+
case 'vec':
|
|
34
|
+
return <>[{val.map((v, i) => <ScValStruct key={i} indent={indent} separate={val.length - i}>
|
|
35
|
+
<ScVal value={v} indent={indent} nested/>
|
|
36
|
+
</ScValStruct>)}]</>
|
|
37
|
+
case 'map':
|
|
38
|
+
const values = val.map((kv, i) =>
|
|
39
|
+
<ScValStruct key={i} indent={indent} separate={val.length - i}>
|
|
40
|
+
<ScVal value={kv.key()} indent={indent} nested/>: <ScVal value={kv.val()} indent={indent} nested/>
|
|
41
|
+
</ScValStruct>)
|
|
42
|
+
return wrapObjects ? <>{{values}}</> : <>{values}</>
|
|
43
|
+
case 'b':
|
|
44
|
+
return <>{val.toString()}<ScValType type="bool"/></>
|
|
45
|
+
case 'i32':
|
|
46
|
+
case 'u32':
|
|
47
|
+
return <>{val}<ScValType type={value._arm}/></>
|
|
48
|
+
case 'i256':
|
|
49
|
+
case 'u256':
|
|
50
|
+
case 'i128':
|
|
51
|
+
case 'u128':
|
|
52
|
+
case 'i64':
|
|
53
|
+
case 'u64':
|
|
54
|
+
case 'timepoint':
|
|
55
|
+
case 'duration':
|
|
56
|
+
return <>{scValToBigInt(value).toString()}<ScValType type={value._arm}/></>
|
|
57
|
+
case 'address':
|
|
58
|
+
switch (val._arm) {
|
|
59
|
+
case 'accountId':
|
|
60
|
+
return <AccountAddress account={xdrParserUtils.xdrParseAccountAddress(val.value())}/>
|
|
61
|
+
case 'contractId':
|
|
62
|
+
return <AccountAddress account={xdrParserUtils.xdrParseContractAddress(val.value())}/>
|
|
63
|
+
case 'muxedAccount':
|
|
64
|
+
return <AccountAddress account={xdrParserUtils.xdrParseMuxedScAddress(val.value())}/>
|
|
65
|
+
}
|
|
66
|
+
return <span className="dimmed">(unsupported address)</span>
|
|
67
|
+
case 'bytes':
|
|
68
|
+
const asBytes = val.toString('base64')
|
|
69
|
+
return <><span className="condensed">{shortenString(asBytes, 86)}</span><ScValType type="bytes"/></>
|
|
70
|
+
case 'str':
|
|
71
|
+
case 'sym':
|
|
72
|
+
return <span className="word-break">"{val.toString()}"<ScValType type={value._arm}/></span>
|
|
73
|
+
case 'nonceKey':
|
|
74
|
+
return <>{val.nonce()._value.toString()}<ScValType type="nonce"/></>
|
|
75
|
+
case 'instance':
|
|
76
|
+
if (val._attributes.executable._switch.name==="contractExecutableStellarAsset")
|
|
77
|
+
return <span>StellarAsset<ScValType type="instance"/></span>
|
|
78
|
+
return <span className="word-break">{val._attributes.executable.wasmHash().toString('hex')}<ScValType type="wasm"/></span>
|
|
79
|
+
case 'error':
|
|
80
|
+
const errMessage = value.toXDR('base64')
|
|
81
|
+
return <><span className="condensed" title={errMessage}>{shortenString(errMessage, 50)}</span><ScValType type="error"/></>
|
|
82
|
+
case 'contractId':
|
|
83
|
+
return <AccountAddress account={xdrParserUtils.xdrParseContractAddress(value._value)}/>
|
|
84
|
+
default:
|
|
85
|
+
switch (value._switch.name) {
|
|
86
|
+
case 'scvVoid':
|
|
87
|
+
return '()'
|
|
88
|
+
case 'scvContractInstance':
|
|
89
|
+
return '<ContractInstance>'
|
|
90
|
+
case 'scvLedgerKeyContractInstance':
|
|
91
|
+
return '<LedgerKeyContractInstance>'
|
|
92
|
+
case 'scvLedgerKeyNonce':
|
|
93
|
+
return '<LedgerKeyNonce>'
|
|
94
|
+
}
|
|
95
|
+
return <span className="dimmed">(unknown)</span>
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Parse a base64-encoded XDR ScVal string into an xdr.ScVal object
|
|
101
|
+
* @param {string} value - Base64-encoded XDR string
|
|
102
|
+
* @return {xdr.ScVal}
|
|
103
|
+
*/
|
|
104
|
+
export function parseScValValue(value) {
|
|
105
|
+
return xdr.ScVal.fromXDR(value, 'base64')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const ScValType = React.memo(function ScValType({type}) {
|
|
109
|
+
return <sub className="dimmed text-tiny" style={{padding: '0 0.2em'}}>{type}</sub>
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Structural wrapper for ScVal elements, handling indentation and separators
|
|
114
|
+
* @param {Object} props
|
|
115
|
+
* @param {boolean} [props.indent] - Enable block-level indentation
|
|
116
|
+
* @param {*} props.children - Nested content
|
|
117
|
+
* @param {number} [props.separate] - Show comma separator when > 1
|
|
118
|
+
*/
|
|
119
|
+
export const ScValStruct = React.memo(function ScValStruct({indent, children, separate}) {
|
|
120
|
+
const separator = separate > 1 ? <>, </> : null
|
|
121
|
+
if (!indent)
|
|
122
|
+
return <>{children}{separator}</>
|
|
123
|
+
return <div className="block-indent">
|
|
124
|
+
{children}{separator}
|
|
125
|
+
</div>
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Set of primitive ScVal type identifiers
|
|
130
|
+
* @type {Set<string>}
|
|
131
|
+
*/
|
|
108
132
|
export const primitiveTypes = new Set(['b', 'i32', 'u32', 'i256', 'u256', 'i128', 'u128', 'i64', 'u64', 'timepoint', 'duration', 'address', 'bytes', 'str', 'sym', 'nonceKey', 'contractId', 'instance'])
|
package/controls/button-group.js
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import PropTypes from 'prop-types'
|
|
3
|
-
import './button-group.scss'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
ButtonGroup
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import './button-group.scss'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Groups multiple buttons together with consistent spacing
|
|
7
|
+
* @param {Object} props
|
|
8
|
+
* @param {boolean} [props.inline] - Render as inline element (`<span>`) instead of block (`<div>`)
|
|
9
|
+
* @param {*} props.children - Nested buttons
|
|
10
|
+
*/
|
|
11
|
+
export const ButtonGroup = React.memo(function ButtonGroup({inline, children, ...otherProps}) {
|
|
12
|
+
if (inline)
|
|
13
|
+
return <span className="button-group" {...otherProps}>{children}</span>
|
|
14
|
+
return <div className="button-group" {...otherProps}>{children}</div>
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
ButtonGroup.propTypes = {
|
|
18
|
+
/**
|
|
19
|
+
* Nested buttons
|
|
20
|
+
*/
|
|
21
|
+
children: PropTypes.any.isRequired,
|
|
22
|
+
/**
|
|
23
|
+
* Whether to render the group as inline element (span)
|
|
24
|
+
*/
|
|
25
|
+
inline: PropTypes.bool
|
|
20
26
|
}
|