@stellar-expert/ui-framework 1.13.5 → 1.13.7
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.
|
@@ -22,9 +22,9 @@ export default function InvocationInfoView({contract, func, args, result, sac})
|
|
|
22
22
|
<code>{func}({args.map((arg, i) => <ScValStruct key={i} separate={args.length - i}>
|
|
23
23
|
<ScVal value={arg} nested/>
|
|
24
24
|
</ScValStruct>)})<InvocationResult result={result}/></code>
|
|
25
|
-
<Tooltip trigger={<i className="trigger icon-info"/>} desiredPlace="top" activation="click" maxWidth="Min(60em, 40vw)">
|
|
25
|
+
{!!contract && <Tooltip trigger={<i className="trigger icon-info"/>} desiredPlace="top" activation="click" maxWidth="Min(60em, 40vw)">
|
|
26
26
|
<ExtendedInvocationInfoView {...{contract, func, args, result, sac}}/>
|
|
27
|
-
</Tooltip
|
|
27
|
+
</Tooltip>}{' '}
|
|
28
28
|
</>
|
|
29
29
|
}
|
|
30
30
|
|
package/contract/sc-val.js
CHANGED
|
@@ -63,15 +63,23 @@ export const ScVal = React.memo(function ScVal({value, nested = false, indent =
|
|
|
63
63
|
case 'nonceKey':
|
|
64
64
|
return <>{val.nonce()._value.toString()}<ScValType type="nonce"/></>
|
|
65
65
|
case 'instance':
|
|
66
|
-
return
|
|
66
|
+
return <span className="word-break">{val._attributes.executable.wasmHash().toString('hex')}<ScValType type="wasm"/></span>
|
|
67
67
|
case 'error':
|
|
68
68
|
const errMessage = value.toXDR('base64')
|
|
69
69
|
return <><span className="condensed" title={errMessage}>{shortenString(errMessage, 50)}</span><ScValType type="error"/></>
|
|
70
70
|
case 'contractId':
|
|
71
71
|
return <AccountAddress account={xdrParserUtils.xdrParseContractAddress(value._value)}/>
|
|
72
72
|
default:
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
switch (value._switch.name) {
|
|
74
|
+
case 'scvVoid':
|
|
75
|
+
return '()'
|
|
76
|
+
case 'scvContractInstance':
|
|
77
|
+
return '<ContractInstance>'
|
|
78
|
+
case 'scvLedgerKeyContractInstance':
|
|
79
|
+
return '<LedgerKeyContractInstance>'
|
|
80
|
+
case 'scvLedgerKeyNonce':
|
|
81
|
+
return '<LedgerKeyNonce>'
|
|
82
|
+
}
|
|
75
83
|
return <span className="dimmed">(unknown)</span>
|
|
76
84
|
}
|
|
77
85
|
})
|
|
@@ -14,6 +14,7 @@ import InvocationInfoView from '../contract/invocation-info-view'
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* @param {{}} effect
|
|
17
|
+
* @param {{}} operation
|
|
17
18
|
* @return {JSX.Element}
|
|
18
19
|
* @constructor
|
|
19
20
|
*/
|
|
@@ -25,10 +26,10 @@ export function EffectDescription({effect, operation}) {
|
|
|
25
26
|
return <>Account <AccountAddress account={effect.source}/> removed</>
|
|
26
27
|
case 'accountCredited':
|
|
27
28
|
return <><Amount asset={effect.asset} amount={effect.amount} adjust/> credited to
|
|
28
|
-
{effect.source.startsWith('C') ? 'contract' : 'account'} <AccountAddress account={effect.source}/></>
|
|
29
|
+
{effect.source.startsWith('C') ? ' contract' : ' account'} <AccountAddress account={effect.source}/></>
|
|
29
30
|
case 'accountDebited':
|
|
30
31
|
return <><Amount asset={effect.asset} amount={effect.amount} adjust/> debited from
|
|
31
|
-
{effect.source.startsWith('C') ? 'contract' : 'account'} <AccountAddress account={effect.source}/></>
|
|
32
|
+
{effect.source.startsWith('C') ? ' contract' : ' account'} <AccountAddress account={effect.source}/></>
|
|
32
33
|
case 'accountThresholdsUpdated':
|
|
33
34
|
return <>Account <AccountAddress account={effect.source}/> set thresholds to {effect.thresholds.join('/')}</>
|
|
34
35
|
case 'accountHomeDomainUpdated':
|
|
@@ -211,13 +212,15 @@ export function EffectDescription({effect, operation}) {
|
|
|
211
212
|
case 'inflation':
|
|
212
213
|
return <>Inflation distribution initialized</>
|
|
213
214
|
case 'contractCodeUploaded':
|
|
214
|
-
return <>Contract code <ContractCodeWasm wasm={effect.wasm}
|
|
215
|
+
return <>Contract code <LedgerKeyHint effect={effect}><ContractCodeWasm wasm={effect.wasm}/></LedgerKeyHint> uploaded</>
|
|
215
216
|
case 'contractCreated':
|
|
216
217
|
return <>Contract <AccountAddress account={effect.contract}/> created <ContractDetails effect={effect}/></>
|
|
218
|
+
case 'contractUpdated':
|
|
219
|
+
return <>Contract <AccountAddress account={effect.contract}/> updated <ContractDetails effect={effect}/></>
|
|
217
220
|
case 'contractInvoked':
|
|
218
221
|
return <>{effect.depth > 0 &&
|
|
219
222
|
<i className="icon-level-down text-tiny color-primary" style={{paddingLeft: (effect.depth - 1) + 'em'}}/>}
|
|
220
|
-
|
|
223
|
+
Invoked contract <AccountAddress account={effect.contract}/>{' '}
|
|
221
224
|
<InvocationInfoView func={effect.function} args={effect.rawArgs} contract={effect.contract} result={effect.result} sac={operation.operation.sacMap?.[effect.contract]}/>
|
|
222
225
|
</>
|
|
223
226
|
case 'contractEvent':
|
|
@@ -227,10 +230,11 @@ export function EffectDescription({effect, operation}) {
|
|
|
227
230
|
case 'contractDataUpdated':
|
|
228
231
|
return <>Contract <AccountAddress account={effect.owner}/>
|
|
229
232
|
{effect.type === 'contractDataCreated' ? ' created ' : ' updated '} {effect.durability} data{' '}
|
|
230
|
-
<ScVal value={effect.key}
|
|
233
|
+
<LedgerKeyHint effect={effect}><ScVal value={effect.key}/></LedgerKeyHint> with value <ScVal value={effect.value}/>
|
|
231
234
|
</>
|
|
232
235
|
case 'contractDataRemoved':
|
|
233
|
-
return <>Contract <AccountAddress account={effect.owner}/> removed {effect.durability}
|
|
236
|
+
return <>Contract <AccountAddress account={effect.owner}/> removed {effect.durability}{' '}
|
|
237
|
+
data <LedgerKeyHint effect={effect}><ScVal value={effect.key}/></LedgerKeyHint></>
|
|
234
238
|
case 'contractError':
|
|
235
239
|
let errCode = effect.code
|
|
236
240
|
if (errCode?.name) {
|
|
@@ -238,6 +242,12 @@ export function EffectDescription({effect, operation}) {
|
|
|
238
242
|
}
|
|
239
243
|
return <>Execution error {errCode ? <><code>{errCode}</code> </> : null}in <AccountAddress account={effect.contract}/>{': '}
|
|
240
244
|
<code>{JSON.stringify(effect.details)}</code> </>
|
|
245
|
+
case 'setTtl':
|
|
246
|
+
return <>Time-to-live extended to ledger {effect.ttl} for {!!effect.owner && <AccountAddress account={effect.owner}/>}{' '}
|
|
247
|
+
{ledgerEntryKind[effect.kind]}{' '}
|
|
248
|
+
<CopyToClipboard text={effect.keyHash}>
|
|
249
|
+
<code title={effect.keyHash + ' - click to copy'}>{shortenString(effect.keyHash, 12)}</code>
|
|
250
|
+
</CopyToClipboard></>
|
|
241
251
|
case 'feeCharged':
|
|
242
252
|
return <><Amount asset="XLM" amount={effect.charged} adjust/> fee charged from <AccountAddress account={effect.source}/> (
|
|
243
253
|
bid <Amount asset="XLM" amount={effect.bid} adjust/>)</>
|
|
@@ -299,6 +309,26 @@ function ContractDetails({effect}) {
|
|
|
299
309
|
}
|
|
300
310
|
}
|
|
301
311
|
|
|
312
|
+
function ConstructorDetails({effect}) {
|
|
313
|
+
if (!effect.constructorArgs?.length)
|
|
314
|
+
return null
|
|
315
|
+
return <span>{' '}<InvocationInfoView func="__constructor" args={effect.constructorArgs}/></span>
|
|
316
|
+
}
|
|
317
|
+
|
|
302
318
|
function ContractCodeWasm({wasm}) {
|
|
303
|
-
return
|
|
319
|
+
return <>
|
|
320
|
+
<code title={wasm}>{shortenString(wasm, 16)}</code>
|
|
321
|
+
<CopyToClipboard text={wasm}/>
|
|
322
|
+
</>
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function LedgerKeyHint({effect, children}) {
|
|
326
|
+
if (!effect.keyHash)
|
|
327
|
+
return children
|
|
328
|
+
return <span title={'Ledger key ' + effect.keyHash}>{children}</span>
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const ledgerEntryKind = {
|
|
332
|
+
contractData: 'contract state entry',
|
|
333
|
+
contractCode: 'contract code WASM'
|
|
304
334
|
}
|
|
@@ -37,10 +37,19 @@ function sortContractEffects(effects) {
|
|
|
37
37
|
if (aInvocation && bInvocation)
|
|
38
38
|
return 0
|
|
39
39
|
if (!aInvocation && !bInvocation) {
|
|
40
|
-
const aData = a.type.startsWith('contractData')
|
|
41
|
-
const bData = b.type.startsWith('contractData')
|
|
42
|
-
if (aData === bData)
|
|
40
|
+
const aData = a.type === 'setTtl' || a.type.startsWith('contractData')
|
|
41
|
+
const bData = b.type === 'setTtl' || b.type.startsWith('contractData')
|
|
42
|
+
if (aData === bData) {
|
|
43
|
+
if (a.type === 'setTtl')
|
|
44
|
+
return 1
|
|
45
|
+
if (b.type === 'setTtl')
|
|
46
|
+
return -1
|
|
47
|
+
if (a.durability === 'instance' && a.durability !== b.durability)
|
|
48
|
+
return -1
|
|
49
|
+
if (b.durability === 'instance' && a.durability !== b.durability)
|
|
50
|
+
return 1
|
|
43
51
|
return 0
|
|
52
|
+
}
|
|
44
53
|
return aData ? 1 : -1
|
|
45
54
|
}
|
|
46
55
|
return aInvocation ? -1 : 1
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stellar-expert/ui-framework",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.7",
|
|
4
4
|
"description": "StellarExpert shared UI components library",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
"author": "orbitlens <orbit@stellar.expert>",
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"peerDependencies": {
|
|
17
|
-
"@stellar/stellar-base": "^
|
|
18
|
-
"@stellar/stellar-sdk": "^
|
|
17
|
+
"@stellar/stellar-base": "^13.0.0",
|
|
18
|
+
"@stellar/stellar-sdk": "^13.0.0",
|
|
19
19
|
"@stellar-expert/asset-descriptor": "^1.3.3",
|
|
20
20
|
"@stellar-expert/claimable-balance-utils": "^1.4.1",
|
|
21
21
|
"@stellar-expert/client-cache": "github:stellar-expert/client-cache",
|
|
22
22
|
"@stellar-expert/contract-wasm-interface-parser": "^3.1.0",
|
|
23
23
|
"@stellar-expert/formatter": "^2.3.0",
|
|
24
24
|
"@stellar-expert/navigation": "github:stellar-expert/navigation#v1.0.2",
|
|
25
|
-
"@stellar-expert/tx-meta-effects-parser": "
|
|
25
|
+
"@stellar-expert/tx-meta-effects-parser": "6.2.0",
|
|
26
26
|
"classnames": ">=2",
|
|
27
27
|
"prop-types": ">=15",
|
|
28
28
|
"qrcode.react": "^3.1.0",
|
package/tx/op-description.scss
CHANGED
package/tx/op-icon.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import cn from 'classnames'
|
|
2
3
|
|
|
3
4
|
const opIconMapping = {
|
|
4
5
|
feeCharge: 'send-circle',
|
|
@@ -50,15 +51,19 @@ const opIconMapping = {
|
|
|
50
51
|
/**
|
|
51
52
|
* Transaction operation icon
|
|
52
53
|
* @param {OperationDescriptor|'feeCharge'} op - Operation descriptor
|
|
54
|
+
* @param {Boolean} failed - Whether the transaction failed during execution
|
|
53
55
|
* @constructor
|
|
54
56
|
*/
|
|
55
|
-
export const OpIcon = React.memo(function OpIcon({op}) {
|
|
57
|
+
export const OpIcon = React.memo(function OpIcon({op, failed = false}) {
|
|
56
58
|
let type
|
|
59
|
+
let title
|
|
57
60
|
if (op === 'feeCharge') {
|
|
58
61
|
type = 'feeCharge'
|
|
62
|
+
title = 'Transaction fees charge'
|
|
59
63
|
} else {
|
|
60
64
|
const {operation} = op
|
|
61
|
-
type = operation.type
|
|
65
|
+
title = type = operation.type
|
|
66
|
+
title = title[0].toUpperCase() + title.substring(1) + ' operation'
|
|
62
67
|
switch (type) {
|
|
63
68
|
case 'payment':
|
|
64
69
|
case 'accountMerge':
|
|
@@ -84,10 +89,11 @@ export const OpIcon = React.memo(function OpIcon({op}) {
|
|
|
84
89
|
break
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
if (failed) {
|
|
93
|
+
title += ' - Transaction failed'
|
|
94
|
+
}
|
|
89
95
|
const icon = opIconMapping[type]
|
|
90
|
-
return <div className=
|
|
96
|
+
return <div className={cn('op-icon', {failed})} title={title}>
|
|
91
97
|
<i className={`icon-${icon}`}/>
|
|
92
98
|
</div>
|
|
93
99
|
})
|
package/tx/tx-operations-list.js
CHANGED
|
@@ -48,7 +48,7 @@ const TxChargedFee = React.memo(function TxChargedFee({parsedTx, compact}) {
|
|
|
48
48
|
return null
|
|
49
49
|
return <div className="op-container">
|
|
50
50
|
<div className="op-layout">
|
|
51
|
-
<OpIcon op="feeCharge"/>
|
|
51
|
+
<OpIcon op="feeCharge" failed={!parsedTx.successful}/>
|
|
52
52
|
<TxFeeEffect feeEffect={fee} compact={compact}/>
|
|
53
53
|
{!!compact && !parsedTx.isEphemeral && <TxFeeAccountingChanges amount={fee.charged}/>}
|
|
54
54
|
</div>
|
|
@@ -73,7 +73,7 @@ export const TxOperationsList = React.memo(function TxOperationsList({
|
|
|
73
73
|
const [opsExpanded, setOpsExpanded] = useState(false)
|
|
74
74
|
const toggleEffects = useCallback(e => setEffectsExpanded(e.expanded), [])
|
|
75
75
|
const toggleAdditionalOps = useCallback(e => setOpsExpanded(e.expanded), [])
|
|
76
|
-
let {operations} = parsedTx
|
|
76
|
+
let {operations, successful} = parsedTx
|
|
77
77
|
let opdiff = 0
|
|
78
78
|
if (!opsExpanded) {
|
|
79
79
|
//filter operations if filtered output is requested
|
|
@@ -100,7 +100,7 @@ export const TxOperationsList = React.memo(function TxOperationsList({
|
|
|
100
100
|
<div className="condensed">
|
|
101
101
|
{operations.map((op, i) => <div className="op-container" key={op.txHash + op.order + op.isEphemeral}>
|
|
102
102
|
<div className="op-layout">
|
|
103
|
-
<OpIcon op={op}/>
|
|
103
|
+
<OpIcon op={op} failed={!successful}/>
|
|
104
104
|
<div>
|
|
105
105
|
<OpDescriptionView key={parsedTx.txHash + op.order} op={op} compact={compact}/>
|
|
106
106
|
</div>
|