@dynamic-labs/midnight 4.91.1 → 4.91.2
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/CHANGELOG.md +24 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +8 -8
- package/src/utils/MidnightUiTransaction/MidnightUiTransaction.cjs +80 -40
- package/src/utils/MidnightUiTransaction/MidnightUiTransaction.d.ts +14 -5
- package/src/utils/MidnightUiTransaction/MidnightUiTransaction.js +81 -41
- package/src/waas/connector/DynamicWaasMidnightConnector.cjs +31 -18
- package/src/waas/connector/DynamicWaasMidnightConnector.d.ts +20 -14
- package/src/waas/connector/DynamicWaasMidnightConnector.js +32 -19
- package/src/wallet/MidnightWallet.cjs +5 -4
- package/src/wallet/MidnightWallet.js +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
|
|
2
|
+
### [4.91.2](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.1...v4.91.2) (2026-06-26)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### ⚠ BREAKING CHANGES
|
|
6
|
+
|
|
7
|
+
* **waas:** require expectedAddresses on migrateFromFireblocks (#11730)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **midnight:** support shielded/unshielded transfers and dust states in the embedded Send flow ([#11731](https://github.com/dynamic-labs/dynamic-auth/issues/11731)) ([663d171](https://github.com/dynamic-labs/dynamic-auth/commit/663d171a9628c634586831ee35c234e9331e3f80))
|
|
12
|
+
* **react-native-extension:** instrument all embedded webview failure paths ([#11737](https://github.com/dynamic-labs/dynamic-auth/issues/11737)) ([172998b](https://github.com/dynamic-labs/dynamic-auth/commit/172998b56e9bee04fbb8da71e83ce8885bc378ff))
|
|
13
|
+
* **waas:** migrateFromFireblocks connector method + demo panel (browser-wallet-client 1.0.46) ([#11702](https://github.com/dynamic-labs/dynamic-auth/issues/11702)) ([6bfc844](https://github.com/dynamic-labs/dynamic-auth/commit/6bfc8443fbaedabe1e7bee0ed78742cbbe5d0084))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* add coverage for scenario with passkey re-login and smart account ([#11726](https://github.com/dynamic-labs/dynamic-auth/issues/11726)) ([5364a72](https://github.com/dynamic-labs/dynamic-auth/commit/5364a72a750d835b9b2da602a91e8b5d7d305db7))
|
|
19
|
+
* remediate high-severity dependency vulnerabilities ([#11721](https://github.com/dynamic-labs/dynamic-auth/issues/11721)) ([cdb9306](https://github.com/dynamic-labs/dynamic-auth/commit/cdb93061365a20b8f73a1f8bea8352332e282c1e))
|
|
20
|
+
* replace node-fetch v2 with native fetch to fix Node 22 stream failure ([#11732](https://github.com/dynamic-labs/dynamic-auth/issues/11732)) ([b98f801](https://github.com/dynamic-labs/dynamic-auth/commit/b98f801e307b52dbd7e4b241a9a4a2d34d89118e))
|
|
21
|
+
* **zerodev-extension:** derive kernel 7702 vs 4337 per-wallet, not from global dashboard flag ([#11735](https://github.com/dynamic-labs/dynamic-auth/issues/11735)) ([72cf6a7](https://github.com/dynamic-labs/dynamic-auth/commit/72cf6a70a4857a4ea469faa555c485dbad8d0217))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
* **waas:** require expectedAddresses on migrateFromFireblocks ([#11730](https://github.com/dynamic-labs/dynamic-auth/issues/11730)) ([c94824e](https://github.com/dynamic-labs/dynamic-auth/commit/c94824ebe11e0433a6ffbd2a5a9dd4283aeed31e))
|
|
25
|
+
|
|
2
26
|
### [4.91.1](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.0...v4.91.1) (2026-06-24)
|
|
3
27
|
|
|
4
28
|
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/midnight",
|
|
3
|
-
"version": "4.91.
|
|
3
|
+
"version": "4.91.2",
|
|
4
4
|
"description": "A React SDK for implementing wallet web3 authentication and authorization to your website.",
|
|
5
5
|
"author": "Dynamic Labs, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
},
|
|
19
19
|
"homepage": "https://www.dynamic.xyz/",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@dynamic-labs/assert-package-version": "4.91.
|
|
21
|
+
"@dynamic-labs/assert-package-version": "4.91.2",
|
|
22
22
|
"@dynamic-labs/sdk-api-core": "0.0.1046",
|
|
23
23
|
"@midnight-ntwrk/dapp-connector-api": "4.0.1",
|
|
24
|
-
"@dynamic-labs/logger": "4.91.
|
|
25
|
-
"@dynamic-labs/types": "4.91.
|
|
26
|
-
"@dynamic-labs/utils": "4.91.
|
|
27
|
-
"@dynamic-labs/waas": "4.91.
|
|
28
|
-
"@dynamic-labs/wallet-book": "4.91.
|
|
29
|
-
"@dynamic-labs/wallet-connector-core": "4.91.
|
|
24
|
+
"@dynamic-labs/logger": "4.91.2",
|
|
25
|
+
"@dynamic-labs/types": "4.91.2",
|
|
26
|
+
"@dynamic-labs/utils": "4.91.2",
|
|
27
|
+
"@dynamic-labs/waas": "4.91.2",
|
|
28
|
+
"@dynamic-labs/wallet-book": "4.91.2",
|
|
29
|
+
"@dynamic-labs/wallet-connector-core": "4.91.2"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {}
|
|
32
32
|
}
|
|
@@ -8,6 +8,10 @@ var constants = require('../../constants.cjs');
|
|
|
8
8
|
var formatMidnightAtomicBalance = require('../formatMidnightAtomicBalance/formatMidnightAtomicBalance.cjs');
|
|
9
9
|
var parseMidnightAtomicAmount = require('../parseMidnightAtomicAmount/parseMidnightAtomicAmount.cjs');
|
|
10
10
|
|
|
11
|
+
// Shielded tokens aren't NIGHT and have no decimals metadata, so they're shown
|
|
12
|
+
// at their raw amount (decimals 0); native NIGHT keeps 6-decimal formatting.
|
|
13
|
+
const SHIELDED_TOKEN_DECIMALS = 0;
|
|
14
|
+
const shortTokenLabel = (address) => `TOKEN: ${address.slice(0, 8)}...${address.slice(-8)}`;
|
|
11
15
|
class MidnightUiTransaction {
|
|
12
16
|
constructor(opts) {
|
|
13
17
|
this.to = undefined;
|
|
@@ -17,68 +21,104 @@ class MidnightUiTransaction {
|
|
|
17
21
|
this.chain = 'MIDNIGHT';
|
|
18
22
|
this.fee = { gas: undefined };
|
|
19
23
|
this.feeTokenSymbol = 'DUST';
|
|
24
|
+
// Pool defaults to unshielded; it is derived from the selected token (or the
|
|
25
|
+
// transaction-mode toggle), never inferred from a hard-coded token hash.
|
|
20
26
|
this.pool = 'unshielded';
|
|
27
|
+
this.selectedTransactionMode = 'unshielded';
|
|
28
|
+
this.selectedTokenAddress = constants.MIDNIGHT_NATIVE_TOKEN_TYPE;
|
|
21
29
|
this.from = opts.from;
|
|
30
|
+
this.balances = opts.balances;
|
|
31
|
+
this.shieldedAddresses = new Set(Object.keys(opts.balances.shielded));
|
|
22
32
|
this.onSubmitFn = opts.onSubmit;
|
|
23
|
-
this.getUnshieldedBalanceFn = opts.getUnshieldedBalance;
|
|
24
|
-
this.getShieldedBalanceFn = opts.getShieldedBalance;
|
|
25
33
|
this.fetchDustFeeFn = opts.fetchDustFee;
|
|
26
34
|
}
|
|
27
35
|
get activePool() {
|
|
28
36
|
return this.pool;
|
|
29
37
|
}
|
|
38
|
+
get transactionModes() {
|
|
39
|
+
return [
|
|
40
|
+
{ id: 'unshielded', label: 'Unshielded' },
|
|
41
|
+
{ id: 'shielded', label: 'Shielded' },
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
get selectedTokenDecimals() {
|
|
45
|
+
return this.selectedTokenAddress === constants.MIDNIGHT_NATIVE_TOKEN_TYPE
|
|
46
|
+
? constants.MIDNIGHT_NATIVE_UNSHIELDED_DECIMALS
|
|
47
|
+
: SHIELDED_TOKEN_DECIMALS;
|
|
48
|
+
}
|
|
49
|
+
// Pool a token belongs to — used by the send form to filter the picker.
|
|
50
|
+
getTokenPool(contractAddress) {
|
|
51
|
+
return this.shieldedAddresses.has(contractAddress)
|
|
52
|
+
? 'shielded'
|
|
53
|
+
: 'unshielded';
|
|
54
|
+
}
|
|
55
|
+
setTransactionMode(modeId) {
|
|
56
|
+
this.selectedTransactionMode = modeId;
|
|
57
|
+
this.pool = modeId === 'shielded' ? 'shielded' : 'unshielded';
|
|
58
|
+
this.to = undefined;
|
|
59
|
+
this.value = undefined;
|
|
60
|
+
}
|
|
30
61
|
setSelectedToken(contractAddress) {
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
: 'unshielded';
|
|
62
|
+
this.selectedTokenAddress = contractAddress;
|
|
63
|
+
this.pool = this.getTokenPool(contractAddress);
|
|
64
|
+
this.selectedTransactionMode = this.pool;
|
|
35
65
|
this.to = undefined;
|
|
36
66
|
this.value = undefined;
|
|
37
67
|
}
|
|
38
68
|
getSendableTokenBalances() {
|
|
39
69
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
]);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
var _a;
|
|
71
|
+
const toDisplay = (raw, decimals) => Number(formatMidnightAtomicBalance.formatMidnightAtomicBalance(raw, decimals));
|
|
72
|
+
// Native unshielded NIGHT — always shown, even at a zero balance.
|
|
73
|
+
const unshieldedNightRaw = (_a = this.balances.unshielded[constants.MIDNIGHT_NATIVE_TOKEN_TYPE]) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
74
|
+
const nightEntry = {
|
|
75
|
+
address: constants.MIDNIGHT_NATIVE_TOKEN_TYPE,
|
|
76
|
+
balance: toDisplay(unshieldedNightRaw, constants.MIDNIGHT_NATIVE_UNSHIELDED_DECIMALS),
|
|
77
|
+
decimals: constants.MIDNIGHT_NATIVE_UNSHIELDED_DECIMALS,
|
|
78
|
+
isNative: true,
|
|
79
|
+
logoURI: '',
|
|
80
|
+
name: 'NIGHT',
|
|
81
|
+
rawBalance: Number(unshieldedNightRaw),
|
|
82
|
+
rawBalanceString: unshieldedNightRaw.toString(),
|
|
83
|
+
symbol: 'NIGHT',
|
|
84
|
+
};
|
|
85
|
+
// Non-NIGHT tokens (other unshielded + every shielded token), shown at raw
|
|
86
|
+
// amount. `isNative: true` is deliberate — like Aleo, every Midnight token
|
|
87
|
+
// uses the `transaction.parse`/`getBalance` path; the form's non-native
|
|
88
|
+
// branch (`parseNonNativeToken`) is EVM-only and doesn't apply here.
|
|
89
|
+
const tokenEntry = (address, raw) => ({
|
|
90
|
+
address,
|
|
91
|
+
balance: toDisplay(raw, SHIELDED_TOKEN_DECIMALS),
|
|
92
|
+
decimals: SHIELDED_TOKEN_DECIMALS,
|
|
93
|
+
isNative: true,
|
|
94
|
+
logoURI: '',
|
|
95
|
+
name: shortTokenLabel(address),
|
|
96
|
+
rawBalance: Number(raw),
|
|
97
|
+
rawBalanceString: raw.toString(),
|
|
98
|
+
symbol: '',
|
|
99
|
+
});
|
|
100
|
+
const otherUnshielded = Object.entries(this.balances.unshielded)
|
|
101
|
+
.filter(([address, raw]) => address !== constants.MIDNIGHT_NATIVE_TOKEN_TYPE && raw > BigInt(0))
|
|
102
|
+
.map(([address, raw]) => tokenEntry(address, raw));
|
|
103
|
+
const shielded = Object.entries(this.balances.shielded)
|
|
104
|
+
.filter(([, raw]) => raw > BigInt(0))
|
|
105
|
+
.map(([address, raw]) => tokenEntry(address, raw));
|
|
106
|
+
return [nightEntry, ...otherUnshielded, ...shielded];
|
|
69
107
|
});
|
|
70
108
|
}
|
|
71
109
|
parse(input) {
|
|
72
|
-
return parseMidnightAtomicAmount.parseMidnightAtomicAmount(input,
|
|
110
|
+
return parseMidnightAtomicAmount.parseMidnightAtomicAmount(input, this.selectedTokenDecimals);
|
|
73
111
|
}
|
|
74
112
|
format(value) {
|
|
75
|
-
return formatMidnightAtomicBalance.formatMidnightAtomicBalance(value,
|
|
113
|
+
return formatMidnightAtomicBalance.formatMidnightAtomicBalance(value, this.selectedTokenDecimals);
|
|
76
114
|
}
|
|
77
115
|
getBalance() {
|
|
78
116
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
117
|
+
var _a;
|
|
118
|
+
const map = this.pool === 'shielded'
|
|
119
|
+
? this.balances.shielded
|
|
120
|
+
: this.balances.unshielded;
|
|
121
|
+
return (_a = map[this.selectedTokenAddress]) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
82
122
|
});
|
|
83
123
|
}
|
|
84
124
|
fetchFee() {
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { TokenBalance } from '@dynamic-labs/sdk-api-core';
|
|
2
|
-
import type { IUITransaction } from '@dynamic-labs/types';
|
|
2
|
+
import type { IUITransaction, TransactionModeOption } from '@dynamic-labs/types';
|
|
3
3
|
type MidnightPool = 'unshielded' | 'shielded';
|
|
4
|
+
export type MidnightBalanceMaps = {
|
|
5
|
+
shielded: Record<string, bigint>;
|
|
6
|
+
unshielded: Record<string, bigint>;
|
|
7
|
+
};
|
|
4
8
|
type MidnightUiTransactionOpts = {
|
|
5
9
|
from: string;
|
|
6
10
|
onSubmit: (tx: MidnightUiTransaction) => Promise<string>;
|
|
7
|
-
|
|
8
|
-
getShieldedBalance: () => Promise<bigint>;
|
|
11
|
+
balances: MidnightBalanceMaps;
|
|
9
12
|
fetchDustFee: () => Promise<bigint>;
|
|
10
13
|
};
|
|
11
14
|
export declare class MidnightUiTransaction implements IUITransaction {
|
|
@@ -20,12 +23,18 @@ export declare class MidnightUiTransaction implements IUITransaction {
|
|
|
20
23
|
};
|
|
21
24
|
feeTokenSymbol: string;
|
|
22
25
|
private pool;
|
|
26
|
+
selectedTransactionMode: string;
|
|
27
|
+
selectedTokenAddress: string;
|
|
28
|
+
private readonly balances;
|
|
29
|
+
private readonly shieldedAddresses;
|
|
23
30
|
private readonly onSubmitFn;
|
|
24
|
-
private readonly getUnshieldedBalanceFn;
|
|
25
|
-
private readonly getShieldedBalanceFn;
|
|
26
31
|
private readonly fetchDustFeeFn;
|
|
27
32
|
constructor(opts: MidnightUiTransactionOpts);
|
|
28
33
|
get activePool(): MidnightPool;
|
|
34
|
+
get transactionModes(): TransactionModeOption[];
|
|
35
|
+
private get selectedTokenDecimals();
|
|
36
|
+
getTokenPool(contractAddress: string): MidnightPool;
|
|
37
|
+
setTransactionMode(modeId: string): void;
|
|
29
38
|
setSelectedToken(contractAddress: string): void;
|
|
30
39
|
getSendableTokenBalances(): Promise<TokenBalance[]>;
|
|
31
40
|
parse(input: string): bigint;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import { __awaiter } from '../../../_virtual/_tslib.js';
|
|
3
|
-
import {
|
|
3
|
+
import { MIDNIGHT_NATIVE_TOKEN_TYPE, MIDNIGHT_NATIVE_UNSHIELDED_DECIMALS } from '../../constants.js';
|
|
4
4
|
import { formatMidnightAtomicBalance } from '../formatMidnightAtomicBalance/formatMidnightAtomicBalance.js';
|
|
5
5
|
import { parseMidnightAtomicAmount } from '../parseMidnightAtomicAmount/parseMidnightAtomicAmount.js';
|
|
6
6
|
|
|
7
|
+
// Shielded tokens aren't NIGHT and have no decimals metadata, so they're shown
|
|
8
|
+
// at their raw amount (decimals 0); native NIGHT keeps 6-decimal formatting.
|
|
9
|
+
const SHIELDED_TOKEN_DECIMALS = 0;
|
|
10
|
+
const shortTokenLabel = (address) => `TOKEN: ${address.slice(0, 8)}...${address.slice(-8)}`;
|
|
7
11
|
class MidnightUiTransaction {
|
|
8
12
|
constructor(opts) {
|
|
9
13
|
this.to = undefined;
|
|
@@ -13,68 +17,104 @@ class MidnightUiTransaction {
|
|
|
13
17
|
this.chain = 'MIDNIGHT';
|
|
14
18
|
this.fee = { gas: undefined };
|
|
15
19
|
this.feeTokenSymbol = 'DUST';
|
|
20
|
+
// Pool defaults to unshielded; it is derived from the selected token (or the
|
|
21
|
+
// transaction-mode toggle), never inferred from a hard-coded token hash.
|
|
16
22
|
this.pool = 'unshielded';
|
|
23
|
+
this.selectedTransactionMode = 'unshielded';
|
|
24
|
+
this.selectedTokenAddress = MIDNIGHT_NATIVE_TOKEN_TYPE;
|
|
17
25
|
this.from = opts.from;
|
|
26
|
+
this.balances = opts.balances;
|
|
27
|
+
this.shieldedAddresses = new Set(Object.keys(opts.balances.shielded));
|
|
18
28
|
this.onSubmitFn = opts.onSubmit;
|
|
19
|
-
this.getUnshieldedBalanceFn = opts.getUnshieldedBalance;
|
|
20
|
-
this.getShieldedBalanceFn = opts.getShieldedBalance;
|
|
21
29
|
this.fetchDustFeeFn = opts.fetchDustFee;
|
|
22
30
|
}
|
|
23
31
|
get activePool() {
|
|
24
32
|
return this.pool;
|
|
25
33
|
}
|
|
34
|
+
get transactionModes() {
|
|
35
|
+
return [
|
|
36
|
+
{ id: 'unshielded', label: 'Unshielded' },
|
|
37
|
+
{ id: 'shielded', label: 'Shielded' },
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
get selectedTokenDecimals() {
|
|
41
|
+
return this.selectedTokenAddress === MIDNIGHT_NATIVE_TOKEN_TYPE
|
|
42
|
+
? MIDNIGHT_NATIVE_UNSHIELDED_DECIMALS
|
|
43
|
+
: SHIELDED_TOKEN_DECIMALS;
|
|
44
|
+
}
|
|
45
|
+
// Pool a token belongs to — used by the send form to filter the picker.
|
|
46
|
+
getTokenPool(contractAddress) {
|
|
47
|
+
return this.shieldedAddresses.has(contractAddress)
|
|
48
|
+
? 'shielded'
|
|
49
|
+
: 'unshielded';
|
|
50
|
+
}
|
|
51
|
+
setTransactionMode(modeId) {
|
|
52
|
+
this.selectedTransactionMode = modeId;
|
|
53
|
+
this.pool = modeId === 'shielded' ? 'shielded' : 'unshielded';
|
|
54
|
+
this.to = undefined;
|
|
55
|
+
this.value = undefined;
|
|
56
|
+
}
|
|
26
57
|
setSelectedToken(contractAddress) {
|
|
27
|
-
this.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
: 'unshielded';
|
|
58
|
+
this.selectedTokenAddress = contractAddress;
|
|
59
|
+
this.pool = this.getTokenPool(contractAddress);
|
|
60
|
+
this.selectedTransactionMode = this.pool;
|
|
31
61
|
this.to = undefined;
|
|
32
62
|
this.value = undefined;
|
|
33
63
|
}
|
|
34
64
|
getSendableTokenBalances() {
|
|
35
65
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
]);
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
var _a;
|
|
67
|
+
const toDisplay = (raw, decimals) => Number(formatMidnightAtomicBalance(raw, decimals));
|
|
68
|
+
// Native unshielded NIGHT — always shown, even at a zero balance.
|
|
69
|
+
const unshieldedNightRaw = (_a = this.balances.unshielded[MIDNIGHT_NATIVE_TOKEN_TYPE]) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
70
|
+
const nightEntry = {
|
|
71
|
+
address: MIDNIGHT_NATIVE_TOKEN_TYPE,
|
|
72
|
+
balance: toDisplay(unshieldedNightRaw, MIDNIGHT_NATIVE_UNSHIELDED_DECIMALS),
|
|
73
|
+
decimals: MIDNIGHT_NATIVE_UNSHIELDED_DECIMALS,
|
|
74
|
+
isNative: true,
|
|
75
|
+
logoURI: '',
|
|
76
|
+
name: 'NIGHT',
|
|
77
|
+
rawBalance: Number(unshieldedNightRaw),
|
|
78
|
+
rawBalanceString: unshieldedNightRaw.toString(),
|
|
79
|
+
symbol: 'NIGHT',
|
|
80
|
+
};
|
|
81
|
+
// Non-NIGHT tokens (other unshielded + every shielded token), shown at raw
|
|
82
|
+
// amount. `isNative: true` is deliberate — like Aleo, every Midnight token
|
|
83
|
+
// uses the `transaction.parse`/`getBalance` path; the form's non-native
|
|
84
|
+
// branch (`parseNonNativeToken`) is EVM-only and doesn't apply here.
|
|
85
|
+
const tokenEntry = (address, raw) => ({
|
|
86
|
+
address,
|
|
87
|
+
balance: toDisplay(raw, SHIELDED_TOKEN_DECIMALS),
|
|
88
|
+
decimals: SHIELDED_TOKEN_DECIMALS,
|
|
89
|
+
isNative: true,
|
|
90
|
+
logoURI: '',
|
|
91
|
+
name: shortTokenLabel(address),
|
|
92
|
+
rawBalance: Number(raw),
|
|
93
|
+
rawBalanceString: raw.toString(),
|
|
94
|
+
symbol: '',
|
|
95
|
+
});
|
|
96
|
+
const otherUnshielded = Object.entries(this.balances.unshielded)
|
|
97
|
+
.filter(([address, raw]) => address !== MIDNIGHT_NATIVE_TOKEN_TYPE && raw > BigInt(0))
|
|
98
|
+
.map(([address, raw]) => tokenEntry(address, raw));
|
|
99
|
+
const shielded = Object.entries(this.balances.shielded)
|
|
100
|
+
.filter(([, raw]) => raw > BigInt(0))
|
|
101
|
+
.map(([address, raw]) => tokenEntry(address, raw));
|
|
102
|
+
return [nightEntry, ...otherUnshielded, ...shielded];
|
|
65
103
|
});
|
|
66
104
|
}
|
|
67
105
|
parse(input) {
|
|
68
|
-
return parseMidnightAtomicAmount(input,
|
|
106
|
+
return parseMidnightAtomicAmount(input, this.selectedTokenDecimals);
|
|
69
107
|
}
|
|
70
108
|
format(value) {
|
|
71
|
-
return formatMidnightAtomicBalance(value,
|
|
109
|
+
return formatMidnightAtomicBalance(value, this.selectedTokenDecimals);
|
|
72
110
|
}
|
|
73
111
|
getBalance() {
|
|
74
112
|
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
113
|
+
var _a;
|
|
114
|
+
const map = this.pool === 'shielded'
|
|
115
|
+
? this.balances.shielded
|
|
116
|
+
: this.balances.unshielded;
|
|
117
|
+
return (_a = map[this.selectedTokenAddress]) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
78
118
|
});
|
|
79
119
|
}
|
|
80
120
|
fetchFee() {
|
|
@@ -87,6 +87,8 @@ class DynamicWaasMidnightConnector extends waas.withDynamicWaas(WaasMidnightWall
|
|
|
87
87
|
*/
|
|
88
88
|
afterWalletSelectHook(walletAddress) {
|
|
89
89
|
this.setActiveAccountAddress(walletAddress);
|
|
90
|
+
// Different wallet → its balances are unrelated; drop any cached snapshot.
|
|
91
|
+
this.clearSendBalanceCache();
|
|
90
92
|
}
|
|
91
93
|
/**
|
|
92
94
|
* Requires and returns the signed session ID
|
|
@@ -165,7 +167,9 @@ class DynamicWaasMidnightConnector extends waas.withDynamicWaas(WaasMidnightWall
|
|
|
165
167
|
*/
|
|
166
168
|
disconnect() {
|
|
167
169
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
168
|
-
// WaaS doesn't require explicit disconnect
|
|
170
|
+
// WaaS doesn't require explicit disconnect, but drop the balance snapshot
|
|
171
|
+
// so a shielded balance isn't retained after the wallet is disconnected.
|
|
172
|
+
this.clearSendBalanceCache();
|
|
169
173
|
});
|
|
170
174
|
}
|
|
171
175
|
/**
|
|
@@ -268,47 +272,54 @@ class DynamicWaasMidnightConnector extends waas.withDynamicWaas(WaasMidnightWall
|
|
|
268
272
|
return signature;
|
|
269
273
|
});
|
|
270
274
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
* @returns A new IUITransaction instance
|
|
275
|
-
*/
|
|
275
|
+
clearSendBalanceCache() {
|
|
276
|
+
this.sendBalanceCache = undefined;
|
|
277
|
+
}
|
|
276
278
|
createUiTransaction(from) {
|
|
277
279
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
278
280
|
yield this.validateActiveWallet(from);
|
|
281
|
+
// Balances from the connector (MPC state) — never the redcoast
|
|
282
|
+
// public-balance endpoint, which rejects Midnight addresses. Reused from the
|
|
283
|
+
// short-lived cache across recreations (see field doc).
|
|
284
|
+
const now = Date.now();
|
|
285
|
+
if (!this.sendBalanceCache ||
|
|
286
|
+
now - this.sendBalanceCache.at >
|
|
287
|
+
DynamicWaasMidnightConnector.SEND_BALANCE_TTL_MS) {
|
|
288
|
+
const { shielded, unshielded } = yield this.getBalances();
|
|
289
|
+
this.sendBalanceCache = { at: now, maps: { shielded, unshielded } };
|
|
290
|
+
}
|
|
291
|
+
const balances = this.sendBalanceCache.maps;
|
|
279
292
|
return new MidnightUiTransaction.MidnightUiTransaction({
|
|
293
|
+
balances,
|
|
280
294
|
// No on-chain dust-fee estimate is exposed yet; DUST fees are charged
|
|
281
295
|
// at submit time. TODO: surface a real estimate from the wallet client.
|
|
282
296
|
fetchDustFee: () => _tslib.__awaiter(this, void 0, void 0, function* () { return BigInt(0); }),
|
|
283
297
|
from,
|
|
284
|
-
// Balances come from the connector (MPC state), reusing the cached
|
|
285
|
-
// synced wallet — never from the redcoast public-balance endpoint,
|
|
286
|
-
// which doesn't support Midnight addresses.
|
|
287
|
-
getShieldedBalance: () => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
288
|
-
var _a;
|
|
289
|
-
return (_a = (yield this.getBalances()).shielded[constants.MIDNIGHT_NATIVE_SHIELDED_TOKEN_TYPE]) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
290
|
-
}),
|
|
291
|
-
getUnshieldedBalance: () => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
292
|
-
var _b;
|
|
293
|
-
return (_b = (yield this.getBalances()).unshielded[constants.MIDNIGHT_NATIVE_TOKEN_TYPE]) !== null && _b !== void 0 ? _b : BigInt(0);
|
|
294
|
-
}),
|
|
295
298
|
onSubmit: (tx) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
296
299
|
if (tx.to === undefined || tx.value === undefined) {
|
|
297
300
|
throw new utils.DynamicError('Recipient and amount are required before submitting');
|
|
298
301
|
}
|
|
302
|
+
// Native NIGHT needs no tokenType; any other (shielded) token is passed
|
|
303
|
+
// by its ledger token type so the correct balance is debited.
|
|
304
|
+
const tokenType = tx.selectedTokenAddress === constants.MIDNIGHT_NATIVE_TOKEN_TYPE
|
|
305
|
+
? undefined
|
|
306
|
+
: tx.selectedTokenAddress;
|
|
299
307
|
// 3-step Midnight transfer: build → sign (ZK prove) → submit.
|
|
300
308
|
const { serializedTransaction } = yield this.createTransferTransaction({
|
|
301
309
|
transfers: [
|
|
302
310
|
{
|
|
303
311
|
amount: tx.value.toString(),
|
|
304
312
|
recipientAddress: tx.to,
|
|
313
|
+
tokenType,
|
|
305
314
|
type: tx.activePool,
|
|
306
315
|
},
|
|
307
316
|
],
|
|
308
317
|
});
|
|
309
318
|
const finalized = yield this.signTransaction(serializedTransaction);
|
|
310
|
-
// Return the tx hash so the Send flow advances to the success view.
|
|
311
319
|
const { txHash } = yield this.submitTransaction(finalized);
|
|
320
|
+
// Balances changed — drop the snapshot so the next send fetches fresh.
|
|
321
|
+
this.clearSendBalanceCache();
|
|
322
|
+
// Return the tx hash so the Send flow advances to the success view.
|
|
312
323
|
return txHash;
|
|
313
324
|
}),
|
|
314
325
|
});
|
|
@@ -580,5 +591,7 @@ class DynamicWaasMidnightConnector extends waas.withDynamicWaas(WaasMidnightWall
|
|
|
580
591
|
});
|
|
581
592
|
}
|
|
582
593
|
}
|
|
594
|
+
// Max age of the Send-flow balance snapshot (see `sendBalanceCache`).
|
|
595
|
+
DynamicWaasMidnightConnector.SEND_BALANCE_TTL_MS = 30000;
|
|
583
596
|
|
|
584
597
|
exports.DynamicWaasMidnightConnector = DynamicWaasMidnightConnector;
|
|
@@ -67,11 +67,6 @@ declare const DynamicWaasMidnightConnector_base: (abstract new (...args: any[])
|
|
|
67
67
|
password?: string | undefined;
|
|
68
68
|
bitcoinConfig?: import("@dynamic-labs-wallet/browser-wallet-client").BitcoinConfig | undefined;
|
|
69
69
|
} | undefined): Promise<{
|
|
70
|
-
/**
|
|
71
|
-
* Requires and returns the signed session ID
|
|
72
|
-
* @returns The signed session ID
|
|
73
|
-
* @throws {DynamicError} If signed session ID is not available
|
|
74
|
-
*/
|
|
75
70
|
chainName: string;
|
|
76
71
|
accountAddress: string;
|
|
77
72
|
publicKeyHex: string;
|
|
@@ -82,15 +77,18 @@ declare const DynamicWaasMidnightConnector_base: (abstract new (...args: any[])
|
|
|
82
77
|
thresholdSignatureScheme?: string | undefined;
|
|
83
78
|
publicAddressCheck?: string | undefined;
|
|
84
79
|
addressType?: string | undefined;
|
|
85
|
-
/**
|
|
86
|
-
* Validates that the expected wallet address matches the active wallet
|
|
87
|
-
* Updates the active account address if it doesn't match
|
|
88
|
-
* @param expectedAddress - The expected wallet address to validate
|
|
89
|
-
* @throws {DynamicError} If signed session ID is not available or account is not found
|
|
90
|
-
*/
|
|
91
80
|
legacyWalletId?: string | undefined;
|
|
92
81
|
password?: string | undefined;
|
|
93
82
|
}): Promise<void>;
|
|
83
|
+
migrateFromFireblocks({ deviceId, jwt, walletPassword, ncwStorage, expectedAddresses, coinTypes, password, }: {
|
|
84
|
+
deviceId: string;
|
|
85
|
+
jwt: string;
|
|
86
|
+
walletPassword: string;
|
|
87
|
+
ncwStorage: Record<string, string>;
|
|
88
|
+
expectedAddresses: Record<string, string>;
|
|
89
|
+
coinTypes?: Record<string, number> | undefined;
|
|
90
|
+
password?: string | undefined;
|
|
91
|
+
}): Promise<import("@dynamic-labs-wallet/browser-wallet-client").MigrateFromFireblocksResponse>;
|
|
94
92
|
exportPrivateKey({ accountAddress, displayContainer, password, }?: {
|
|
95
93
|
accountAddress?: string | undefined;
|
|
96
94
|
displayContainer?: HTMLIFrameElement | undefined;
|
|
@@ -109,6 +107,10 @@ declare const DynamicWaasMidnightConnector_base: (abstract new (...args: any[])
|
|
|
109
107
|
googleDriveAccessToken?: string | undefined;
|
|
110
108
|
}): Promise<void>;
|
|
111
109
|
exportClientKeysharesFromGoogleDrive({ accountAddress, password, }: {
|
|
110
|
+
/**
|
|
111
|
+
* When active account is not set (e.g. primary wallet restored from session),
|
|
112
|
+
* fall back to the first Midnight verified credential so signing and getAddress work.
|
|
113
|
+
*/
|
|
112
114
|
accountAddress: string;
|
|
113
115
|
password?: string | undefined;
|
|
114
116
|
}): Promise<void>;
|
|
@@ -130,14 +132,15 @@ declare const DynamicWaasMidnightConnector_base: (abstract new (...args: any[])
|
|
|
130
132
|
thresholdSignatureScheme: string;
|
|
131
133
|
password?: string | undefined;
|
|
132
134
|
}): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Connects to the WaaS wallet client
|
|
137
|
+
*/
|
|
133
138
|
revokeDelegation({ accountAddress, password, }: {
|
|
134
139
|
accountAddress: string;
|
|
135
140
|
password?: string | undefined;
|
|
136
141
|
}): Promise<void>;
|
|
137
142
|
updatePassword({ accountAddress, existingPassword, newPassword, }: {
|
|
138
|
-
accountAddress: string;
|
|
139
|
-
* Connects to the WaaS wallet client
|
|
140
|
-
*/
|
|
143
|
+
accountAddress: string;
|
|
141
144
|
existingPassword?: string | undefined;
|
|
142
145
|
newPassword: string;
|
|
143
146
|
}): Promise<void>;
|
|
@@ -198,6 +201,7 @@ export declare class DynamicWaasMidnightConnector extends DynamicWaasMidnightCon
|
|
|
198
201
|
overrideKey: string;
|
|
199
202
|
isEmbeddedWallet: boolean;
|
|
200
203
|
logger: Logger;
|
|
204
|
+
private static readonly SEND_BALANCE_TTL_MS;
|
|
201
205
|
activeAccountAddress: string | undefined;
|
|
202
206
|
verifiedCredentials: JwtVerifiedCredential[] | undefined;
|
|
203
207
|
protected walletUiUtils: WalletUiUtils<InternalWalletConnector>;
|
|
@@ -310,6 +314,8 @@ export declare class DynamicWaasMidnightConnector extends DynamicWaasMidnightCon
|
|
|
310
314
|
* @param from - The sender's address
|
|
311
315
|
* @returns A new IUITransaction instance
|
|
312
316
|
*/
|
|
317
|
+
private sendBalanceCache;
|
|
318
|
+
private clearSendBalanceCache;
|
|
313
319
|
createUiTransaction(from: string): Promise<IUITransaction>;
|
|
314
320
|
/**
|
|
315
321
|
* Returns the provider.
|
|
@@ -5,7 +5,7 @@ import { DynamicError } from '@dynamic-labs/utils';
|
|
|
5
5
|
import { withDynamicWaas } from '@dynamic-labs/waas';
|
|
6
6
|
import { isSameAddress } from '@dynamic-labs/wallet-connector-core';
|
|
7
7
|
import { Logger } from '@dynamic-labs/logger';
|
|
8
|
-
import {
|
|
8
|
+
import { MIDNIGHT_NATIVE_TOKEN_TYPE } from '../../constants.js';
|
|
9
9
|
import { MidnightUiTransaction } from '../../utils/MidnightUiTransaction/MidnightUiTransaction.js';
|
|
10
10
|
import { MidnightWallet } from '../../wallet/MidnightWallet.js';
|
|
11
11
|
import { WaasMidnightWalletConnector } from '../WaasMidnightWalletConnector.js';
|
|
@@ -83,6 +83,8 @@ class DynamicWaasMidnightConnector extends withDynamicWaas(WaasMidnightWalletCon
|
|
|
83
83
|
*/
|
|
84
84
|
afterWalletSelectHook(walletAddress) {
|
|
85
85
|
this.setActiveAccountAddress(walletAddress);
|
|
86
|
+
// Different wallet → its balances are unrelated; drop any cached snapshot.
|
|
87
|
+
this.clearSendBalanceCache();
|
|
86
88
|
}
|
|
87
89
|
/**
|
|
88
90
|
* Requires and returns the signed session ID
|
|
@@ -161,7 +163,9 @@ class DynamicWaasMidnightConnector extends withDynamicWaas(WaasMidnightWalletCon
|
|
|
161
163
|
*/
|
|
162
164
|
disconnect() {
|
|
163
165
|
return __awaiter(this, void 0, void 0, function* () {
|
|
164
|
-
// WaaS doesn't require explicit disconnect
|
|
166
|
+
// WaaS doesn't require explicit disconnect, but drop the balance snapshot
|
|
167
|
+
// so a shielded balance isn't retained after the wallet is disconnected.
|
|
168
|
+
this.clearSendBalanceCache();
|
|
165
169
|
});
|
|
166
170
|
}
|
|
167
171
|
/**
|
|
@@ -264,47 +268,54 @@ class DynamicWaasMidnightConnector extends withDynamicWaas(WaasMidnightWalletCon
|
|
|
264
268
|
return signature;
|
|
265
269
|
});
|
|
266
270
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
* @returns A new IUITransaction instance
|
|
271
|
-
*/
|
|
271
|
+
clearSendBalanceCache() {
|
|
272
|
+
this.sendBalanceCache = undefined;
|
|
273
|
+
}
|
|
272
274
|
createUiTransaction(from) {
|
|
273
275
|
return __awaiter(this, void 0, void 0, function* () {
|
|
274
276
|
yield this.validateActiveWallet(from);
|
|
277
|
+
// Balances from the connector (MPC state) — never the redcoast
|
|
278
|
+
// public-balance endpoint, which rejects Midnight addresses. Reused from the
|
|
279
|
+
// short-lived cache across recreations (see field doc).
|
|
280
|
+
const now = Date.now();
|
|
281
|
+
if (!this.sendBalanceCache ||
|
|
282
|
+
now - this.sendBalanceCache.at >
|
|
283
|
+
DynamicWaasMidnightConnector.SEND_BALANCE_TTL_MS) {
|
|
284
|
+
const { shielded, unshielded } = yield this.getBalances();
|
|
285
|
+
this.sendBalanceCache = { at: now, maps: { shielded, unshielded } };
|
|
286
|
+
}
|
|
287
|
+
const balances = this.sendBalanceCache.maps;
|
|
275
288
|
return new MidnightUiTransaction({
|
|
289
|
+
balances,
|
|
276
290
|
// No on-chain dust-fee estimate is exposed yet; DUST fees are charged
|
|
277
291
|
// at submit time. TODO: surface a real estimate from the wallet client.
|
|
278
292
|
fetchDustFee: () => __awaiter(this, void 0, void 0, function* () { return BigInt(0); }),
|
|
279
293
|
from,
|
|
280
|
-
// Balances come from the connector (MPC state), reusing the cached
|
|
281
|
-
// synced wallet — never from the redcoast public-balance endpoint,
|
|
282
|
-
// which doesn't support Midnight addresses.
|
|
283
|
-
getShieldedBalance: () => __awaiter(this, void 0, void 0, function* () {
|
|
284
|
-
var _a;
|
|
285
|
-
return (_a = (yield this.getBalances()).shielded[MIDNIGHT_NATIVE_SHIELDED_TOKEN_TYPE]) !== null && _a !== void 0 ? _a : BigInt(0);
|
|
286
|
-
}),
|
|
287
|
-
getUnshieldedBalance: () => __awaiter(this, void 0, void 0, function* () {
|
|
288
|
-
var _b;
|
|
289
|
-
return (_b = (yield this.getBalances()).unshielded[MIDNIGHT_NATIVE_TOKEN_TYPE]) !== null && _b !== void 0 ? _b : BigInt(0);
|
|
290
|
-
}),
|
|
291
294
|
onSubmit: (tx) => __awaiter(this, void 0, void 0, function* () {
|
|
292
295
|
if (tx.to === undefined || tx.value === undefined) {
|
|
293
296
|
throw new DynamicError('Recipient and amount are required before submitting');
|
|
294
297
|
}
|
|
298
|
+
// Native NIGHT needs no tokenType; any other (shielded) token is passed
|
|
299
|
+
// by its ledger token type so the correct balance is debited.
|
|
300
|
+
const tokenType = tx.selectedTokenAddress === MIDNIGHT_NATIVE_TOKEN_TYPE
|
|
301
|
+
? undefined
|
|
302
|
+
: tx.selectedTokenAddress;
|
|
295
303
|
// 3-step Midnight transfer: build → sign (ZK prove) → submit.
|
|
296
304
|
const { serializedTransaction } = yield this.createTransferTransaction({
|
|
297
305
|
transfers: [
|
|
298
306
|
{
|
|
299
307
|
amount: tx.value.toString(),
|
|
300
308
|
recipientAddress: tx.to,
|
|
309
|
+
tokenType,
|
|
301
310
|
type: tx.activePool,
|
|
302
311
|
},
|
|
303
312
|
],
|
|
304
313
|
});
|
|
305
314
|
const finalized = yield this.signTransaction(serializedTransaction);
|
|
306
|
-
// Return the tx hash so the Send flow advances to the success view.
|
|
307
315
|
const { txHash } = yield this.submitTransaction(finalized);
|
|
316
|
+
// Balances changed — drop the snapshot so the next send fetches fresh.
|
|
317
|
+
this.clearSendBalanceCache();
|
|
318
|
+
// Return the tx hash so the Send flow advances to the success view.
|
|
308
319
|
return txHash;
|
|
309
320
|
}),
|
|
310
321
|
});
|
|
@@ -576,5 +587,7 @@ class DynamicWaasMidnightConnector extends withDynamicWaas(WaasMidnightWalletCon
|
|
|
576
587
|
});
|
|
577
588
|
}
|
|
578
589
|
}
|
|
590
|
+
// Max age of the Send-flow balance snapshot (see `sendBalanceCache`).
|
|
591
|
+
DynamicWaasMidnightConnector.SEND_BALANCE_TTL_MS = 30000;
|
|
579
592
|
|
|
580
593
|
export { DynamicWaasMidnightConnector };
|
|
@@ -69,18 +69,19 @@ class MidnightWallet extends walletConnectorCore.Wallet {
|
|
|
69
69
|
getFormattedBalances() {
|
|
70
70
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
71
71
|
const raw = yield this._connector.getBalances();
|
|
72
|
-
const shieldedRaw = raw.shielded[constants.MIDNIGHT_NATIVE_SHIELDED_TOKEN_TYPE];
|
|
73
72
|
const unshieldedRaw = raw.unshielded[constants.MIDNIGHT_NATIVE_TOKEN_TYPE];
|
|
74
73
|
const dustEmpty = raw.dust.balance === BigInt(0) && raw.dust.cap === BigInt(0);
|
|
74
|
+
// The shielded pool holds non-NIGHT token types only, so surface a count of
|
|
75
|
+
// distinct tokens with a positive balance rather than a (non-existent)
|
|
76
|
+
// shielded NIGHT amount.
|
|
77
|
+
const shieldedTokenCount = Object.values(raw.shielded).filter((amount) => amount > BigInt(0)).length;
|
|
75
78
|
return {
|
|
76
79
|
dustBalance: dustEmpty
|
|
77
80
|
? undefined
|
|
78
81
|
: formatMidnightConnectorDustBalance.formatMidnightConnectorDustBalance(raw.dust.balance, raw.dust.cap),
|
|
79
82
|
// Passthrough (undefined for injected/external wallets, which omit it).
|
|
80
83
|
dustSyncing: raw.dustSyncing,
|
|
81
|
-
|
|
82
|
-
? formatMidnightNativeUnshieldedBalance.formatMidnightNativeUnshieldedBalance(shieldedRaw)
|
|
83
|
-
: undefined,
|
|
84
|
+
shieldedTokenCount,
|
|
84
85
|
unshieldedBalance: unshieldedRaw !== undefined
|
|
85
86
|
? formatMidnightNativeUnshieldedBalance.formatMidnightNativeUnshieldedBalance(unshieldedRaw)
|
|
86
87
|
: undefined,
|
|
@@ -65,18 +65,19 @@ class MidnightWallet extends Wallet {
|
|
|
65
65
|
getFormattedBalances() {
|
|
66
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
67
67
|
const raw = yield this._connector.getBalances();
|
|
68
|
-
const shieldedRaw = raw.shielded[MIDNIGHT_NATIVE_SHIELDED_TOKEN_TYPE];
|
|
69
68
|
const unshieldedRaw = raw.unshielded[MIDNIGHT_NATIVE_TOKEN_TYPE];
|
|
70
69
|
const dustEmpty = raw.dust.balance === BigInt(0) && raw.dust.cap === BigInt(0);
|
|
70
|
+
// The shielded pool holds non-NIGHT token types only, so surface a count of
|
|
71
|
+
// distinct tokens with a positive balance rather than a (non-existent)
|
|
72
|
+
// shielded NIGHT amount.
|
|
73
|
+
const shieldedTokenCount = Object.values(raw.shielded).filter((amount) => amount > BigInt(0)).length;
|
|
71
74
|
return {
|
|
72
75
|
dustBalance: dustEmpty
|
|
73
76
|
? undefined
|
|
74
77
|
: formatMidnightConnectorDustBalance(raw.dust.balance, raw.dust.cap),
|
|
75
78
|
// Passthrough (undefined for injected/external wallets, which omit it).
|
|
76
79
|
dustSyncing: raw.dustSyncing,
|
|
77
|
-
|
|
78
|
-
? formatMidnightNativeUnshieldedBalance(shieldedRaw)
|
|
79
|
-
: undefined,
|
|
80
|
+
shieldedTokenCount,
|
|
80
81
|
unshieldedBalance: unshieldedRaw !== undefined
|
|
81
82
|
? formatMidnightNativeUnshieldedBalance(unshieldedRaw)
|
|
82
83
|
: undefined,
|