@dynamic-labs/sdk-react-core 4.80.0 → 4.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +12 -12
- package/src/lib/components/SendBalanceForm/SendBalanceForm.cjs +63 -3
- package/src/lib/components/SendBalanceForm/SendBalanceForm.js +63 -3
- package/src/lib/components/SendBalanceForm/TransactionModeSegmentedControl/TransactionModeSegmentedControl.cjs +40 -0
- package/src/lib/components/SendBalanceForm/TransactionModeSegmentedControl/TransactionModeSegmentedControl.d.ts +16 -0
- package/src/lib/components/SendBalanceForm/TransactionModeSegmentedControl/TransactionModeSegmentedControl.js +36 -0
- package/src/lib/components/SendBalanceForm/TransactionModeSegmentedControl/icons.cjs +17 -0
- package/src/lib/components/SendBalanceForm/TransactionModeSegmentedControl/icons.d.ts +8 -0
- package/src/lib/components/SendBalanceForm/TransactionModeSegmentedControl/icons.js +12 -0
- package/src/lib/components/SendBalanceForm/TransactionModeSegmentedControl/index.d.ts +1 -0
- package/src/lib/styles/index.shadow.cjs +1 -1
- package/src/lib/styles/index.shadow.js +1 -1
- package/src/lib/utils/hooks/useAleoShieldedBalances/index.d.ts +1 -0
- package/src/lib/utils/hooks/useAleoShieldedBalances/useAleoShieldedBalances.cjs +372 -0
- package/src/lib/utils/hooks/useAleoShieldedBalances/useAleoShieldedBalances.d.ts +24 -0
- package/src/lib/utils/hooks/useAleoShieldedBalances/useAleoShieldedBalances.js +368 -0
- package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.cjs +1 -0
- package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.d.ts +1 -0
- package/src/lib/utils/hooks/useEmbeddedWallet/useEmbeddedWallet.js +1 -0
- package/src/lib/views/SendBalanceView/SendBalanceView.cjs +53 -0
- package/src/lib/views/SendBalanceView/SendBalanceView.js +53 -0
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/ActiveWalletBalance.cjs +191 -11
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/ActiveWalletBalance.js +191 -11
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/TokenBalanceItem/TokenBalanceItem.cjs +5 -2
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/TokenBalanceItem/TokenBalanceItem.d.ts +10 -1
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/TokenBalanceItem/TokenBalanceItem.js +5 -2
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/TokenBalanceItem/index.d.ts +1 -0
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/TokenBalanceList/TokenBalanceList.cjs +2 -2
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/TokenBalanceList/TokenBalanceList.d.ts +3 -1
- package/src/lib/widgets/DynamicWidget/components/ActiveWalletBalance/TokenBalanceList/TokenBalanceList.js +2 -2
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../../../../../_virtual/_tslib.js';
|
|
3
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
4
|
+
import { ChainEnum } from '@dynamic-labs/sdk-api-core';
|
|
5
|
+
import '../../../context/DynamicContext/DynamicContext.js';
|
|
6
|
+
import '../../../store/state/loadingAndLifecycle/loadingAndLifecycle.js';
|
|
7
|
+
import '@dynamic-labs/iconic';
|
|
8
|
+
import '@dynamic-labs/wallet-connector-core';
|
|
9
|
+
import 'react/jsx-runtime';
|
|
10
|
+
import '../../../context/ViewContext/ViewContext.js';
|
|
11
|
+
import '../../../shared/logger.js';
|
|
12
|
+
import '@dynamic-labs/wallet-book';
|
|
13
|
+
import '@dynamic-labs/utils';
|
|
14
|
+
import '../../constants/colors.js';
|
|
15
|
+
import '../../constants/values.js';
|
|
16
|
+
import '../../../shared/consts/index.js';
|
|
17
|
+
import '../../../events/dynamicEvents.js';
|
|
18
|
+
import '../../../context/CaptchaContext/CaptchaContext.js';
|
|
19
|
+
import '../../../context/ErrorContext/ErrorContext.js';
|
|
20
|
+
import '@dynamic-labs/multi-wallet';
|
|
21
|
+
import 'react-international-phone';
|
|
22
|
+
import '../../../store/state/nonce/nonce.js';
|
|
23
|
+
import '@dynamic-labs-sdk/client/core';
|
|
24
|
+
import 'eventemitter3';
|
|
25
|
+
import '@dynamic-labs-sdk/client';
|
|
26
|
+
import '../../../config/ApiEndpoint.js';
|
|
27
|
+
import '@dynamic-labs/locale';
|
|
28
|
+
import '../../../store/state/dynamicContextProps/dynamicContextProps.js';
|
|
29
|
+
import '../../../store/state/primaryWalletId/primaryWalletId.js';
|
|
30
|
+
import '../../../store/state/connectedWalletsInfo/connectedWalletsInfo.js';
|
|
31
|
+
import '../../functions/getWaasAddressTypeLabel/getWaasAddressTypeLabel.js';
|
|
32
|
+
import '../../../context/AccessDeniedContext/AccessDeniedContext.js';
|
|
33
|
+
import '../../../context/AccountExistsContext/AccountExistsContext.js';
|
|
34
|
+
import '../../../context/UserWalletsContext/UserWalletsContext.js';
|
|
35
|
+
import '../../../store/state/authMode/authMode.js';
|
|
36
|
+
import '../../../context/VerificationContext/VerificationContext.js';
|
|
37
|
+
import 'react-dom';
|
|
38
|
+
import '../../functions/compareChains/compareChains.js';
|
|
39
|
+
import '../../../views/Passkey/utils/findPrimaryEmbeddedChain/findPrimaryEmbeddedChain.js';
|
|
40
|
+
import '../../../context/ThemeContext/ThemeContext.js';
|
|
41
|
+
import '../useUserUpdateRequest/useUpdateUser/userFieldsSchema.js';
|
|
42
|
+
import 'bs58';
|
|
43
|
+
import '@dynamic-labs/types';
|
|
44
|
+
import '../../../context/SocialRedirectContext/SocialRedirectContext.js';
|
|
45
|
+
import '../../../context/LoadingContext/LoadingContext.js';
|
|
46
|
+
import '../../../context/WalletContext/WalletContext.js';
|
|
47
|
+
import '../useEmbeddedWallet/useSecureEnclaveEmbeddedWallet/constants.js';
|
|
48
|
+
import 'yup';
|
|
49
|
+
import '../../../context/MockContext/MockContext.js';
|
|
50
|
+
import '../../../views/CollectUserDataView/useFields.js';
|
|
51
|
+
import '../../../context/FieldsStateContext/FieldsStateContext.js';
|
|
52
|
+
import '../../../context/UserFieldEditorContext/UserFieldEditorContext.js';
|
|
53
|
+
import '@dynamic-labs/rpc-providers';
|
|
54
|
+
import '../../../store/state/walletOptions/walletOptions.js';
|
|
55
|
+
import 'react-i18next';
|
|
56
|
+
import '../../../components/Accordion/components/AccordionItem/AccordionItem.js';
|
|
57
|
+
import '../../../components/Alert/Alert.js';
|
|
58
|
+
import '../../../components/ShadowDOM/ShadowDOM.js';
|
|
59
|
+
import '../../../components/IconButton/IconButton.js';
|
|
60
|
+
import '../../../components/InlineWidget/InlineWidget.js';
|
|
61
|
+
import '../../../components/Input/Input.js';
|
|
62
|
+
import '../../../components/IsBrowser/IsBrowser.js';
|
|
63
|
+
import '../../../components/MenuList/Dropdown/Dropdown.js';
|
|
64
|
+
import '../../../components/OverlayCard/OverlayCard.js';
|
|
65
|
+
import '../../../components/Transition/ZoomTransition/ZoomTransition.js';
|
|
66
|
+
import '../../../components/Transition/SlideInUpTransition/SlideInUpTransition.js';
|
|
67
|
+
import '../../../components/Transition/OpacityTransition/OpacityTransition.js';
|
|
68
|
+
import '../../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.js';
|
|
69
|
+
import '../../../components/Popper/Popper/Popper.js';
|
|
70
|
+
import '../../../components/Popper/PopperContext/PopperContext.js';
|
|
71
|
+
import 'react-focus-lock';
|
|
72
|
+
import 'qrcode';
|
|
73
|
+
import 'formik';
|
|
74
|
+
import '../useSubdomainCheck/useSubdomainCheck.js';
|
|
75
|
+
import '../../../context/WalletGroupContext/WalletGroupContext.js';
|
|
76
|
+
import '../../../widgets/DynamicWidget/context/DynamicWidgetContext.js';
|
|
77
|
+
import '../useGetMfaToken/useGetMfaToken.js';
|
|
78
|
+
import '../useWalletBackup/useWalletBackup.js';
|
|
79
|
+
import '../useWalletBackup/types.js';
|
|
80
|
+
import '../useWalletBackup/cloudProviders.js';
|
|
81
|
+
import '../../../context/IpConfigurationContext/IpConfigurationContext.js';
|
|
82
|
+
import '../../../context/ConnectWithOtpContext/ConnectWithOtpContext.js';
|
|
83
|
+
import '../../../widgets/DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.js';
|
|
84
|
+
import '@hcaptcha/react-hcaptcha';
|
|
85
|
+
import '../../../widgets/DynamicWidget/helpers/convertExchangeKeyAndProviderEnum.js';
|
|
86
|
+
import '../../../views/ExchangeWhitelistWarning/ExchangeWhitelistWarning.js';
|
|
87
|
+
import '../../../context/ErrorContext/hooks/useErrorText/useErrorText.js';
|
|
88
|
+
import '../../../context/FooterAnimationContext/index.js';
|
|
89
|
+
import '../../../views/MfaChooseDeviceView/useGetMfaOptions/useGetMfaOptions.js';
|
|
90
|
+
import '../../../context/PasskeyContext/PasskeyContext.js';
|
|
91
|
+
import '../../../context/OnrampContext/OnrampContext.js';
|
|
92
|
+
import '../../../store/state/sendBalances.js';
|
|
93
|
+
import '../../../store/state/connectorsInitializing/connectorsInitializing.js';
|
|
94
|
+
import '../../../components/OverlayCardBase/OverlayCardTarget/OverlayCardTarget.js';
|
|
95
|
+
import '../../../widgets/DynamicWidget/components/DynamicWidgetHeader/DynamicWidgetHeader.js';
|
|
96
|
+
import '../../../views/TransactionConfirmationView/TransactionConfirmationView.js';
|
|
97
|
+
import '../../../widgets/DynamicWidget/components/PasskeyCard/PasskeyCard.js';
|
|
98
|
+
import '../../../widgets/DynamicWidget/views/CryptoComOnramp/CryptoComOnramp.js';
|
|
99
|
+
import '../../../../index.js';
|
|
100
|
+
import '../../../widgets/DynamicWidget/views/ManagePasskeysMfaWidgetView/ManagePasskeysMfaWidgetView.js';
|
|
101
|
+
import '../../../widgets/DynamicWidget/views/ManageTotpMfaWidgetView/ManageTotpMfaWidgetView.js';
|
|
102
|
+
import '../../../widgets/DynamicWidget/views/ReceiveWalletFunds/ReceiveWalletFunds.js';
|
|
103
|
+
import '../../../store/state/tokenBalances.js';
|
|
104
|
+
import '../../../store/state/multichainBalances.js';
|
|
105
|
+
import '@dynamic-labs/store';
|
|
106
|
+
import '../../../shared/utils/functions/getInitialUrl/getInitialUrl.js';
|
|
107
|
+
import { useInternalDynamicContext } from '../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.js';
|
|
108
|
+
|
|
109
|
+
const MICROCREDITS_PER_CREDIT = 1000000;
|
|
110
|
+
const ALEO_CREDITS_LOGO = 'https://app.dynamic.xyz/assets/networks/aleo.svg';
|
|
111
|
+
// Generic dark "?" token icon — matches redcoast's `DEFAULT_TOKEN_LOGO_URI`
|
|
112
|
+
// used by the multichain endpoint when an unshielded token has no curated
|
|
113
|
+
// logo. Reusing it here keeps the Shielded tab visually consistent with
|
|
114
|
+
// the Unshielded tab for the same token.
|
|
115
|
+
const UNKNOWN_TOKEN_LOGO = 'https://app.dynamic.xyz/assets/tokens/unknown.svg';
|
|
116
|
+
const TOKEN_REGISTRY_PROGRAM = 'token_registry.aleo';
|
|
117
|
+
const TOKEN_REGISTRY_RECORD = 'Token';
|
|
118
|
+
// Non-credits tokens deliberately omit `logoURI` — Aleo doesn't have a
|
|
119
|
+
// curated icon list yet, so leaving it undefined surfaces the widget's
|
|
120
|
+
// generic placeholder (`?` skeleton) consistent with the unshielded feed.
|
|
121
|
+
const KNOWN_SHIELDED_TOKENS = [
|
|
122
|
+
{
|
|
123
|
+
contractAddress: 'usad_stablecoin.aleo',
|
|
124
|
+
decimals: 6,
|
|
125
|
+
name: 'USAD',
|
|
126
|
+
programName: 'usad_stablecoin.aleo',
|
|
127
|
+
recordName: 'Token',
|
|
128
|
+
symbol: 'USAD',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
contractAddress: 'test_usad_stablecoin.aleo',
|
|
132
|
+
decimals: 6,
|
|
133
|
+
name: 'USAD',
|
|
134
|
+
programName: 'test_usad_stablecoin.aleo',
|
|
135
|
+
recordName: 'Token',
|
|
136
|
+
symbol: 'USAD',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
contractAddress: 'usdcx_stablecoin.aleo',
|
|
140
|
+
decimals: 6,
|
|
141
|
+
name: 'USDCx',
|
|
142
|
+
programName: 'usdcx_stablecoin.aleo',
|
|
143
|
+
recordName: 'Token',
|
|
144
|
+
symbol: 'USDCx',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
contractAddress: 'test_usdcx_stablecoin.aleo',
|
|
148
|
+
decimals: 6,
|
|
149
|
+
name: 'USDCx',
|
|
150
|
+
programName: 'test_usdcx_stablecoin.aleo',
|
|
151
|
+
recordName: 'Token',
|
|
152
|
+
symbol: 'USDCx',
|
|
153
|
+
},
|
|
154
|
+
// ARC-21 (Hyperlane warp routes) — mainnet only. Token IDs match the
|
|
155
|
+
// values pinned in `packages/aleo/src/utils/aleoSendableTokens` and the
|
|
156
|
+
// redcoast `aleoArc21Tokens` registry. Decimals match each token's
|
|
157
|
+
// `token_info` metadata on-chain.
|
|
158
|
+
{
|
|
159
|
+
contractAddress: 'hyp_warp_token_sol.aleo',
|
|
160
|
+
decimals: 9,
|
|
161
|
+
name: 'Wrapped SOL',
|
|
162
|
+
programName: TOKEN_REGISTRY_PROGRAM,
|
|
163
|
+
recordName: TOKEN_REGISTRY_RECORD,
|
|
164
|
+
symbol: 'wSOL',
|
|
165
|
+
tokenId: '2045969100091121326225168054634646230244820821909676777152465722877810201564field',
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
contractAddress: 'hyp_warp_token_eth.aleo',
|
|
169
|
+
decimals: 18,
|
|
170
|
+
name: 'Wrapped ETH',
|
|
171
|
+
programName: TOKEN_REGISTRY_PROGRAM,
|
|
172
|
+
recordName: TOKEN_REGISTRY_RECORD,
|
|
173
|
+
symbol: 'wETH',
|
|
174
|
+
tokenId: '8189585964265444162798552221009403350643900573290534096996249214099143169251field',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
contractAddress: 'hyp_warp_token_wbtc.aleo',
|
|
178
|
+
decimals: 8,
|
|
179
|
+
name: 'Wrapped BTC',
|
|
180
|
+
programName: TOKEN_REGISTRY_PROGRAM,
|
|
181
|
+
recordName: TOKEN_REGISTRY_RECORD,
|
|
182
|
+
symbol: 'wBTC',
|
|
183
|
+
tokenId: '3491859903473482085250871387962132231204352466326026409883548131580582527809field',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
contractAddress: 'hyp_warp_token_usdt.aleo',
|
|
187
|
+
decimals: 6,
|
|
188
|
+
name: 'Tether USD',
|
|
189
|
+
programName: TOKEN_REGISTRY_PROGRAM,
|
|
190
|
+
recordName: TOKEN_REGISTRY_RECORD,
|
|
191
|
+
symbol: 'USDT',
|
|
192
|
+
tokenId: '7881654794448182580124231856035865816599796419758925654292946277940935117913field',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
contractAddress: 'hyp_warp_token_usdc.aleo',
|
|
196
|
+
decimals: 6,
|
|
197
|
+
name: 'USD Coin',
|
|
198
|
+
programName: TOKEN_REGISTRY_PROGRAM,
|
|
199
|
+
recordName: TOKEN_REGISTRY_RECORD,
|
|
200
|
+
symbol: 'USDC',
|
|
201
|
+
tokenId: '4697275201844475848710842677807162058146139844643350200269139278887318953049field',
|
|
202
|
+
},
|
|
203
|
+
];
|
|
204
|
+
/**
|
|
205
|
+
* Match a record to a shielded-token spec. Stablecoins match on
|
|
206
|
+
* (program, record); ARC-21 entries additionally require the spec's
|
|
207
|
+
* `tokenId` to appear inside `record_plaintext` (since every ARC-21 token
|
|
208
|
+
* shares `token_registry.aleo / Token`).
|
|
209
|
+
*/
|
|
210
|
+
const findTokenSpec = (record) => {
|
|
211
|
+
for (const spec of KNOWN_SHIELDED_TOKENS) {
|
|
212
|
+
if (record.program_name !== spec.programName)
|
|
213
|
+
continue;
|
|
214
|
+
if (record.record_name !== spec.recordName)
|
|
215
|
+
continue;
|
|
216
|
+
if (spec.tokenId) {
|
|
217
|
+
if (typeof record.record_plaintext !== 'string' ||
|
|
218
|
+
!record.record_plaintext.includes(`token_id: ${spec.tokenId}`)) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return spec;
|
|
223
|
+
}
|
|
224
|
+
return undefined;
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Hook that returns the active wallet's shielded (private) Aleo token
|
|
228
|
+
* balances as a `TokenBalance[]` so the widget can render them through the
|
|
229
|
+
* same TokenBalanceList path it uses for unshielded balances.
|
|
230
|
+
*
|
|
231
|
+
* - Records come from the iframe via `connector.listOwnedRecords()` (the
|
|
232
|
+
* Provable RecordScanner; view key never leaves the iframe).
|
|
233
|
+
* - Aggregates `credits.aleo/credits` (sum `microcredits` → ALEO) plus any
|
|
234
|
+
* tier-3 stablecoin Token records (sum `amount` per program → USAD/USDCx).
|
|
235
|
+
* ARC-21 multi-token grouped-by-`token_id` is Phase 2B.
|
|
236
|
+
*
|
|
237
|
+
* Returns an empty list when:
|
|
238
|
+
* - The wallet isn't Aleo
|
|
239
|
+
* - The connector doesn't expose `listOwnedRecords` (e.g. external Aleo wallet)
|
|
240
|
+
* - The user owns no records that match a known program/record pair
|
|
241
|
+
*/
|
|
242
|
+
const useAleoShieldedBalances = () => {
|
|
243
|
+
const { primaryWallet, network } = useInternalDynamicContext();
|
|
244
|
+
const [tokenBalances, setTokenBalances] = useState([]);
|
|
245
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
246
|
+
const [error, setError] = useState();
|
|
247
|
+
const connector = primaryWallet === null || primaryWallet === void 0 ? void 0 : primaryWallet.connector;
|
|
248
|
+
const isAleo = (connector === null || connector === void 0 ? void 0 : connector.connectedChain) === ChainEnum.Aleo;
|
|
249
|
+
const supportsShielded = isAleo &&
|
|
250
|
+
typeof (connector === null || connector === void 0 ? void 0 : connector.listOwnedRecords) === 'function';
|
|
251
|
+
// Mirror the live connector into a ref so `fetchShielded` can read it
|
|
252
|
+
// without depending on the (often unstable) object reference. Some test
|
|
253
|
+
// setups mock context with a factory that returns a fresh `primaryWallet`
|
|
254
|
+
// every render — depending on that ref directly turned this into an
|
|
255
|
+
// infinite render loop.
|
|
256
|
+
const connectorRef = useRef(connector);
|
|
257
|
+
connectorRef.current = connector;
|
|
258
|
+
const connectorKey = connector === null || connector === void 0 ? void 0 : connector.key;
|
|
259
|
+
const networkKey = network !== undefined && network !== null ? String(network) : undefined;
|
|
260
|
+
const fetchShielded = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
261
|
+
var _a, _b, _c;
|
|
262
|
+
const liveConnector = connectorRef.current;
|
|
263
|
+
if (!supportsShielded || !liveConnector) {
|
|
264
|
+
setTokenBalances((prev) => (prev.length === 0 ? prev : []));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
setIsLoading(true);
|
|
268
|
+
setError(undefined);
|
|
269
|
+
try {
|
|
270
|
+
const result = yield liveConnector.listOwnedRecords();
|
|
271
|
+
const records = (_a = result === null || result === void 0 ? void 0 : result.records) !== null && _a !== void 0 ? _a : [];
|
|
272
|
+
const networkIdNumeric = Number(networkKey);
|
|
273
|
+
const safeNetworkId = Number.isFinite(networkIdNumeric)
|
|
274
|
+
? networkIdNumeric
|
|
275
|
+
: undefined;
|
|
276
|
+
const balances = [];
|
|
277
|
+
// Tier 1: native credits — sum microcredits across credits.aleo records.
|
|
278
|
+
const creditsRecords = records.filter((r) => (r === null || r === void 0 ? void 0 : r.program_name) === 'credits.aleo' &&
|
|
279
|
+
(r === null || r === void 0 ? void 0 : r.record_name) === 'credits' &&
|
|
280
|
+
typeof (r === null || r === void 0 ? void 0 : r.microcredits) === 'string');
|
|
281
|
+
if (creditsRecords.length > 0) {
|
|
282
|
+
const totalMicrocredits = creditsRecords.reduce((sum, r) => sum + BigInt(r.microcredits), BigInt(0));
|
|
283
|
+
// BigInt → number for the TokenBalance shape. Aleo balances stay well
|
|
284
|
+
// below Number.MAX_SAFE_INTEGER for a single wallet (max u64 supply is
|
|
285
|
+
// 1.5B credits = 1.5e15 microcredits; Number can hold up to ~9e15).
|
|
286
|
+
const rawBalance = Number(totalMicrocredits);
|
|
287
|
+
balances.push({
|
|
288
|
+
address: '0x0',
|
|
289
|
+
balance: rawBalance / MICROCREDITS_PER_CREDIT,
|
|
290
|
+
decimals: 6,
|
|
291
|
+
isNative: true,
|
|
292
|
+
logoURI: ALEO_CREDITS_LOGO,
|
|
293
|
+
name: 'Aleo Credits',
|
|
294
|
+
networkId: safeNetworkId,
|
|
295
|
+
rawBalance,
|
|
296
|
+
symbol: 'ALEO',
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
// Tier 3 + ARC-21: Token records. Each record matches at most one
|
|
300
|
+
// spec (stablecoin programs disambiguate by program; ARC-21 records
|
|
301
|
+
// share `token_registry.aleo / Token` and disambiguate by tokenId
|
|
302
|
+
// inside the plaintext). Sum the `amount` field per spec.
|
|
303
|
+
const sumsByContract = new Map();
|
|
304
|
+
const specsByContract = new Map();
|
|
305
|
+
for (const r of records) {
|
|
306
|
+
const spec = findTokenSpec(r);
|
|
307
|
+
if (!spec || typeof r.amount !== 'string')
|
|
308
|
+
continue;
|
|
309
|
+
try {
|
|
310
|
+
const prev = (_b = sumsByContract.get(spec.contractAddress)) !== null && _b !== void 0 ? _b : BigInt(0);
|
|
311
|
+
sumsByContract.set(spec.contractAddress, prev + BigInt(r.amount));
|
|
312
|
+
specsByContract.set(spec.contractAddress, spec);
|
|
313
|
+
}
|
|
314
|
+
catch (_d) {
|
|
315
|
+
/* ignore — malformed amount string */
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
for (const [contractAddress, total] of sumsByContract.entries()) {
|
|
319
|
+
const spec = specsByContract.get(contractAddress);
|
|
320
|
+
if (!spec)
|
|
321
|
+
continue;
|
|
322
|
+
const rawBalance = Number(total);
|
|
323
|
+
balances.push({
|
|
324
|
+
address: spec.contractAddress,
|
|
325
|
+
balance: rawBalance / Math.pow(10, spec.decimals),
|
|
326
|
+
decimals: spec.decimals,
|
|
327
|
+
// Use redcoast's `DEFAULT_TOKEN_LOGO_URI` for stablecoins + ARC-21
|
|
328
|
+
// so they render the same dark "?" icon the Unshielded tab shows
|
|
329
|
+
// for these tokens (the multichain endpoint applies that fallback
|
|
330
|
+
// itself; we mirror it here for visual parity).
|
|
331
|
+
logoURI: (_c = spec.logoURI) !== null && _c !== void 0 ? _c : UNKNOWN_TOKEN_LOGO,
|
|
332
|
+
name: spec.name,
|
|
333
|
+
networkId: safeNetworkId,
|
|
334
|
+
rawBalance,
|
|
335
|
+
symbol: spec.symbol,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
setTokenBalances(balances);
|
|
339
|
+
}
|
|
340
|
+
catch (err) {
|
|
341
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
342
|
+
setError(msg);
|
|
343
|
+
setTokenBalances((prev) => (prev.length === 0 ? prev : []));
|
|
344
|
+
}
|
|
345
|
+
finally {
|
|
346
|
+
setIsLoading(false);
|
|
347
|
+
}
|
|
348
|
+
}), [connectorKey, networkKey, supportsShielded]);
|
|
349
|
+
useEffect(() => {
|
|
350
|
+
if (!supportsShielded) {
|
|
351
|
+
setTokenBalances((prev) => (prev.length === 0 ? prev : []));
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
fetchShielded().catch(() => {
|
|
355
|
+
// fetchShielded already records the error in component state;
|
|
356
|
+
// the .catch keeps the fire-and-forget shape lint-clean.
|
|
357
|
+
});
|
|
358
|
+
}, [supportsShielded, fetchShielded]);
|
|
359
|
+
return {
|
|
360
|
+
error,
|
|
361
|
+
isLoading,
|
|
362
|
+
refetch: fetchShielded,
|
|
363
|
+
supportsShielded,
|
|
364
|
+
tokenBalances,
|
|
365
|
+
};
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
export { useAleoShieldedBalances };
|
|
@@ -119,6 +119,7 @@ var useInternalDynamicContext = require('../../../context/DynamicContext/useDyna
|
|
|
119
119
|
|
|
120
120
|
// Hook exposed to customers and used internally to trigger embedded wallet creation
|
|
121
121
|
/**
|
|
122
|
+
* @deprecated This hook is deprecated and will be removed in a future release. Use `useDynamicWaas` instead.
|
|
122
123
|
* @returns {
|
|
123
124
|
* createEmbeddedWallet, - creates Dynamic embedded wallet according to the settings
|
|
124
125
|
* createOrRestoreSession, - creates or restores session for the embedded wallet
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EmbeddedWalletChainEnum, EmbeddedWalletVersionEnum } from '@dynamic-labs/sdk-api-core';
|
|
2
2
|
import { Wallet } from '../../../shared';
|
|
3
3
|
/**
|
|
4
|
+
* @deprecated This hook is deprecated and will be removed in a future release. Use `useDynamicWaas` instead.
|
|
4
5
|
* @returns {
|
|
5
6
|
* createEmbeddedWallet, - creates Dynamic embedded wallet according to the settings
|
|
6
7
|
* createOrRestoreSession, - creates or restores session for the embedded wallet
|
|
@@ -115,6 +115,7 @@ import { useInternalDynamicContext } from '../../../context/DynamicContext/useDy
|
|
|
115
115
|
|
|
116
116
|
// Hook exposed to customers and used internally to trigger embedded wallet creation
|
|
117
117
|
/**
|
|
118
|
+
* @deprecated This hook is deprecated and will be removed in a future release. Use `useDynamicWaas` instead.
|
|
118
119
|
* @returns {
|
|
119
120
|
* createEmbeddedWallet, - creates Dynamic embedded wallet according to the settings
|
|
120
121
|
* createOrRestoreSession, - creates or restores session for the embedded wallet
|
|
@@ -183,6 +183,52 @@ const SendBalanceView = ({ initialRecipientAddress = '', initialValue, onClickBa
|
|
|
183
183
|
if (orderedTokenBalances)
|
|
184
184
|
setTokenBalances(orderedTokenBalances);
|
|
185
185
|
}, [orderedTokenBalances]);
|
|
186
|
+
// Chain override: when the active IUITransaction provides
|
|
187
|
+
// `getSendableTokenBalances`, prefer that list for the picker. Used by
|
|
188
|
+
// chains where the spendable balance source diverges from
|
|
189
|
+
// `useTokenBalances` (e.g. Aleo Send always spends from private
|
|
190
|
+
// records, not the public-balance mapping redcoast returns). Chains
|
|
191
|
+
// that don't implement the method get the default fetcher unchanged.
|
|
192
|
+
//
|
|
193
|
+
// Also re-anchors `currentToken` to the matching entry in the override
|
|
194
|
+
// list. Without this, the picker's row renders the override balance
|
|
195
|
+
// (it reads from `tokenBalances`) but the form's "Available" line
|
|
196
|
+
// renders the original public balance (it reads from `currentToken`),
|
|
197
|
+
// which is stale.
|
|
198
|
+
React.useEffect(() => {
|
|
199
|
+
if (!(transaction === null || transaction === void 0 ? void 0 : transaction.getSendableTokenBalances))
|
|
200
|
+
return;
|
|
201
|
+
let cancelled = false;
|
|
202
|
+
transaction
|
|
203
|
+
.getSendableTokenBalances()
|
|
204
|
+
.then((overrideBalances) => {
|
|
205
|
+
if (cancelled)
|
|
206
|
+
return;
|
|
207
|
+
if (!overrideBalances || overrideBalances.length === 0)
|
|
208
|
+
return;
|
|
209
|
+
setTokenBalances(overrideBalances);
|
|
210
|
+
setCurrentToken((prev) => {
|
|
211
|
+
if (!prev)
|
|
212
|
+
return overrideBalances[0];
|
|
213
|
+
const match = overrideBalances.find((t) => t.address === prev.address);
|
|
214
|
+
if (!match)
|
|
215
|
+
return overrideBalances[0];
|
|
216
|
+
// Skip the swap if values are unchanged — avoids a re-render
|
|
217
|
+
// loop when transaction recreation re-fires this effect.
|
|
218
|
+
if (match.rawBalance === prev.rawBalance &&
|
|
219
|
+
match.balance === prev.balance) {
|
|
220
|
+
return prev;
|
|
221
|
+
}
|
|
222
|
+
return match;
|
|
223
|
+
});
|
|
224
|
+
})
|
|
225
|
+
.catch((err) => {
|
|
226
|
+
logger.logger.debug('[SendBalanceView] getSendableTokenBalances threw — falling back to default token list', err);
|
|
227
|
+
});
|
|
228
|
+
return () => {
|
|
229
|
+
cancelled = true;
|
|
230
|
+
};
|
|
231
|
+
}, [transaction]);
|
|
186
232
|
React.useEffect(() => {
|
|
187
233
|
if (!walletConnector)
|
|
188
234
|
return;
|
|
@@ -201,6 +247,13 @@ const SendBalanceView = ({ initialRecipientAddress = '', initialValue, onClickBa
|
|
|
201
247
|
transaction.nonNativeValue = BigInt(0);
|
|
202
248
|
transaction.nonNativeDecimal = currentToken === null || currentToken === void 0 ? void 0 : currentToken.decimals;
|
|
203
249
|
}
|
|
250
|
+
// Chain hook: tells the transaction which picker entry the user
|
|
251
|
+
// landed on (or just switched to). Aleo uses this to flip submit
|
|
252
|
+
// between credits / stablecoin / ARC-21 program signatures + to
|
|
253
|
+
// re-anchor decimals for parse/format.
|
|
254
|
+
if (currentToken && transaction.setSelectedToken) {
|
|
255
|
+
transaction.setSelectedToken(currentToken.address);
|
|
256
|
+
}
|
|
204
257
|
setTransaction(transaction);
|
|
205
258
|
})
|
|
206
259
|
.catch((error) => {
|
|
@@ -179,6 +179,52 @@ const SendBalanceView = ({ initialRecipientAddress = '', initialValue, onClickBa
|
|
|
179
179
|
if (orderedTokenBalances)
|
|
180
180
|
setTokenBalances(orderedTokenBalances);
|
|
181
181
|
}, [orderedTokenBalances]);
|
|
182
|
+
// Chain override: when the active IUITransaction provides
|
|
183
|
+
// `getSendableTokenBalances`, prefer that list for the picker. Used by
|
|
184
|
+
// chains where the spendable balance source diverges from
|
|
185
|
+
// `useTokenBalances` (e.g. Aleo Send always spends from private
|
|
186
|
+
// records, not the public-balance mapping redcoast returns). Chains
|
|
187
|
+
// that don't implement the method get the default fetcher unchanged.
|
|
188
|
+
//
|
|
189
|
+
// Also re-anchors `currentToken` to the matching entry in the override
|
|
190
|
+
// list. Without this, the picker's row renders the override balance
|
|
191
|
+
// (it reads from `tokenBalances`) but the form's "Available" line
|
|
192
|
+
// renders the original public balance (it reads from `currentToken`),
|
|
193
|
+
// which is stale.
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
if (!(transaction === null || transaction === void 0 ? void 0 : transaction.getSendableTokenBalances))
|
|
196
|
+
return;
|
|
197
|
+
let cancelled = false;
|
|
198
|
+
transaction
|
|
199
|
+
.getSendableTokenBalances()
|
|
200
|
+
.then((overrideBalances) => {
|
|
201
|
+
if (cancelled)
|
|
202
|
+
return;
|
|
203
|
+
if (!overrideBalances || overrideBalances.length === 0)
|
|
204
|
+
return;
|
|
205
|
+
setTokenBalances(overrideBalances);
|
|
206
|
+
setCurrentToken((prev) => {
|
|
207
|
+
if (!prev)
|
|
208
|
+
return overrideBalances[0];
|
|
209
|
+
const match = overrideBalances.find((t) => t.address === prev.address);
|
|
210
|
+
if (!match)
|
|
211
|
+
return overrideBalances[0];
|
|
212
|
+
// Skip the swap if values are unchanged — avoids a re-render
|
|
213
|
+
// loop when transaction recreation re-fires this effect.
|
|
214
|
+
if (match.rawBalance === prev.rawBalance &&
|
|
215
|
+
match.balance === prev.balance) {
|
|
216
|
+
return prev;
|
|
217
|
+
}
|
|
218
|
+
return match;
|
|
219
|
+
});
|
|
220
|
+
})
|
|
221
|
+
.catch((err) => {
|
|
222
|
+
logger.debug('[SendBalanceView] getSendableTokenBalances threw — falling back to default token list', err);
|
|
223
|
+
});
|
|
224
|
+
return () => {
|
|
225
|
+
cancelled = true;
|
|
226
|
+
};
|
|
227
|
+
}, [transaction]);
|
|
182
228
|
useEffect(() => {
|
|
183
229
|
if (!walletConnector)
|
|
184
230
|
return;
|
|
@@ -197,6 +243,13 @@ const SendBalanceView = ({ initialRecipientAddress = '', initialValue, onClickBa
|
|
|
197
243
|
transaction.nonNativeValue = BigInt(0);
|
|
198
244
|
transaction.nonNativeDecimal = currentToken === null || currentToken === void 0 ? void 0 : currentToken.decimals;
|
|
199
245
|
}
|
|
246
|
+
// Chain hook: tells the transaction which picker entry the user
|
|
247
|
+
// landed on (or just switched to). Aleo uses this to flip submit
|
|
248
|
+
// between credits / stablecoin / ARC-21 program signatures + to
|
|
249
|
+
// re-anchor decimals for parse/format.
|
|
250
|
+
if (currentToken && transaction.setSelectedToken) {
|
|
251
|
+
transaction.setSelectedToken(currentToken.address);
|
|
252
|
+
}
|
|
200
253
|
setTransaction(transaction);
|
|
201
254
|
})
|
|
202
255
|
.catch((error) => {
|