@stellar-expert/ui-framework 1.15.3 → 1.15.5

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.
@@ -1,352 +1,345 @@
1
- import React from 'react'
2
- import PropTypes from 'prop-types'
3
- import {AuthRequiredFlag, AuthRevocableFlag, AuthImmutableFlag, AuthClawbackEnabledFlag} from '@stellar/stellar-base'
4
- import {AssetDescriptor} from '@stellar-expert/asset-descriptor'
5
- import {shortenString, formatWithAutoPrecision} from '@stellar-expert/formatter'
6
- import {AccountAddress} from '../account/account-address'
7
- import {SignerKey} from '../account/signer-key'
8
- import {OfferLink, PoolLink} from '../ledger/ledger-entry-link'
9
- import {AssetLink} from '../asset/asset-link'
10
- import {Amount} from '../asset/amount'
11
- import {CopyToClipboard} from '../interaction/copy-to-clipboard'
12
- import {ScVal} from '../contract/sc-val'
13
- import InvocationInfoView from '../contract/invocation-info-view'
14
-
15
- /**
16
- * @param {{}} effect
17
- * @param {{}} operation
18
- * @return {JSX.Element}
19
- * @constructor
20
- */
21
- export function EffectDescription({effect, operation}) {
22
- switch (effect.type) {
23
- case 'accountCreated':
24
- return <>Account <AccountAddress account={effect.account}/> created</>
25
- case 'accountRemoved':
26
- return <>Account <AccountAddress account={effect.source}/> removed</>
27
- case 'accountCredited':
28
- return <><Amount asset={effect.asset} amount={effect.amount} adjust/> credited to
29
- {effect.source.startsWith('C') ? ' contract' : ' account'} <AccountAddress account={effect.source}/></>
30
- case 'accountDebited':
31
- return <><Amount asset={effect.asset} amount={effect.amount} adjust/> debited from
32
- {effect.source.startsWith('C') ? ' contract' : ' account'} <AccountAddress account={effect.source}/></>
33
- case 'accountThresholdsUpdated':
34
- return <>Account <AccountAddress account={effect.source}/> set thresholds to {effect.thresholds.join('/')}</>
35
- case 'accountHomeDomainUpdated':
36
- return <>
37
- Account <AccountAddress account={effect.source}/> set home domain to{' '}
38
- <a href={'https://' + effect.home_domain} target="_blank" rel="noreferrer noopener">{effect.home_domain}</a>
39
- </>
40
- case 'accountFlagsUpdated':
41
- return <>Account <AccountAddress account={effect.source}/> updated authorization
42
- flags: {decodeAccountAuthFlags(effect.flags).join(', ')}</>
43
- case 'accountInflationDestinationUpdated':
44
- return <>Account <AccountAddress account={effect.source}/> set inflation destination
45
- to <AccountAddress account={effect.inflationDestination}/></>
46
- case 'accountSignerCreated':
47
- return <>Account <AccountAddress account={effect.source}/> added
48
- signer <AccountAddress account={effect.signer}/>(w:{effect.weight})</>
49
- case 'accountSignerUpdated':
50
- return <>Account <AccountAddress account={effect.source}/> updated
51
- signer <AccountAddress account={effect.signer}/>(w:{effect.weight})</>
52
- case 'accountSignerRemoved':
53
- return <>Account <AccountAddress account={effect.source}/> removed
54
- signer <AccountAddress account={effect.signer}/></>
55
- case 'trustlineCreated':
56
- return <>
57
- Account <AccountAddress account={effect.source}/> established trustline to <AssetLink asset={effect.asset}/> with
58
- limit <Amount asset={effect.asset} amount={effect.limit} issuer={false} icon={false} adjust/>
59
- </>
60
- case 'trustlineUpdated':
61
- return <>
62
- Account <AccountAddress account={effect.source}/> updated trustline to <AssetLink asset={effect.asset}/> with
63
- limit <Amount asset={effect.asset} amount={effect.limit} issuer={false} icon={false} adjust/>
64
- </>
65
- case 'trustlineRemoved':
66
- return <>Account <AccountAddress account={effect.source}/> removed trustline to <AssetLink asset={effect.asset}/></>
67
- case 'trustlineAuthorizationUpdated':
68
- return <>
69
- Account <AccountAddress account={effect.source}/> updated <AssetLink asset={effect.asset}/> trustline authorization
70
- flags ({decodeTrustlineFlags(effect.flags)}) for <AccountAddress account={effect.trustor}/>
71
- </>
72
- case 'assetMinted':
73
- return <><Amount asset={effect.asset} amount={effect.amount} adjust/> minted</>
74
- case 'assetBurned':
75
- return <>Account <AccountAddress account={effect.source}/> burned <Amount asset={effect.asset} amount={effect.amount} adjust/></>
76
- case 'offerCreated':
77
- return <OfferChange effect={effect} action="created"/>
78
- case 'offerUpdated':
79
- return <OfferChange effect={effect} action="updated"/>
80
- case 'offerRemoved':
81
- return <>DEX offer <OfferLink offer={effect.offer}/> removed</>
82
- case 'trade':
83
- return <span>
84
- Account <AccountAddress account={effect.source}/> exchanged{' '}
85
- <span className="nowrap">
86
- <Amount asset={effect.asset[0]} amount={effect.amount[0]} adjust/>{' '}
87
- <span className="icon icon-shuffle color-primary"/>{' '}
88
- <Amount asset={effect.asset[1]} amount={effect.amount[1]} adjust/>
89
- </span>{' '}
90
- {effect.pool ?
91
- <>(pool <PoolLink pool={effect.pool}/>)</> :
92
- <>(DEX offer <OfferLink offer={effect.offer}/> by <AccountAddress account={effect.seller}/>)</>}
93
- </span>
94
- case 'sequenceBumped':
95
- return <>Account <AccountAddress account={effect.source}/> bumped sequence to {effect.sequence}</>
96
- case 'dataEntryCreated':
97
- case 'dataEntryUpdated':
98
- return <>
99
- Account <AccountAddress account={effect.source}/> {effect.type === 'dataEntryCreated' ? 'created' : 'updated'} data entry
100
- <span className="word-break condensed text-small"><code>"{effect.name}"</code> = <code>"{effect.value}"</code></span>
101
- </>
102
- case 'dataEntryRemoved':
103
- return <>
104
- Account <AccountAddress account={effect.source}/> removed data entry
105
- <span className="word-break condensed text-small"><code>"{effect.name}"</code></span>
106
- </>
107
- case 'claimableBalanceCreated':
108
- return <>
109
- Account <AccountAddress account={effect.source}/> created claimable
110
- balance <ClaimableBalance effect={effect}/> <Amount asset={effect.asset} amount={effect.amount} adjust/>
111
- </>
112
- case 'claimableBalanceRemoved':
113
- return <>
114
- Account <AccountAddress account={effect.source}/> claimed claimable
115
- balance <ClaimableBalance effect={effect}/> <Amount asset={effect.asset} amount={effect.amount} adjust/>
116
- </>
117
- case 'accountSponsorshipCreated':
118
- case 'accountSponsorshipUpdated':
119
- return <>
120
- Account <AccountAddress account={effect.sponsor}/> sponsored account base reserve
121
- for <AccountAddress account={effect.account}/>
122
- </>
123
- case 'accountSponsorshipRemoved':
124
- return <>
125
- Account <AccountAddress account={effect.prevSponsor}/> revoked account sponsorship
126
- for <AccountAddress account={effect.account}/>
127
- </>
128
- case 'trustlineSponsorshipCreated':
129
- case 'trustlineSponsorshipUpdated':
130
- return <>
131
- Account <AccountAddress account={effect.sponsor}/> sponsored <AssetLink asset={effect.asset}/> trustline reserve
132
- for <AccountAddress account={effect.account}/>
133
- </>
134
- case 'trustlineSponsorshipRemoved':
135
- return <>
136
- Account <AccountAddress account={effect.prevSponsor}/> revoked <AssetLink asset={effect.asset}/> trustline sponsorship
137
- for <AccountAddress account={effect.account}/>
138
- </>
139
- case 'offerSponsorshipCreated':
140
- case 'offerSponsorshipUpdated':
141
- return <>
142
- Account <AccountAddress account={effect.sponsor}/> sponsored offer <OfferLink offer={effect.offer}/> reserve
143
- for <AccountAddress account={effect.account}/>
144
- </>
145
- case 'offerSponsorshipRemoved':
146
- return <>
147
- Account <AccountAddress account={effect.prevSponsor}/> revoked offer <OfferLink offer={effect.offer}/> sponsorship
148
- for <AccountAddress account={effect.account}/>
149
- </>
150
- case 'dataSponsorshipCreated':
151
- case 'dataSponsorshipUpdated':
152
- return <>
153
- Account <AccountAddress account={effect.sponsor}/> sponsored "{shortenString(effect.name)}" data reserve
154
- for <AccountAddress account={effect.account}/>
155
- </>
156
- case 'dataSponsorshipRemoved':
157
- return <>
158
- Account <AccountAddress account={effect.prevSponsor}/> revoked "{shortenString(effect.name)}" data sponsorship
159
- for <AccountAddress account={effect.account}/>
160
- </>
161
- case 'claimableBalanceSponsorshipCreated':
162
- case 'claimableBalanceSponsorshipUpdated':
163
- return <>
164
- Account <AccountAddress account={effect.sponsor}/> sponsored claimable balance <ClaimableBalance effect={effect}/>
165
- {effect.source !== effect.sponsor && <> for account <AccountAddress account={effect.source}/></>}
166
- </>
167
- case 'claimableBalanceSponsorshipRemoved':
168
- return <>
169
- Account <AccountAddress account={effect.prevSponsor}/> revoked claimable
170
- balance <ClaimableBalance effect={effect}/> sponsorship
171
- {effect.source !== effect.prevSponsor && <> for account <AccountAddress account={effect.source}/></>}
172
- </>
173
- case 'signerSponsorshipCreated':
174
- case 'signerSponsorshipUpdated':
175
- return <>
176
- Account <AccountAddress account={effect.sponsor}/> sponsored signer <SignerKey account={effect.signer}/>{' '}
177
- for account <AccountAddress account={effect.account}/>
178
- </>
179
- case 'signerSponsorshipRemoved':
180
- return <>
181
- Account <AccountAddress account={effect.prevSponsor}/> revoked signer <SignerKey account={effect.signer}/> sponsorship{' '}
182
- for account <AccountAddress account={effect.account}/>
183
- </>
184
- case 'liquidityPoolDeposited':
185
- return <>
186
- <span className="nowrap">
187
- <Amount asset={effect.assets[0].asset} amount={effect.assets[0].amount} adjust/>{' '}
188
- and <Amount asset={effect.assets[1].asset} amount={effect.assets[1].amount} adjust/>
189
- </span>{' '}
190
- deposited to liquidity <span className="nowrap">pool <AssetLink asset={effect.pool}/></span>{' '}
191
- <i className="icon icon-shuffle"/> <span className="nowrap">{formatWithAutoPrecision(effect.shares)} pool shares</span>
192
- </>
193
- case 'liquidityPoolWithdrew':
194
- return <>
195
- {formatWithAutoPrecision(effect.shares)} pool shares <i className="icon icon-shuffle"/>{' '}
196
- <span className="nowrap">
197
- <Amount asset={effect.assets[0].asset} amount={effect.assets[0].amount} adjust/>{' '}
198
- and <Amount asset={effect.assets[1].asset} amount={effect.assets[1].amount} adjust/>
199
- </span>{' '}
200
- withdrawn from <span className="nowrap"><AssetLink asset={effect.pool}/> pool</span>
201
- </>
202
- case 'liquidityPoolCreated':
203
- return <>Liquidity pool <AssetLink asset={effect.pool}/> created</>
204
- case 'liquidityPoolUpdated':
205
- return <>Liquidity pool <AssetLink asset={effect.pool}/> updated / {' '}
206
- <span className="nowrap">
207
- <Amount asset={effect.reserves[0].asset} amount={effect.reserves[0].amount} adjust/> <i className="icon-plus"/>{' '}
208
- <Amount asset={effect.reserves[1].asset} amount={effect.reserves[1].amount} adjust/></span> /{' '}
209
- <span className="nowrap">{formatWithAutoPrecision(effect.shares)} pool shares</span>,{' '}
210
- <span className="nowrap">{effect.accounts} accounts</span></>
211
- case 'liquidityPoolRemoved':
212
- return <>Liquidity pool <AssetLink asset={effect.pool}/> removed</>
213
- case 'inflation':
214
- return <>Inflation distribution initialized</>
215
- case 'contractCodeUploaded':
216
- case 'contractCodeRestored':
217
- return <>Contract code {getEffectAction(effect, 'contractCode')}
218
- <LedgerKeyHint effect={effect}><ContractCodeWasm wasm={effect.wasm || effect.wasmHash}/></LedgerKeyHint></>
219
- case 'contractCreated':
220
- case 'contractUpdated':
221
- case 'contractRestored':
222
- return <>Contract <AccountAddress account={effect.contract}/> {getEffectAction(effect, 'contract')}
223
- <ContractDetails effect={effect}/><ConstructorDetails effect={effect}/></>
224
- case 'contractInvoked':
225
- return <>{effect.depth > 0 &&
226
- <i className="icon-level-down text-tiny color-primary" style={{paddingLeft: (effect.depth - 1) + 'em'}}/>}
227
- Invoked contract <AccountAddress account={effect.contract}/>{' '}
228
- <InvocationInfoView func={effect.function} args={effect.rawArgs} contract={effect.contract} result={effect.result} sac={operation.operation.sacMap?.[effect.contract]}/>
229
- </>
230
- case 'contractEvent':
231
- return <>Contract <AccountAddress account={effect.contract}/> raised event <ScVal value={effect.rawTopics}/>{' '}
232
- with data <ScVal value={effect.rawData}/></>
233
- case 'contractDataCreated':
234
- case 'contractDataUpdated':
235
- case 'contractDataRestored':
236
- return <>Contract <AccountAddress account={effect.owner}/> {getEffectAction(effect, 'contractData')}
237
- {effect.durability} data{' '}
238
- <LedgerKeyHint effect={effect}><ScVal value={effect.key}/></LedgerKeyHint> = <ScVal value={effect.value}/>
239
- </>
240
- case 'contractDataRemoved':
241
- return <>Contract <AccountAddress account={effect.owner}/> removed {effect.durability}{' '}
242
- data <LedgerKeyHint effect={effect}><ScVal value={effect.key}/></LedgerKeyHint></>
243
- case 'contractError':
244
- let errCode = effect.code
245
- if (errCode?.name) {
246
- errCode = errCode.name
247
- }
248
- return <>Execution error {errCode ? <><code>{errCode}</code> </> : null}in <AccountAddress account={effect.contract}/>{': '}
249
- <code>{JSON.stringify(effect.details)}</code> </>
250
- case 'setTtl':
251
- return <>Time-to-live extended to ledger {effect.ttl} for {!!effect.owner && <AccountAddress account={effect.owner}/>}{' '}
252
- {ledgerEntryKind[effect.kind]}{' '}
253
- <CopyToClipboard text={effect.keyHash}>
254
- <code title={effect.keyHash + ' - click to copy'}>{shortenString(effect.keyHash, 12)}</code>
255
- </CopyToClipboard></>
256
- case 'feeCharged':
257
- return <><Amount asset="XLM" amount={effect.charged} adjust/> fee charged from <AccountAddress account={effect.source}/> (
258
- bid <Amount asset="XLM" amount={effect.bid} adjust/>)</>
259
- }
260
- return <><i className="icon-warning color-warning"/> Effect {effect.type} not supported</>
261
- }
262
-
263
- EffectDescription.propTypes = {
264
- effect: PropTypes.object.isRequired
265
- }
266
-
267
- function decodeAccountAuthFlags(flags) {
268
- const res = []
269
- if ((flags & AuthRequiredFlag) === AuthRequiredFlag) {
270
- res.push('REQUIRED')
271
- }
272
- if ((flags & AuthRevocableFlag) === AuthRevocableFlag) {
273
- res.push('REVOCABLE')
274
- }
275
- if ((flags & AuthImmutableFlag) === AuthImmutableFlag) {
276
- res.push('IMMUTABLE')
277
- }
278
- if ((flags & AuthClawbackEnabledFlag) === AuthClawbackEnabledFlag) {
279
- res.push('CLAWBACK_ENABLED')
280
- }
281
- return res
282
- }
283
-
284
- function decodeTrustlineFlags(flags) {
285
- if ((flags & 2) === 2)
286
- return 'FROZEN'
287
- if ((flags & 1) === 1)
288
- return 'AUTHORIZED'
289
- return 'UNAUTHORIZED'
290
- }
291
-
292
- function OfferChange({effect, action}) {
293
- return <>DEX offer <OfferLink offer={effect.offer}/> {action} /{' '}
294
- <span className="nowrap">
295
- <Amount asset={effect.asset[0]} amount={effect.amount} adjust/> <i className="icon icon-shuffle color-primary"/>{' '}
296
- <AssetLink asset={effect.asset[1]}/>
297
- </span> at <span className="nowrap">
298
- {formatWithAutoPrecision(parseFloat(effect.price))}{' '}
299
- {AssetDescriptor.parse(effect.asset[1]).toCurrency()}/{AssetDescriptor.parse(effect.asset[0]).toCurrency()}
300
- </span>
301
- </>
302
- }
303
-
304
- function ContractDetails({effect}) {
305
- switch (effect.kind) {
306
- case 'wasm':
307
- return <>from WASM <ContractCodeWasm wasm={effect.wasmHash}/></>
308
- case 'fromAddress':
309
- return <>from issuer <AccountAddress account={effect.issuer}/> with salt <ContractCodeWasm wasm={effect.salt}/></>
310
- case 'fromAsset':
311
- return <>from asset <AssetLink asset={effect.asset}/></>
312
- default:
313
- return <span className="dimme">(contract type not supported)</span>
314
- }
315
- }
316
-
317
- function ConstructorDetails({effect}) {
318
- if (!effect.constructorArgs?.length)
319
- return null
320
- return <span>{' '}<InvocationInfoView func="__constructor" args={effect.constructorArgs}/></span>
321
- }
322
-
323
- function ContractCodeWasm({wasm}) {
324
- return <>
325
- <code title={wasm}>{shortenString(wasm, 16)}</code>
326
- <CopyToClipboard text={wasm}/>
327
- </>
328
- }
329
-
330
- function ClaimableBalance({effect}) {
331
- const {balance} = effect
332
- return <>
333
- {shortenString(balance)} <CopyToClipboard text={balance}/>{/*<InfoTooltip icon="icon-plus">
334
- <CopyToClipboard text={balance}>{balance}</CopyToClipboard>
335
- </InfoTooltip>*/}
336
- </>
337
- }
338
-
339
- function LedgerKeyHint({effect, children}) {
340
- if (!effect.keyHash)
341
- return children
342
- return <span title={'Ledger key ' + effect.keyHash}>{children}</span>
343
- }
344
-
345
- function getEffectAction(effect, prefix) {
346
- return effect.type.replace(prefix, '').toLowerCase() + ' '
347
- }
348
-
349
- const ledgerEntryKind = {
350
- contractData: 'contract state entry',
351
- contractCode: 'contract code WASM'
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import {AuthRequiredFlag, AuthRevocableFlag, AuthImmutableFlag, AuthClawbackEnabledFlag} from '@stellar/stellar-base'
4
+ import {AssetDescriptor} from '@stellar-expert/asset-descriptor'
5
+ import {shortenString, formatWithAutoPrecision} from '@stellar-expert/formatter'
6
+ import {AccountAddress} from '../account/account-address'
7
+ import {SignerKey} from '../account/signer-key'
8
+ import {OfferLink, PoolLink} from '../ledger/ledger-entry-link'
9
+ import {AssetLink} from '../asset/asset-link'
10
+ import {ClaimableBalanceId} from '../claimable-balance/claimable-balance-id'
11
+ import {Amount} from '../asset/amount'
12
+ import {CopyToClipboard} from '../interaction/copy-to-clipboard'
13
+ import {ScVal} from '../contract/sc-val'
14
+ import InvocationInfoView from '../contract/invocation-info-view'
15
+
16
+ /**
17
+ * @param {{}} effect
18
+ * @param {{}} operation
19
+ * @return {JSX.Element}
20
+ * @constructor
21
+ */
22
+ export function EffectDescription({effect, operation}) {
23
+ switch (effect.type) {
24
+ case 'accountCreated':
25
+ return <>Account <AccountAddress account={effect.account}/> created</>
26
+ case 'accountRemoved':
27
+ return <>Account <AccountAddress account={effect.source}/> removed</>
28
+ case 'accountCredited':
29
+ return <><Amount asset={effect.asset} amount={effect.amount} adjust/> credited to
30
+ {effect.source.startsWith('C') ? ' contract' : ' account'} <AccountAddress account={effect.source}/></>
31
+ case 'accountDebited':
32
+ return <><Amount asset={effect.asset} amount={effect.amount} adjust/> debited from
33
+ {effect.source.startsWith('C') ? ' contract' : ' account'} <AccountAddress account={effect.source}/></>
34
+ case 'accountThresholdsUpdated':
35
+ return <>Account <AccountAddress account={effect.source}/> set thresholds to {effect.thresholds.join('/')}</>
36
+ case 'accountHomeDomainUpdated':
37
+ return <>
38
+ Account <AccountAddress account={effect.source}/> set home domain to{' '}
39
+ <a href={'https://' + effect.home_domain} target="_blank" rel="noreferrer noopener">{effect.home_domain}</a>
40
+ </>
41
+ case 'accountFlagsUpdated':
42
+ return <>Account <AccountAddress account={effect.source}/> updated authorization
43
+ flags: {decodeAccountAuthFlags(effect.flags).join(', ')}</>
44
+ case 'accountInflationDestinationUpdated':
45
+ return <>Account <AccountAddress account={effect.source}/> set inflation destination
46
+ to <AccountAddress account={effect.inflationDestination}/></>
47
+ case 'accountSignerCreated':
48
+ return <>Account <AccountAddress account={effect.source}/> added
49
+ signer <AccountAddress account={effect.signer}/>(w:{effect.weight})</>
50
+ case 'accountSignerUpdated':
51
+ return <>Account <AccountAddress account={effect.source}/> updated
52
+ signer <AccountAddress account={effect.signer}/>(w:{effect.weight})</>
53
+ case 'accountSignerRemoved':
54
+ return <>Account <AccountAddress account={effect.source}/> removed
55
+ signer <AccountAddress account={effect.signer}/></>
56
+ case 'trustlineCreated':
57
+ return <>
58
+ Account <AccountAddress account={effect.source}/> established trustline to <AssetLink asset={effect.asset}/> with
59
+ limit <Amount asset={effect.asset} amount={effect.limit} issuer={false} icon={false} adjust/>
60
+ </>
61
+ case 'trustlineUpdated':
62
+ return <>
63
+ Account <AccountAddress account={effect.source}/> updated trustline to <AssetLink asset={effect.asset}/> with
64
+ limit <Amount asset={effect.asset} amount={effect.limit} issuer={false} icon={false} adjust/>
65
+ </>
66
+ case 'trustlineRemoved':
67
+ return <>Account <AccountAddress account={effect.source}/> removed trustline to <AssetLink asset={effect.asset}/></>
68
+ case 'trustlineAuthorizationUpdated':
69
+ return <>
70
+ Account <AccountAddress account={effect.source}/> updated <AssetLink asset={effect.asset}/> trustline authorization
71
+ flags ({decodeTrustlineFlags(effect.flags)}) for <AccountAddress account={effect.trustor}/>
72
+ </>
73
+ case 'assetMinted':
74
+ return <><Amount asset={effect.asset} amount={effect.amount} adjust/> minted</>
75
+ case 'assetBurned':
76
+ return <>Account <AccountAddress account={effect.source}/> burned <Amount asset={effect.asset} amount={effect.amount} adjust/></>
77
+ case 'offerCreated':
78
+ return <OfferChange effect={effect} action="created"/>
79
+ case 'offerUpdated':
80
+ return <OfferChange effect={effect} action="updated"/>
81
+ case 'offerRemoved':
82
+ return <>DEX offer <OfferLink offer={effect.offer}/> removed</>
83
+ case 'trade':
84
+ return <span>
85
+ Account <AccountAddress account={effect.source}/> exchanged{' '}
86
+ <span className="nowrap">
87
+ <Amount asset={effect.asset[0]} amount={effect.amount[0]} adjust/>{' '}
88
+ <span className="icon icon-shuffle color-primary"/>{' '}
89
+ <Amount asset={effect.asset[1]} amount={effect.amount[1]} adjust/>
90
+ </span>{' '}
91
+ {effect.pool ?
92
+ <>(pool <PoolLink pool={effect.pool}/>)</> :
93
+ <>(DEX offer <OfferLink offer={effect.offer}/> by <AccountAddress account={effect.seller}/>)</>}
94
+ </span>
95
+ case 'sequenceBumped':
96
+ return <>Account <AccountAddress account={effect.source}/> bumped sequence to {effect.sequence}</>
97
+ case 'dataEntryCreated':
98
+ case 'dataEntryUpdated':
99
+ return <>
100
+ Account <AccountAddress account={effect.source}/> {effect.type === 'dataEntryCreated' ? 'created' : 'updated'} data entry
101
+ <span className="word-break condensed text-small"><code>"{effect.name}"</code> = <code>"{effect.value}"</code></span>
102
+ </>
103
+ case 'dataEntryRemoved':
104
+ return <>
105
+ Account <AccountAddress account={effect.source}/> removed data entry
106
+ <span className="word-break condensed text-small"><code>"{effect.name}"</code></span>
107
+ </>
108
+ case 'claimableBalanceCreated':
109
+ return <>
110
+ Account <AccountAddress account={effect.source}/> created claimable
111
+ balance <ClaimableBalanceId balance={effect.balance}/> <Amount asset={effect.asset} amount={effect.amount} adjust/>
112
+ </>
113
+ case 'claimableBalanceRemoved':
114
+ return <>
115
+ Account <AccountAddress account={effect.source}/> claimed claimable
116
+ balance <ClaimableBalanceId balance={effect.balance}/> <Amount asset={effect.asset} amount={effect.amount} adjust/>
117
+ </>
118
+ case 'accountSponsorshipCreated':
119
+ case 'accountSponsorshipUpdated':
120
+ return <>
121
+ Account <AccountAddress account={effect.sponsor}/> sponsored account base reserve
122
+ for <AccountAddress account={effect.account}/>
123
+ </>
124
+ case 'accountSponsorshipRemoved':
125
+ return <>
126
+ Account <AccountAddress account={effect.prevSponsor}/> revoked account sponsorship
127
+ for <AccountAddress account={effect.account}/>
128
+ </>
129
+ case 'trustlineSponsorshipCreated':
130
+ case 'trustlineSponsorshipUpdated':
131
+ return <>
132
+ Account <AccountAddress account={effect.sponsor}/> sponsored <AssetLink asset={effect.asset}/> trustline reserve
133
+ for <AccountAddress account={effect.account}/>
134
+ </>
135
+ case 'trustlineSponsorshipRemoved':
136
+ return <>
137
+ Account <AccountAddress account={effect.prevSponsor}/> revoked <AssetLink asset={effect.asset}/> trustline sponsorship
138
+ for <AccountAddress account={effect.account}/>
139
+ </>
140
+ case 'offerSponsorshipCreated':
141
+ case 'offerSponsorshipUpdated':
142
+ return <>
143
+ Account <AccountAddress account={effect.sponsor}/> sponsored offer <OfferLink offer={effect.offer}/> reserve
144
+ for <AccountAddress account={effect.account}/>
145
+ </>
146
+ case 'offerSponsorshipRemoved':
147
+ return <>
148
+ Account <AccountAddress account={effect.prevSponsor}/> revoked offer <OfferLink offer={effect.offer}/> sponsorship
149
+ for <AccountAddress account={effect.account}/>
150
+ </>
151
+ case 'dataSponsorshipCreated':
152
+ case 'dataSponsorshipUpdated':
153
+ return <>
154
+ Account <AccountAddress account={effect.sponsor}/> sponsored "{shortenString(effect.name)}" data reserve
155
+ for <AccountAddress account={effect.account}/>
156
+ </>
157
+ case 'dataSponsorshipRemoved':
158
+ return <>
159
+ Account <AccountAddress account={effect.prevSponsor}/> revoked "{shortenString(effect.name)}" data sponsorship
160
+ for <AccountAddress account={effect.account}/>
161
+ </>
162
+ case 'claimableBalanceSponsorshipCreated':
163
+ case 'claimableBalanceSponsorshipUpdated':
164
+ return <>
165
+ Account <AccountAddress account={effect.sponsor}/> sponsored
166
+ claimable balance <ClaimableBalanceId balance={effect.balance}/>
167
+ {effect.source !== effect.sponsor && <> for account <AccountAddress account={effect.source}/></>}
168
+ </>
169
+ case 'claimableBalanceSponsorshipRemoved':
170
+ return <>
171
+ Account <AccountAddress account={effect.prevSponsor}/> revoked claimable
172
+ balance <ClaimableBalanceId balance={effect.balance}/> sponsorship
173
+ {effect.source !== effect.prevSponsor && <> for account <AccountAddress account={effect.source}/></>}
174
+ </>
175
+ case 'signerSponsorshipCreated':
176
+ case 'signerSponsorshipUpdated':
177
+ return <>
178
+ Account <AccountAddress account={effect.sponsor}/> sponsored signer <SignerKey account={effect.signer}/>{' '}
179
+ for account <AccountAddress account={effect.account}/>
180
+ </>
181
+ case 'signerSponsorshipRemoved':
182
+ return <>
183
+ Account <AccountAddress account={effect.prevSponsor}/> revoked signer <SignerKey account={effect.signer}/> sponsorship{' '}
184
+ for account <AccountAddress account={effect.account}/>
185
+ </>
186
+ case 'liquidityPoolDeposited':
187
+ return <>
188
+ <span className="nowrap">
189
+ <Amount asset={effect.assets[0].asset} amount={effect.assets[0].amount} adjust/>{' '}
190
+ and <Amount asset={effect.assets[1].asset} amount={effect.assets[1].amount} adjust/>
191
+ </span>{' '}
192
+ deposited to liquidity <span className="nowrap">pool <AssetLink asset={effect.pool}/></span>{' '}
193
+ <i className="icon icon-shuffle"/> <span className="nowrap">{formatWithAutoPrecision(effect.shares)} pool shares</span>
194
+ </>
195
+ case 'liquidityPoolWithdrew':
196
+ return <>
197
+ {formatWithAutoPrecision(effect.shares)} pool shares <i className="icon icon-shuffle"/>{' '}
198
+ <span className="nowrap">
199
+ <Amount asset={effect.assets[0].asset} amount={effect.assets[0].amount} adjust/>{' '}
200
+ and <Amount asset={effect.assets[1].asset} amount={effect.assets[1].amount} adjust/>
201
+ </span>{' '}
202
+ withdrawn from <span className="nowrap"><AssetLink asset={effect.pool}/> pool</span>
203
+ </>
204
+ case 'liquidityPoolCreated':
205
+ return <>Liquidity pool <AssetLink asset={effect.pool}/> created</>
206
+ case 'liquidityPoolUpdated':
207
+ return <>Liquidity pool <AssetLink asset={effect.pool}/> updated / {' '}
208
+ <span className="nowrap">
209
+ <Amount asset={effect.reserves[0].asset} amount={effect.reserves[0].amount} adjust/> <i className="icon-plus"/>{' '}
210
+ <Amount asset={effect.reserves[1].asset} amount={effect.reserves[1].amount} adjust/></span> /{' '}
211
+ <span className="nowrap">{formatWithAutoPrecision(effect.shares)} pool shares</span>,{' '}
212
+ <span className="nowrap">{effect.accounts} accounts</span></>
213
+ case 'liquidityPoolRemoved':
214
+ return <>Liquidity pool <AssetLink asset={effect.pool}/> removed</>
215
+ case 'inflation':
216
+ return <>Inflation distribution initialized</>
217
+ case 'contractCodeUploaded':
218
+ case 'contractCodeRestored':
219
+ return <>Contract code {getEffectAction(effect, 'contractCode')}
220
+ <LedgerKeyHint effect={effect}><ContractCodeWasm wasm={effect.wasm || effect.wasmHash}/></LedgerKeyHint></>
221
+ case 'contractCreated':
222
+ case 'contractUpdated':
223
+ case 'contractRestored':
224
+ return <>Contract <AccountAddress account={effect.contract}/> {getEffectAction(effect, 'contract')}
225
+ <ContractDetails effect={effect}/><ConstructorDetails effect={effect}/></>
226
+ case 'contractInvoked':
227
+ return <>{effect.depth > 0 &&
228
+ <i className="icon-level-down text-tiny color-primary" style={{paddingLeft: (effect.depth - 1) + 'em'}}/>}
229
+ Invoked contract <AccountAddress account={effect.contract}/>{' '}
230
+ <InvocationInfoView func={effect.function} args={effect.rawArgs} contract={effect.contract} result={effect.result} sac={operation.operation.sacMap?.[effect.contract]}/>
231
+ </>
232
+ case 'contractEvent':
233
+ return <>Contract <AccountAddress account={effect.contract}/> raised event <ScVal value={effect.rawTopics}/>{' '}
234
+ with data <ScVal value={effect.rawData}/></>
235
+ case 'contractDataCreated':
236
+ case 'contractDataUpdated':
237
+ case 'contractDataRestored':
238
+ return <>Contract <AccountAddress account={effect.owner}/> {getEffectAction(effect, 'contractData')}
239
+ {effect.durability} data{' '}
240
+ <LedgerKeyHint effect={effect}><ScVal value={effect.key}/></LedgerKeyHint> = <ScVal value={effect.value}/>
241
+ </>
242
+ case 'contractDataRemoved':
243
+ return <>Contract <AccountAddress account={effect.owner}/> removed {effect.durability}{' '}
244
+ data <LedgerKeyHint effect={effect}><ScVal value={effect.key}/></LedgerKeyHint></>
245
+ case 'contractError':
246
+ let errCode = effect.code
247
+ if (errCode?.name) {
248
+ errCode = errCode.name
249
+ }
250
+ return <>Execution error {errCode ? <><code>{errCode}</code> </> : null}in <AccountAddress account={effect.contract}/>{': '}
251
+ <code>{JSON.stringify(effect.details)}</code> </>
252
+ case 'setTtl':
253
+ return <>Time-to-live extended to ledger {effect.ttl} for {!!effect.owner && <AccountAddress account={effect.owner}/>}{' '}
254
+ {ledgerEntryKind[effect.kind]}{' '}
255
+ <CopyToClipboard text={effect.keyHash}>
256
+ <code title={effect.keyHash + ' - click to copy'}>{shortenString(effect.keyHash, 12)}</code>
257
+ </CopyToClipboard></>
258
+ case 'feeCharged':
259
+ return <><Amount asset="XLM" amount={effect.charged} adjust/> fee charged from <AccountAddress account={effect.source}/> (
260
+ bid <Amount asset="XLM" amount={effect.bid} adjust/>)</>
261
+ }
262
+ return <><i className="icon-warning color-warning"/> Effect {effect.type} not supported</>
263
+ }
264
+
265
+ EffectDescription.propTypes = {
266
+ effect: PropTypes.object.isRequired
267
+ }
268
+
269
+ function decodeAccountAuthFlags(flags) {
270
+ const res = []
271
+ if ((flags & AuthRequiredFlag) === AuthRequiredFlag) {
272
+ res.push('REQUIRED')
273
+ }
274
+ if ((flags & AuthRevocableFlag) === AuthRevocableFlag) {
275
+ res.push('REVOCABLE')
276
+ }
277
+ if ((flags & AuthImmutableFlag) === AuthImmutableFlag) {
278
+ res.push('IMMUTABLE')
279
+ }
280
+ if ((flags & AuthClawbackEnabledFlag) === AuthClawbackEnabledFlag) {
281
+ res.push('CLAWBACK_ENABLED')
282
+ }
283
+ return res
284
+ }
285
+
286
+ function decodeTrustlineFlags(flags) {
287
+ if ((flags & 2) === 2)
288
+ return 'FROZEN'
289
+ if ((flags & 1) === 1)
290
+ return 'AUTHORIZED'
291
+ return 'UNAUTHORIZED'
292
+ }
293
+
294
+ function OfferChange({effect, action}) {
295
+ return <>DEX offer <OfferLink offer={effect.offer}/> {action} /{' '}
296
+ <span className="nowrap">
297
+ <Amount asset={effect.asset[0]} amount={effect.amount} adjust/> <i className="icon icon-shuffle color-primary"/>{' '}
298
+ <AssetLink asset={effect.asset[1]}/>
299
+ </span> at <span className="nowrap">
300
+ {formatWithAutoPrecision(parseFloat(effect.price))}{' '}
301
+ {AssetDescriptor.parse(effect.asset[1]).toCurrency()}/{AssetDescriptor.parse(effect.asset[0]).toCurrency()}
302
+ </span>
303
+ </>
304
+ }
305
+
306
+ function ContractDetails({effect}) {
307
+ switch (effect.kind) {
308
+ case 'wasm':
309
+ return <>from WASM <ContractCodeWasm wasm={effect.wasmHash}/></>
310
+ case 'fromAddress':
311
+ return <>from issuer <AccountAddress account={effect.issuer}/> with salt <ContractCodeWasm wasm={effect.salt}/></>
312
+ case 'fromAsset':
313
+ return <>from asset <AssetLink asset={effect.asset}/></>
314
+ default:
315
+ return <span className="dimme">(contract type not supported)</span>
316
+ }
317
+ }
318
+
319
+ function ConstructorDetails({effect}) {
320
+ if (!effect.constructorArgs?.length)
321
+ return null
322
+ return <span>{' '}<InvocationInfoView func="__constructor" args={effect.constructorArgs}/></span>
323
+ }
324
+
325
+ function ContractCodeWasm({wasm}) {
326
+ return <>
327
+ <code title={wasm}>{shortenString(wasm, 16)}</code>
328
+ <CopyToClipboard text={wasm}/>
329
+ </>
330
+ }
331
+
332
+ function LedgerKeyHint({effect, children}) {
333
+ if (!effect.keyHash)
334
+ return children
335
+ return <span title={'Ledger key ' + effect.keyHash}>{children}</span>
336
+ }
337
+
338
+ function getEffectAction(effect, prefix) {
339
+ return effect.type.replace(prefix, '').toLowerCase() + ' '
340
+ }
341
+
342
+ const ledgerEntryKind = {
343
+ contractData: 'contract state entry',
344
+ contractCode: 'contract code WASM'
352
345
  }