@lukso/transaction-view-core 0.5.0-dev.5916302 → 0.5.0-dev.5ea12c5
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/.turbo/turbo-build.log +19 -19
- package/dist/index.cjs +62 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +62 -93
- package/dist/index.js.map +1 -1
- package/dist/shared/index.cjs +4 -8
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.d.cts +4 -4
- package/dist/shared/index.d.ts +4 -4
- package/dist/shared/index.js +4 -8
- package/dist/shared/index.js.map +1 -1
- package/dist/styles/index.cjs +1 -1
- package/dist/styles/index.cjs.map +1 -1
- package/dist/styles/index.js +1 -1
- package/dist/styles/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/asset-card.ts +58 -61
- package/src/components/permissions-block.ts +5 -7
- package/src/shared/image-list.ts +1 -0
- package/src/shared/notification-view.ts +2 -2
- package/src/shared/value-view.ts +19 -5
- package/src/utils.test.ts +0 -47
- package/src/utils.ts +0 -82
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lukso/transaction-view-core",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.5ea12c5",
|
|
4
4
|
"description": "Core components and hooks for LUKSO transaction display",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@preact/signals-core": "^1.12.1",
|
|
36
36
|
"ethereum-blockies-base64": "^1.0.2",
|
|
37
37
|
"lit": "^3.3.1",
|
|
38
|
-
"@lukso/transaction-decoder": "1.3.0-dev.
|
|
39
|
-
"@lukso/transaction-view-headless": "0.4.0-dev.
|
|
38
|
+
"@lukso/transaction-decoder": "1.3.0-dev.5ea12c5",
|
|
39
|
+
"@lukso/transaction-view-headless": "0.4.0-dev.5ea12c5"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@tailwindcss/typography": "^0.5.19",
|
|
@@ -16,7 +16,21 @@ import {
|
|
|
16
16
|
} from '@lukso/transaction-view-headless'
|
|
17
17
|
import { safeCustomElement } from '../shared/safe-custom-element.js'
|
|
18
18
|
import { CoreLitElement } from '../styles'
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
// Value formatting utilities
|
|
21
|
+
function formatUnits(value: bigint, decimals = 18): string {
|
|
22
|
+
const divisor = 10n ** BigInt(decimals)
|
|
23
|
+
const quotient = value / divisor
|
|
24
|
+
const remainder = value % divisor
|
|
25
|
+
|
|
26
|
+
if (remainder === 0n) {
|
|
27
|
+
return quotient.toString()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const remainderStr = remainder.toString().padStart(decimals, '0')
|
|
31
|
+
const trimmed = remainderStr.replace(/0+$/, '')
|
|
32
|
+
return `${quotient}.${trimmed}`
|
|
33
|
+
}
|
|
20
34
|
|
|
21
35
|
/**
|
|
22
36
|
* Asset card component for displaying token/NFT information
|
|
@@ -44,6 +58,9 @@ export class AssetCard extends CoreLitElement {
|
|
|
44
58
|
@property({ type: String, attribute: 'function-icon' })
|
|
45
59
|
functionIcon: string = 'code-outline'
|
|
46
60
|
|
|
61
|
+
@property({ type: String })
|
|
62
|
+
size: 'small' | 'medium' | 'large' = 'medium'
|
|
63
|
+
|
|
47
64
|
@property({ type: Boolean, attribute: 'show-info-button' })
|
|
48
65
|
showInfoButton = true
|
|
49
66
|
|
|
@@ -194,7 +211,9 @@ export class AssetCard extends CoreLitElement {
|
|
|
194
211
|
const displayTokenId = formattedTokenId ? `${formattedTokenId}` : ''
|
|
195
212
|
if (displayTokenId) return displayTokenId
|
|
196
213
|
// If its a collection, do not show tokenId
|
|
197
|
-
return this.tokenId
|
|
214
|
+
return this.tokenId && !this._resolvedData?.isCollection
|
|
215
|
+
? `${parseInt(this.tokenId, 16)}`
|
|
216
|
+
: undefined
|
|
198
217
|
}
|
|
199
218
|
|
|
200
219
|
private _renderTokenId() {
|
|
@@ -259,7 +278,6 @@ export class AssetCard extends CoreLitElement {
|
|
|
259
278
|
private _renderImages() {
|
|
260
279
|
const images = (this._resolvedData as any)?.images || []
|
|
261
280
|
if (images.length === 0) return ''
|
|
262
|
-
if (!this.address) return ''
|
|
263
281
|
|
|
264
282
|
return html`
|
|
265
283
|
<image-list
|
|
@@ -274,7 +292,6 @@ export class AssetCard extends CoreLitElement {
|
|
|
274
292
|
private _renderAssets() {
|
|
275
293
|
const assets = (this._resolvedData as any)?.assets || []
|
|
276
294
|
if (assets.length === 0) return ''
|
|
277
|
-
if (!this.address) return ''
|
|
278
295
|
|
|
279
296
|
return html`
|
|
280
297
|
<div class="section">
|
|
@@ -292,11 +309,11 @@ export class AssetCard extends CoreLitElement {
|
|
|
292
309
|
return html`
|
|
293
310
|
<div class="flex justify-between items-center my-4">
|
|
294
311
|
<function-name-view
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
312
|
+
label=${this.functionName}
|
|
313
|
+
size="small"
|
|
314
|
+
icon=${this.functionIcon ? this.functionIcon : 'code-outline'}
|
|
298
315
|
></function-name-view>
|
|
299
|
-
<function-name-view label=${this._resolvedData?.standard
|
|
316
|
+
<function-name-view label=${this._resolvedData?.standard} size="small"></function-name-view>
|
|
300
317
|
</div>
|
|
301
318
|
`
|
|
302
319
|
}
|
|
@@ -317,15 +334,6 @@ export class AssetCard extends CoreLitElement {
|
|
|
317
334
|
`
|
|
318
335
|
}
|
|
319
336
|
|
|
320
|
-
private _formattedAmount() {
|
|
321
|
-
const data = this._resolutionTask.value
|
|
322
|
-
const amt = this.amount
|
|
323
|
-
if (amt === undefined || amt === null || amt === '') return undefined
|
|
324
|
-
const bigintAmount = parseBigInt(amt as any)
|
|
325
|
-
if (bigintAmount === undefined) return undefined
|
|
326
|
-
return formatUnits(bigintAmount, data?.decimals)
|
|
327
|
-
}
|
|
328
|
-
|
|
329
337
|
private renderFormattedTokenIdBadge() {
|
|
330
338
|
if (!this.displayedTokenId) return ''
|
|
331
339
|
return html`
|
|
@@ -337,47 +345,30 @@ export class AssetCard extends CoreLitElement {
|
|
|
337
345
|
return html`
|
|
338
346
|
<div >
|
|
339
347
|
${this._renderStandards()}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
)}
|
|
356
|
-
</div>
|
|
357
|
-
<div style="height: 1px;" class="bg-neutral-90 w-full"></div>
|
|
358
|
-
<div class="px-2">
|
|
359
|
-
${this._renderAddressSection()}
|
|
360
|
-
</div>
|
|
348
|
+
<div class="mt-6 flex-col">
|
|
349
|
+
<div class="flex items-center justify-center gap-4">
|
|
350
|
+
<div class="flex justify-end w-[48%]">
|
|
351
|
+
<div class="border relative border-neutral-90 rounded-xl">
|
|
352
|
+
${this.renderFormattedTokenIdBadge()}
|
|
353
|
+
<div class="p-2 relative">
|
|
354
|
+
<icon-view
|
|
355
|
+
address="${this.address}"
|
|
356
|
+
size="2x-large"
|
|
357
|
+
.showName=${false}
|
|
358
|
+
></icon-view>
|
|
359
|
+
</div>
|
|
360
|
+
<div style="height: 1px;" class="bg-neutral-90 w-full"></div>
|
|
361
|
+
<div class="px-2">
|
|
362
|
+
${this._renderAddressSection()}
|
|
361
363
|
</div>
|
|
362
364
|
</div>
|
|
365
|
+
</div>
|
|
363
366
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
${when(
|
|
370
|
-
this.amount,
|
|
371
|
-
() => html`
|
|
372
|
-
<span class="">${this._formattedAmount() ?? ''}</span>
|
|
373
|
-
<span class="ml-1 text-neutral-60 max-w-[60px] whitespace-nowrap overflow-hidden text-ellipsis text-[14px] font-semibold">${
|
|
374
|
-
this._resolvedData?.lsp4TokenSymbol || ''
|
|
375
|
-
}</span>
|
|
376
|
-
`,
|
|
377
|
-
() => html`${this._resolvedData?.lsp4TokenSymbol || ''}`
|
|
378
|
-
)}
|
|
379
|
-
</div>
|
|
380
|
-
|
|
367
|
+
<div class="flex flex-col gap-1 w-[51%]">
|
|
368
|
+
<div class="text-[14px] font-bold text-neutral-20">
|
|
369
|
+
${this._resolvedData?.lsp4TokenName || 'UNKNOWN'}
|
|
370
|
+
</div>
|
|
371
|
+
<div class="text-[17px] font-semibold text-neutral-20">
|
|
381
372
|
${when(
|
|
382
373
|
this.amount,
|
|
383
374
|
() => html`
|
|
@@ -388,14 +379,20 @@ export class AssetCard extends CoreLitElement {
|
|
|
388
379
|
`,
|
|
389
380
|
() => html`${this._resolvedData?.lsp4TokenSymbol || ''}`
|
|
390
381
|
)}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
382
|
+
</div>
|
|
383
|
+
|
|
384
|
+
${when(
|
|
385
|
+
this.displayedTokenId,
|
|
386
|
+
() =>
|
|
387
|
+
html`<div class="text-[14px] font-medium text-neutral-60"><span class="font-bold">#${this.displayedTokenId}</span></div>`
|
|
388
|
+
)}
|
|
389
|
+
<div class="mt-4">
|
|
390
|
+
${when(this.showCreator, () => this._renderCreatorSection())}
|
|
394
391
|
</div>
|
|
395
392
|
</div>
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
393
|
+
</div>
|
|
394
|
+
<div class="border-neutral-90 pt-2">
|
|
395
|
+
${this._renderTokenDetails()}
|
|
399
396
|
</div>
|
|
400
397
|
</div>
|
|
401
398
|
`
|
|
@@ -79,15 +79,13 @@ export class PermissionsBlock extends CoreLitElement {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
private renderPermission(p: PermissionLevels) {
|
|
82
|
-
const nameBase = (p.icon || p.permissionName || '')
|
|
83
|
-
.toLowerCase()
|
|
84
|
-
.replace(/_/g, '-')
|
|
82
|
+
const nameBase = (p.icon || p.permissionName || '').toLowerCase()
|
|
85
83
|
const activeIcon = `${nameBase}-activated`
|
|
86
84
|
const inactiveIcon = `${nameBase}-inactive`
|
|
87
85
|
return html`
|
|
88
86
|
<div class="mt-4 grid grid-cols-[40px,1fr,20px] gap-x-2 items-start">
|
|
89
87
|
<div class="relative w-10 h-10">
|
|
90
|
-
<
|
|
88
|
+
<svg-icon
|
|
91
89
|
class="active absolute bottom-0 opacity-0 z-[99] transition-opacity duration-200 ${
|
|
92
90
|
p.isActive ? 'opacity-100' : ''
|
|
93
91
|
}"
|
|
@@ -95,14 +93,14 @@ export class PermissionsBlock extends CoreLitElement {
|
|
|
95
93
|
width="40"
|
|
96
94
|
height="40"
|
|
97
95
|
color=${this.color}
|
|
98
|
-
></
|
|
99
|
-
<
|
|
96
|
+
></svg-icon>
|
|
97
|
+
<svg-icon
|
|
100
98
|
class="inactive absolute bottom-0 ${p.isActive ? 'opacity-0' : 'opacity-100'}"
|
|
101
99
|
name=${inactiveIcon}
|
|
102
100
|
width="40"
|
|
103
101
|
height="40"
|
|
104
102
|
color=${this.color}
|
|
105
|
-
></
|
|
103
|
+
></svg-icon>
|
|
106
104
|
</div>
|
|
107
105
|
|
|
108
106
|
<div>
|
package/src/shared/image-list.ts
CHANGED
|
@@ -58,7 +58,7 @@ export class NotificationView extends CoreLitElement {
|
|
|
58
58
|
return html`
|
|
59
59
|
<div class="grid grid-cols-[24px_1fr] items-start gap-3 p-3 rounded-xl text-neutral-10 leading-snug ${this.getVariantBackgroundClass()}">
|
|
60
60
|
<div class="flex items-center justify-center text-[16px] text-neutral-20 self-center" aria-hidden="true">
|
|
61
|
-
<lukso-icon name="${this.renderIcon()}" size="
|
|
61
|
+
<lukso-icon name="${this.renderIcon()}" size="large" color="${this.getVariantColor()}"></lukso-icon>
|
|
62
62
|
</div>
|
|
63
63
|
<div class="text-[14px] flex flex-col gap-1.5">
|
|
64
64
|
${
|
|
@@ -66,7 +66,7 @@ export class NotificationView extends CoreLitElement {
|
|
|
66
66
|
? html`<div class="font-semibold text-neutral-20 paragraph-inter-14-semi-bold">${this.title}</div>`
|
|
67
67
|
: ''
|
|
68
68
|
}
|
|
69
|
-
<div class="text-neutral-
|
|
69
|
+
<div class="text-neutral-30"><slot>${this.message}</slot></div>
|
|
70
70
|
${
|
|
71
71
|
this.acknowledgeable
|
|
72
72
|
? html`
|
package/src/shared/value-view.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Task } from '@lit/task'
|
|
2
2
|
import { useAddressResolver } from '@lukso/transaction-view-headless'
|
|
3
|
-
import { html
|
|
3
|
+
import { html } from 'lit'
|
|
4
4
|
import { property, state } from 'lit/decorators.js'
|
|
5
5
|
import { when } from 'lit/directives/when.js'
|
|
6
6
|
import { safeCustomElement } from './safe-custom-element'
|
|
@@ -8,7 +8,21 @@ import { safeCustomElement } from './safe-custom-element'
|
|
|
8
8
|
// Import LUKSO web components
|
|
9
9
|
import './load-web-components'
|
|
10
10
|
import { CoreLitElement } from '../styles'
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
// Value formatting utilities
|
|
13
|
+
function formatUnits(value: bigint, decimals = 18): string {
|
|
14
|
+
const divisor = 10n ** BigInt(decimals)
|
|
15
|
+
const quotient = value / divisor
|
|
16
|
+
const remainder = value % divisor
|
|
17
|
+
|
|
18
|
+
if (remainder === 0n) {
|
|
19
|
+
return quotient.toString()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const remainderStr = remainder.toString().padStart(decimals, '0')
|
|
23
|
+
const trimmed = remainderStr.replace(/0+$/, '')
|
|
24
|
+
return `${quotient}.${trimmed}`
|
|
25
|
+
}
|
|
12
26
|
|
|
13
27
|
/**
|
|
14
28
|
* Value display component
|
|
@@ -33,7 +47,7 @@ export class ValueView extends CoreLitElement {
|
|
|
33
47
|
* The value to display (required)
|
|
34
48
|
* Can be string, number, boolean, or bigint
|
|
35
49
|
*/
|
|
36
|
-
@property() value?:
|
|
50
|
+
@property() value?: string | number | boolean | bigint | null
|
|
37
51
|
|
|
38
52
|
/**
|
|
39
53
|
* The key name (used for special formatting logic)
|
|
@@ -84,7 +98,7 @@ export class ValueView extends CoreLitElement {
|
|
|
84
98
|
/**
|
|
85
99
|
* Optional label to show in card header
|
|
86
100
|
*/
|
|
87
|
-
@property() label?: string
|
|
101
|
+
@property() label?: string
|
|
88
102
|
|
|
89
103
|
/**
|
|
90
104
|
* Maximum width for truncation
|
|
@@ -366,7 +380,7 @@ export class ValueView extends CoreLitElement {
|
|
|
366
380
|
|
|
367
381
|
if (effectiveType === 'currency') {
|
|
368
382
|
const { numeric, symbol } = this.getCurrencyParts()
|
|
369
|
-
if (this.label) {
|
|
383
|
+
if (this.label && this.label.trim() !== '') {
|
|
370
384
|
headerText = this.label
|
|
371
385
|
contentTemplate = html`
|
|
372
386
|
<span class="inline-block overflow-hidden text-ellipsis whitespace-nowrap min-w-0 ${this.getNumericClass()}">${numeric}</span>
|
package/src/utils.test.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { formatUnits, parseBigInt } from './utils.js'
|
|
3
|
-
|
|
4
|
-
describe('formatUnits', () => {
|
|
5
|
-
it('returns integer string when remainder is zero', () => {
|
|
6
|
-
expect(formatUnits(1000000000000000000n)).toBe('1')
|
|
7
|
-
expect(formatUnits(5000n, 3)).toBe('5')
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
it('formats values with fractional part respecting decimals', () => {
|
|
11
|
-
expect(formatUnits(123000000000000000n)).toBe('0.123')
|
|
12
|
-
expect(formatUnits(987654321n, 6)).toBe('987.654321')
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('trims trailing zeros in fractional part', () => {
|
|
16
|
-
expect(formatUnits(120n, 2)).toBe('1.2')
|
|
17
|
-
expect(formatUnits(1001000n, 6)).toBe('1.001')
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('handles zero value', () => {
|
|
21
|
-
expect(formatUnits(0n)).toBe('0')
|
|
22
|
-
})
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
describe('parseBigInt', () => {
|
|
26
|
-
it('parses decimal and hex strings with optional suffix', () => {
|
|
27
|
-
expect(parseBigInt('42')).toBe(42n)
|
|
28
|
-
expect(parseBigInt('0x10')).toBe(16n)
|
|
29
|
-
expect(parseBigInt('21n')).toBe(21n)
|
|
30
|
-
expect(parseBigInt(' 0xFFn ')).toBe(255n)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('returns bigint directly or from integer numbers', () => {
|
|
34
|
-
const value = 123n
|
|
35
|
-
expect(parseBigInt(value)).toBe(value)
|
|
36
|
-
expect(parseBigInt(9007199254740991)).toBe(9007199254740991n)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('returns undefined for invalid inputs', () => {
|
|
40
|
-
expect(parseBigInt('')).toBeUndefined()
|
|
41
|
-
expect(parseBigInt('1.5')).toBeUndefined()
|
|
42
|
-
expect(parseBigInt('0xG')).toBeUndefined()
|
|
43
|
-
expect(parseBigInt(1.1)).toBeUndefined()
|
|
44
|
-
expect(parseBigInt(null)).toBeUndefined()
|
|
45
|
-
expect(parseBigInt(undefined)).toBeUndefined()
|
|
46
|
-
})
|
|
47
|
-
})
|
package/src/utils.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
// Value formatting utilities
|
|
2
|
-
/**
|
|
3
|
-
* Convert a token amount from base units (bigint) to a decimal string.
|
|
4
|
-
*
|
|
5
|
-
* - Handles arbitrary `decimals` without floating point precision loss.
|
|
6
|
-
* - Trims trailing zeros in the fractional part.
|
|
7
|
-
* - Returns only the integer part when remainder is zero.
|
|
8
|
-
*
|
|
9
|
-
* @param value - The amount in base units as a bigint (e.g., wei for ETH).
|
|
10
|
-
* @param decimals - Number of decimal places the token uses (default 18).
|
|
11
|
-
* @returns A human-readable decimal string.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* // 1 ether in wei
|
|
15
|
-
* formatUnits(1000000000000000000n) // '1'
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* // 1.23 tokens with 2 decimals
|
|
19
|
-
* formatUnits(123n, 2) // '1.23'
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* // No remainder: return integer part only
|
|
23
|
-
* formatUnits(2000000000000000000n) // '2'
|
|
24
|
-
*/
|
|
25
|
-
export function formatUnits(value: bigint, decimals = 18): string {
|
|
26
|
-
const divisor = 10n ** BigInt(decimals)
|
|
27
|
-
const quotient = value / divisor
|
|
28
|
-
const remainder = value % divisor
|
|
29
|
-
|
|
30
|
-
if (remainder === 0n) {
|
|
31
|
-
return quotient.toString()
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const remainderStr = remainder.toString().padStart(decimals, '0')
|
|
35
|
-
const trimmed = remainderStr.replace(/0+$/, '')
|
|
36
|
-
return `${quotient}.${trimmed}`
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function isBigIntString(str: string): boolean {
|
|
40
|
-
const trimmed = str.trim()
|
|
41
|
-
if (trimmed.endsWith('n'))
|
|
42
|
-
return /^[0-9]+n$/.test(trimmed) || /^0x[0-9a-fA-F]+n$/.test(trimmed)
|
|
43
|
-
return /^[0-9]+$/.test(trimmed) || /^0x[0-9a-fA-F]+$/.test(trimmed)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Parse loose bigint inputs coming from attributes, JSON, or user input.
|
|
48
|
-
*
|
|
49
|
-
* - Accepts bigint literals (`123n`), decimal/hex strings, and integers.
|
|
50
|
-
* - Trims whitespace and optional trailing `n` suffix.
|
|
51
|
-
* - Returns `undefined` for invalid formats (floats, empty strings, non-numeric text).
|
|
52
|
-
*
|
|
53
|
-
* @param value - Source value to parse (string | number | bigint | null | undefined).
|
|
54
|
-
* @returns BigInt when parsing succeeds, otherwise `undefined`.
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* parseBigInt('42') // 42n
|
|
58
|
-
* @example
|
|
59
|
-
* parseBigInt('0x10n') // 16n
|
|
60
|
-
* @example
|
|
61
|
-
* parseBigInt(1000n) // 1000n (passthrough)
|
|
62
|
-
* @example
|
|
63
|
-
* parseBigInt('1.5') // undefined (decimals not allowed)
|
|
64
|
-
*/
|
|
65
|
-
export function parseBigInt(
|
|
66
|
-
value: string | number | bigint | null | undefined
|
|
67
|
-
): bigint | undefined {
|
|
68
|
-
if (!value) return undefined
|
|
69
|
-
if (typeof value === 'bigint') return value
|
|
70
|
-
if (typeof value === 'number') {
|
|
71
|
-
if (!Number.isInteger(value)) return undefined
|
|
72
|
-
return BigInt(value)
|
|
73
|
-
}
|
|
74
|
-
const trimmed = value.trim()
|
|
75
|
-
const cleaned = trimmed.endsWith('n') ? trimmed.slice(0, -1) : trimmed
|
|
76
|
-
if (!isBigIntString(cleaned)) return undefined
|
|
77
|
-
try {
|
|
78
|
-
return BigInt(cleaned)
|
|
79
|
-
} catch {
|
|
80
|
-
return undefined
|
|
81
|
-
}
|
|
82
|
-
}
|